Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
@@ -0,0 +1,130 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/connectionproxytest.cpp
// Created by : Steinberg, 08/2021
// Description : Test connection proxy
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/connectionproxy.h"
#include "public.sdk/source/vst/hosting/hostclasses.h"
#include "public.sdk/source/vst/utility/testing.h"
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <thread>
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
class ConnectionPoint : public IConnectionPoint
{
public:
tresult PLUGIN_API connect (IConnectionPoint* inOther) override
{
other = inOther;
return kResultTrue;
}
tresult PLUGIN_API disconnect (IConnectionPoint* inOther) override
{
if (inOther != other)
return kResultFalse;
return kResultTrue;
}
tresult PLUGIN_API notify (IMessage*) override
{
messageReceived = true;
return kResultTrue;
}
tresult PLUGIN_API queryInterface (const TUID, void**) override { return kNotImplemented; }
uint32 PLUGIN_API addRef () override { return 100; }
uint32 PLUGIN_API release () override { return 100; }
IConnectionPoint* other {nullptr};
bool messageReceived {false};
};
//------------------------------------------------------------------------
ModuleInitializer ConnectionProxyTests ([] () {
constexpr auto TestSuiteName = "ConnectionProxy";
registerTest (TestSuiteName, STR ("Connect and disconnect"), [] (ITestResult* testResult) {
ConnectionPoint cp1;
ConnectionPoint cp2;
ConnectionProxy proxy (&cp1);
EXPECT_EQ (proxy.connect (&cp2), kResultTrue);
EXPECT_EQ (proxy.disconnect (&cp2), kResultTrue);
return true;
});
registerTest (TestSuiteName, STR ("Disconnect wrong object"), [] (ITestResult* testResult) {
ConnectionPoint cp1;
ConnectionPoint cp2;
ConnectionPoint cp3;
ConnectionProxy proxy (&cp1);
EXPECT_EQ (proxy.connect (&cp2), kResultTrue);
EXPECT_NE (proxy.disconnect (&cp3), kResultTrue);
return true;
});
registerTest (TestSuiteName, STR ("Send message on UI thread"), [] (ITestResult* testResult) {
ConnectionPoint cp1;
ConnectionPoint cp2;
ConnectionProxy proxy (&cp1);
EXPECT_EQ (proxy.connect (&cp2), kResultTrue);
EXPECT_FALSE (cp2.messageReceived);
HostMessage msg;
EXPECT_EQ (proxy.notify (&msg), kResultTrue);
EXPECT_TRUE (cp2.messageReceived);
return true;
});
registerTest (TestSuiteName, STR ("Send message on 2nd thread"), [] (ITestResult* testResult) {
ConnectionPoint cp1;
ConnectionPoint cp2;
ConnectionProxy proxy (&cp1);
EXPECT_EQ (proxy.connect (&cp2), kResultTrue);
EXPECT_FALSE (cp2.messageReceived);
std::condition_variable cv;
std::mutex m;
std::optional<tresult> notifyResult;
std::thread thread ([&] () {
HostMessage msg;
{
const std::scoped_lock sl (m);
notifyResult = proxy.notify (&msg);
}
cv.notify_one ();
});
std::unique_lock ul (m);
cv.wait (ul, [&] { return notifyResult.has_value (); });
EXPECT_NE (*notifyResult, kResultTrue);
EXPECT_FALSE (cp2.messageReceived);
thread.join ();
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
//------------------------------------------------------------------------
} // Vst
} // Steinberg
@@ -0,0 +1,92 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/eventlisttest.cpp
// Created by : Steinberg, 08/2021
// Description : Test event list
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/eventlist.h"
#include "public.sdk/source/vst/utility/testing.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
ModuleInitializer EventListTests ([] () {
constexpr auto TestSuiteName = "EventList";
registerTest (TestSuiteName, STR ("Set and get single event"), [] (ITestResult* testResult) {
EventList eventList;
Event event1 = {};
event1.type = Event::kNoteOnEvent;
event1.noteOn.noteId = 10;
EXPECT_EQ (eventList.addEvent (event1), kResultTrue);
Event event2;
EXPECT_EQ (eventList.getEvent (0, event2), kResultTrue);
EXPECT_EQ (memcmp (&event1, &event2, sizeof (Event)), 0);
return true;
});
registerTest (TestSuiteName, STR ("Count events"), [] (ITestResult* testResult) {
EventList eventList;
Event event = {};
for (auto i = 0; i < 20; ++i)
{
EXPECT_EQ (eventList.addEvent (event), kResultTrue);
}
EXPECT_EQ (eventList.getEventCount (), 20);
return true;
});
registerTest (TestSuiteName, STR ("Overflow"), [] (ITestResult* testResult) {
EventList eventList (20);
Event event = {};
for (auto i = 0; i < 20; ++i)
{
EXPECT_EQ (eventList.addEvent (event), kResultTrue);
}
EXPECT_EQ (eventList.getEventCount (), 20);
EXPECT_NE (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.getEventCount (), 20);
return true;
});
registerTest (TestSuiteName, STR ("Get unknown event"), [] (ITestResult* testResult) {
EventList eventList;
Event event {};
EXPECT_NE (eventList.getEvent (0, event), kResultTrue);
return true;
});
registerTest (TestSuiteName, STR ("Resize"), [] (ITestResult* testResult) {
EventList eventList (1);
Event event {};
EXPECT_NE (eventList.getEvent (0, event), kResultTrue);
event = {};
EXPECT_EQ (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.getEventCount (), 1);
EXPECT_NE (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.getEventCount (), 1);
eventList.setMaxSize (2);
EXPECT_EQ (eventList.getEventCount (), 0);
EXPECT_EQ (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.getEventCount (), 2);
EXPECT_NE (eventList.addEvent (event), kResultTrue);
EXPECT_EQ (eventList.getEventCount (), 2);
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
} // Vst
} // Steinberg
@@ -0,0 +1,129 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/hostclassestest.cpp
// Created by : Steinberg, 08/2021
// Description : Test host classes
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/hostclasses.h"
#include "public.sdk/source/vst/utility/testing.h"
#include "pluginterfaces/base/fstrdefs.h"
#include <array>
#include <vector>
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
ModuleInitializer HostApplicationTests ([] () {
constexpr auto TestSuiteName = "HostApplication";
registerTest (
TestSuiteName, STR ("Create instance of IAttributeList"), [] (ITestResult* testResult) {
HostApplication hostApp;
FUnknown* instance {nullptr};
TUID iid;
IAttributeList::iid.toTUID (iid);
EXPECT_EQ (hostApp.createInstance (iid, iid, reinterpret_cast<void**> (&instance)),
kResultTrue);
EXPECT_NE (instance, nullptr);
instance->release ();
return true;
});
registerTest (TestSuiteName, STR ("Create instance of IMessage"), [] (ITestResult* testResult) {
HostApplication hostApp;
FUnknown* instance {nullptr};
TUID iid;
IMessage::iid.toTUID (iid);
EXPECT_EQ (hostApp.createInstance (iid, iid, reinterpret_cast<void**> (&instance)),
kResultTrue);
EXPECT_NE (instance, nullptr);
instance->release ();
return true;
});
});
//------------------------------------------------------------------------
ModuleInitializer HostAttributeListTests ([] () {
constexpr auto TestSuiteName = "HostAttributeList";
registerTest (TestSuiteName, STR ("Int"), [] (ITestResult* testResult) {
auto attrList = HostAttributeList::make ();
constexpr int64 testValue = 5;
EXPECT_EQ (attrList->setInt ("Int", testValue), kResultTrue);
int64 value = 0;
EXPECT_EQ (attrList->getInt ("Int", value), kResultTrue);
EXPECT_EQ (value, testValue);
return true;
});
registerTest (TestSuiteName, STR ("Float"), [] (ITestResult* testResult) {
auto attrList = HostAttributeList::make ();
constexpr double testValue = 2.636;
EXPECT_EQ (attrList->setFloat ("Float", testValue), kResultTrue);
double value = 0;
EXPECT_EQ (attrList->getFloat ("Float", value), kResultTrue);
EXPECT_EQ (value, testValue);
return true;
});
registerTest (TestSuiteName, STR ("String"), [] (ITestResult* testResult) {
auto attrList = HostAttributeList::make ();
constexpr const TChar* testValue = STR ("TestValue");
EXPECT_EQ (attrList->setString ("Str", testValue), kResultTrue);
TChar value[10];
EXPECT_EQ (attrList->getString ("Str", value, 10 * sizeof (TChar)), kResultTrue);
EXPECT_EQ (tstrcmp (testValue, value), 0);
return true;
});
registerTest (TestSuiteName, STR ("Binary"), [] (ITestResult* testResult) {
auto attrList = HostAttributeList::make ();
std::array<int32, 20> testData {};
int32 val = 0;
for (auto item : testData)
{
item = val++;
}
uint32 testDataSize = static_cast<uint32>(testData.size ()) * sizeof (int32);
EXPECT_EQ (attrList->setBinary ("Binary", testData.data (), testDataSize), kResultTrue);
const void* data;
uint32 dataSize {0};
EXPECT_EQ (attrList->getBinary ("Binary", data, dataSize), kResultTrue);
EXPECT_EQ (dataSize, testDataSize);
auto s = reinterpret_cast<const int32*> (data);
for (auto i : testData)
{
EXPECT_EQ (i, *s);
s++;
}
return true;
});
registerTest (TestSuiteName, STR ("Multiple Set"), [] (ITestResult* testResult) {
auto attrList = HostAttributeList::make ();
constexpr int64 testValue1 = 5;
constexpr int64 testValue2 = 6;
constexpr int64 testValue3 = 7;
EXPECT_EQ (attrList->setInt ("Int", testValue1), kResultTrue);
EXPECT_EQ (attrList->setInt ("Int", testValue2), kResultTrue);
EXPECT_EQ (attrList->setInt ("Int", testValue3), kResultTrue);
int64 value = 0;
EXPECT_EQ (attrList->getInt ("Int", value), kResultTrue);
EXPECT_EQ (value, testValue3);
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
} // Vst
} // Steinberg
@@ -0,0 +1,273 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/parameterchangestest.cpp
// Created by : Steinberg, 08/2021
// Description : Test parameter changes
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/parameterchanges.h"
#include "public.sdk/source/vst/utility/testing.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
struct ValuePoint
{
int32 sampleOffset {};
ParamValue value {};
};
//------------------------------------------------------------------------
ModuleInitializer ParameterValueQueueTests ([] () {
constexpr auto TestSuiteName = "ParameterValueQueue";
registerTest (TestSuiteName, STR ("Set paramID"), [] (ITestResult* testResult) {
ParameterValueQueue queue (10);
EXPECT_EQ (queue.getParameterId (), 10);
queue.setParamID (5);
EXPECT_EQ (queue.getParameterId (), 5);
return true;
});
registerTest (TestSuiteName, STR ("Set/get point"), [] (ITestResult* testResult) {
ParameterValueQueue queue (0);
ValuePoint vp {100, 0.5};
int32 index {};
EXPECT_EQ (queue.addPoint (vp.sampleOffset, vp.value, index), kResultTrue);
EXPECT_EQ (queue.getPointCount (), 1);
EXPECT_EQ (index, 0);
ValuePoint test;
EXPECT_EQ (queue.getPoint (index, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp.value, test.value);
return true;
});
registerTest (TestSuiteName, STR ("Set/get multiple points"), [] (ITestResult* testResult) {
ParameterValueQueue queue (0);
ValuePoint vp1 {10, 0.1};
ValuePoint vp2 {30, 0.3};
ValuePoint vp3 {50, 0.6};
ValuePoint vp4 {70, 0.8};
int32 index {};
EXPECT_EQ (queue.addPoint (vp1.sampleOffset, vp1.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp2.sampleOffset, vp2.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp3.sampleOffset, vp3.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp4.sampleOffset, vp4.value, index), kResultTrue);
EXPECT_EQ (queue.getPointCount (), 4);
EXPECT_EQ (index, 3);
ValuePoint test;
EXPECT_EQ (queue.getPoint (0, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp1.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp1.value, test.value);
EXPECT_EQ (queue.getPoint (1, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp2.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp2.value, test.value);
EXPECT_EQ (queue.getPoint (2, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp3.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp3.value, test.value);
EXPECT_EQ (queue.getPoint (3, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp4.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp4.value, test.value);
return true;
});
registerTest (TestSuiteName, STR ("Ordered points"), [] (ITestResult* testResult) {
ParameterValueQueue queue (0);
ValuePoint vp1 {70, 0.1};
ValuePoint vp2 {50, 0.3};
ValuePoint vp3 {30, 0.6};
ValuePoint vp4 {10, 0.8};
int32 index {};
EXPECT_EQ (queue.addPoint (vp1.sampleOffset, vp1.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp2.sampleOffset, vp2.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp3.sampleOffset, vp3.value, index), kResultTrue);
EXPECT_EQ (queue.addPoint (vp4.sampleOffset, vp4.value, index), kResultTrue);
EXPECT_EQ (queue.getPointCount (), 4);
ValuePoint test;
EXPECT_EQ (queue.getPoint (0, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp4.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp4.value, test.value);
EXPECT_EQ (queue.getPoint (1, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp3.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp3.value, test.value);
EXPECT_EQ (queue.getPoint (2, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp2.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp2.value, test.value);
EXPECT_EQ (queue.getPoint (3, test.sampleOffset, test.value), kResultTrue);
EXPECT_EQ (vp1.sampleOffset, test.sampleOffset);
EXPECT_EQ (vp1.value, test.value);
return true;
});
registerTest (TestSuiteName, STR ("Clear"), [] (ITestResult* testResult) {
ParameterValueQueue queue (0);
ValuePoint vp {100, 0.5};
int32 index {};
EXPECT_EQ (queue.addPoint (vp.sampleOffset, vp.value, index), kResultTrue);
EXPECT_EQ (queue.getPointCount (), 1);
EXPECT_EQ (index, 0);
queue.clear ();
EXPECT_EQ (queue.getPointCount (), 0);
ValuePoint test;
EXPECT_NE (queue.getPoint (index, test.sampleOffset, test.value), kResultTrue);
return true;
});
});
//------------------------------------------------------------------------
ModuleInitializer ParameterChangesTests ([] () {
constexpr auto TestSuiteName = "ParameterChanges";
registerTest (TestSuiteName, STR ("Parameter count"), [] (ITestResult* testResult) {
ParameterChanges changes (1);
EXPECT_EQ (changes.getParameterCount (), 0);
int32 index {};
auto queue = changes.addParameterData (0, index);
EXPECT_NE (queue, nullptr);
EXPECT_EQ (index, 0);
EXPECT_EQ (changes.getParameterCount (), 1);
return true;
});
registerTest (TestSuiteName, STR ("Clear queue"), [] (ITestResult* testResult) {
ParameterChanges changes (1);
int32 index {};
EXPECT_EQ (changes.getParameterCount (), 0);
changes.addParameterData (0, index);
EXPECT_EQ (changes.getParameterCount (), 1);
changes.clearQueue ();
EXPECT_EQ (changes.getParameterCount (), 0);
return true;
});
registerTest (TestSuiteName, STR ("Increase max parameters"), [] (ITestResult* testResult) {
ParameterChanges changes (1);
int32 index {};
EXPECT_EQ (changes.getParameterCount (), 0);
changes.addParameterData (0, index);
EXPECT_EQ (changes.getParameterCount (), 1);
EXPECT_NE (changes.addParameterData (1, index), nullptr);
EXPECT_EQ (changes.getParameterCount (), 2);
changes.setMaxParameters (4);
EXPECT_EQ (changes.getParameterCount (), 2);
return true;
});
registerTest (TestSuiteName, STR ("Get parameter data"), [] (ITestResult* testResult) {
ParameterChanges changes (1);
int32 index {};
auto queue1 = changes.addParameterData (0, index);
auto queue2 = changes.getParameterData (index);
EXPECT_EQ (queue1, queue2);
return true;
});
});
//------------------------------------------------------------------------
struct ParamChange
{
ParamID id {};
ParamValue value {};
int32 sampleOffset {};
bool operator== (const ParamChange& o) const
{
return id == o.id && value == o.value && sampleOffset == o.sampleOffset;
}
bool operator!= (const ParamChange& o) const
{
return id != o.id || value != o.value || sampleOffset != o.sampleOffset;
}
};
//------------------------------------------------------------------------
ModuleInitializer ParameterChangeTransferTests ([] () {
constexpr auto TestSuiteName = "ParameterChangeTransfer";
registerTest (TestSuiteName, STR ("Add/get change"), [] (ITestResult* testResult) {
ParameterChangeTransfer transfer (1);
ParamChange change {1, 0.8, 2};
transfer.addChange (change.id, change.value, change.sampleOffset);
ParamChange test {};
EXPECT_NE (change, test);
EXPECT_TRUE (transfer.getNextChange (test.id, test.value, test.sampleOffset));
EXPECT_EQ (change, test);
return true;
});
registerTest (TestSuiteName, STR ("Remove changes"), [] (ITestResult* testResult) {
ParameterChangeTransfer transfer (1);
ParamChange change {1, 0.8, 2};
transfer.addChange (change.id, change.value, change.sampleOffset);
transfer.removeChanges ();
ParamChange test {};
EXPECT_FALSE (transfer.getNextChange (test.id, test.value, test.sampleOffset));
return true;
});
registerTest (TestSuiteName, STR ("Transfer changes to"), [] (ITestResult* testResult) {
ParameterChangeTransfer transfer (10);
ParamChange ch1 {1, 0.8, 2};
ParamChange ch2 {2, 0.4, 8};
transfer.addChange (ch1.id, ch1.value, ch1.sampleOffset);
transfer.addChange (ch2.id, ch2.value, ch2.sampleOffset);
ParameterChanges changes (2);
transfer.transferChangesTo (changes);
EXPECT_EQ (changes.getParameterCount (), 2);
auto valueQueue1 = changes.getParameterData (0);
EXPECT_NE (valueQueue1, nullptr);
auto valueQueue2 = changes.getParameterData (1);
EXPECT_NE (valueQueue2, nullptr);
auto pid1 = valueQueue1->getParameterId ();
auto pid2 = valueQueue2->getParameterId ();
EXPECT (pid1 == ch1.id || pid1 == ch2.id);
EXPECT (pid2 == ch1.id || pid2 == ch2.id);
EXPECT_NE (pid1, pid2);
ValuePoint vp1;
ValuePoint vp2;
if (pid1 == ch1.id)
{
EXPECT_EQ (valueQueue1->getPoint (0, vp1.sampleOffset, vp1.value), kResultTrue);
EXPECT_EQ (valueQueue2->getPoint (0, vp2.sampleOffset, vp2.value), kResultTrue);
}
else
{
EXPECT_EQ (valueQueue2->getPoint (0, vp1.sampleOffset, vp1.value), kResultTrue);
EXPECT_EQ (valueQueue1->getPoint (0, vp2.sampleOffset, vp2.value), kResultTrue);
}
return true;
});
registerTest (TestSuiteName, STR ("Transfer changes from"), [] (ITestResult* testResult) {
ParamChange ch1 {1, 0.8, 2};
ParamChange ch2 {2, 0.4, 8};
ParameterChangeTransfer transfer (2);
ParameterChanges changes;
int32 index {};
auto valueQueue = changes.addParameterData (ch1.id, index);
EXPECT_NE (valueQueue, nullptr);
EXPECT_EQ (valueQueue->addPoint (ch1.sampleOffset, ch1.value, index), kResultTrue);
valueQueue = changes.addParameterData (ch2.id, index);
EXPECT_NE (valueQueue, nullptr);
EXPECT_EQ (valueQueue->addPoint (ch2.sampleOffset, ch2.value, index), kResultTrue);
transfer.transferChangesFrom (changes);
ParamChange test1 {};
ParamChange test2 {};
ParamChange test3 {};
EXPECT_TRUE (transfer.getNextChange (test1.id, test1.value, test1.sampleOffset));
EXPECT_TRUE (transfer.getNextChange (test2.id, test2.value, test2.sampleOffset));
EXPECT_FALSE (transfer.getNextChange (test3.id, test3.value, test3.sampleOffset));
EXPECT (test1 == ch1 || test1 == ch2);
EXPECT (test2 == ch1 || test2 == ch2);
EXPECT_NE (test1, test2);
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
} // Vst
} // Steinberg
@@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/pluginterfacesupporttest.cpp
// Created by : Steinberg, 08/2021
// Description : Test pluginterface support helper
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/pluginterfacesupport.h"
#include "public.sdk/source/vst/utility/testing.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstmessage.h"
#include "pluginterfaces/vst/ivstunits.h"
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
ModuleInitializer PlugInterfaceSupportTests ([] () {
constexpr auto TestSuiteName = "PlugInterfaceSupport";
registerTest (TestSuiteName, STR ("Initial interfaces"), [] (ITestResult* testResult) {
PlugInterfaceSupport pis;
//---VST 3.0.0--------------------------------
EXPECT_EQ (pis.isPlugInterfaceSupported (IComponent::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IAudioProcessor::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IEditController::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IConnectionPoint::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IUnitInfo::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IUnitData::iid), kResultTrue);
EXPECT_EQ (pis.isPlugInterfaceSupported (IProgramListData::iid), kResultTrue);
//---VST 3.0.1--------------------------------
EXPECT_EQ (pis.isPlugInterfaceSupported (IMidiMapping::iid), kResultTrue);
//---VST 3.1----------------------------------
EXPECT_EQ (pis.isPlugInterfaceSupported (IEditController2::iid), kResultTrue);
return true;
});
registerTest (TestSuiteName, STR ("Add interface"), [] (ITestResult* testResult) {
PlugInterfaceSupport pis;
EXPECT_NE (pis.isPlugInterfaceSupported (IEditControllerHostEditing::iid), kResultTrue);
pis.addPlugInterfaceSupported (IEditControllerHostEditing::iid);
EXPECT_EQ (pis.isPlugInterfaceSupported (IEditControllerHostEditing::iid), kResultTrue);
return true;
});
registerTest (TestSuiteName, STR ("Remove interface"), [] (ITestResult* testResult) {
PlugInterfaceSupport pis;
EXPECT_NE (pis.isPlugInterfaceSupported (IEditControllerHostEditing::iid), kResultTrue);
pis.addPlugInterfaceSupported (IEditControllerHostEditing::iid);
EXPECT_EQ (pis.isPlugInterfaceSupported (IEditControllerHostEditing::iid), kResultTrue);
EXPECT_TRUE (pis.removePlugInterfaceSupported (IEditControllerHostEditing::iid));
EXPECT_NE (pis.isPlugInterfaceSupported (IEditControllerHostEditing::iid), kResultTrue);
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
} // Vst
} // Steinberg
@@ -0,0 +1,351 @@
//-----------------------------------------------------------------------------
// Project : VST SDK
//
// Category : Helpers
// Filename : public.sdk/source/vst/hosting/test/processdatatest.cpp
// Created by : Steinberg, 08/2021
// Description : Test process data helper
// Flags : clang-format SMTGSequencer
//
//-----------------------------------------------------------------------------
// This file is part of a Steinberg SDK. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this distribution
// and at www.steinberg.net/sdklicenses.
// No part of the SDK, including this file, may be copied, modified, propagated,
// or distributed except according to the terms contained in the LICENSE file.
//-----------------------------------------------------------------------------
#include "public.sdk/source/main/moduleinit.h"
#include "public.sdk/source/vst/hosting/processdata.h"
#include "public.sdk/source/vst/utility/testing.h"
#include "pluginterfaces/vst/ivstaudioprocessor.h"
#include "pluginterfaces/vst/ivsteditcontroller.h"
#include "pluginterfaces/vst/ivstmessage.h"
#include "pluginterfaces/vst/ivstunits.h"
#include <functional>
#include <memory>
//------------------------------------------------------------------------
namespace Steinberg {
namespace Vst {
namespace {
//------------------------------------------------------------------------
struct TestComponent : public IComponent
{
using GetBusCountFunc = std::function<int32 (BusDirection dir)>;
using GetBusInfoFunc = std::function<tresult (BusDirection dir, int32 index, BusInfo& bus)>;
tresult PLUGIN_API queryInterface (const TUID /*_iid*/, void** /*obj*/) override
{
return kNoInterface;
}
uint32 PLUGIN_API addRef () override { return 100; }
uint32 PLUGIN_API release () override { return 100; }
tresult PLUGIN_API initialize (FUnknown* /*context*/) override { return kResultTrue; }
tresult PLUGIN_API terminate () override { return kResultTrue; }
tresult PLUGIN_API getControllerClassId (TUID /*classId*/) override { return kNotImplemented; }
tresult PLUGIN_API setIoMode (IoMode /*mode*/) override { return kNotImplemented; }
int32 PLUGIN_API getBusCount (MediaType type, BusDirection dir) override
{
if (type != MediaTypes::kAudio)
return 0;
return getBusCountFunc (dir);
}
tresult PLUGIN_API getBusInfo (MediaType type, BusDirection dir, int32 index,
BusInfo& bus) override
{
if (type != MediaTypes::kAudio)
return kResultFalse;
return getBusInfoFunc (dir, index, bus);
}
tresult PLUGIN_API getRoutingInfo (RoutingInfo& /*inInfo*/, RoutingInfo& /*outInfo*/) override
{
return kNotImplemented;
}
tresult PLUGIN_API activateBus (MediaType /*type*/, BusDirection /*dir*/, int32 /*index*/,
TBool /*state*/) override
{
return kNotImplemented;
}
tresult PLUGIN_API setActive (TBool /*state*/) override { return kNotImplemented; }
tresult PLUGIN_API setState (IBStream* /*state*/) override { return kNotImplemented; }
tresult PLUGIN_API getState (IBStream* /*state*/) override { return kNotImplemented; }
GetBusCountFunc getBusCountFunc = [] (BusDirection /*dir*/) { return 0; };
GetBusInfoFunc getBusInfoFunc = [] (BusDirection /*dir*/, int32 /*index*/, BusInfo& /*bus*/) {
return kNotImplemented;
};
};
//------------------------------------------------------------------------
ModuleInitializer HostProcessDataTests ([] () {
constexpr auto TestSuiteName = "HostProcessData";
registerTest (TestSuiteName, STR ("No bus"), [] (ITestResult* testResult) {
TestComponent tc;
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 1024, kSample32));
EXPECT_EQ (processData.numInputs, 0);
EXPECT_EQ (processData.numOutputs, 0);
return true;
});
registerTest (TestSuiteName, STR ("1 out bus no channels"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection dir) {
return dir == BusDirections::kOutput ? 1 : 0;
};
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 1024, kSample32));
EXPECT_EQ (processData.numInputs, 0);
EXPECT_EQ (processData.numOutputs, 1);
EXPECT_EQ (processData.outputs[0].numChannels, 0);
return true;
});
registerTest (TestSuiteName, STR ("1 out bus 2 channels"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection dir) {
return dir == BusDirections::kOutput ? 1 : 0;
};
tc.getBusInfoFunc = [] (BusDirection dir, int32 index, BusInfo& bus) {
if (dir == BusDirections::kInput || index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 1024, kSample32));
EXPECT_EQ (processData.numInputs, 0);
EXPECT_EQ (processData.numOutputs, 1);
EXPECT_EQ (processData.outputs[0].numChannels, 2);
EXPECT_NE (processData.outputs[0].channelBuffers32[0], nullptr);
EXPECT_NE (processData.outputs[0].channelBuffers32[1], nullptr);
return true;
});
registerTest (TestSuiteName, STR ("1 in & out bus 2 channels"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 1024, kSample32));
EXPECT_EQ (processData.numOutputs, 1);
EXPECT_EQ (processData.outputs[0].numChannels, 2);
EXPECT_NE (processData.outputs[0].channelBuffers32[0], nullptr);
EXPECT_NE (processData.outputs[0].channelBuffers32[1], nullptr);
EXPECT_EQ (processData.numInputs, 1);
EXPECT_EQ (processData.inputs[0].numChannels, 2);
EXPECT_NE (processData.inputs[0].channelBuffers32[0], nullptr);
EXPECT_NE (processData.inputs[0].channelBuffers32[1], nullptr);
return true;
});
registerTest (TestSuiteName, STR ("2 in & out bus dif channels"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 2; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index < 0 || index > 1)
return kResultFalse;
bus.channelCount = index == 0 ? 4 : 1;
return kResultTrue;
};
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 1024, kSample32));
EXPECT_EQ (processData.numOutputs, 2);
EXPECT_EQ (processData.outputs[0].numChannels, 4);
EXPECT_NE (processData.outputs[0].channelBuffers32[0], nullptr);
EXPECT_NE (processData.outputs[0].channelBuffers32[1], nullptr);
EXPECT_NE (processData.outputs[0].channelBuffers32[2], nullptr);
EXPECT_NE (processData.outputs[0].channelBuffers32[3], nullptr);
EXPECT_EQ (processData.outputs[1].numChannels, 1);
EXPECT_NE (processData.outputs[1].channelBuffers32[0], nullptr);
EXPECT_EQ (processData.numInputs, 2);
EXPECT_EQ (processData.inputs[0].numChannels, 4);
EXPECT_NE (processData.inputs[0].channelBuffers32[0], nullptr);
EXPECT_NE (processData.inputs[0].channelBuffers32[1], nullptr);
EXPECT_NE (processData.inputs[0].channelBuffers32[2], nullptr);
EXPECT_NE (processData.inputs[0].channelBuffers32[3], nullptr);
EXPECT_EQ (processData.inputs[1].numChannels, 1);
EXPECT_NE (processData.inputs[1].channelBuffers32[0], nullptr);
return true;
});
registerTest (TestSuiteName, STR ("Set all channel buffers 32"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto buffer = std::unique_ptr<float[]> (new float[10]);
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 0, kSample32));
EXPECT_EQ (processData.numInputs, 1);
EXPECT_EQ (processData.numOutputs, 1);
EXPECT_FALSE (processData.setChannelBuffers (BusDirections::kInput, 1, nullptr));
EXPECT_FALSE (processData.setChannelBuffers64 (BusDirections::kInput, 1, nullptr));
EXPECT_TRUE (processData.setChannelBuffers (BusDirections::kInput, 0, buffer.get ()));
EXPECT_TRUE (processData.setChannelBuffers (BusDirections::kOutput, 0, buffer.get ()));
EXPECT_FALSE (processData.setChannelBuffers64 (BusDirections::kInput, 0, nullptr));
EXPECT_FALSE (processData.setChannelBuffers64 (BusDirections::kOutput, 0, nullptr));
EXPECT_EQ (processData.inputs[0].channelBuffers32[0], buffer.get ());
EXPECT_EQ (processData.inputs[0].channelBuffers32[1], buffer.get ());
EXPECT_EQ (processData.outputs[0].channelBuffers32[0], buffer.get ());
EXPECT_EQ (processData.outputs[0].channelBuffers32[1], buffer.get ());
return true;
});
registerTest (TestSuiteName, STR ("Set all channel buffers 64"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto buffer = std::unique_ptr<double[]> (new double[10]);
HostProcessData processData;
EXPECT_TRUE (processData.prepare (tc, 0, kSample64));
EXPECT_EQ (processData.numInputs, 1);
EXPECT_EQ (processData.numOutputs, 1);
EXPECT_FALSE (processData.setChannelBuffers (BusDirections::kInput, 1, nullptr));
EXPECT_FALSE (processData.setChannelBuffers64 (BusDirections::kInput, 1, nullptr));
EXPECT_TRUE (processData.setChannelBuffers64 (BusDirections::kInput, 0, buffer.get ()));
EXPECT_TRUE (processData.setChannelBuffers64 (BusDirections::kOutput, 0, buffer.get ()));
EXPECT_FALSE (processData.setChannelBuffers (BusDirections::kInput, 0, nullptr));
EXPECT_FALSE (processData.setChannelBuffers (BusDirections::kOutput, 0, nullptr));
EXPECT_EQ (processData.inputs[0].channelBuffers64[0], buffer.get ());
EXPECT_EQ (processData.inputs[0].channelBuffers64[1], buffer.get ());
EXPECT_EQ (processData.outputs[0].channelBuffers64[0], buffer.get ());
EXPECT_EQ (processData.outputs[0].channelBuffers64[1], buffer.get ());
return true;
});
registerTest (
TestSuiteName, STR ("Set individual channel buffers 32"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto bufferL = std::unique_ptr<float[]> (new float[10]);
auto bufferR = std::unique_ptr<float[]> (new float[10]);
HostProcessData pd;
EXPECT_TRUE (pd.prepare (tc, 0, kSample32));
EXPECT_EQ (pd.numInputs, 1);
EXPECT_EQ (pd.numOutputs, 1);
EXPECT_FALSE (pd.setChannelBuffer (BusDirections::kInput, 1, 0, nullptr));
EXPECT_FALSE (pd.setChannelBuffer64 (BusDirections::kInput, 1, 0, nullptr));
EXPECT_TRUE (pd.setChannelBuffer (BusDirections::kInput, 0, 0, bufferL.get ()));
EXPECT_TRUE (pd.setChannelBuffer (BusDirections::kInput, 0, 1, bufferR.get ()));
EXPECT_TRUE (pd.setChannelBuffer (BusDirections::kOutput, 0, 0, bufferL.get ()));
EXPECT_TRUE (pd.setChannelBuffer (BusDirections::kOutput, 0, 1, bufferR.get ()));
EXPECT_FALSE (pd.setChannelBuffer64 (BusDirections::kInput, 0, 0, nullptr));
EXPECT_FALSE (pd.setChannelBuffer64 (BusDirections::kOutput, 0, 1, nullptr));
EXPECT_EQ (pd.inputs[0].channelBuffers32[0], bufferL.get ());
EXPECT_EQ (pd.inputs[0].channelBuffers32[1], bufferR.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers32[0], bufferL.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers32[1], bufferR.get ());
return true;
});
registerTest (TestSuiteName, STR ("Set individual channel buffers 32 combined"),
[] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto bufferL = std::unique_ptr<float[]> (new float[10]);
auto bufferR = std::unique_ptr<float[]> (new float[10]);
float* buffers[2] = {bufferL.get (), bufferR.get ()};
HostProcessData pd;
EXPECT_TRUE (pd.prepare (tc, 0, kSample32));
EXPECT_EQ (pd.numInputs, 1);
EXPECT_EQ (pd.numOutputs, 1);
EXPECT_FALSE (pd.setChannelBuffers (BusDirections::kInput, 1, nullptr, 0));
EXPECT_FALSE (pd.setChannelBuffers64 (BusDirections::kInput, 1, nullptr, 0));
EXPECT_TRUE (pd.setChannelBuffers (BusDirections::kInput, 0, buffers, 2));
EXPECT_TRUE (pd.setChannelBuffers (BusDirections::kOutput, 0, buffers, 2));
EXPECT_FALSE (pd.setChannelBuffers64 (BusDirections::kInput, 0, nullptr, 0));
EXPECT_FALSE (pd.setChannelBuffers64 (BusDirections::kOutput, 0, nullptr, 0));
EXPECT_EQ (pd.inputs[0].channelBuffers32[0], bufferL.get ());
EXPECT_EQ (pd.inputs[0].channelBuffers32[1], bufferR.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers32[0], bufferL.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers32[1], bufferR.get ());
return true;
});
registerTest (
TestSuiteName, STR ("Set individual channel buffers 64"), [] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto bufferL = std::unique_ptr<double[]> (new double[10]);
auto bufferR = std::unique_ptr<double[]> (new double[10]);
HostProcessData pd;
EXPECT_TRUE (pd.prepare (tc, 0, kSample64));
EXPECT_EQ (pd.numInputs, 1);
EXPECT_EQ (pd.numOutputs, 1);
EXPECT_FALSE (pd.setChannelBuffer (BusDirections::kInput, 1, 0, nullptr));
EXPECT_FALSE (pd.setChannelBuffer64 (BusDirections::kInput, 1, 0, nullptr));
EXPECT_TRUE (pd.setChannelBuffer64 (BusDirections::kInput, 0, 0, bufferL.get ()));
EXPECT_TRUE (pd.setChannelBuffer64 (BusDirections::kInput, 0, 1, bufferR.get ()));
EXPECT_TRUE (pd.setChannelBuffer64 (BusDirections::kOutput, 0, 0, bufferL.get ()));
EXPECT_TRUE (pd.setChannelBuffer64 (BusDirections::kOutput, 0, 1, bufferR.get ()));
EXPECT_FALSE (pd.setChannelBuffer (BusDirections::kInput, 0, 0, nullptr));
EXPECT_FALSE (pd.setChannelBuffer (BusDirections::kOutput, 0, 1, nullptr));
EXPECT_EQ (pd.inputs[0].channelBuffers64[0], bufferL.get ());
EXPECT_EQ (pd.inputs[0].channelBuffers64[1], bufferR.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers64[0], bufferL.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers64[1], bufferR.get ());
return true;
});
registerTest (TestSuiteName, STR ("Set individual channel buffers 64 combined"),
[] (ITestResult* testResult) {
TestComponent tc;
tc.getBusCountFunc = [] (BusDirection /*dir*/) { return 1; };
tc.getBusInfoFunc = [] (BusDirection /*dir*/, int32 index, BusInfo& bus) {
if (index != 0)
return kResultFalse;
bus.channelCount = 2;
return kResultTrue;
};
auto bufferL = std::unique_ptr<double[]> (new double[10]);
auto bufferR = std::unique_ptr<double[]> (new double[10]);
double* buffers[2] = {bufferL.get (), bufferR.get ()};
HostProcessData pd;
EXPECT_TRUE (pd.prepare (tc, 0, kSample64));
EXPECT_EQ (pd.numInputs, 1);
EXPECT_EQ (pd.numOutputs, 1);
EXPECT_FALSE (pd.setChannelBuffers (BusDirections::kInput, 1, nullptr, 0));
EXPECT_FALSE (pd.setChannelBuffers64 (BusDirections::kInput, 1, nullptr, 0));
EXPECT_TRUE (pd.setChannelBuffers64 (BusDirections::kInput, 0, buffers, 2));
EXPECT_TRUE (pd.setChannelBuffers64 (BusDirections::kOutput, 0, buffers, 2));
EXPECT_FALSE (pd.setChannelBuffers (BusDirections::kInput, 0, nullptr, 0));
EXPECT_FALSE (pd.setChannelBuffers (BusDirections::kOutput, 0, nullptr, 0));
EXPECT_EQ (pd.inputs[0].channelBuffers64[0], bufferL.get ());
EXPECT_EQ (pd.inputs[0].channelBuffers64[1], bufferR.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers64[0], bufferL.get ());
EXPECT_EQ (pd.outputs[0].channelBuffers64[1], bufferR.get ());
return true;
});
});
//------------------------------------------------------------------------
} // anonymous
} // Vst
} // Steinberg