void NamedValueSet::setFromXmlAttributes (const XmlElement& xml) { clear(); LinkedListPointer<NamedValue>::Appender appender (values); const int numAtts = xml.getNumAttributes(); // xxx inefficient - should write an att iterator.. for (int i = 0; i < numAtts; ++i) { const String& name = xml.getAttributeName (i); const String& value = xml.getAttributeValue (i); if (name.startsWith ("base64:")) { MemoryBlock mb; if (mb.fromBase64Encoding (value)) { appender.append (new NamedValue (name.substring (7), var (mb))); continue; } } appender.append (new NamedValue (name, var (value))); } }
void NamedValueSet::setFromXmlAttributes (const XmlElement& xml) { clear(); LinkedListPointer<NamedValue>::Appender appender (values); const int numAtts = xml.getNumAttributes(); // xxx inefficient - should write an att iterator.. for (int i = 0; i < numAtts; ++i) appender.append (new NamedValue (xml.getAttributeName (i), var (xml.getAttributeValue (i)))); }
ValueTree ValueTree::fromXml (const XmlElement& xml) { ValueTree v (xml.getTagName()); const int numAtts = xml.getNumAttributes(); // xxx inefficient - should write an att iterator.. for (int i = 0; i < numAtts; ++i) v.setProperty (xml.getAttributeName (i), var (xml.getAttributeValue (i)), 0); forEachXmlChildElement (xml, e) { v.addChild (fromXml (*e), -1, 0); }
void InstanceProcessor::setStateInformation (const void* data, int sizeInBytes) { ScopedPointer<XmlElement> xml(getXmlFromBinary(data, sizeInBytes)); if(xml != nullptr) { if(xml->hasTagName("CamomileSettings")) { String name = xml->getStringAttribute("name"); String path = xml->getStringAttribute("path"); if(File::isAbsolutePath(path)) { File file(path + File::separatorString + name); if(!file.exists()) { file = File(m_path + File::separatorString + name); if(!file.exists()) { file = File(File::getCurrentWorkingDirectory().getFullPathName() + File::separatorString + name); if(!file.exists()) { file = File(File::getSpecialLocation(juce::File::SpecialLocationType::userDocumentsDirectory).getFullPathName() + File::separatorString + name); if(!file.exists()) { file = File(path + File::separatorString + name); } } } } loadPatch(name.toStdString(), path.toStdString()); } XmlElement* params = xml->getChildByName(juce::StringRef("params")); if(params) { for(int i = 0; i < params->getNumAttributes(); i++) { int index = getParameterIndex(params->getAttributeName(i)); if(index >= 0) { setParameterNotifyingHost(index, params->getAttributeValue(i).getDoubleValue()); } } } } } }
void MLPluginProcessor::setStateFromXML(const XmlElement& xmlState, bool setViewAttributes) { if (!(xmlState.hasTagName (JucePlugin_Name))) return; if (!(mEngine.getCompileStatus() == MLProc::OK)) return; // TODO revisit need to compile first // getCallbackLock() is in juce_AudioProcessor // process lock is a quick fix. it is here to prevent doParams() from getting called in // process() methods and thereby setting mParamsChanged to false before the real changes take place. // A better alternative would be a lock-free queue of parameter changes. const ScopedLock sl (getCallbackLock()); // only the differences between default parameters and the program state are saved in a program, // so the first step is to set the default parameters. setDefaultParameters(); // get program version of saved state unsigned blobVersion = xmlState.getIntAttribute ("pluginVersion"); unsigned pluginVersion = JucePlugin_VersionCode; if (blobVersion > pluginVersion) { // TODO show error to user MLError() << "MLPluginProcessor::setStateFromXML: saved program version is newer than plugin version!\n"; return; } // try to load scale if a scale attribute exists // TODO auto save all state including this const String scaleDir = xmlState.getStringAttribute ("scaleDir"); // look for old-style dir attribute const String scaleName = xmlState.getStringAttribute ("scaleName"); String fullName; if(scaleName != String::empty) { fullName = scaleName; if(scaleDir != String::empty) { fullName = scaleDir + String("/") + fullName + ".scl"; } } else { fullName = "12-equal"; } std::string fullScaleName(fullName.toUTF8()); setProperty("key_scale", fullScaleName); bool loaded = false; // look for scale under full name with path if(fullScaleName != std::string()) { const MLFilePtr f = mScaleFiles->getFileByName(fullScaleName); if(f != MLFilePtr()) { loadScale(f->mFile); loaded = true; } } if(!loaded) { loadDefaultScale(); } // get preset name saved in blob. when saving from AU host, name will also be set from RestoreState(). const String presetName = xmlState.getStringAttribute ("presetName"); setProperty("preset", std::string(presetName.toUTF8())); /* debug() << "MLPluginProcessor: setStateFromXML: loading program " << presetName << ", version " << std::hex << blobVersion << std::dec << "\n"; MemoryOutputStream myStream; xmlState->writeToStream (myStream, ""); debug() << myStream.toString(); */ /* setCurrentPresetName(presetName.toUTF8()); setCurrentPresetDir(presetDir.toUTF8()); */ // get plugin-specific translation table for updating older versions of data std::map<MLSymbol, MLSymbol> translationTable; // TODO move this into Aalto! // make translation tables based on program version. // if (blobVersion <= 0x00010120) { // translate seq parameters for(unsigned n=0; n<16; ++n) { std::stringstream pName; std::stringstream pName2; pName << "seq_value" << n; pName2 << "seq_pulse" << n; MLSymbol oldSym(pName.str()); MLSymbol newSym = MLSymbol("seq_value#").withFinalNumber(n); MLSymbol oldSym2(pName2.str()); MLSymbol newSym2 = MLSymbol("seq_pulse#").withFinalNumber(n); translationTable[oldSym] = newSym; translationTable[oldSym2] = newSym2; } } if (blobVersion <= 0x00010200) { MLSymbol oldSym = MLSymbol("seq_value"); MLSymbol newSym = MLSymbol("seq_value").withFinalNumber(0); MLSymbol oldSym2 = MLSymbol("seq_pulse"); MLSymbol newSym2 = MLSymbol("seq_pulse").withFinalNumber(0); translationTable[oldSym] = newSym; translationTable[oldSym2] = newSym2; // translate seq parameters for(unsigned n=1; n<16; ++n) { oldSym = MLSymbol("seq_value#").withFinalNumber(n); newSym = MLSymbol("seq_value").withFinalNumber(n); oldSym2 = MLSymbol("seq_pulse#").withFinalNumber(n); newSym2 = MLSymbol("seq_pulse").withFinalNumber(n); translationTable[oldSym] = newSym; translationTable[oldSym2] = newSym2; } } // get params from xml const unsigned numAttrs = xmlState.getNumAttributes(); String patcherInputStr ("patcher_input_"); for(unsigned i=0; i<numAttrs; ++i) { // get name / value pair. const String& attrName = xmlState.getAttributeName(i); const MLParamValue paramVal = xmlState.getDoubleAttribute(attrName); // if not a patcher input setting, if (!attrName.contains(patcherInputStr)) { // see if we have this named parameter in our engine. MLSymbol paramSym = XMLAttrToSymbol(attrName); const int pIdx = getParameterIndex(paramSym); if (pIdx >= 0) { // debug() << "setStateFromXML: <" << paramSym << " = " << paramVal << ">\n"; setPropertyImmediate(paramSym, paramVal); } else // try finding a match through translation table. { //debug() << "Looking for parameter " << paramSym << " in table...\n"; std::map<MLSymbol, MLSymbol>::iterator it; it = translationTable.find(paramSym); if (it != translationTable.end()) { const MLSymbol newSym = translationTable[paramSym]; const int pNewIdx = getParameterIndex(newSym); if (pNewIdx >= 0) { //debug() << "translated parameter to " << newSym << " .\n"; setPropertyImmediate(newSym, paramVal); } else { MLError() << "MLPluginProcessor::setStateFromXML: no such parameter! \n"; } } else { // fail silently on unfound params, because we have deprecated some but they may still // be around in old presets. //debug() << "MLPluginProcessor::setStateFromXML: parameter " << paramSym << " not found!\n"; } } } } // get editor state from XML if(setViewAttributes) { int x = xmlState.getIntAttribute("editor_x"); int y = xmlState.getIntAttribute("editor_y"); int width = xmlState.getIntAttribute("editor_width"); int height = xmlState.getIntAttribute("editor_height"); mEditorRect = MLRect(x, y, width, height); mEditorNumbersOn = xmlState.getIntAttribute("editor_num", 1); mEditorAnimationsOn = xmlState.getIntAttribute("editor_anim", 1); } }