Update slider from code does not update ValueTreeState?

I have a plugin with several sliders and an option to save the settings using the ValueTreeState. This works fine, except when the slider value is changed by code. I am using:

Slider.setValue(newvalue);

The slider is updated and the program is applying the new values. But when I save the ValueTreeState to a file, it appears that the old value is saved. Eventhough the slider as an attachment and the notification is sent. I have tried also forcing: sendNotification, sendNotificationSync and sendNotificationAsync. But none works. Only when the user moves the slider, the value is updated.

How do I get the value to the ValueTreeState from code?

Don’t set the Slider value - set the parameter value which will cause the slider to update.

Rail

Thank you. I have tried your suggestion, but I do not get it to work. I tried two things:

auto pParam = audioProcessor.apvts.getParameter(slider_id);
pParam->setValue(value);

Nothing happened.

I also tried:

pParam->beginChangeGesture();
pParam->setValueNotifyingHost(value);
pParam->endChangeGesture();

Now the slider always jumps to the max value, no matter what the value is.

So clearly I do not understand how to set the parameter the proper way. Could you point me in the right direction?

pParam->beginChangeGesture();
pParam->setValueNotifyingHost(value);
pParam->endChangeGesture();

This method is correct. But the value here needs to be the normalised value, i.e., a float between 0.0 and 1.0. You may use juce::NormalisableRange::convertTo0to1 to do the normalization for you.

Thank you, that is very helpful!

This method is correct. But the value here needs to be the normalised value, i.e., a float between 0.0 and 1.0. You may use juce::NormalisableRange::convertTo0to1 to do the normalization for you.

I got it this to work, but it did not solve the problem. The value is still not updated in the AudioProcessorValueTreeState. At least: If I save it to XML, the values are still the old values, except for values of sliders that were changed by hand.

What I try to do: On the change of one specific slider, the value of other sliders is updated with new values. Here is the code:

void RibbonToNotesAudioProcessorEditor::sliderDragEnded(juce::Slider* slider)
{
    if(slider == &sldZones)
    {
        for(;i < MAX_ZONES;i++)
        {
             int value = CalculateNewValue(i);
             *audioProcessor.splitValues[i] = value; //may be this is unnecessary, because this is a pointer to the value of pParam?
             auto pParam = audioProcessor.apvts.getParameter(SPLITS_ID + std::to_string(i));
             pParam->beginChangeGesture();
             pParam->setValueNotifyingHost(pParam->convertTo0to1(value));
             pParam->endChangeGesture();  
         }        
    }
}

Okay, I have found the problem. It is this part of the code that is wrong:

*audioProcessor.splitValues[i] = value; //<= PROBLEM!!!

This is wrong. This is a pointer to the value in the AudioValueTreeState, and should not be changed this way. I think because it is not thread safe. Anyway, by setting pParam->setValueNotifyingHost, this value is already updated.

Leaving it out, and everything works fine (I have commented the wrong line to show what is changed):

void RibbonToNotesAudioProcessorEditor::sliderDragEnded(juce::Slider* slider)
{
   if(slider == &sldZones)
   {
       for(;i < MAX_ZONES;i++)
       {
            int value = CalculateNewValue(i);
           // *audioProcessor.splitValues[i] = value; <= PROBLEM!!! 
            auto pParam = audioProcessor.apvts.getParameter(SPLITS_ID + std::to_string(i));
            pParam->beginChangeGesture();
            pParam->setValueNotifyingHost(pParam->convertTo0to1(value));
            pParam->endChangeGesture();  
        }        
   }
}