2
0
Fork 0

Rewrite save/load state via JSON.

Remember to update GUI after state changed.
This commit is contained in:
Frits Talbot 2014-08-26 23:24:51 +02:00
parent c75d2a60dd
commit 25dd5a5707
2 changed files with 44 additions and 37 deletions

View file

@ -4,6 +4,8 @@
#include "IntFloatParameter.h" #include "IntFloatParameter.h"
#include "SbiLoader.h" #include "SbiLoader.h"
const char *JuceOplvstiAudioProcessor::PROGRAM_INDEX = "Program Index";
//============================================================================== //==============================================================================
JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor() JuceOplvstiAudioProcessor::JuceOplvstiAudioProcessor()
: i_program(-1) : i_program(-1)
@ -739,62 +741,67 @@ AudioProcessorEditor* JuceOplvstiAudioProcessor::createEditor()
return gui; return gui;
} }
// FIXME: these two funcs and get-/setStateInformation should be replaced by a proper cross-platform archiving API, e.g. eos portable archive or boost text archive
template<class T>
void push(char *&cursor, T value)
{
*reinterpret_cast<T *>(cursor)=value;
cursor+=sizeof(T);
}
template<class T>
void pop(const char *&cursor, T &value)
{
value=*reinterpret_cast<const T *>(cursor);
cursor+=sizeof(T);
}
//============================================================================== //==============================================================================
// JUCE requires that JSON names are valid Identifiers (restricted character set) even though the JSON standard allows any valid string.
// Per http://www.juce.com/forum/topic/problem-spaces-json-identifier jules allowed Strings to bypass the assertion check
// but a regression occured in 4317f60 re-enabling this check, so we need to sanitize the names.
// Technically, the code still works without this, but it will trigger a gargantuan number of assertions hindering effective debugging.
Identifier stringToIdentifier(const String &s)
{
return s.replaceCharacters(" ", "_");
}
void JuceOplvstiAudioProcessor::getStateInformation(MemoryBlock& destData) void JuceOplvstiAudioProcessor::getStateInformation(MemoryBlock& destData)
{ {
destData.ensureSize(sizeof(CURRENT_VERSION)+sizeof(i_program)+sizeof(float) * getNumParameters()); ReferenceCountedObjectPtr<DynamicObject> v(new DynamicObject);
char *cursor = static_cast<char *>(destData.getData()); v->setProperty(stringToIdentifier(PROGRAM_INDEX), i_program);
push(cursor, CURRENT_VERSION);
push(cursor, i_program);
for (int i = 0; i < getNumParameters(); i++) { for (int i = 0; i < getNumParameters(); i++) {
float p = getParameter(i); double p = getParameter(i);
push(cursor, p);
v->setProperty(stringToIdentifier(getParameterName(i)), p);
} }
String s = JSON::toString(v.get());
destData.setSize(s.length());
destData.copyFrom(s.getCharPointer(), 0, destData.getSize());
} }
void JuceOplvstiAudioProcessor::setStateInformation (const void* data, int sizeInBytes) void JuceOplvstiAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{ {
if (sizeInBytes < sizeof(CURRENT_VERSION)) if (sizeInBytes < 1)
return; return;
const char *cursor = static_cast<const char *>(data); const char *first = static_cast<const char *>(data);
const char *end = cursor+sizeInBytes; const char *last = first + sizeInBytes - 1;
int version;
pop(cursor, version); // simple check for JSON data - assume always object
if (*first=='{' && *last=='}')
if (version == CURRENT_VERSION)
{ {
pop(cursor, i_program); // json format
String s(first, sizeInBytes);
var v = JSON::fromString(s);
const int parametersToLoad = std::min<int>(static_cast<int>(std::distance(cursor, end)) / sizeof(float), getNumParameters());
for (int i = 0; i < parametersToLoad; i++)
{ {
float p; var program = v[stringToIdentifier(PROGRAM_INDEX)];
pop(cursor, p); if (!program.isVoid())
setParameter(i, p); i_program = program;
} }
for (int i=0; i<getNumParameters(); ++i)
{
var param = v[stringToIdentifier(getParameterName(i))];
if (!param.isVoid())
setParameter(i, param);
}
updateGuiIfPresent();
return; return;
} }

View file

@ -91,7 +91,7 @@ private:
int i_program; int i_program;
bool velocity; bool velocity;
static const int NO_NOTE=-1; static const int NO_NOTE=-1;
static const int CURRENT_VERSION = 0x09720100; // OPL2 v01.00 magic static const char *PROGRAM_INDEX;
int active_notes[Hiopl::CHANNELS+1]; // keyed by channel int active_notes[Hiopl::CHANNELS+1]; // keyed by channel
std::deque<int> available_channels; // most recently freed at end std::deque<int> available_channels; // most recently freed at end
std::deque<int> used_channels; // most recently used at end std::deque<int> used_channels; // most recently used at end