Styling the Standalone plugin window?

We should rename this preprocessor define as it’s no longer only relevant to AUv3.

2 Likes

Hey! I’d like to just override a method or two. Is there a way of doing so?
Seems like when I enable the macro I have to start from scratch?

Sorry, but this doesn’t seem clear.

So to use our own standalone class, we should set JUCE_USE_CUSTOM_AU3_STANDALONE_APP to 1 and then create a class that’s called StandaloneFilterApp?

Ahh thanks for pointing that out. In fact, we broke the functionality of JUCE_USE_CUSTOM_AU3_STANDALONE_APP with JUCE 5.

I’ve now fixed this on develop and also renamed the macro to JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP. Simply define this to 1 in your AppConfig.h (or add it as a custom compiler pre-processor definition) and then use the START_JUCE_APPLICATION macro as you would in a normal standalone app.

1 Like

Sorry @fabian, but I still don’t understand. You say to use the START_JUCE_APPLICATION macro as I normally would, but I’ve never used that macro before nor do I know how to use it.

Just to be clear, I just want to style the standalone app to look as close as possible to a proper OS app, which the generated JUCE code does not do…and shouldn’t it?

Do I need to create a subclass of StandaloneFilterApp or StandaloneFilterWindow or both?

Please, just a little example code here would go a long way. Thank you.

1 Like

There are two approaches here that you could do:

  1. you use the standalone app that JUCE already provides for you. Then you don’t need any macros etc. This is the approach that JUCE’s audio plugin demo uses. If you want different behaviour in your standalone app (compared to your plug-in), you can use:

    PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone

    For example, you could use this in a parentHierarchyChanged callback in your plug-ins editor to change the window styling of the top-level window.

  1. You write your own standalone app class just the way you would when writing a standalone JUCE app. If you look at any JUCE GUI example project (which isn’t a plugin), there is a START_JUCE_APPLICATION (JUCEHelloWorldApplication) at the very end. So for this option, you subclass JUCEApplication, just as you would when writing a standalone app, and it’s up to you to initialise the device manager and instantiate your AudioProcessor etc. This is obviously much more work, but gives you a lot more flexibility.

To try out option 2) just copy the source files of the HelloWorld project into the JUCE audio plugin demo. Then in the Projucer add the source files (Main.cpp, MainComponent.cpp, MainComponent.h) to the audio demo plugin project and ensure that JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1 in Preprocesser definitions. Then just build and run your app. The standalone target will now just show the HelloWorld window. Obviously, for an audio plug-in you would change the HelloWorld code to instantiate your plug-in and editor.

4 Likes

Hi Fabian,

Perhaps you an give me a pointer on what’s the simplest way to have the Standalone allow all the outputs available for the selected driver… for instance SoundFlower 64 has 32 stereo Outputs available… my plug-in has

