#pragma once #include // Simplified HelperPluginHost — ONLY tests if a plugin can load. // No audio processing, no GUI, no IPC. Just load and report. class HelperPluginHost { public: HelperPluginHost() { #if JUCE_PLUGINHOST_VST3 formatManager.addFormat(new juce::VST3PluginFormat()); #endif #if JUCE_PLUGINHOST_AU formatManager.addFormat(new juce::AudioUnitPluginFormat()); #endif } // Try to load a plugin. Returns true if successful. // If the plugin crashes (abort(), NSAlert, etc.), this process dies // and the parent sees exit code != 0. bool testLoad(const juce::String& path) { juce::File pluginFile(path); if (!pluginFile.exists()) return false; juce::OwnedArray typesFound; for (int i = 0; i < formatManager.getNumFormats(); ++i) { auto* format = formatManager.getFormat(i); bool isVST3 = pluginFile.getFileExtension() == ".vst3"; bool isAU = pluginFile.getFileExtension() == ".component"; if (isVST3 && format->getName() != "VST3") continue; if (isAU && format->getName() != "AudioUnit") continue; format->findAllTypesForFile(typesFound, pluginFile.getFullPathName()); if (typesFound.size() > 0) break; } if (typesFound.isEmpty()) return false; juce::String errorMessage; auto instance = formatManager.createPluginInstance( *typesFound[0], 44100.0, 512, errorMessage); if (instance == nullptr) { DBG("HelperPluginHost: Load failed: " + errorMessage); return false; } // Successfully loaded — release and report safe instance->releaseResources(); instance.reset(); return true; } private: juce::AudioPluginFormatManager formatManager; };