How I can change the PluginName that XML stateinformation procedure uses?

Hi,
I am trying to add the feature " Storing and retrieving parameters" to my plugin.
I have used the code that is given in the Juce tutorial

void getStateInformation (MemoryBlock& destData) override
{
auto state = parameters.copyState();
std::unique_ptr xml (state.createXml());
copyXmlToBinary (*xml, destData);
}

But I got the exception at the line

jassert (isValidXmlName (tagName));

When I monitor the tagName it is named “2RuleSynth” (this is the name of my plugin)
I know that Tag names can’t start with the letters xml , a number , or punctuation,

How I can change the PluginName that XML procedure of stateinformation uses?

Thanks in advance

It depends, if you do it the old way, adding the parameters to the AudioProcessorValueTreeState, you assign a ValueTree at the end of the constructor, which is the root node of the XML.
If you use the new way by supplying a ParameterLayout in the AudioProcessorValueTreeState constructor, the third parameter is a string, which is the tagName of your root XML node.

1 Like

valueTreeState.state = ValueTree(Identifier(JucePlugin_Name));
I fount it.
ok thank you daniel

This is kind of redundant since, as Daniel said, the third parameter in the APVTS constructor is used to set the internal ValueTree’s state:

: apvts(*this, &undoManager, juce::Identifier(JucePlugin_Name), createParameterLayout())
1 Like

Thanks Jimmi,
But I did not implemented the JUCE tutorial exactly that you have mentioned, I created another custom class responsible of creation of parameters. That is different than pre initialization parameter layout of PluginProcessor constructor . So I have to use the valueTreeState.state = ValueTree(Identifier(JucePlugin_Name)); in the code

I may not be able to explain it clearly, sorry for that.

Hi, I have the same problem and It doesn’t store states :confused: Can anybody please have a look at it ? I did everything i found in tutorials and docs . There are so many post about this topic but everything is mixed and i don’t know which one is the right way to save and load these states .

PluginEditor.h

 Slider mVolumeSlider{ Slider::RotaryHorizontalVerticalDrag,   Slider::TextBoxBelow };

 AudioProcessorValueTreeState::SliderAttachment mVolumeAttachment{ processor.getValueTreeState(),
																TestAudioProcessor::paramVolume,
																mVolumeSlider };

PluginProcessor.h :

AudioProcessorValueTreeState& getValueTreeState();

static String paramVolume;
Atomic<float>               mVolume{ 0.0f };
UndoManager                  mUndoManager;
AudioProcessorValueTreeState mState;

PluginProcessor.cpp

 #include "PluginProcessor.h"
 #include "PluginEditor.h"

  String TestAudioProcessor::paramVolume("volume");

  TestAudioProcessor::TestAudioProcessor()
 #ifndef JucePlugin_PreferredChannelConfigurations
: AudioProcessor(BusesProperties()
 #if ! JucePlugin_IsMidiEffect
 #if ! JucePlugin_IsSynth
	.withInput("Input", AudioChannelSet::stereo(), true)
 #endif
	.withOutput("Output", AudioChannelSet::stereo(), true)
 #endif
), mState(*this, &mUndoManager, "Test Plugin",
	{
		std::make_unique<AudioParameterFloat>(paramVolume,
											  TRANS("Volume"),
											  NormalisableRange<float>(0.0f,1.0f,1.0f),
											  mVolume.get()," ",
											  AudioProcessorParameter::genericParameter,
											  [](float v, int) {return String(v,2) + "  "; },
											  [](const String& t) {return t.dropLastCharacters(2).getFloatValue(); }),

#endif
 {

mState.addParameterListener(paramVolume, this);

 }

   const String TestAudioProcessor::getName() const
 {
    return "Test Plugin";
  }

  void TestAudioProcessor::parameterChanged(const String& parameterID, float newValue)
{

if (parameterID == paramVolume) {
	mVolume = newValue;
   }
 }


  AudioProcessorValueTreeState& TestAudioProcessor::getValueTreeState()
  {
       return mState;
     }  

   //===================================================================
   bool TestAudioProcessor::hasEditor() const
   {
        return true; // (change this to false if you choose to not supply an editor)
    } 

    AudioProcessorEditor* TestAudioProcessor::createEditor()
   { 
       return new TestAudioProcessor(*this);
    }

    void TestAudioProcessor::getStateInformation(MemoryBlock& destData)
      {
            mState.state = ValueTree(Identifier(JucePlugin_Name));
            auto state = mState.copyState();
            std::unique_ptr<XmlElement> xml(state.createXml());
           copyXmlToBinary(*xml, destData);

      }

      void TestAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
   {
            std::unique_ptr<XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes));

    	    if (xmlState.get() != nullptr)
	         if (xmlState->hasTagName(mState.state.getType()))
		         mState.replaceState(ValueTree::fromXml(*xmlState));
 }

When you wrote this:

mState (*this, &mUndoManager, "Test Plugin", ...

the mState.state is already populated with a ValueTree (“Test Plugin”).
So you can (or I think you should) drop this line:

mState.state = ValueTree(Identifier(JucePlugin_Name));

Also having a space in a XML tag name is probably not working as expected.

Those are the things I would check first.

“Test_Plugin” this worked :smiley: thank you very much :pray: . I was trying implement everything i could find:D I know juce community is huge but somehow on some topics contents are mixed . It is really so hard for me to follow the latest version of methods.

I just want to make sure, Could you please tell me? Is this the latest implementation of value tree state ? Do I need to add more stuff ? :smiley: if I don’t need to add more ,as a next step I will add a file browser component to provide “preset selection” feature. But first of all i will learn more about xml files.