MyPluginProc:: MyPluginProc() : AudioProcessor (BusesProperties()
                                .withOutput ("Out 1-2",  AudioChannelSet::stereo(), true)
                                .withOutput ("Out 3-4",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 5-6",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 7-8",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 9-10",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 11-12",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 13-14",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 15-16",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 17-18",  AudioChannelSet::stereo(), false)
                                .withOutput ("Out 19-20", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 21-22", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 23-24", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 25-26", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 27-28", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 29-30", AudioChannelSet::stereo(), false)
                                .withOutput ("Out 31-32", AudioChannelSet::stereo(), false)
                                                             ),
 : 
 {
     if (wrapperType == AudioProcessor::wrapperType_Standalone)
           enableAllBuses();
     :
 }

and

 bool MyPluginProc::isBusesLayoutSupported (const BusesLayout& layouts) const
{
    if (layouts.getMainInputChannels() == 0 && layouts.getMainOutputChannels() == 2)
        return true;

    if (layouts.getMainInputChannels() == 0 && layouts.getMainOutputChannels() == 32)
        return true;

    return false;
}

This is working as a plug-in… and also as Standalone with stereo out.

However, in the Audio Setup you can’t select more than a stereo output (you can change which stereo outputs are used, but you can’t select more than one stereo output at a time).

Any ideas?

It may just be easier to use AudioAppComponent in a fresh GUI App. and load the VST into an AudioProcessorGraph.

Thanks,

Rail

The standalone plugin will only ever use a single bus. So in standalone mode you should only have a single output bus which should be capable of many channels.

Okay - I think it’ll just be easier to roll my own Standalone using AudioAppComponent and loading the VST… I don’t think you have an output bus which can have 32 discrete outputs (unless I’m missing something).

Cheers,

Rail

You can just use discrete channels AudioChannelSet::discreteChannels (X).

Oh, cool… I’ll try that!

Thanks,

Rail

Oh yes, can you please add AsyncQuitRetrier() to the Standalone code so it doesn’t crash if you quit while the Audio/MIDI Setup dialog is open?

Thanks,

Rail

1 Like

OK the standalone code won’t assert anymore when quitting. Fix is on develop with commit b78ce1f.

1 Like

Thanks!

Hi fabian,

So this kinda works… If I change my code for testing to:

MyProcessor:: MyProcessor() : AudioProcessor (BusesProperties().withOutput ("Out", AudioChannelSet::discreteChannels (32), true))
{
:
}

The Audio/MIDI Setup for SoundFlower64 now shows all the outputs and if I leave everything as the default with all outputs enabled/selected then all my routing works perfectly… the problem is if I try and change anything in the Audio/MIDI Setup… say I de-select Output 3+4 then I need to get a callback to indicate that Out 3+4 is disabled to my plug-in so I can modify my graph connections (otherwise everything is offset by the 2 disabled Outputs - personally I’d prefer that they get disabled and everything else stay constant)… is there a callback for that? The other thing is that if you do disable Output 3+4 you hit two asserts in the code in AudioProcessor::setPlayConfigDetails() and if you then try and re-enable Output 3+4 it does… but after that the options in the Setup don’t respond to any Output selections after that (even if you select a different output device and switch back to SoundFlower64).

Any thoughts?

Thanks,

Rail

I assume this is when you run your plug-in in standalone mode, right? To be honest, we’ve never really tried this with more than two channels. I’ve just tried this now with Loopback instead of SoundFlower and I can confirm that the standalone target works well if everything is left as default.

How are you disabling outputs? In JUCE’s audio settings screen or in Apple’s Audio/MIDI Setup? I can’t seem to disable any of the channels in both.

Correct, this is only an issue for Standalone. Everything works perfectly fine in all the other formats.

I changed some code slightly to allow disabling the outputs… I’ll be sending you a PM soon showing the issue(s) and another company’s Standalone JUCE based plug-in trying to do the same thing as I’m trying to do (and failing on and off).

Rail

Thinking about this… perhaps it’s correct to not allow the user to remove/change the Outputs for the device… which means this will be fine with the change… If it is, other than relying on the preprocessor defined JucePlugin_Build_Standalone at compile time to set up the output buses which would mean building the Standalone separately… is there any way to change the BusesProperties at run time when the AudioProcessor is created?

Thanks,

Rail

Hi fabian. I’m having real trouble getting this to work without causing lots of redefinition problems on OSX and Windows.

Here is my class:

Which is essentially a copy of juce_StandaloneFilterApp.cpp with a mainWindow->setUsingNativeTitleBar (true) added to initialise() to set native windows.

I think I’ve followed your instructions, though obviously the HelloWorldApplication doesn’t contain any of the standalone filter window code contained in the juce_StandaloneFilterApp.cpp default app. I managed to get this working for debug on OSX but ran in to lots of redefinitions for release on OSX - now trying to get it working on Windows and hitting lots of re definitions again. Feels like I’m doing something wrong just to be able to call setUsingNativeTitleBar (true).

Thx

I just got this working yesterday… PM me if you need help… It took a little work to get it working right.

I’ll be watching the game and handing out candy… so it may be a slower response :wink:

EDIT: See Reference to point is ambiguous

Rail