diff --git a/src/common/serialization/vst3/plugin-factory.cpp b/src/common/serialization/vst3/plugin-factory.cpp index cb1534fa..ba9dd46c 100644 --- a/src/common/serialization/vst3/plugin-factory.cpp +++ b/src/common/serialization/vst3/plugin-factory.cpp @@ -26,12 +26,24 @@ YaPluginFactory::YaPluginFactory( // TODO: We should only copy the interfaces that we support. This should use // the same list as that used in `createInstance()`. known_iids.insert(factory->iid); + if (Steinberg::PFactoryInfo info; factory->getFactoryInfo(&info) == Steinberg::kResultOk) { factory_info = info; } + num_classes = factory->countClasses(); + // TODO: At this point we don't know what this class is and thus we can't + // filter unsupported classes, right? + class_infos_1.resize(num_classes); + for (int i = 0; i < num_classes; i++) { + Steinberg::PClassInfo info; + if (factory->getClassInfo(i, &info) == Steinberg::kResultOk) { + class_infos_1[i] = info; + } + } + auto factory2 = Steinberg::FUnknownPtr(factory); if (!factory2) { return; @@ -93,11 +105,18 @@ int32 PLUGIN_API YaPluginFactory::countClasses() { return num_classes; } -tresult PLUGIN_API -YaPluginFactory::getClassInfo(Steinberg::int32 /*index*/, - Steinberg::PClassInfo* /*info*/) { - // TODO: Implement - return 0; +tresult PLUGIN_API YaPluginFactory::getClassInfo(Steinberg::int32 index, + Steinberg::PClassInfo* info) { + if (index >= static_cast(class_infos_1.size())) { + return Steinberg::kInvalidArgument; + } + + if (class_infos_1[index]) { + *info = *class_infos_1[index]; + return Steinberg::kResultOk; + } else { + return Steinberg::kResultFalse; + } } tresult PLUGIN_API diff --git a/src/common/serialization/vst3/plugin-factory.h b/src/common/serialization/vst3/plugin-factory.h index 3a6ef4a5..c93accde 100644 --- a/src/common/serialization/vst3/plugin-factory.h +++ b/src/common/serialization/vst3/plugin-factory.h @@ -86,10 +86,22 @@ class YaPluginFactory : public Steinberg::IPluginFactory3 { */ std::set known_iids; - // For `IPluginFactory::getFactoryInfo` + /** + * For `IPluginFactory::getFactoryInfo`. + */ std::optional factory_info; - // For `IPluginFactory::countClasses` + /** + * For `IPluginFactory::countClasses`. + */ int num_classes; + /** + * For `IPluginFactory::getClassInfo`. We need to store all four class info + * versions if the plugin can provide them since we don't know which version + * of the interface the host will use. Will be `std::nullopt` if the plugin + * doesn't return a class info. + */ + std::vector> class_infos_1; + // TODO: Callback interface for `createInstance()` template void serialize(S& s) { @@ -97,9 +109,12 @@ class YaPluginFactory : public Steinberg::IPluginFactory3 { [](S& s, Steinberg::FUID& iid) { s.ext(iid, bitsery::ext::FUID{}); }); - s.ext(factory_info, bitsery::ext::StdOptional{}, - [](S& s, Steinberg::PFactoryInfo& info) { s.object(info); }); + s.ext(factory_info, bitsery::ext::StdOptional{}); s.value4b(num_classes); + s.container(class_infos_1, 2048, + [](S& s, std::optional& info) { + s.ext(info, bitsery::ext::StdOptional{}); + }); } }; @@ -108,6 +123,14 @@ class YaPluginFactory : public Steinberg::IPluginFactory3 { // Serialization functions have to live in the same namespace as the objects // they're serializing namespace Steinberg { +template +void serialize(S& s, PClassInfo& class_info) { + s.container1b(class_info.cid); + s.value4b(class_info.cardinality); + s.text1b(class_info.category); + s.text1b(class_info.name); +} + template void serialize(S& s, PFactoryInfo& factory_info) { s.text1b(factory_info.vendor);