Skip to content

Commit

Permalink
Future Dev 08: Program: fix redirection when loading preset from host
Browse files Browse the repository at this point in the history
Hosts support saving current plugin state as user presets. And some
hosts like REAPER will set program index to 0 when loading them. At this
time, if plugin still load factory program #0, users won't get their own
presets. Such a "redirection" is unexpected.

One of the best solutions is: reserve factory program #0 as "initial
program". No matter when host or user set to this value, plugin state
will always stays untouched.

Then, correspondingly, move factory programs forward by one item. Always
keep in mind that programs displayed in host's menu is independent, as
it's enumerated by effGetProgramNameIndexed when loading plugin instance.

So, we can just let factory programs display from item amsynth#1, then when user
choose factory programs, reduce choice index by 1 in effSetProgram, and
this is the actual preset index kept by Amsynth preset manager.
  • Loading branch information
AnClark committed Mar 28, 2022
1 parent b65254c commit 1684f7e
Showing 1 changed file with 26 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/amsynth_vst_imgui.cpp
Expand Up @@ -159,9 +159,19 @@ static intptr_t dispatcher(AEffect *effect, int opcode, int index, intptr_t val,
// Stop all sound before applying preset
panic_on_dsp_side(effect);

// Program #0 is reserved for default / user-defined presets.
// Do not apply factory program at this time.
if (val <= 0) {
plugin->presetName = "Initial";
plugin->programNumber = 0;
return 1;
}

// Obtain bank and preset
auto &bank = PresetController::getPresetBanks().at(val / kPresetsPerBank);
auto &preset = bank.presets[val % kPresetsPerBank];
// The corresponding factory program index is just by one item before host's index.
int actual_index = val - 1;
auto &bank = PresetController::getPresetBanks().at(actual_index / kPresetsPerBank);
auto &preset = bank.presets[actual_index % kPresetsPerBank];

// Keep current preset name / index via our own variables
plugin->presetName = preset.getName();
Expand Down Expand Up @@ -199,12 +209,24 @@ static intptr_t dispatcher(AEffect *effect, int opcode, int index, intptr_t val,
// Host will query every built-in program by invoking effGetProgramNameIndexed.
// @param index: The program index where the host queries

// Reserve program #0 as default/customized program as "Initial",
// so that users can load user-defined presets from host instead of always being redirected to factory program #0.
// NOTE: Hosts like REAPER will set index to 0 when loading user-defined presets.
if (index <= 0) {
strncpy((char *)ptr, "Initial", 24);
return 1;
}

// Check if there were preset files or not
// If you don't check, host will crash if no preset was installed
if (PresetController::getPresetBanks().size()) {
// As #0 is "Initial", other factory programs should be put into the next hole.
// "index" is host's display index, and "actual_index" is the corresponding bank's index.
int actual_index = index - 1;

// Obtain bank and preset
auto &bank = PresetController::getPresetBanks().at(index / kPresetsPerBank);
auto &preset = bank.presets[index % kPresetsPerBank];
auto &bank = PresetController::getPresetBanks().at(actual_index / kPresetsPerBank);
auto &preset = bank.presets[actual_index % kPresetsPerBank];

// Set current obtained preset name, then show the name on host
plugin->presetName = preset.getName();
Expand Down

0 comments on commit 1684f7e

Please sign in to comment.