Initial release
This commit is contained in:
+75
@@ -0,0 +1,75 @@
|
||||
|
||||
if(SMTG_ENABLE_VST3_HOSTING_EXAMPLES AND TARGET vstgui AND TARGET vstgui_standalone)
|
||||
|
||||
##########################################################################################
|
||||
set(target VST3Inspector)
|
||||
|
||||
##########################################################################################
|
||||
set(${target}_sources
|
||||
"${SDK_ROOT}/pluginterfaces/base/coreiids.cpp"
|
||||
"${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfocreator.cpp"
|
||||
"${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.cpp"
|
||||
"source/app.cpp"
|
||||
"source/window.cpp"
|
||||
"source/window.h"
|
||||
)
|
||||
|
||||
set(${target}_resources
|
||||
"resource/window.uidesc"
|
||||
)
|
||||
|
||||
##########################################################################################
|
||||
if(SMTG_MAC)
|
||||
set(${target}_sources
|
||||
${${target}_sources}
|
||||
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm"
|
||||
)
|
||||
set_source_files_properties(
|
||||
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
|
||||
COMPILE_FLAGS "-fobjc-arc"
|
||||
)
|
||||
elseif(SMTG_WIN)
|
||||
set(${target}_sources
|
||||
${${target}_sources}
|
||||
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp"
|
||||
)
|
||||
elseif(SMTG_LINUX)
|
||||
set(${target}_sources
|
||||
${${target}_sources}
|
||||
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp"
|
||||
)
|
||||
endif(SMTG_MAC)
|
||||
|
||||
##########################################################################################
|
||||
# 'vstgui_add_executable' links both targets 'vstgui' and 'vstgui_standalone' to 'VST3Inspector'
|
||||
vstgui_add_executable(${target} "${${target}_sources}")
|
||||
vstgui_set_target_bundle_id(${target} "com.steinberg.vstsdk.vst3inspector")
|
||||
|
||||
target_link_libraries(${target}
|
||||
PRIVATE
|
||||
sdk_hosting
|
||||
)
|
||||
if(NOT SMTG_MAC)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<$<CONFIG:Debug>:bin/Debug>$<$<CONFIG:Release>:bin/Release>$<$<CONFIG:ReleaseLTO>:bin/ReleaseLTO>/VST3Inspector
|
||||
)
|
||||
endif(NOT SMTG_MAC)
|
||||
|
||||
vstgui_add_resources(${target} "${${target}_resources}")
|
||||
vstgui_set_target_infoplist(${target} "resource/Info.plist")
|
||||
|
||||
target_include_directories(${target}
|
||||
PRIVATE
|
||||
"${SMTG_VSTGUI_SOURCE_DIR}/"
|
||||
"${SDK_ROOT}"
|
||||
)
|
||||
|
||||
if(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES
|
||||
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
|
||||
)
|
||||
endif(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,18 @@
|
||||
# VST 3 Inspector Application
|
||||
|
||||
## Introduction
|
||||
|
||||
As Cross-platform source code: Simple cross-platform (Win/macOS/Linux) host application, built with [VSTGUI](https://steinbergmedia.github.io/vst3_dev_portal/pages/What+is+the+VST+3+SDK/VST3Inspector.html), which scans the **VST 3** Folder, collects information from the factory about each **VST 3** plug-in and display it in its UI.
|
||||
|
||||
> See also: [Online Documentation](https://steinbergmedia.github.io/vst3_dev_portal/pages/What+is+the+VST+3+SDK/AudioHost.html#audiohost-application).
|
||||
|
||||
## Getting Started
|
||||
|
||||
This application is part of the VST 3 SDK package. It is created with the VST 3 SDK root project.
|
||||
|
||||
> See the top-level README of the VST 3 SDK: https://github.com/steinbergmedia/vst3sdk.git
|
||||
|
||||
## Getting Help
|
||||
|
||||
* Read through the SDK documentation on the **[VST 3 Developer Portal](https://steinbergmedia.github.io/vst3_dev_portal/pages/index.html)**
|
||||
* Ask some real people in the official **[VST 3 Developer Forum](https://forums.steinberg.net/c/developer/103)**
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.steinberg.vstsdk.vst3inspector</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>VST3Inspector</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2021 Steinberg Media Technologies. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
+1512
File diff suppressed because it is too large
Load Diff
+50
@@ -0,0 +1,50 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : VST3Inspector
|
||||
// Filename : public.sdk/samples/vst-hosting/inspectorapp/app.cpp
|
||||
// Created by : Steinberg, 01/2021
|
||||
// Description : VST3 Inspector Application
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "vstgui/standalone/include/helpers/appdelegate.h"
|
||||
#include "vstgui/standalone/include/helpers/windowlistener.h"
|
||||
#include "vstgui/standalone/include/iapplication.h"
|
||||
#include "window.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VST3Inspector {
|
||||
|
||||
using namespace VSTGUI;
|
||||
using namespace VSTGUI::Standalone;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct App : Application::DelegateAdapter, WindowListenerAdapter
|
||||
{
|
||||
App () : Application::DelegateAdapter ({"VST3Inspector", "1.0.0", VSTGUI_STANDALONE_APP_URI}) {}
|
||||
|
||||
void finishLaunching () override
|
||||
{
|
||||
if (auto window = makeWindow ())
|
||||
{
|
||||
window->registerWindowListener (this);
|
||||
window->show ();
|
||||
}
|
||||
}
|
||||
|
||||
void onClosed (const IWindow& window) override { IApplication::instance ().quit (); }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static Application::Init gAppDelegate (std::make_unique<App> ());
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VST3Inspector
|
||||
+500
@@ -0,0 +1,500 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : VST3Inspector
|
||||
// Filename : public.sdk/samples/vst-hosting/inspectorapp/window.cpp
|
||||
// Created by : Steinberg, 01/2021
|
||||
// Description : VST3 Inspector Application
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "window.h"
|
||||
#include "vstgui/lib/cbitmap.h"
|
||||
#include "vstgui/lib/platform/platformfactory.h"
|
||||
#include "vstgui/standalone/include/helpers/menubuilder.h"
|
||||
#include "vstgui/standalone/include/helpers/uidesc/customization.h"
|
||||
#include "vstgui/standalone/include/helpers/value.h"
|
||||
#include "vstgui/standalone/include/helpers/valuelistener.h"
|
||||
#include "vstgui/standalone/include/helpers/windowcontroller.h"
|
||||
#include "vstgui/standalone/include/ialertbox.h"
|
||||
#include "vstgui/standalone/include/iapplication.h"
|
||||
#include "vstgui/standalone/include/iasync.h"
|
||||
#include "vstgui/standalone/include/iuidescwindow.h"
|
||||
#include "vstgui/uidescription/cstream.h"
|
||||
#include "vstgui/uidescription/delegationcontroller.h"
|
||||
#include "vstgui/uidescription/iuidescription.h"
|
||||
#include "vstgui/uidescription/uiattributes.h"
|
||||
#include "public.sdk/source/vst/hosting/module.h"
|
||||
#include "public.sdk/source/vst/moduleinfo/moduleinfo.h"
|
||||
#include "public.sdk/source/vst/moduleinfo/moduleinfocreator.h"
|
||||
#include "public.sdk/source/vst/moduleinfo/moduleinfoparser.h"
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VST3Inspector {
|
||||
namespace {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
std::string loadFile (const std::string& path)
|
||||
{
|
||||
std::ifstream file (path, std::ios_base::in | std::ios_base::binary);
|
||||
if (!file.is_open ())
|
||||
return {};
|
||||
auto size = file.seekg (0, std::ios_base::end).tellg ();
|
||||
file.seekg (0, std::ios_base::beg);
|
||||
std::string data;
|
||||
data.resize (size);
|
||||
file.read (data.data (), data.size ());
|
||||
if (file.bad ())
|
||||
return {};
|
||||
return data;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // anonymous
|
||||
|
||||
using namespace VSTGUI;
|
||||
using namespace VSTGUI::Standalone;
|
||||
using namespace Steinberg;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class DummyFactory : public IPluginFactory
|
||||
{
|
||||
public:
|
||||
static DummyFactory* instance ()
|
||||
{
|
||||
static DummyFactory gInstance;
|
||||
return &gInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
tresult PLUGIN_API getFactoryInfo (PFactoryInfo* info) override
|
||||
{
|
||||
*info = {};
|
||||
return kResultTrue;
|
||||
}
|
||||
int32 PLUGIN_API countClasses () override { return 0; }
|
||||
tresult PLUGIN_API getClassInfo (int32 /*index*/, PClassInfo* /*info*/) override
|
||||
{
|
||||
return kResultFalse;
|
||||
}
|
||||
tresult PLUGIN_API createInstance (FIDString /*cid*/, FIDString /*_iid*/,
|
||||
void** /*obj*/) override
|
||||
{
|
||||
return kNoInterface;
|
||||
}
|
||||
tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) override
|
||||
{
|
||||
QUERY_INTERFACE (_iid, obj, IPluginFactory::iid, IPluginFactory)
|
||||
QUERY_INTERFACE (_iid, obj, FUnknown::iid, FUnknown)
|
||||
return kNoInterface;
|
||||
}
|
||||
uint32 PLUGIN_API addRef () override { return 1000; }
|
||||
uint32 PLUGIN_API release () override { return 1000; }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class InvalidModule : public VST3::Hosting::Module
|
||||
{
|
||||
public:
|
||||
InvalidModule () { factory = VST3::Hosting::PluginFactory (DummyFactory::instance ()); }
|
||||
|
||||
private:
|
||||
bool load (const std::string& /*path*/, std::string& /*errorDescription*/) override
|
||||
{
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ValueMap
|
||||
{
|
||||
ValuePtr addValue (const ValuePtr& value)
|
||||
{
|
||||
auto index = valueList.size ();
|
||||
valueList.push_back (value);
|
||||
valueMap.insert ({value->getID ().getString (), index});
|
||||
return value;
|
||||
}
|
||||
|
||||
ValuePtr get (const std::string& ID)
|
||||
{
|
||||
auto it = valueMap.find (ID);
|
||||
if (it != valueMap.end ())
|
||||
return valueList.at (it->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto get (const std::string& ID)
|
||||
{
|
||||
if (auto value = get (ID))
|
||||
{
|
||||
return std::dynamic_pointer_cast<T> (value);
|
||||
}
|
||||
return std::shared_ptr<T> (nullptr);
|
||||
}
|
||||
|
||||
const UIDesc::IModelBinding::ValueList& getValues () const { return valueList; }
|
||||
|
||||
private:
|
||||
UIDesc::IModelBinding::ValueList valueList;
|
||||
std::unordered_map<std::string, size_t> valueMap;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static constexpr auto ModulePathListID = "ModulePathList";
|
||||
static constexpr auto ModulePathID = "Module::Path";
|
||||
static constexpr auto FactoryVendorID = "Factory::Vendor";
|
||||
static constexpr auto FactoryUrlID = "Factory::URL";
|
||||
static constexpr auto FactoryEMailID = "Factory::EMail";
|
||||
static constexpr auto FactoryFlagsID = "Factory::Flags";
|
||||
static constexpr auto ClassInfoListID = "ClassInfoList";
|
||||
static constexpr auto ClassInfoClassID = "ClassInfo::ClassID";
|
||||
static constexpr auto ClassInfoCategoryID = "ClassInfo::Category";
|
||||
static constexpr auto ClassInfoNameID = "ClassInfo::Name";
|
||||
static constexpr auto ClassInfoVendorID = "ClassInfo::Vendor";
|
||||
static constexpr auto ClassInfoVersionID = "ClassInfo::Version";
|
||||
static constexpr auto ClassInfoSDKVersionID = "ClassInfo::SDKVersion";
|
||||
static constexpr auto ClassInfoSubCategoriesID = "ClassInfo::SubCategories";
|
||||
static constexpr auto ClassInfoCardinalityID = "ClassInfo::Cardinality";
|
||||
static constexpr auto ClassInfoClassFlagsID = "ClassInfo::ClassFlags";
|
||||
|
||||
using namespace VST3::Hosting;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct SnapshotController : DelegationController, NonAtomicReferenceCounted
|
||||
{
|
||||
SnapshotController (IController* parent) : DelegationController (parent) {}
|
||||
~SnapshotController () noexcept override {}
|
||||
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override
|
||||
{
|
||||
if (auto viewName = attributes.getAttributeValue (IUIDescription::kCustomViewName))
|
||||
{
|
||||
if (*viewName == "ImageView")
|
||||
{
|
||||
imageView = VSTGUI::shared (new CView (CRect ()));
|
||||
return imageView;
|
||||
}
|
||||
}
|
||||
return controller->createView (attributes, description);
|
||||
}
|
||||
|
||||
void setSnapshot (const std::string& moduleBasePath,
|
||||
const ModuleInfo::SnapshotList* newSnapshot)
|
||||
{
|
||||
snapshot = newSnapshot ? *newSnapshot : ModuleInfo::SnapshotList ();
|
||||
if (snapshot.empty ())
|
||||
{
|
||||
imageView->setBackground (nullptr);
|
||||
imageView->setViewSize ({});
|
||||
}
|
||||
else
|
||||
{
|
||||
SharedPointer<CBitmap> bitmap;
|
||||
const auto& factory = getPlatformFactory ();
|
||||
for (const auto& imageDesc : snapshot)
|
||||
{
|
||||
if (auto pb = factory.createBitmapFromPath (
|
||||
(moduleBasePath + "/" + imageDesc.path).data ()))
|
||||
{
|
||||
pb->setScaleFactor (imageDesc.scaleFactor);
|
||||
if (bitmap)
|
||||
bitmap->addBitmap (pb);
|
||||
else
|
||||
bitmap = VSTGUI::owned (new CBitmap (pb));
|
||||
}
|
||||
}
|
||||
imageView->setBackground (bitmap);
|
||||
if (bitmap)
|
||||
{
|
||||
auto viewSize = imageView->getViewSize ();
|
||||
viewSize.setSize (bitmap->getSize ());
|
||||
imageView->setViewSize (viewSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SharedPointer<CView> imageView;
|
||||
ModuleInfo::SnapshotList snapshot;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct WindowController : WindowControllerAdapter,
|
||||
UIDesc::CustomizationAdapter,
|
||||
UIDesc::IModelBinding,
|
||||
MenuBuilderAdapter,
|
||||
ValueListenerAdapter
|
||||
{
|
||||
WindowController ()
|
||||
{
|
||||
values.addValue (Value::makeStringListValue (ModulePathListID, {"", ""}))
|
||||
->registerListener (this);
|
||||
|
||||
// Module Values
|
||||
values.addValue (Value::makeStringValue (ModulePathID, ""));
|
||||
// Factory Values
|
||||
values.addValue (Value::makeStringValue (FactoryVendorID, ""));
|
||||
values.addValue (Value::makeStringValue (FactoryUrlID, ""));
|
||||
values.addValue (Value::makeStringValue (FactoryEMailID, ""));
|
||||
values.addValue (Value::makeStringValue (FactoryFlagsID, ""));
|
||||
|
||||
values.addValue (Value::makeStringListValue (ClassInfoListID, {"", ""}))
|
||||
->registerListener (this);
|
||||
// Class Info Values
|
||||
values.addValue (Value::makeStringValue (ClassInfoClassID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoCategoryID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoNameID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoVendorID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoVersionID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoSDKVersionID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoSubCategoriesID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoCardinalityID, ""));
|
||||
values.addValue (Value::makeStringValue (ClassInfoClassFlagsID, ""));
|
||||
|
||||
Async::schedule (Async::backgroundQueue (), [this] () {
|
||||
auto modulePaths = Module::getModulePaths ();
|
||||
Async::schedule (Async::mainQueue (),
|
||||
[this, paths = std::move (modulePaths)] () mutable {
|
||||
setModulePaths (std::move (paths));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static Optional<std::string> lastPathComponent (const std::string& path)
|
||||
{
|
||||
#if SMTG_WINDOWS
|
||||
static constexpr auto pathSeparator = '\\';
|
||||
#else
|
||||
static constexpr auto pathSeparator = '/';
|
||||
#endif
|
||||
size_t sepPos = path.find_last_of (pathSeparator);
|
||||
if (sepPos == std::string::npos)
|
||||
return {};
|
||||
return {path.substr (sepPos + 1)};
|
||||
}
|
||||
|
||||
void setModulePaths (Module::PathList&& pathList)
|
||||
{
|
||||
modulePathList = std::move (pathList);
|
||||
std::sort (modulePathList.begin (), modulePathList.end (),
|
||||
[] (const auto& lhs, const auto& rhs) {
|
||||
auto lhsName = lastPathComponent (lhs);
|
||||
auto rhsName = lastPathComponent (rhs);
|
||||
if (lhsName && rhsName)
|
||||
{
|
||||
std::for_each (lhsName->begin (), lhsName->end (),
|
||||
[] (auto& c) { c = std::tolower (c); });
|
||||
std::for_each (rhsName->begin (), rhsName->end (),
|
||||
[] (auto& c) { c = std::tolower (c); });
|
||||
return *lhsName < *rhsName;
|
||||
}
|
||||
return lhs < rhs;
|
||||
});
|
||||
moduleInfos.clear ();
|
||||
moduleInfos.resize (modulePathList.size ());
|
||||
|
||||
IStringListValue::StringList nameList;
|
||||
for (const auto& path : modulePathList)
|
||||
{
|
||||
if (auto name = lastPathComponent (path))
|
||||
nameList.emplace_back (*name);
|
||||
else
|
||||
nameList.emplace_back (path);
|
||||
}
|
||||
if (auto value = values.get<IStringListValue> (ModulePathListID))
|
||||
value->updateStringList (nameList);
|
||||
if (auto value = values.get (ModulePathListID))
|
||||
Value::performSingleEdit (*value, 0.);
|
||||
}
|
||||
|
||||
void onEndEdit (IValue& value) override
|
||||
{
|
||||
if (value.getID () == ModulePathListID)
|
||||
{
|
||||
onModuleSelection (static_cast<uint32_t> (
|
||||
value.getConverter ().normalizedToPlain (value.getValue ())));
|
||||
}
|
||||
if (value.getID () == ClassInfoListID)
|
||||
{
|
||||
onClassInfoSelection (static_cast<uint32_t> (
|
||||
value.getConverter ().normalizedToPlain (value.getValue ())));
|
||||
}
|
||||
}
|
||||
|
||||
void setStringValue (const std::string& valueID, const std::string& string)
|
||||
{
|
||||
auto value = values.get (valueID);
|
||||
if (value)
|
||||
Value::performStringValueEdit (*value, UTF8String (string));
|
||||
}
|
||||
|
||||
std::string createFlagsString (int32_t flags) const
|
||||
{
|
||||
std::string flagsString = "0b";
|
||||
for (int32_t i = 31; i >= 0; --i)
|
||||
{
|
||||
if (flags & (1 << i))
|
||||
flagsString += "1";
|
||||
else
|
||||
flagsString += "0";
|
||||
}
|
||||
return flagsString;
|
||||
}
|
||||
|
||||
std::string createSubCategoryString (const ModuleInfo::ClassInfo& info) const
|
||||
{
|
||||
std::string result;
|
||||
for (const auto& cat : info.subCategories)
|
||||
{
|
||||
if (result.empty () == false)
|
||||
result += "|";
|
||||
result += cat;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void onClassInfoSelection (uint32_t index)
|
||||
{
|
||||
if (index >= moduleInfos[currentSelectedModule].classes.size ())
|
||||
{
|
||||
setStringValue (ClassInfoClassID, "");
|
||||
setStringValue (ClassInfoCategoryID, "");
|
||||
setStringValue (ClassInfoNameID, "");
|
||||
setStringValue (ClassInfoVendorID, "");
|
||||
setStringValue (ClassInfoVersionID, "");
|
||||
setStringValue (ClassInfoSDKVersionID, "");
|
||||
setStringValue (ClassInfoSubCategoriesID, "");
|
||||
setStringValue (ClassInfoCardinalityID, "");
|
||||
setStringValue (ClassInfoClassFlagsID, "");
|
||||
if (snapShotController)
|
||||
snapShotController->setSnapshot ("", nullptr);
|
||||
return;
|
||||
}
|
||||
const auto& cl = moduleInfos[currentSelectedModule].classes[index];
|
||||
setStringValue (ClassInfoClassID, cl.cid);
|
||||
setStringValue (ClassInfoCategoryID, cl.category);
|
||||
setStringValue (ClassInfoNameID, cl.name);
|
||||
setStringValue (ClassInfoVendorID, cl.vendor);
|
||||
setStringValue (ClassInfoVersionID, cl.version);
|
||||
setStringValue (ClassInfoSDKVersionID, cl.sdkVersion);
|
||||
setStringValue (ClassInfoSubCategoriesID, createSubCategoryString (cl));
|
||||
if (cl.cardinality == Steinberg::PClassInfo::ClassCardinality::kManyInstances)
|
||||
setStringValue (ClassInfoCardinalityID, "");
|
||||
else
|
||||
setStringValue (ClassInfoCardinalityID, std::to_string (cl.cardinality));
|
||||
setStringValue (ClassInfoClassFlagsID, createFlagsString (cl.flags));
|
||||
if (snapShotController)
|
||||
snapShotController->setSnapshot (modulePathList[currentSelectedModule], &cl.snapshots);
|
||||
}
|
||||
|
||||
void updateModuleInfo (uint32_t index)
|
||||
{
|
||||
const auto& modulePath = modulePathList[index];
|
||||
if (auto moduleInfoPath = Module::getModuleInfoPath (modulePath))
|
||||
{
|
||||
auto moduleJson = loadFile (*moduleInfoPath);
|
||||
if (auto moduleInfo = ModuleInfoLib::parseJson (moduleJson, nullptr))
|
||||
{
|
||||
moduleInfos[index] = *moduleInfo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorDesc;
|
||||
if (auto module = Module::create (modulePath, errorDesc))
|
||||
{
|
||||
moduleInfos[index] = ModuleInfoLib::createModuleInfo (*module.get (), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onModuleSelection (uint32_t index)
|
||||
{
|
||||
if (index >= modulePathList.size ())
|
||||
return;
|
||||
currentSelectedModule = index;
|
||||
if (moduleInfos[index].name.empty ())
|
||||
{
|
||||
updateModuleInfo (index);
|
||||
}
|
||||
const auto& moduleInfo = moduleInfos[index];
|
||||
const auto& modulePath = modulePathList[index];
|
||||
setStringValue (ModulePathID, modulePath);
|
||||
setStringValue (FactoryVendorID, moduleInfo.factoryInfo.vendor);
|
||||
setStringValue (FactoryUrlID, moduleInfo.factoryInfo.url);
|
||||
setStringValue (FactoryEMailID, moduleInfo.factoryInfo.email);
|
||||
setStringValue (FactoryFlagsID, createFlagsString (moduleInfo.factoryInfo.flags));
|
||||
IStringListValue::StringList classInfoList;
|
||||
for (const auto& classInfo : moduleInfo.classes)
|
||||
{
|
||||
classInfoList.emplace_back (classInfo.name);
|
||||
}
|
||||
if (auto value = values.get<IStringListValue> (ClassInfoListID))
|
||||
{
|
||||
value->updateStringList (classInfoList);
|
||||
}
|
||||
// select first class info
|
||||
if (auto value = values.get (ClassInfoListID))
|
||||
Value::performSingleEdit (*value, 0.);
|
||||
}
|
||||
|
||||
const ValueList& getValues () const override { return values.getValues (); }
|
||||
|
||||
IController* createController (const UTF8StringView& name, IController* parent,
|
||||
const IUIDescription* /*uiDesc*/) override
|
||||
{
|
||||
if (name == "SnapshotViewController")
|
||||
{
|
||||
snapShotController = VSTGUI::shared (new SnapshotController (parent));
|
||||
return snapShotController;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool showCommandInMenu (const Interface& /*context*/, const Command& /*cmd*/) const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
ValueMap values;
|
||||
ValuePtr modulePathListValue;
|
||||
SharedPointer<SnapshotController> snapShotController;
|
||||
|
||||
using ModuleInfoList = std::vector<ModuleInfo>;
|
||||
|
||||
Module::PathList modulePathList;
|
||||
ModuleInfoList moduleInfos;
|
||||
uint32_t currentSelectedModule {0};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
WindowPtr makeWindow ()
|
||||
{
|
||||
auto controller = std::make_shared<WindowController> ();
|
||||
|
||||
UIDesc::Config config;
|
||||
config.uiDescFileName = "window.uidesc";
|
||||
config.viewName = "MainWindow";
|
||||
config.windowConfig.autoSaveFrameName = "MainWindow";
|
||||
config.windowConfig.type = WindowType::Document;
|
||||
config.windowConfig.style = WindowStyle ().border ().close ().centered ().size ();
|
||||
config.windowConfig.title = "VST3 Inspector";
|
||||
config.customization = controller;
|
||||
config.modelBinding = controller;
|
||||
return UIDesc::makeWindow (config);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VST3Inspector
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : VST3Inspector
|
||||
// Filename : public.sdk/samples/vst-hosting/inspectorapp/window.h
|
||||
// Created by : Steinberg, 01/2021
|
||||
// Description : VST3 Inspector Application
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "vstgui/standalone/include/iwindow.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VST3Inspector {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
VSTGUI::Standalone::WindowPtr makeWindow ();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VST3Inspector
|
||||
Reference in New Issue
Block a user