void MLPluginProcessor::loadStateFromPath(const std::string& path) { if(path != std::string()) { const MLFilePtr f = mPresetFiles->getFileByName(path); if(f != MLFilePtr()) { loadStateFromFile(f->mFile); std::string shortPath = stripExtension(path); setProperty("preset", shortPath); } } }
void MLFile::insert(const std::string& path, MLFilePtr f) { // debug() << "INSERTING: " << path << "\n"; int len = path.length(); if(len) { int b = path.find_first_of("/"); if(b == std::string::npos) { // leaf, insert file here creating dir if needed // debug() << " LEAF: " << path << "\n\n" ; // add leaf file to map mFiles[path] = f; } else { std::string firstDir = path.substr(0, b); std::string restOfDirs = path.substr(b + 1, len - b); // debug() << " FIRST: " << firstDir << ", REST " << restOfDirs << "\n"; // find or add first dir if(firstDir == "") { MLError() << "MLFile::insert: empty directory name!\n"; } else { if(mFiles.find(firstDir) == mFiles.end()) { mFiles[firstDir] = MLFilePtr(new MLFile(firstDir)); } mFiles[firstDir]->insert(restOfDirs, f); } } } else { MLError() << "MLFile::insert: empty file name!\n"; } }
MLFilePtr MLFile::find(const std::string& path) { // debug() << "FINDING: " << path << "\n"; int len = path.length(); if(len) { int b = path.find_first_of("/"); if(b == std::string::npos) { // end of path, find short name here or return fail. //debug() << " path end: " << path << "\n\n" ; nameToFileMap::const_iterator it; it = mFiles.find(path); if(it != mFiles.end()) { // return the found file. return it->second; } else { //debug() << "MLFile::find: did not find " << path << " in :\n"; nameToFileMap::const_iterator it2; for(it2 = mFiles.begin(); it2 != mFiles.end(); ++it2) { //debug() << it2->first << ", "; } //debug() << "\n"; return MLFilePtr(); } } else { std::string firstDir = path.substr(0, b); std::string restOfDirs = path.substr(b + 1, len - b); //debug() << " FIRST: " << firstDir << ", REST " << restOfDirs << "\n"; // find file matching first dir if(firstDir == "") { MLError() << "MLFile::find: empty directory name!\n"; } else if(mFiles.find(firstDir) != mFiles.end()) { // look for rest of dirs in found non-leaf file return mFiles[firstDir]->find(restOfDirs); } else { return MLFilePtr(); } } } else { MLError() << "MLFile::find: empty file name!\n"; } return MLFilePtr(); }
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); } }