Skip to content

Commit

Permalink
Fix #279 - Fail to render when non-VST fx are in fx chains (#280)
Browse files Browse the repository at this point in the history
* Update reaper_plugin_functions.h to MODIFIED v6.37

v6.37 supports TrackFX_GetNamedConfigParm( track, 0, "fx_name" )
Some earlier versions support TrackFX_GetNamedConfigParm, but not with the "fx_name" arg
Modification is to address this bug in the header: https://forum.cockos.com/showthread.php?p=2548853 (post 4)

* Use TrackFX_GetNamedConfigParm over custom state chunk parsing

* Remove redundant funcs and associated tests

* Update CHANGELOG.md
  • Loading branch information
firthm01 authored Jun 4, 2024
1 parent 8e5f79a commit a9e2cfb
Show file tree
Hide file tree
Showing 7 changed files with 380 additions and 491 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
UNRELEASED
Note: This release bumps the minimum required REAPER version from v6.11 to v6.37

* Fix occasional crash bug in start up of Binaural Monitoring plugin [#277](https://github.com/ebu/ear-production-suite/issues/277) [#278](https://github.com/ebu/ear-production-suite/pull/278)
* Fix fail to render when non-VST plugins are in FX chains [#279](https://github.com/ebu/ear-production-suite/issues/279) [#280](https://github.com/ebu/ear-production-suite/pull/280)

Version 1.1.0b

Expand Down
558 changes: 362 additions & 196 deletions reaper-adm-extension/src/reaper_adm/reaper_plugin_functions.h

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions reaper-adm-extension/src/reaper_adm/reaperapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,6 @@ class ReaperAPI {
virtual void CleanFXName(std::string& name) const = 0;
virtual int TrackFX_PositionByActualName(MediaTrack* track, const std::string& fxName) const = 0;
virtual int TrackFX_AddByActualName(MediaTrack* track, const char* fxname, bool recFX, int instantiate) const = 0;
virtual std::vector<std::pair<int, std::string>> GetVSTElementsFromTrackStateChunk(const std::string& fullChunk) const = 0;
virtual std::vector<std::string> SplitVSTElement(const std::string& elm, bool stripBoundingQuotes, bool includeSeperators) const = 0;
virtual std::string GetTrackStateChunkStr(MediaTrack* track) const = 0;
virtual int GetDawChannelCount() const = 0;

};
Expand Down
181 changes: 16 additions & 165 deletions reaper-adm-extension/src/reaper_adm/reaperapiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -824,186 +824,37 @@ std::optional<std::pair<double, double>> admplug::ReaperAPIImpl::getTrackAudioBo
return std::optional<std::pair<double, double>>();
}

std::vector<std::pair<int, std::string>> admplug::ReaperAPIImpl::GetVSTElementsFromTrackStateChunk(const std::string& fullChunk) const
{
std::vector<std::pair<int, std::string>> vst3Elements;

const std::vector<char> quoteMarks{ '\'', '`', '"' };
int elmStart = -1;

for (int pos = 0; pos < fullChunk.length(); ++pos) {

bool escapedQuote = false;
for (auto quote : quoteMarks) {
if (fullChunk[pos] == quote) {
// Entered a quote mark
if (pos == fullChunk.length() - 1) {
// Already at EOF - don't attempt to find
escapedQuote = true;
break;
}
// Find end quote mark
auto newPos = fullChunk.find(quote, pos + 1);
if (newPos == std::string::npos) {
// End not found to EOF - abort
escapedQuote = true;
break;
}
pos = newPos;
}
}
if (escapedQuote) {
break;
}

if (elmStart == -1) {
// Not in an element - check if at start of one
if (fullChunk.substr(pos, 5) == "<VST ") {
elmStart = pos;
}
}
else {
// In an element - check if at end
if (fullChunk.substr(pos, 1) == ">") {
vst3Elements.push_back(std::make_pair(
elmStart,
fullChunk.substr(elmStart, pos - elmStart + 1))
);
elmStart = -1;
}
}
}

return vst3Elements;
}

std::vector<std::string> admplug::ReaperAPIImpl::SplitVSTElement(const std::string& elm, bool stripBoundingQuotes, bool includeSeperators) const
{
std::vector<std::string> sec;

const std::vector<char> quoteMarks{ '\'', '`', '"' };
const std::vector<char> splitMarks{ ' ', '\r', '\n' };
int secStart = 5;

for (int pos = 5; pos < elm.length(); ++pos) {

bool escapedQuote = false;
for (auto quote : quoteMarks) {
if (elm[pos] == quote) {
// Entered a quote mark
if (pos == elm.length() - 1) {
// Already at EOF - don't attempt to find
escapedQuote = true;
break;
}
// Find end quote mark
auto newPos = elm.find(quote, pos + 1);
if (newPos == std::string::npos) {
// End not found to EOF - abort
escapedQuote = true;
break;
}
pos = newPos;
}
}
if (escapedQuote) {
break;
}

for (auto splitMark : splitMarks) {
if (elm[pos] == splitMark) {
// Close this section and start a new one
sec.push_back(elm.substr(secStart, pos - secStart));
if (includeSeperators) {
sec.push_back(std::string{ splitMark });
}
secStart = pos + 1;
break;
}
}
}

if (stripBoundingQuotes) {
for (auto& s : sec) {
if (s.length() >= 2) {
for (auto quote : quoteMarks) {
if (s[0] == quote && s[s.length() - 1] == quote) {
s = s.substr(1, s.length() - 2);
break;
}
}
}
}
}

return sec;
}

std::string admplug::ReaperAPIImpl::GetTrackStateChunkStr(MediaTrack* track) const
{
const size_t chunkMaxLen = 65535; // Should be plenty
char chunk[chunkMaxLen];
auto res = GetTrackStateChunk(track, chunk, chunkMaxLen, false);
if (!res) return std::string();
std::string fullChunk{ chunk, strnlen(chunk, chunkMaxLen) };
return fullChunk;
}

int admplug::ReaperAPIImpl::GetDawChannelCount() const
{
return GetReaperChannelCount(GetAppVersion());
}

bool admplug::ReaperAPIImpl::TrackFX_GetActualFXName(MediaTrack* track, int fx, std::string& name) const
bool admplug::ReaperAPIImpl::TrackFX_GetActualFXName(MediaTrack* track, int fxNum, std::string& name) const
{
// Note that;
// TrackFX_GetNamedConfigParm( track, 0, "fx_name" )
// can get the pre-aliased name but is only supported from v6.37
// Also does not support FX renamed in FX selection window
// (although neither does this)

auto chunk = GetTrackStateChunkStr(track);

auto vst3Elements = GetVSTElementsFromTrackStateChunk(chunk);
if (fx >= vst3Elements.size()) {
return false;
}

const int nameSectionNum = 0;

auto vst3Sections = SplitVSTElement(vst3Elements[fx].second, true, false);
if (vst3Sections.size() <= nameSectionNum) {
return false;
}

name = vst3Sections[nameSectionNum];;
const size_t fxNameMaxLen = 1024; // Should be plenty
char fxName[fxNameMaxLen];
auto fxNameRes = TrackFX_GetNamedConfigParm(track, fxNum, "fx_name", fxName, fxNameMaxLen);
if (!fxNameRes) return false;
name = std::string{ fxName, strnlen(fxName, fxNameMaxLen) };
return true;
}

std::vector<std::string> admplug::ReaperAPIImpl::TrackFX_GetActualFXNames(MediaTrack* track) const
{
// Only gets and parses state chunk once
// More efficient when you want to query every plugin on the track

std::vector<std::string> names;

auto chunk = GetTrackStateChunkStr(track);

auto vst3Elements = GetVSTElementsFromTrackStateChunk(chunk);

const int nameSectionNum = 0;

for (auto const& elmPair : vst3Elements) {
auto vst3Sections = SplitVSTElement(elmPair.second, true, false);
if (vst3Sections.size() <= nameSectionNum) {
names.push_back("");
std::vector<std::string> fxNames;
auto numFx = TrackFX_GetCount(track);
for (int fxNum = 0; fxNum < numFx; fxNum++) {
const size_t fxNameMaxLen = 1024; // Should be plenty
char fxName[fxNameMaxLen];
auto fxNameRes = TrackFX_GetNamedConfigParm(track, fxNum, "fx_name", fxName, fxNameMaxLen);
if (fxNameRes) {
fxNames.push_back(std::string{ fxName, strnlen(fxName, fxNameMaxLen) });
}
else {
names.push_back(vst3Sections[nameSectionNum]);
fxNames.push_back("");
}
}

return names;
return fxNames;
}

void admplug::ReaperAPIImpl::CleanFXName(std::string& fxName) const
Expand Down
3 changes: 0 additions & 3 deletions reaper-adm-extension/src/reaper_adm/reaperapiimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,6 @@ class ReaperAPIImpl : public ReaperAPI
void CleanFXName(std::string& name) const override;
int TrackFX_PositionByActualName(MediaTrack* track, const std::string& fxName) const override;
int TrackFX_AddByActualName(MediaTrack* track, const char* fxname, bool recFX, int instantiate) const override;
std::vector<std::pair<int, std::string>> GetVSTElementsFromTrackStateChunk(const std::string& fullChunk) const override;
std::vector<std::string> SplitVSTElement(const std::string& elm, bool stripBoundingQuotes, bool includeSeperators) const override;
std::string GetTrackStateChunkStr(MediaTrack* track) const override;
int GetDawChannelCount() const override;

private:
Expand Down
3 changes: 0 additions & 3 deletions reaper-adm-extension/test/reaper_adm/mocks/reaperapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,6 @@ class MockReaperAPI : public ReaperAPI {
MOCK_CONST_METHOD1(CleanFXName, void(std::string& name));
MOCK_CONST_METHOD2(TrackFX_PositionByActualName, int(MediaTrack* track, const std::string& fxName));
MOCK_CONST_METHOD4(TrackFX_AddByActualName, int(MediaTrack* track, const char* fxname, bool recFX, int instantiate));
MOCK_CONST_METHOD1(GetVSTElementsFromTrackStateChunk, std::vector<std::pair<int, std::string>>(const std::string& fullChunk));
MOCK_CONST_METHOD3(SplitVSTElement, std::vector<std::string>(const std::string& elm, bool stripBoundingQuotes, bool includeSeperators));
MOCK_CONST_METHOD1(GetTrackStateChunkStr, std::string(MediaTrack* track));
MOCK_CONST_METHOD0(GetDawChannelCount, int());
};

Expand Down
121 changes: 0 additions & 121 deletions reaper-adm-extension/test/reaper_adm/pluginrenametests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,129 +2,8 @@
#include <catch2/catch_all.hpp>
#include <reaperapiimpl.h>

const std::string trackState =
R"STATESTRING(<TRACK
NAME ""
PEAKCOL 16576
BEAT -1
AUTOMODE 0
VOLPAN 1 0 -1 -1 1
MUTESOLO 0 0 0
IPHASE 0
PLAYOFFS 0 1
ISBUS 0 0
BUSCOMP 0 0 0 0 0
SHOWINMIX 1 0.6667 0.5 1 0.5 0 -1 0
REC 0 0 0 0 0 0 0
VU 2
TRACKHEIGHT 0 0 0 0 0 0
INQ 0 0 0 0.5 100 0 0 100
NCHAN 64
FX 1
TRACKID {BD8FCB16-184B-4852-83A2-A916009600D0}
PERF 0
MIDIOUT -1
MAINSEND 1 0
<FXCHAIN
SHOW 0
LASTSEL 0
DOCKED 0
BYPASS 0 0 0
<VST "VST3: EAR Object (EBU)" "EAR Object.vst3" 0 "Custom Name" 1933719658{ABCDEF019182FAEB4542552045505311} ""
ajhCc+5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAEAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAA
QAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAA
AAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgJ0BAAABAAAA//8QgA==
jQEAAAEAAABWQzIhSAEAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+IDxPYmplY3RzUGx1Z2luIGNvbm5lY3Rpb25faWQ9IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIgcm91dGluZz0iLTEiIGdhaW49IjAuMCIgYXppbXV0aD0iMC4wIiBlbGV2YXRpb249IjAuMCIgZGlzdGFuY2U9IjEuMCIgbGlua19zaXplPSIwIiBzaXpl
PSIwLjAiIHdpZHRoPSIwLjAiIGhlaWdodD0iMC4wIiBkZXB0aD0iMC4wIiBkaWZmdXNlPSIwLjAiIGRpdmVyZ2VuY2U9IjAiIGZhY3Rvcj0iMC4wIiByYW5nZT0iNDUuMCIgdXNlX3RyYWNrX25hbWU9IjEiIG5hbWU9IlRyYWNrIDEiLz4AAAAAAAAAAABKVUNFUHJpdmF0ZURhdGEAAQFCeXBhc3MAAQEDAB0AAAAAAAAASlVDRVByaXZhdGVEYXRhAAAAAAAAAAA=
AFByb2dyYW0gMQAQAAAA
>
PRESETNAME "Program 1"
FLOATPOS 1944 -62 616 512
FXID {159FD704-E101-42BC-A4D2-8F3F263F5160}
WAK 0 0
BYPASS 0 0 0
<VST "VST3: EAR Object (EBU)" "EAR Object.vst3" 0 SingleWord 1933719658{ABCDEF019182FAEB4542552045505311} ""
ajhCc+5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAEAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAA
QAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAA
AAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgJ0BAAABAAAA//8QAA==
jQEAAAEAAABWQzIhSAEAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+IDxPYmplY3RzUGx1Z2luIGNvbm5lY3Rpb25faWQ9IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIgcm91dGluZz0iLTEiIGdhaW49IjAuMCIgYXppbXV0aD0iMC4wIiBlbGV2YXRpb249IjAuMCIgZGlzdGFuY2U9IjEuMCIgbGlua19zaXplPSIwIiBzaXpl
PSIwLjAiIHdpZHRoPSIwLjAiIGhlaWdodD0iMC4wIiBkZXB0aD0iMC4wIiBkaWZmdXNlPSIwLjAiIGRpdmVyZ2VuY2U9IjAiIGZhY3Rvcj0iMC4wIiByYW5nZT0iNDUuMCIgdXNlX3RyYWNrX25hbWU9IjEiIG5hbWU9IlRyYWNrIDEiLz4AAAAAAAAAAABKVUNFUHJpdmF0ZURhdGEAAQFCeXBhc3MAAQEDAB0AAAAAAAAASlVDRVByaXZhdGVEYXRhAAAAAAAAAAA=
AFByb2dyYW0gMQAQAAAA
>
PRESETNAME "Program 1"
FLOATPOS 1944 -62 742 738
FXID {66EFE191-C8CE-4786-8C38-4BE42D751146}
WAK 0 0
BYPASS 0 0 0
<VST "VST3: EAR Object (EBU)" "EAR Object.vst3" 0 `'quote' "Marks" 'lol'` 1933719658{ABCDEF019182FAEB4542552045505311} ""
ajhCc+5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAEAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAA
QAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAA
AAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgJ0BAAABAAAA//8QAA==
jQEAAAEAAABWQzIhSAEAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+IDxPYmplY3RzUGx1Z2luIGNvbm5lY3Rpb25faWQ9IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIgcm91dGluZz0iLTEiIGdhaW49IjAuMCIgYXppbXV0aD0iMC4wIiBlbGV2YXRpb249IjAuMCIgZGlzdGFuY2U9IjEuMCIgbGlua19zaXplPSIwIiBzaXpl
PSIwLjAiIHdpZHRoPSIwLjAiIGhlaWdodD0iMC4wIiBkZXB0aD0iMC4wIiBkaWZmdXNlPSIwLjAiIGRpdmVyZ2VuY2U9IjAiIGZhY3Rvcj0iMC4wIiByYW5nZT0iNDUuMCIgdXNlX3RyYWNrX25hbWU9IjEiIG5hbWU9IlRyYWNrIDEiLz4AAAAAAAAAAABKVUNFUHJpdmF0ZURhdGEAAQFCeXBhc3MAAQEDAB0AAAAAAAAASlVDRVByaXZhdGVEYXRhAAAAAAAAAAA=
AFByb2dyYW0gMQAQAAAA
>
PRESETNAME "Program 1"
FLOATPOS 1944 -62 742 738
FXID {24D3CD65-1A9A-44D6-B8A1-5FBC65C39DD5}
WAK 0 0
BYPASS 0 0 0
<VST "VST3: EAR Object (EBU)" "EAR Object.vst3" 0 '"just in quotes"' 1933719658{ABCDEF019182FAEB4542552045505311} ""
ajhCc+5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAEAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAA
QAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAA
AAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgJ0BAAABAAAA//8QAA==
jQEAAAEAAABWQzIhSAEAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+IDxPYmplY3RzUGx1Z2luIGNvbm5lY3Rpb25faWQ9IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIgcm91dGluZz0iLTEiIGdhaW49IjAuMCIgYXppbXV0aD0iMC4wIiBlbGV2YXRpb249IjAuMCIgZGlzdGFuY2U9IjEuMCIgbGlua19zaXplPSIwIiBzaXpl
PSIwLjAiIHdpZHRoPSIwLjAiIGhlaWdodD0iMC4wIiBkZXB0aD0iMC4wIiBkaWZmdXNlPSIwLjAiIGRpdmVyZ2VuY2U9IjAiIGZhY3Rvcj0iMC4wIiByYW5nZT0iNDUuMCIgdXNlX3RyYWNrX25hbWU9IjEiIG5hbWU9IlRyYWNrIDEiLz4AAAAAAAAAAABKVUNFUHJpdmF0ZURhdGEAAQFCeXBhc3MAAQEDAB0AAAAAAAAASlVDRVByaXZhdGVEYXRhAAAAAAAAAAA=
AFByb2dyYW0gMQAQAAAA
>
PRESETNAME "Program 1"
FLOATPOS 1944 -62 742 738
FXID {493829B3-8224-4E57-AC50-ED2C5E652E31}
WAK 0 0
BYPASS 0 0 0
<VST "VST3: EAR Object (EBU)" "EAR Object.vst3" 0 "" 1933719658{ABCDEF019182FAEB4542552045505311} ""
ajhCc+5e7f4CAAAAAQAAAAAAAAACAAAAAAAAAEAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAA
QAAAAAAAAACAAAAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAQAAAAAAAAACAAAAAAAAA
AAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAgJ0BAAABAAAA//8QAA==
jQEAAAEAAABWQzIhSAEAADw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+IDxPYmplY3RzUGx1Z2luIGNvbm5lY3Rpb25faWQ9IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIgcm91dGluZz0iLTEiIGdhaW49IjAuMCIgYXppbXV0aD0iMC4wIiBlbGV2YXRpb249IjAuMCIgZGlzdGFuY2U9IjEuMCIgbGlua19zaXplPSIwIiBzaXpl
PSIwLjAiIHdpZHRoPSIwLjAiIGhlaWdodD0iMC4wIiBkZXB0aD0iMC4wIiBkaWZmdXNlPSIwLjAiIGRpdmVyZ2VuY2U9IjAiIGZhY3Rvcj0iMC4wIiByYW5nZT0iNDUuMCIgdXNlX3RyYWNrX25hbWU9IjEiIG5hbWU9IlRyYWNrIDEiLz4AAAAAAAAAAABKVUNFUHJpdmF0ZURhdGEAAQFCeXBhc3MAAQEDAB0AAAAAAAAASlVDRVByaXZhdGVEYXRhAAAAAAAAAAA=
AFByb2dyYW0gMQAQAAAA
>
PRESETNAME "Program 1"
FLOATPOS 1944 -62 742 738
FXID {17FB49CB-DDA3-41B4-BAF3-9365DF7AC29C}
WAK 0 0
>
>)STATESTRING";

using namespace admplug;

TEST_CASE("Track State Chunk Parsing") {

reaper_plugin_info_t info{};
admplug::ReaperAPIImpl api(info);

auto vst3Elements = api.GetVSTElementsFromTrackStateChunk(trackState);

REQUIRE(vst3Elements.size() == 5);

for (int i = 0; i < vst3Elements.size(); ++i) {
auto el = vst3Elements[i];
auto s = api.SplitVSTElement(el.second, true, false);

REQUIRE(s.size() >= 6);
REQUIRE(s[0] == "VST3: EAR Object (EBU)");
REQUIRE(s[1] == "EAR Object.vst3");

if (i == 0) REQUIRE(s[3] == "Custom Name");
if (i == 1) REQUIRE(s[3] == "SingleWord");
if (i == 2) REQUIRE(s[3] == "'quote' \"Marks\" 'lol'");
if (i == 3) REQUIRE(s[3] == "\"just in quotes\"");
if (i == 4) REQUIRE(s[3] == "");
}

}

TEST_CASE("Clean Plugin Name") {

reaper_plugin_info_t info{};
Expand Down

0 comments on commit a9e2cfb

Please sign in to comment.