mirror of
https://codeberg.org/armin/trommelkiste.git
synced 2026-09-01 04:10:46 +02:00
Add user preset save/load to the preset menu
This commit is contained in:
parent
ff96ab1a69
commit
143e0bac76
4 changed files with 212 additions and 28 deletions
|
|
@ -13,6 +13,7 @@ TrommelkisteProcessor::TrommelkisteProcessor()
|
|||
formatManager.registerBasicFormats();
|
||||
scanSamples();
|
||||
loadKit(0);
|
||||
refreshUserPresets();
|
||||
}
|
||||
|
||||
TrommelkisteProcessor::~TrommelkisteProcessor() {}
|
||||
|
|
@ -605,19 +606,12 @@ static const TrommelkisteProcessor::Kit kits[] = {
|
|||
|
||||
const TrommelkisteProcessor::Kit* TrommelkisteProcessor::getKitList() { return kits; }
|
||||
int TrommelkisteProcessor::getNumKits() const { return 4; }
|
||||
juce::String TrommelkisteProcessor::getCurrentKitName() const
|
||||
{
|
||||
if (currentKitIndex >= 0 && currentKitIndex < getNumKits())
|
||||
return kits[currentKitIndex].name;
|
||||
return {};
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::loadKit(int index)
|
||||
{
|
||||
if (index < 0 || index >= getNumKits())
|
||||
return;
|
||||
|
||||
currentKitIndex = index;
|
||||
const auto& kit = kits[index];
|
||||
|
||||
for (int t = 0; t < NUM_TRACKS; ++t)
|
||||
|
|
@ -647,18 +641,161 @@ void TrommelkisteProcessor::loadKit(int index)
|
|||
}
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::nextKit()
|
||||
juce::String TrommelkisteProcessor::getPresetName(int index) const
|
||||
{
|
||||
int idx = currentKitIndex + 1;
|
||||
if (idx >= getNumKits()) idx = 0;
|
||||
loadKit(idx);
|
||||
if (index < 0 || index >= getNumPresets())
|
||||
return {};
|
||||
if (index < getNumKits())
|
||||
return kits[index].name;
|
||||
return userPresets[index - getNumKits()].name;
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::prevKit()
|
||||
void TrommelkisteProcessor::loadPreset(int index)
|
||||
{
|
||||
int idx = currentKitIndex - 1;
|
||||
if (idx < 0) idx = getNumKits() - 1;
|
||||
loadKit(idx);
|
||||
if (index < 0 || index >= getNumPresets())
|
||||
return;
|
||||
|
||||
currentPresetIndex = index;
|
||||
if (index < getNumKits())
|
||||
loadKit(index);
|
||||
else
|
||||
loadUserPreset(index - getNumKits());
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::nextPreset()
|
||||
{
|
||||
const int n = getNumPresets();
|
||||
if (n <= 0) return;
|
||||
loadPreset((currentPresetIndex + 1) % n);
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::prevPreset()
|
||||
{
|
||||
const int n = getNumPresets();
|
||||
if (n <= 0) return;
|
||||
loadPreset((currentPresetIndex + n - 1) % n);
|
||||
}
|
||||
|
||||
// ── User presets ───────────────────────────────────────────────
|
||||
|
||||
static juce::File getUserPresetDirectory()
|
||||
{
|
||||
return juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory)
|
||||
.getChildFile("Trommelkiste").getChildFile("Presets");
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::refreshUserPresets()
|
||||
{
|
||||
userPresets.clear();
|
||||
|
||||
auto dir = getUserPresetDirectory();
|
||||
if (! dir.isDirectory())
|
||||
return;
|
||||
|
||||
juce::Array<juce::File> files =
|
||||
dir.findChildFiles(juce::File::findFiles, false, "*.trommelpreset");
|
||||
files.sort();
|
||||
|
||||
for (const auto& f : files)
|
||||
{
|
||||
auto xml = juce::XmlDocument::parse(f);
|
||||
if (xml == nullptr)
|
||||
continue;
|
||||
|
||||
UserPreset p;
|
||||
p.name = xml->getStringAttribute("name");
|
||||
if (p.name.isEmpty())
|
||||
p.name = f.getFileNameWithoutExtension();
|
||||
p.file = f;
|
||||
userPresets.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::saveUserPreset(const juce::String& name)
|
||||
{
|
||||
auto dir = getUserPresetDirectory();
|
||||
dir.createDirectory();
|
||||
|
||||
juce::String safeName = name;
|
||||
safeName = safeName.replaceCharacter('\\', '_').replaceCharacter('/', '_');
|
||||
auto file = dir.getChildFile(safeName + ".trommelpreset");
|
||||
|
||||
auto state = apvts.copyState();
|
||||
state.setProperty("name", name, nullptr);
|
||||
|
||||
juce::ValueTree samples("Samples");
|
||||
for (int i = 0; i < NUM_TRACKS; ++i)
|
||||
{
|
||||
juce::ValueTree tr("Track" + juce::String(i));
|
||||
tr.setProperty("path", tracks[i].filePath, nullptr);
|
||||
tr.setProperty("sampleIndex", currentSampleIndex[i], nullptr);
|
||||
if (currentSampleIndex[i] >= 0 && currentSampleIndex[i] < trackSamples[i].size())
|
||||
tr.setProperty("sampleName", trackSamples[i][currentSampleIndex[i]].name, nullptr);
|
||||
samples.appendChild(tr, nullptr);
|
||||
}
|
||||
state.appendChild(samples, nullptr);
|
||||
|
||||
std::unique_ptr<juce::XmlElement> xml(state.createXml());
|
||||
if (! xml->writeToFile(file, {}))
|
||||
return;
|
||||
|
||||
refreshUserPresets();
|
||||
|
||||
for (int i = 0; i < userPresets.size(); ++i)
|
||||
{
|
||||
if (userPresets[i].file == file)
|
||||
{
|
||||
currentPresetIndex = getNumKits() + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrommelkisteProcessor::loadUserPreset(int index)
|
||||
{
|
||||
if (index < 0 || index >= userPresets.size())
|
||||
return;
|
||||
|
||||
std::unique_ptr<juce::XmlElement> xml = juce::XmlDocument::parse(userPresets[index].file);
|
||||
if (xml == nullptr)
|
||||
return;
|
||||
|
||||
auto state = juce::ValueTree::fromXml(*xml);
|
||||
apvts.replaceState(state);
|
||||
|
||||
auto samples = state.getChildWithName("Samples");
|
||||
if (samples.isValid())
|
||||
{
|
||||
for (int i = 0; i < NUM_TRACKS; ++i)
|
||||
{
|
||||
auto tr = samples.getChildWithName("Track" + juce::String(i));
|
||||
if (! tr.isValid())
|
||||
continue;
|
||||
|
||||
auto path = tr.getProperty("path", "").toString();
|
||||
auto sampleName = tr.getProperty("sampleName", "").toString();
|
||||
|
||||
if (path.isNotEmpty())
|
||||
{
|
||||
loadSample(i, juce::File(path));
|
||||
currentSampleIndex[i] = (int)tr.getProperty("sampleIndex", -1);
|
||||
}
|
||||
else if (sampleName.isNotEmpty())
|
||||
{
|
||||
int found = -1;
|
||||
for (int s = 0; s < trackSamples[i].size(); ++s)
|
||||
{
|
||||
if (trackSamples[i][s].name.equalsIgnoreCase(sampleName))
|
||||
{
|
||||
found = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found >= 0)
|
||||
loadSampleByIndex(i, found);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
juce::AudioProcessorEditor* TrommelkisteProcessor::createEditor()
|
||||
|
|
@ -670,7 +807,7 @@ void TrommelkisteProcessor::getStateInformation(juce::MemoryBlock& destData)
|
|||
{
|
||||
auto state = apvts.copyState();
|
||||
|
||||
state.setProperty("kitIndex", currentKitIndex, nullptr);
|
||||
state.setProperty("presetIndex", currentPresetIndex, nullptr);
|
||||
|
||||
juce::ValueTree samples("Samples");
|
||||
for (int i = 0; i < NUM_TRACKS; ++i)
|
||||
|
|
@ -697,7 +834,8 @@ void TrommelkisteProcessor::setStateInformation(const void* data, int sizeInByte
|
|||
auto state = juce::ValueTree::fromXml(*xml);
|
||||
apvts.replaceState(state);
|
||||
|
||||
currentKitIndex = (int)state.getProperty("kitIndex", 0);
|
||||
currentPresetIndex = (int)state.getProperty("presetIndex",
|
||||
state.getProperty("kitIndex", 0));
|
||||
|
||||
auto samples = state.getChildWithName("Samples");
|
||||
if (samples.isValid())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue