I got around this by overriding the Standalone wrapper (which we’re strongly encouraged to do anyhow, and I assume you’re doing) and then including the .cpp in Processor.cpp and Editor.cpp. In this way one can access the Standalone methods directly, and one can just do all the housekeeping e.g. MIDI settings once, and the processor (and subsequently the editor) are aware of it.
I’m sure there’s a better way, but I’m a UI programmer, not a C++ Wizard like some here (“I only do eyes”) and this way seems to work.
Okay, I’m going to use our Axon 2 for iOS product as an example.
Step 1: Override [edit: replace, I mean] juce_StandaloneFilterWindow.h and juce_StandaloneFilterApp.cpp. Since the only time we use a standalone is on iOS, I made StandaloneApp.h and StandaloneApp.mm. Copy the contents of the juce library files in to these two, and change the include in the .mm (or .cpp if that’s how you roll) and in one of the usual places, define JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1. After you’ve done these things, and build, your app will be using your standalone wrapper instead of the generated one.
In PluginProcessor.cpp and PluginEditor.cpp and any other components that need access, include StandaloneApp.mm (or .cpp, whichever you used), not .h.
You can now access call methods created in StandaloneApp.mm in your processor or editor.
Here is a trigger in StandaloneApp.mm that opens the audio settings:
In your editor, you can just have, in buttonClicked or whatever:
if (JUCEApplication::isStandaloneApp()) axon_OpenSettings();
And then in StandaloneApp.h, you can have your way with that. I am fairly convinced there is a far better way to do this, but for my needs it works fine.
(Side note: if you make your standalone .mm, everything that touches it needs to compile as Obj-C++, so if you’re not using iOS-specific calls like BlueTooth MIDI or whatever, you might want to stick to .cpp)
You say to "override juce_StandaloneFilterWindow.h and juce_StandaloneFilterApp.cpp"but by copying them, it sounds like you really mean copy and rewrite instead of override in the traditional C++ case, right?
Heh, yes. I’ve never taken any programming courses, so I get the terminology wrong all the time. I mean “replace entirely.” I don’t think you can just override the methods in those, as they’re private.
I have just done this thing this very morning - both of you, thanks for your help!
@pizzafilms, Make sure to import #import "StandaloneFilterWindow.h" in your PluginEditor.m where you have your open settings function. StandalonePluginHolder::getInstance() is a global method that can be called anywhere as long as you have the import.
Thank you @pizzafilms for this summary. We should make it easier to use a custom version of the StandaloneFilterWindow.
For many, it may be easier to just roll your own Application and Window. Luckily doing this is just as easy as creating any standalone GUI app with JUCE. Just create your GUI app as you would any other JUCE standalone GUI app but add JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1 to the list of preprocessor defines in the Projucer.
Thank you @fabian, I definitely agree that JUCE should have an easier way to make a StandaloneFilterWindow, but I would think that considering that all/most of the necessary functionality is already there, it’s more an issue of having some hooks to modify it and less of a desire to start allover from scratch.
In my quest for that desired additional functionality, I hit some major roadblocks trying to go fullscreen. Please take a look at the more complete post here: Standalone issues
Thanks for the great tutorial. I tried it and got a linker error:
ndefined symbols for architecture x86_64:
"juce_CreateApplication()", referenced from:
_main in include_juce_audio_plugin_client_Standalone.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Somehow the linker does not find the class that derivates from JUCEApplication.
I did set JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1. Is there something else i have to do?
I was able to fix it. I just had to add this line: