Serialize ValueTree in PluginProcessor

I made a component that acts as an onscreen keyboard: it has 12 toggle buttons. When the user presses one of them, a juce::Array<juce::var> gets updated so that it looks like this: {0,1,0,1,0,0,0,0,1,0,0,0} where 1 shows which keys that are currently toggled on.

I store the juce::Array into a ValueTree that I instantiated in the PluginEditor. I listen to the ValueTree from other components to update the GUI.

When I re-open the plugin the entire Editor resets and with it the ValueTree. How can I safely move the ValueTree to the Processor and serialize it so that I can preserve its state?

Any help would be very much appreciated! Thank you :slight_smile:

You’d probably want to save and load the tree in the processor’s getStateInformation and setStateInformation methods.

Personally, I would add the GUI ValueTree node as a child to my APVTS’s state and provide access to it from the processor so the editor can get it when it’s constructed.

You’ll need to consider the thread safety of what ever method you choose since the get/set state info methods will usually (always?) be called on the audio thread. I’d guess that they won’t be called while audio is playing so you wouldn’t need to be realtime safe, but don’t quote me on that.

Thank you for this! I got it working quite well with writing the state to the stream. However I realized that getStateInformation and setStateInformation only get called when the session is opened and closed, but not when the plugin window is opened and closed. Do you know how I can save and recall the state in that situation?

When the window is opened and closed, the processor is still active so you don’t really need to save the state at that point. You should just pass the relevant ValueTree node to the editor on construction (or have it ask the processor for it in its constructor). When the editor is deleted, the underlying data will still be stored in the ValueTree owned by the processor, so it won’t be lost.

The saving and loading of the state is handled by the host so, AFAIK, there’s no way to manually trigger a save/load from a plugin.

Ah yes of course! That makes sense. Is there a way to trigger all listeners that listen to the ValueTree when the Editor is constructed again? Or are they already automatically called?

If you had a setup something like this:

class Processor
    const juce::ValueTree& getGuiNode() { return guiNode; }

    juce::ValueTree guiNode;

class Editor
    Editor(Processor& p)
        data = p.getGuiNode();

    juce::ValueTree data;

then anything that’s a listener to Editor::data will get a call to juce::ValueTree::Listener::valueTreeRedirected() when data is set to p.getGuiNode().

Of course that means that you’d have to ensure that any listeners are already setup before the editor’s constructor is called which may not be possible depending on how your code is structured.

Yea that seems to be the problem: the listeners are registered after the constructor… :confused:
But thats alright, I’ll find a way… Thank you Jimmi! :slight_smile: