1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

AudioPluginHost: Allow out-of-process scanner to scan AUv3 plugins

This commit is contained in:
reuk 2022-01-17 16:03:29 +00:00
parent 53f8650ba3
commit 6c046ffc04
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
3 changed files with 61 additions and 32 deletions

View file

@ -35,22 +35,23 @@ class PluginScannerSubprocess : private ChildProcessWorker,
private AsyncUpdater
{
public:
PluginScannerSubprocess()
{
formatManager.addDefaultFormats();
}
using ChildProcessWorker::initialiseFromCommandLine;
private:
void handleMessageFromCoordinator (const MemoryBlock& mb) override
{
{
const std::lock_guard<std::mutex> lock (mutex);
pendingBlocks.emplace (mb);
}
if (mb.isEmpty())
return;
triggerAsyncUpdate();
if (! doScan (mb))
{
{
const std::lock_guard<std::mutex> lock (mutex);
pendingBlocks.emplace (mb);
}
triggerAsyncUpdate();
}
}
void handleConnectionLost() override
@ -58,7 +59,6 @@ private:
JUCEApplicationBase::quit();
}
// It's important to run the plugin scan on the main thread!
void handleAsyncUpdate() override
{
for (;;)
@ -78,27 +78,55 @@ private:
if (block.isEmpty())
return;
MemoryInputStream stream { block, false };
const auto formatName = stream.readString();
const auto identifier = stream.readString();
OwnedArray<PluginDescription> results;
for (auto* format : formatManager.getFormats())
if (format->getName() == formatName)
format->findAllTypesForFile (results, identifier);
XmlElement xml ("LIST");
for (const auto& desc : results)
xml.addChildElement (desc->createXml().release());
const auto str = xml.toString();
sendMessageToCoordinator ({ str.toRawUTF8(), str.getNumBytesAsUTF8() });
doScan (block);
}
}
AudioPluginFormatManager formatManager;
bool doScan (const MemoryBlock& block)
{
AudioPluginFormatManager formatManager;
formatManager.addDefaultFormats();
MemoryInputStream stream { block, false };
const auto formatName = stream.readString();
const auto identifier = stream.readString();
PluginDescription pd;
pd.fileOrIdentifier = identifier;
pd.uniqueId = pd.deprecatedUid = 0;
const auto matchingFormat = [&]() -> AudioPluginFormat*
{
for (auto* format : formatManager.getFormats())
if (format->getName() == formatName)
return format;
return nullptr;
}();
if (matchingFormat == nullptr
|| (! MessageManager::getInstance()->isThisTheMessageThread()
&& ! matchingFormat->requiresUnblockedMessageThreadDuringCreation (pd)))
{
return false;
}
OwnedArray<PluginDescription> results;
matchingFormat->findAllTypesForFile (results, identifier);
sendPluginDescriptions (results);
return true;
}
void sendPluginDescriptions (const OwnedArray<PluginDescription>& results)
{
XmlElement xml ("LIST");
for (const auto& desc : results)
xml.addChildElement (desc->createXml().release());
const auto str = xml.toString();
sendMessageToCoordinator ({ str.toRawUTF8(), str.getNumBytesAsUTF8() });
}
std::mutex mutex;
std::queue<MemoryBlock> pendingBlocks;

View file

@ -137,6 +137,9 @@ public:
*/
virtual FileSearchPath getDefaultLocationsToSearch() = 0;
/** Returns true if instantiation of this plugin type must be done from a non-message thread. */
virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const = 0;
protected:
//==============================================================================
friend class AudioPluginFormatManager;
@ -149,9 +152,6 @@ protected:
virtual void createPluginInstance (const PluginDescription&, double initialSampleRate,
int initialBufferSize, PluginCreationCallback) = 0;
/** Returns true if instantiation of this plugin type must be done from a non-message thread. */
virtual bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const = 0;
private:
struct AsyncCreateMessage;
void handleMessage (const Message&) override;

View file

@ -204,6 +204,7 @@ struct ChildProcessWorker::Connection : public InterprocessConnection,
~Connection() override
{
stopThread (10000);
disconnect();
}
private: