//----------------------------------------------------------------------------- // Project : VST SDK // // Category : Helpers // Filename : public.sdk/source/vst/hosting/module.cpp // Created by : Steinberg, 08/2016 // Description : hosting module classes // //----------------------------------------------------------------------------- // 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 "module.h" #include "public.sdk/source/vst/utility/stringconvert.h" #include "public.sdk/source/vst/utility/optional.h" #include "pluginterfaces/base/funknownimpl.h" #include #include //------------------------------------------------------------------------ namespace VST3 { namespace Hosting { //------------------------------------------------------------------------ FactoryInfo::FactoryInfo (PFactoryInfo&& other) noexcept { *this = std::move (other); } //------------------------------------------------------------------------ FactoryInfo& FactoryInfo::operator= (FactoryInfo&& other) noexcept { info = std::move (other.info); other.info = {}; return *this; } //------------------------------------------------------------------------ FactoryInfo& FactoryInfo::operator= (PFactoryInfo&& other) noexcept { info = std::move (other); other = {}; return *this; } //------------------------------------------------------------------------ std::string FactoryInfo::vendor () const noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; return StringConvert::convert (info.vendor, PFactoryInfo::kNameSize); } //------------------------------------------------------------------------ std::string FactoryInfo::url () const noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; return StringConvert::convert (info.url, PFactoryInfo::kURLSize); } //------------------------------------------------------------------------ std::string FactoryInfo::email () const noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; return StringConvert::convert (info.email, PFactoryInfo::kEmailSize); } //------------------------------------------------------------------------ Steinberg::int32 FactoryInfo::flags () const noexcept { return info.flags; } //------------------------------------------------------------------------ bool FactoryInfo::classesDiscardable () const noexcept { return (info.flags & PFactoryInfo::kClassesDiscardable) != 0; } //------------------------------------------------------------------------ bool FactoryInfo::licenseCheck () const noexcept { return (info.flags & PFactoryInfo::kLicenseCheck) != 0; } //------------------------------------------------------------------------ bool FactoryInfo::componentNonDiscardable () const noexcept { return (info.flags & PFactoryInfo::kComponentNonDiscardable) != 0; } //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ PluginFactory::PluginFactory (const PluginFactoryPtr& factory) noexcept : factory (factory) { } //------------------------------------------------------------------------ void PluginFactory::setHostContext (Steinberg::FUnknown* context) const noexcept { if (auto f = Steinberg::FUnknownPtr (factory)) f->setHostContext (context); } //------------------------------------------------------------------------ FactoryInfo PluginFactory::info () const noexcept { Steinberg::PFactoryInfo i; factory->getFactoryInfo (&i); return FactoryInfo (std::move (i)); } //------------------------------------------------------------------------ uint32_t PluginFactory::classCount () const noexcept { auto count = factory->countClasses (); assert (count >= 0); return static_cast (count); } //------------------------------------------------------------------------ PluginFactory::ClassInfos PluginFactory::classInfos () const noexcept { auto count = classCount (); Optional factoryInfo; ClassInfos classes; classes.reserve (count); auto f3 = Steinberg::U::cast (factory); auto f2 = Steinberg::U::cast (factory); Steinberg::PClassInfo ci; Steinberg::PClassInfo2 ci2; Steinberg::PClassInfoW ci3; for (uint32_t i = 0; i < count; ++i) { if (f3 && f3->getClassInfoUnicode (i, &ci3) == Steinberg::kResultTrue) classes.emplace_back (ci3); else if (f2 && f2->getClassInfo2 (i, &ci2) == Steinberg::kResultTrue) classes.emplace_back (ci2); else if (factory->getClassInfo (i, &ci) == Steinberg::kResultTrue) classes.emplace_back (ci); auto& classInfo = classes.back (); if (classInfo.vendor ().empty ()) { if (!factoryInfo) factoryInfo = Optional (info ()); classInfo.get ().vendor = factoryInfo->vendor (); } } return classes; } //------------------------------------------------------------------------ //------------------------------------------------------------------------ //------------------------------------------------------------------------ const UID& ClassInfo::ID () const noexcept { return data.classID; } //------------------------------------------------------------------------ int32_t ClassInfo::cardinality () const noexcept { return data.cardinality; } //------------------------------------------------------------------------ const std::string& ClassInfo::category () const noexcept { return data.category; } //------------------------------------------------------------------------ const std::string& ClassInfo::name () const noexcept { return data.name; } //------------------------------------------------------------------------ const std::string& ClassInfo::vendor () const noexcept { return data.vendor; } //------------------------------------------------------------------------ const std::string& ClassInfo::version () const noexcept { return data.version; } //------------------------------------------------------------------------ const std::string& ClassInfo::sdkVersion () const noexcept { return data.sdkVersion; } //------------------------------------------------------------------------ const ClassInfo::SubCategories& ClassInfo::subCategories () const noexcept { return data.subCategories; } //------------------------------------------------------------------------ Steinberg::uint32 ClassInfo::classFlags () const noexcept { return data.classFlags; } //------------------------------------------------------------------------ ClassInfo::ClassInfo (const PClassInfo& info) noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; data.classID = info.cid; data.cardinality = info.cardinality; data.category = StringConvert::convert (info.category, PClassInfo::kCategorySize); data.name = StringConvert::convert (info.name, PClassInfo::kNameSize); } //------------------------------------------------------------------------ ClassInfo::ClassInfo (const PClassInfo2& info) noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; data.classID = info.cid; data.cardinality = info.cardinality; data.category = StringConvert::convert (info.category, PClassInfo::kCategorySize); data.name = StringConvert::convert (info.name, PClassInfo::kNameSize); data.vendor = StringConvert::convert (info.vendor, PClassInfo2::kVendorSize); data.version = StringConvert::convert (info.version, PClassInfo2::kVersionSize); data.sdkVersion = StringConvert::convert (info.sdkVersion, PClassInfo2::kVersionSize); parseSubCategories ( StringConvert::convert (info.subCategories, PClassInfo2::kSubCategoriesSize)); data.classFlags = info.classFlags; } //------------------------------------------------------------------------ ClassInfo::ClassInfo (const PClassInfoW& info) noexcept { namespace StringConvert = Steinberg::Vst::StringConvert; data.classID = info.cid; data.cardinality = info.cardinality; data.category = StringConvert::convert (info.category, PClassInfo::kCategorySize); data.name = StringConvert::convert (info.name, PClassInfo::kNameSize); data.vendor = StringConvert::convert (info.vendor, PClassInfo2::kVendorSize); data.version = StringConvert::convert (info.version, PClassInfo2::kVersionSize); data.sdkVersion = StringConvert::convert (info.sdkVersion, PClassInfo2::kVersionSize); parseSubCategories ( StringConvert::convert (info.subCategories, PClassInfo2::kSubCategoriesSize)); data.classFlags = info.classFlags; } //------------------------------------------------------------------------ void ClassInfo::parseSubCategories (const std::string& str) noexcept { std::stringstream stream (str); std::string item; while (std::getline (stream, item, '|')) data.subCategories.emplace_back (std::move (item)); } //------------------------------------------------------------------------ std::string ClassInfo::subCategoriesString () const noexcept { std::string result; if (data.subCategories.empty ()) return result; result = data.subCategories[0]; for (auto index = 1u; index < data.subCategories.size (); ++index) result += "|" + data.subCategories[index]; return result; } //------------------------------------------------------------------------ namespace { //------------------------------------------------------------------------ std::pair rangeOfScaleFactor (const std::string& name) { auto result = std::make_pair (std::string::npos, std::string::npos); size_t xIndex = name.find_last_of ('x'); if (xIndex == std::string::npos) return result; size_t indicatorIndex = name.find_last_of ('_'); if (indicatorIndex == std::string::npos) return result; if (xIndex < indicatorIndex) return result; result.first = indicatorIndex + 1; result.second = xIndex; return result; } //------------------------------------------------------------------------ } // anonymous //------------------------------------------------------------------------ Optional Module::Snapshot::decodeScaleFactor (const std::string& name) { auto range = rangeOfScaleFactor (name); if (range.first == std::string::npos || range.second == std::string::npos) return {}; std::string tmp (name.data () + range.first, range.second - range.first); std::istringstream sstream (tmp); sstream.imbue (std::locale::classic ()); sstream.precision (static_cast (3)); double result; sstream >> result; return Optional (result); } //------------------------------------------------------------------------ Optional Module::Snapshot::decodeUID (const std::string& filename) { if (filename.size () < 45) return {}; if (filename.find ("_snapshot") != 32) return {}; auto uidStr = filename.substr (0, 32); return UID::fromString (uidStr); } //------------------------------------------------------------------------ } // Hosting } // VST3