Storing and loading objects in ValueTree


#1

My apologies if this has been discussed before, but I’d like to know, is there a way to store non-Value objects inside a ValueTree?
I’m asking this because I want to store a MidiFile in a ValueTree and then save the tree as xml.
With my current implementation I have two different trees, one as a ValueTree (holding application data) and the other as Xml (holding midi stuff and plugins states), and they get joined during the saving process as MemoryBlocks.
It would be great to keep just one tree…


#2

You can store any kind of data in a ValueTree if you make it (or wrap it inside) a ReferenceCountedObject. The only problem is that you need to do a bit of extra work in serialising the tree - you can’t use the built-in serialisation functionality as it doesn’t know how to cope with such objects. So, it’s quite easy to have it all as a single tree at run-time, but you’ll still need to have some process of separating that data out for saving. What that process is, well, that’s entirely down to you - there are a prillion ways you could do it!


#3

Thanks! I totally forgot about the possibility to use ref counted objects with the var class.
Now it’s time to think about a way to separate the objects during the saving process :wink:


#4

[quote=“masshacker”]Thanks! I totally forgot about the possibility to use ref counted objects with the var class.
Now it’s time to think about a way to separate the objects during the saving process :wink:[/quote]

Recursively walk the tree, and for each node if it is a basic type then serialize it normally. If it is a reference counted object, then use dynamic_cast to turn it into a pointer to your own base class that implements some virtual method serialize(), call the method, and party on.


#5

Yeah that’s the first thing that came to mind.


#6

Jules, I don't suppose that in your ValueTree work you've started looking at building serialization into the Xml translation? I've done it here, but it'd be a lot neater if it was actually part of the library.


#7

What do you mean by serialisation?


#8

It's a really dry topic.  When I get back to making noises I'm going to be happy. 

I mean ths kind of serialization (http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html)  taking the ReferenceCountedObjects in the ValueTree and converting them into something that can be saved and restored. 

I've popped my whole configuration, including the audio data, gui design, parameters and current settings into a ValueTree (which is now synced to the audio thread).  

Now I want to save part of the tree as the plugin configuration, part as the current preset and so on.  So I want to call one of the ValueTree export functions.  

But the plugin I'm working on handles audio files.  So there's a bunch of ReferenceCountedObjects in there which just cause asserts. 

So I'm preprocessing the tree, calling a serialize function on any ReferenceCountedObjects and having that return a new ValueTree which I swap in.  Then calling toXmlString() or whatever on ValueTree to create the export function. 

The load works in reverse but with a factory class type set-up which parses the ValueTree and recreates the ReferenceCountedObjects *, deleting the serialized versions.

 


#9

Well, I didn't really have any plans for anything along those lines. It'd be easy enough to create a virtual class, e.g. "Serialisable" which your ReferenceCountedObjects could inherit, which would have a method to write itself to a stream, but re-creating those when re-loading would require a lot more messing-about with factory objects and version/error handling.

My general approach in apps like Tracktion is to simply not have ReferenceCountedObjects in the ValueTree - we treat the ValueTree as a direct representation of the saved file contents, so any data that we want to save needs to go into the tree in the format it'll be saved in - i.e. plain old strings/arrays/numbers etc. Then we have temporary classes that wrap parts of the ValueTree and create objects based on this data which we work with, saving their state to/from the ValueTree when necessary.


#10

Ah - okay - I wondered why you hadn't come across the problem and solved it for me :)

I'm using the ValueTree to add key resources too and have them magically shared with the other thread, then saving the conversion to straight data for when saving happens. 

I think it probably works out at about the same effort in the end.  Though it makes the ValueTree to audio thread stuff I"m doing very straightforward.