Issues with ValueTreeSynchronizer

I fiddled around a bit with the ValueTreeSynchronizer.

First, I found out that it does not synchronize removal of properties - the implementation for this is simply missing.
I filed an issue for this.

Then, I found out that calling <myValueTreeSynchroniser>.sendFullSyncCallback() results in the affected tree never ever getting stateChanged anymore (i.e. my trees send and receive changes!).
See my below test case (uncomment one of the lines to fail the test).
Without calling it, everything seems to work fine! (starting with an empty tree).

Is this a bug or am I getting something wrong here?
Am I using it other than intended?
(If it is not allowed to have ValueTrees synchronized biderectionally, that would be a pity… we would need one input tree and one output tree…)

If it is a bug, I can file an issue with this test case.

#include "../JuceLibraryCode/JuceHeader.h"

// create 2 ValueTrees
ValueTree treeA("A"), treeB("B");

// Simple Synchroniser just applying all changes to a specified other tree
class ValueTreeSyncTest : public ValueTreeSynchroniser {
    ValueTreeSyncTest(String name, ValueTree& valueTree, ValueTree& target) : ValueTreeSynchroniser(valueTree), 
        target(&target), name(name) {

    ValueTree * target;
    String name;
    void stateChanged(const void * encodedChange, size_t encodedChangeSize)
       Logger::outputDebugString("Apply from " + name + " to other tree...");
       ValueTreeSynchroniser::applyChange(*target, encodedChange, encodedChangeSize, nullptr);

// create 2 Syncers to have bidirectional sync
ValueTreeSyncTest syncA ("treeA", treeA, treeB), syncB ("treeB", treeB, treeA);

int main (int argc, char* argv[])
    // if you uncomment one of these, the according tree will never receive stateChanged anymore...

    // adding properties works fine
    Logger::outputDebugString("# Set property testA on treeA");
    treeA.setProperty("testA", "valA", nullptr);
    jassert (treeB.hasProperty("testA"));
    Logger::outputDebugString("# Set property testB on treeB");
    treeB.setProperty("testB", "valB", nullptr);
    Logger::outputDebugString("# Set property testC on treeA");
    treeA.setProperty("testC", "valC", nullptr);
    Logger::outputDebugString("# Set property testD on treeB");
    treeB.setProperty("testD", "valD", nullptr);
    return 0;
1 Like

We are having a look at this use case and will answer soon. Hang in there…


Hi @Fabian, now that ADC was successfully done (congratulations, wish I had been there, maybe next time!), do you have some time to look into this issue?
It’s not urgent for me, but maybe others would also be interested…



I believe this issue still affects the latest JUCE (5.4.2, at least). I was unable to get a ValueTreeSynchroniser working after running ValueTreeSynchroniser::sendFullSyncCallback().

I was able to fix it locally by changing the code in juce_ValueTreeSynchroniser.cpp, ValueTreeSynchroniser::applyChange that deals with fullSync:

if (type == ValueTreeSynchroniserHelpers::fullSync)
    root.copyPropertiesAndChildrenFrom(ValueTree::readFromStream (input), undoManager);
    return true;

This way, ValueTreeSynchorniser.root isn’t being changed out from under the original target. I’m not sure if this is the correct way to fix it in the long run, however.