I created console application (cmake → juce_add_console_app)
I scan plugins in the main thread.
Many of the plugins I scan successfully.
But when I start to scan Lindell Audio 50 Series my application crashes without any exception. Even if I surround
pluginDirectoryScanner.scanNextFile with try-catch, it does not reach catch block.
I have debugged juce code to fine out where exactly it crashes, and found that it happens in
loadFrom method on
line 480 in file
bool loadFrom (Steinberg::IPluginFactory* factory, const Steinberg::TUID& uuid)
jassert (factory != nullptr);
*this = nullptr;
return factory->createInstance (uuid, ObjectType::iid, (void**) &source) == Steinberg::kResultOk;
And here is my code, just in case:
String workingPath = File::getCurrentWorkingDirectory().getFullPathName();
plugins_file.reset(new File(workingPath + "/" + PLUGIN_DATA_FILE));
FileSearchPath searchPath (VST3_PLUGINPATH);
PluginDirectoryScanner pluginDirectoryScanner (knownPluginList,
false /*is reccursive*/,
false /*is asyncronous*/);
int index = 0;
String nextname = pluginDirectoryScanner.getNextPluginFileThatWillBeScanned();
std::cout << "scanning " << nextname << std::endl;
// here I just catch a breakpoint when I found the plugin
if (nextname == "/Library/Audio/Plug-Ins/VST3/Lindell 50 Channel.vst3")
auto a = 0;
// at this point the application silently crashes without any exception
if (pluginDirectoryScanner.scanNextFile(true, plugname)==false)
std::cout << "stopped at " << plugname << std::endl;
// and we never go here after silent crash.
std::cout << "failed: " << e.what() << " " << nextname << std::endl;
Are you running in debug or release?
Some plugins crash on purpose when running debug to prevent reverse engineering.
That being said some plugins can still crash in release. A try/catch won’t help since they are crashing, not cleanly throwing an exception.
Also, plugins can crash if scanned along with others, but not when scanned alone, as some corrupt memory.
Finally, plugins need to be loaded on the message thread.
That is why plugin scanning should be done:
- out of process
- on the message thread
- one plugin at a time
- in release mode only
The JUCE Audio plugin host now implements out of process scanning, if you need to see how it’s done.
It looks like you don’t have a message thread running, but some plugins expect to be able to post messages during startup. You might consider basing your project off the GUI app template (but without necessarily showing a GUI window) rather than the console app example, so that the message loop is set up to run during the plugin scanning.
I went thru example of juce plugin host, but did not find a place where it actually calls
scanNextFile. I think it is somewhere in constructor of
CustomPluginListComponent. But I cannot figure out how to provide extra plugin directory.
Maybe you have a hint?
The AudioPluginHost uses a PluginListComponent to display the list of plugins and start the scanning process. This component uses a PluginDirectoryScanner internally to actually do the scanning, and the PluginDirectoryScanner takes a constructor argument that specifies which paths should be scanned.
You can look at the implementation of the PluginListComponent to see how this works. In
Scanner::startScan, the scanner creates a new PluginDirectoryScanner and passes it the paths configured by the user in the
@reuk @dimbouche Thank you guys!
I am successfully doing all plugins scan while my UI is not frozen.
It took some time to study example code from JUCE host app.
Do I get it right now? : I still can run scanning in a thread, but I have to provide a
KnownPluginList object, where
CustomScanner is using Child/Main process system to run the scanning as a process. And when a scanned plugin checks if it is a main thread, it does not know that Child process was run from gui app and thinks it is a main one?
Correct. Each process owns its threads.
So from the main process (main app) you run the scan on a detached thread, which triggers a secondary process (plugin scan app) which scans plugins on the message thread as expected.