ambivalence/Source/PresetManager.cpp

159 lines
5.2 KiB
C++
Raw Normal View History

2026-08-15 15:36:28 +02:00
#include "PresetManager.h"
#include "PluginProcessor.h"
2026-08-15 18:31:51 +02:00
#include "FactoryPresets.h"
2026-08-15 15:36:28 +02:00
PresetManager::PresetManager(FDNReverbAudioProcessor& p)
: processor(p)
{
2026-08-15 18:31:51 +02:00
seedFactoryPresets();
2026-08-15 15:36:28 +02:00
refreshPresetList();
}
2026-08-15 18:31:51 +02:00
// -----------------------------------------------------------------------------
// factory presets
// -----------------------------------------------------------------------------
// embeds Presets/*.ambpreset into the binary, then copies any that are
// missing into the user folder, so the factory set survives fresh installs.
// -----------------------------------------------------------------------------
void PresetManager::seedFactoryPresets()
{
auto folder = getPresetsFolder();
for (int i = 0; i < FactoryPresets::namedResourceListSize; ++i)
{
const auto filename = juce::String::fromUTF8(FactoryPresets::originalFilenames[i]);
auto dest = folder.getChildFile(filename);
if (dest.exists())
continue;
int size = 0;
if (auto* data = FactoryPresets::getNamedResource(FactoryPresets::namedResourceList[i], size))
dest.replaceWithData(data, size);
}
}
2026-08-15 15:36:28 +02:00
// -----------------------------------------------------------------------------
// filesystem
// -----------------------------------------------------------------------------
juce::File PresetManager::getPresetsFolder() const
{
auto folder = juce::File::getSpecialLocation(
juce::File::userDocumentsDirectory)
.getChildFile(kSubFolder);
if (!folder.exists())
folder.createDirectory();
return folder;
}
juce::File PresetManager::getPresetFile(const juce::String& name) const
{
return getPresetsFolder().getChildFile(name + kExtension);
}
void PresetManager::refreshPresetList()
{
presetNames.clear();
auto files = getPresetsFolder().findChildFiles(
juce::File::findFiles, false,
juce::String("*") + kExtension);
files.sort();
for (const auto& f : files)
presetNames.add(f.getFileNameWithoutExtension());
}
// -----------------------------------------------------------------------------
// save
// -----------------------------------------------------------------------------
// reuses PluginProcessor::getStateInformation() directly,
// so no PluginProcessor changes are needed.
// -----------------------------------------------------------------------------
// --- after changes ---
bool PresetManager::savePreset(const juce::String& name)
{
if (name.isEmpty()) return false;
// * fix: notify the Processor of the name before getStateInformation()
// so getStateInformation() writes the correct name into the ValueTree
processor.setLastSavedPresetName(name);
juce::MemoryBlock data;
processor.getStateInformation(data);
auto file = getPresetFile(name);
if (!file.replaceWithData(data.getData(), data.getSize()))
return false;
currentPresetName = name;
refreshPresetList();
if (onPresetListChanged) onPresetListChanged();
if (onPresetLoaded) onPresetLoaded(name);
return true;
}
// -----------------------------------------------------------------------------
// load
// -----------------------------------------------------------------------------
// reuses PluginProcessor::setStateInformation() directly.
// setStateInformation() sets paramsNeedUpdate=true, so
// the next processBlock() sends the new parameters to the engine.
// -----------------------------------------------------------------------------
bool PresetManager::loadPreset(const juce::String& name)
{
auto file = getPresetFile(name);
if (!file.exists()) return false;
juce::MemoryBlock data;
if (!file.loadFileAsData(data)) return false;
processor.setStateInformation(data.getData(), static_cast<int>(data.getSize()));
// * after loading a preset always normal view (Normal Mode)
if (auto* param = processor.apvts.getParameter("promode"))
param->setValueNotifyingHost(0.0f);
currentPresetName = name;
if (onPresetLoaded) onPresetLoaded(name);
return true;
}
// -----------------------------------------------------------------------------
// delete
// -----------------------------------------------------------------------------
bool PresetManager::deletePreset(const juce::String& name)
{
auto file = getPresetFile(name);
if (!file.exists()) return false;
if (!file.deleteFile()) return false;
if (currentPresetName == name)
currentPresetName.clear();
refreshPresetList();
if (onPresetListChanged) onPresetListChanged();
return true;
}
// -----------------------------------------------------------------------------
// navigation
// -----------------------------------------------------------------------------
int PresetManager::getCurrentPresetIndex() const noexcept
{
return presetNames.indexOf(currentPresetName);
}
void PresetManager::loadPrevPreset()
{
if (presetNames.isEmpty()) return;
int idx = getCurrentPresetIndex();
if (idx <= 0)
idx = presetNames.size();
loadPreset(presetNames[idx - 1]);
}
void PresetManager::loadNextPreset()
{
if (presetNames.isEmpty()) return;
int idx = getCurrentPresetIndex();
if (idx < 0 || idx >= presetNames.size() - 1)
idx = -1;
loadPreset(presetNames[idx + 1]);
}