When a user interacts with a plugin, the user assumes that the actual UI (editor) is persistent when the window is closed/reopened. The expectation is that the UI will look exactly the same when it is reopened - all drawings, component settings, component enabled states, waveforms, etc. However, in the code, the editor is destroyed and reconstructed when the plugin window is closed/opened. Because of the disconnect between the user expectation and the way the software treats an editor, there must be significant functionality written to give the illusion that the editor is persistent. It seems like the obvious answer is to not destroy the editor when the window is closed/opened…only destroy it when the plugin is removed and the processor itself is destroyed. Then all of the state of the UI does not have to be maintained by custom software (putting UI state into value trees inside the processor, and so on). Because it is so obvious to not destroy the editor, I assume there it is either not allowed by the audio host software, or it has some other drawback that must be significant. It can’t just be memory savings? I used IPlug library in the past and never had to deal with rebuilding my UI…it somehow took care of it. So, my question is why does the editor get destroyed in Juce when the user closes the plugin window?
I think the GUI gets destroyed and rebuilt just the same in IPlug too. (It’s a long time since I’ve worked with IPlug so I am not 100% sure about that, though.)
JUCE has a stricter separation between the audio processor and the GUI. In IPlug there is stuff like having each IControl be tied to a parameter in the plugin audio processor. (So it’s easy for the GUI to restore the GUI control states from the parameters automatically. This model however breaks up when one wants to use IControls without them being tied to any plugin parameters etc…)
Yeah, that probably explains IPlug. The control/parameter thing was always confusing and limiting.
It just seems like Juce could save the editor privately when the window is closed, and hand it back to the audio host when a new window is opened. So, the host doesn’t realize it is the same editor. I could see that some applications specifically do not want the editor to be persistent. If so, it seems like persistence could just be a settable property inside the editor or something.
There might be something fishy in your GUI code’s design if you can’t easily allow it to be destroyed and get back to the state where it was previously. That said, things can get pretty painful and I’ve myself resorted to things like having AudioThumbnail/AudioThumbNailCache as members of the AudioProcessor in order to retain their state…
What happens when the user closes the host and relaunches it? Surely you need your UI to represent the previous state at that point too?
I might have more state than normal. I have a thing where there is clearly a series of states that occur via button press and show waveforms. The actual control positions of normal knobs and buttons should be managed through the processor value tree…because they need to anyway for presets and automation. But outside of that, there are GUI drawings, waveforms, and enabled state of each control/component. That is just what I have encountered…but I would guess there are other things that fall into the category of “UI state that is not an automatable parameter”.
No, I’ve never seen a plugin UI persist when an audio host relaunches…or even when the plugin is removed (processor destroyed) and reinserted.
Save your state into a single object maybe a struct with everything you want in and have this be a member of the audio processor. That should be a quick way to save state. JUCE has the ValueTree class that should also help with this an make things much easier to manage.
Dave is on the money here, think of a user saving a session and then re-opening that session at a latter date, you will normally want state restored then too.
There are values (parameters) that must be stored in the processor because they are automatable, preset-able, and/or save-able with a session. If this is all your plugin contains, then you don’t have to worry about UI state persistence. There is still code (value tree) that is working to create the illusion of UI persistence, but it is necessary anyway for presets, etc.
There are other UI things that are not automatable/preset-able/save-able. A waveform display (usually). A greyed out button. The text of a label that might be one of several steps instructing a user. I have things are expected to persist across a plugin window close/open, but not across a reboot of the host or plugin. (I was assuming this was a common need, but that may not be so). So, my point is that not destroying the editor would solve this problem, and bring into alignment the software architecture with the expectations of the user. It can also be solved with a value tree or other storage in the processor, and that is what we do now.
Oh I totally understand I usually find users do still want these things to persist between session loads - for example which band of an eq was last selected on an interactive graph.
Storing state in the processor is the right way, having every plugin instance create and persist a GUI is a waste of resources IMHO. If this is what you want then I suspect you can do it, but all the things you need would have to be members of the processor not the editor.
I think you have that backwards. I’ve NEVER, not in 16+ years, seen a plugin NOT persist between re-starts or project-saves.
Yes, you store the complete state of every button, parameter etc. in the processor, so it gets saved/restored. When you open the GUI, you restore all component states.
Since all of this has to be done anyway, there is absolutely no reason to keep the editor around when it’s closed.
All of the clarification you need is above. I was not clear that I was talking about UI elements that are not automatable parameters. No use retyping. I guess the answer is as Anthony pointed out - it is a resource issue. For one plugin I would argue that it is more important for the architecture to match the user experience at the cost of minor memory usage, but I can see the point when it is extrapolated to someone using 100 plugins or more.
No, I was not clear that I meant EVERY component on the screen has to have it’s state preserved, no matter if it’s an automatable parameter or not. Otherwise the users will be really confused. Doing anything less is simply lazy/irresponsible.
The AudioProcessorValueTreeState has the public state member for that reason. You can save whatever you like, and still save the APVTS in a single line in the AudioProcessor::getStateInformation().
Because I wanted to use the same paradigm I use for AudioParameters for GUI elements as well, I created attachments to a raw ValueTree. You can find them on github - ffGuiAttachments