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

StandaloneFilterWindow: Allow plugin to run when no display is present

This is useful on headless Linux systems. When no display is attached,
window creation is bypassed but a StandalonePluginHolder is still
created, allowing audio to be processed.
This commit is contained in:
reuk 2024-10-17 14:32:05 +01:00
parent 420922253f
commit 1f56562652
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
2 changed files with 83 additions and 43 deletions

View file

@ -723,26 +723,11 @@ public:
//==============================================================================
typedef StandalonePluginHolder::PluginInOuts PluginInOuts;
//==============================================================================
/** Creates a window with a given title and colour.
The settings object can be a PropertySet that the class should use to
store its settings (it can also be null). If takeOwnershipOfSettings is
true, then the settings object will be owned and deleted by this object.
*/
StandaloneFilterWindow (const String& title,
Colour backgroundColour,
PropertySet* settingsToUse,
bool takeOwnershipOfSettings,
const String& preferredDefaultDeviceName = String(),
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions = nullptr,
const Array<PluginInOuts>& constrainToConfiguration = {},
#if JUCE_ANDROID || JUCE_IOS
bool autoOpenMidiDevices = true
#else
bool autoOpenMidiDevices = false
#endif
)
std::unique_ptr<StandalonePluginHolder> pluginHolderIn)
: DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton),
pluginHolder (std::move (pluginHolderIn)),
optionsButton ("Options")
{
setConstrainer (&decoratorConstrainer);
@ -757,10 +742,6 @@ public:
optionsButton.setTriggeredOnMouseDown (true);
#endif
pluginHolder.reset (new StandalonePluginHolder (settingsToUse, takeOwnershipOfSettings,
preferredDefaultDeviceName, preferredSetupOptions,
constrainToConfiguration, autoOpenMidiDevices));
#if JUCE_IOS || JUCE_ANDROID
setFullScreen (true);
updateContent();
@ -809,6 +790,36 @@ public:
#endif
}
//==============================================================================
/** Creates a window with a given title and colour.
The settings object can be a PropertySet that the class should use to
store its settings (it can also be null). If takeOwnershipOfSettings is
true, then the settings object will be owned and deleted by this object.
*/
StandaloneFilterWindow (const String& title,
Colour backgroundColour,
PropertySet* settingsToUse,
bool takeOwnershipOfSettings,
const String& preferredDefaultDeviceName = String(),
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions = nullptr,
const Array<PluginInOuts>& constrainToConfiguration = {},
#if JUCE_ANDROID || JUCE_IOS
bool autoOpenMidiDevices = true
#else
bool autoOpenMidiDevices = false
#endif
)
: StandaloneFilterWindow (title,
backgroundColour,
std::make_unique<StandalonePluginHolder> (settingsToUse,
takeOwnershipOfSettings,
preferredDefaultDeviceName,
preferredSetupOptions,
constrainToConfiguration,
autoOpenMidiDevices))
{
}
~StandaloneFilterWindow() override
{
#if (! JUCE_IOS) && (! JUCE_ANDROID)

View file

@ -70,7 +70,7 @@ public:
{
PropertiesFile::Options options;
options.applicationName = appName;
options.applicationName = CharPointer_UTF8 (JucePlugin_Name);
options.filenameSuffix = ".settings";
options.osxLibrarySubFolder = "Application Support";
#if JUCE_LINUX || JUCE_BSD
@ -82,46 +82,72 @@ public:
appProperties.setStorageParameters (options);
}
const String getApplicationName() override { return appName; }
const String getApplicationName() override { return CharPointer_UTF8 (JucePlugin_Name); }
const String getApplicationVersion() override { return JucePlugin_VersionString; }
bool moreThanOneInstanceAllowed() override { return true; }
void anotherInstanceStarted (const String&) override {}
virtual StandaloneFilterWindow* createWindow()
{
#ifdef JucePlugin_PreferredChannelConfigurations
StandalonePluginHolder::PluginInOuts channels[] = { JucePlugin_PreferredChannelConfigurations };
#endif
if (Desktop::getInstance().getDisplays().displays.isEmpty())
{
// No displays are available, so no window will be created!
jassertfalse;
return nullptr;
}
return new StandaloneFilterWindow (getApplicationName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
appProperties.getUserSettings(),
false, {}, nullptr
#ifdef JucePlugin_PreferredChannelConfigurations
, juce::Array<StandalonePluginHolder::PluginInOuts> (channels, juce::numElementsInArray (channels))
#else
, {}
#endif
#if JUCE_DONT_AUTO_OPEN_MIDI_DEVICES_ON_MOBILE
, false
#endif
);
createPluginHolder());
}
virtual std::unique_ptr<StandalonePluginHolder> createPluginHolder()
{
constexpr auto autoOpenMidiDevices =
#if (JUCE_ANDROID || JUCE_IOS) && ! JUCE_DONT_AUTO_OPEN_MIDI_DEVICES_ON_MOBILE
true;
#else
false;
#endif
#ifdef JucePlugin_PreferredChannelConfigurations
constexpr StandalonePluginHolder::PluginInOuts channels[] { JucePlugin_PreferredChannelConfigurations };
const Array<StandalonePluginHolder::PluginInOuts> channelConfig {channels, juce::numElementsInArray (channels));
#else
const Array<StandalonePluginHolder::PluginInOuts> channelConfig;
#endif
return std::make_unique<StandalonePluginHolder> (appProperties.getUserSettings(),
false,
String{},
nullptr,
channelConfig,
autoOpenMidiDevices);
}
//==============================================================================
void initialise (const String&) override
{
mainWindow.reset (createWindow());
mainWindow = rawToUniquePtr (createWindow());
#if JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
Desktop::getInstance().setKioskModeComponent (mainWindow.get(), false);
#endif
if (mainWindow != nullptr)
{
#if JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
Desktop::getInstance().setKioskModeComponent (mainWindow.get(), false);
#endif
mainWindow->setVisible (true);
mainWindow->setVisible (true);
}
else
{
pluginHolder = createPluginHolder();
}
}
void shutdown() override
{
pluginHolder = nullptr;
mainWindow = nullptr;
appProperties.saveIfNeeded();
}
@ -129,6 +155,9 @@ public:
//==============================================================================
void systemRequestedQuit() override
{
if (pluginHolder != nullptr)
pluginHolder->savePluginState();
if (mainWindow != nullptr)
mainWindow->pluginHolder->savePluginState();
@ -151,7 +180,7 @@ protected:
std::unique_ptr<StandaloneFilterWindow> mainWindow;
private:
const String appName { CharPointer_UTF8 (JucePlugin_Name) };
std::unique_ptr<StandalonePluginHolder> pluginHolder;
};
} // namespace juce