From 206271b9a37d076790de886edf501ac006365172 Mon Sep 17 00:00:00 2001 From: Oleg Samarin Date: Mon, 24 Feb 2025 22:30:30 +0300 Subject: [PATCH] Intermediate commit --- src/grandorgue/CMakeLists.txt | 1 + src/grandorgue/combinations/GOSetter.cpp | 622 ++++++++++++++---- src/grandorgue/control/GOElementCreator.cpp | 21 +- src/grandorgue/control/GOElementCreator.h | 6 +- src/grandorgue/midi/objects/GOMidiObject.cpp | 9 +- src/grandorgue/midi/objects/GOMidiObject.h | 8 + .../midi/objects/GOMidiObjectContext.cpp | 28 + .../midi/objects/GOMidiObjectContext.h | 42 ++ src/grandorgue/model/GOManual.cpp | 23 +- src/grandorgue/model/GOManual.h | 12 +- src/grandorgue/model/GOOrganModel.cpp | 15 +- src/grandorgue/model/GOOrganModel.h | 1 - 12 files changed, 645 insertions(+), 143 deletions(-) create mode 100644 src/grandorgue/midi/objects/GOMidiObjectContext.cpp create mode 100644 src/grandorgue/midi/objects/GOMidiObjectContext.h diff --git a/src/grandorgue/CMakeLists.txt b/src/grandorgue/CMakeLists.txt index a8217b4ea..3d53b31df 100644 --- a/src/grandorgue/CMakeLists.txt +++ b/src/grandorgue/CMakeLists.txt @@ -142,6 +142,7 @@ loader/cache/GOCacheCleaner.cpp loader/cache/GOCacheWriter.cpp midi/dialog-creator/GOMidiDialogCreatorProxy.cpp midi/objects/GOMidiObject.cpp +midi/objects/GOMidiObjectContext.cpp midi/objects/GOMidiObjectWithDivision.cpp midi/objects/GOMidiObjectWithShortcut.cpp midi/objects/GOMidiReceivingSendingObject.cpp diff --git a/src/grandorgue/combinations/GOSetter.cpp b/src/grandorgue/combinations/GOSetter.cpp index bd2dc9956..71eb27335 100644 --- a/src/grandorgue/combinations/GOSetter.cpp +++ b/src/grandorgue/combinations/GOSetter.cpp @@ -20,6 +20,7 @@ #include "control/GOCallbackButtonControl.h" #include "control/GODivisionalButtonControl.h" #include "control/GOGeneralButtonControl.h" +#include "midi/objects/GOMidiObjectContext.h" #include "model/GODivisionalCoupler.h" #include "model/GOManual.h" #include "yaml/go-wx-yaml.h" @@ -166,123 +167,522 @@ const wxString GOSetter::GROUP_LOAD_FILE = wxT("SetterLoadFile"); const wxString GOSetter::GROUP_SAVE_FILE = wxT("SetterSaveFile"); const wxString GOSetter::GROUP_SAVE_SETTINGS = wxT("SetterSave"); +static const GOMidiObjectContext MIDI_CONTEXT_SETTER( + wxT("Setter"), _("Setter")); + const struct GOElementCreator::ButtonDefinitionEntry GOSetter::m_element_types[] = { - {wxT("Prev"), ID_SETTER_PREV, true, true, false}, - {wxT("Next"), ID_SETTER_NEXT, true, true, false}, - {wxT("Set"), ID_SETTER_SET, true, false, false}, - {wxT("M1"), ID_SETTER_M1, true, true, false}, - {wxT("M10"), ID_SETTER_M10, true, true, false}, - {wxT("M100"), ID_SETTER_M100, true, true, false}, - {wxT("P1"), ID_SETTER_P1, true, true, false}, - {wxT("P10"), ID_SETTER_P10, true, true, false}, - {wxT("P100"), ID_SETTER_P100, true, true, false}, - {wxT("Current"), ID_SETTER_CURRENT, true, true, false}, - {wxT("Home"), ID_SETTER_HOME, true, true, false}, - {wxT("GC"), ID_SETTER_GC, true, true, false}, - {wxT("L1"), ID_SETTER_L1, true, true, false}, - {wxT("L2"), ID_SETTER_L2, true, true, false}, - {wxT("L3"), ID_SETTER_L3, true, true, false}, - {wxT("L4"), ID_SETTER_L4, true, true, false}, - {wxT("L5"), ID_SETTER_L5, true, true, false}, - {wxT("L6"), ID_SETTER_L6, true, true, false}, - {wxT("L7"), ID_SETTER_L7, true, true, false}, - {wxT("L8"), ID_SETTER_L8, true, true, false}, - {wxT("L9"), ID_SETTER_L9, true, true, false}, - {wxT("L0"), ID_SETTER_L0, true, true, false}, - {wxT("Regular"), ID_SETTER_REGULAR, true, true, false}, - {wxT("Scope"), ID_SETTER_SCOPE, true, true, false}, - {wxT("Scoped"), ID_SETTER_SCOPED, true, true, false}, - {wxT("Full"), ID_SETTER_FULL, true, false, false}, - {wxT("Insert"), ID_SETTER_INSERT, true, true, false}, - {wxT("Delete"), ID_SETTER_DELETE, true, true, false}, - {KEY_REFRESH_FILES, ID_SETTER_REFRESH_FILES, true, true, false}, - {KEY_PREV_FILE, ID_SETTER_PREV_FILE, true, true, false}, - {KEY_NEXT_FILE, ID_SETTER_NEXT_FILE, true, true, false}, - {KEY_LOAD_FILE, ID_SETTER_LOAD_FILE, true, true, false}, - {KEY_SAVE_FILE, ID_SETTER_SAVE_FILE, true, true, false}, - {wxT("General01"), ID_SETTER_GENERAL00, true, true, true}, - {wxT("General02"), ID_SETTER_GENERAL01, true, true, true}, - {wxT("General03"), ID_SETTER_GENERAL02, true, true, true}, - {wxT("General04"), ID_SETTER_GENERAL03, true, true, true}, - {wxT("General05"), ID_SETTER_GENERAL04, true, true, true}, - {wxT("General06"), ID_SETTER_GENERAL05, true, true, true}, - {wxT("General07"), ID_SETTER_GENERAL06, true, true, true}, - {wxT("General08"), ID_SETTER_GENERAL07, true, true, true}, - {wxT("General09"), ID_SETTER_GENERAL08, true, true, true}, - {wxT("General10"), ID_SETTER_GENERAL09, true, true, true}, - {wxT("General11"), ID_SETTER_GENERAL10, true, true, true}, - {wxT("General12"), ID_SETTER_GENERAL11, true, true, true}, - {wxT("General13"), ID_SETTER_GENERAL12, true, true, true}, - {wxT("General14"), ID_SETTER_GENERAL13, true, true, true}, - {wxT("General15"), ID_SETTER_GENERAL14, true, true, true}, - {wxT("General16"), ID_SETTER_GENERAL15, true, true, true}, - {wxT("General17"), ID_SETTER_GENERAL16, true, true, true}, - {wxT("General18"), ID_SETTER_GENERAL17, true, true, true}, - {wxT("General19"), ID_SETTER_GENERAL18, true, true, true}, - {wxT("General20"), ID_SETTER_GENERAL19, true, true, true}, - {wxT("General21"), ID_SETTER_GENERAL20, true, true, true}, - {wxT("General22"), ID_SETTER_GENERAL21, true, true, true}, - {wxT("General23"), ID_SETTER_GENERAL22, true, true, true}, - {wxT("General24"), ID_SETTER_GENERAL23, true, true, true}, - {wxT("General25"), ID_SETTER_GENERAL24, true, true, true}, - {wxT("General26"), ID_SETTER_GENERAL25, true, true, true}, - {wxT("General27"), ID_SETTER_GENERAL26, true, true, true}, - {wxT("General28"), ID_SETTER_GENERAL27, true, true, true}, - {wxT("General29"), ID_SETTER_GENERAL28, true, true, true}, - {wxT("General30"), ID_SETTER_GENERAL29, true, true, true}, - {wxT("General31"), ID_SETTER_GENERAL30, true, true, true}, - {wxT("General32"), ID_SETTER_GENERAL31, true, true, true}, - {wxT("General33"), ID_SETTER_GENERAL32, true, true, true}, - {wxT("General34"), ID_SETTER_GENERAL33, true, true, true}, - {wxT("General35"), ID_SETTER_GENERAL34, true, true, true}, - {wxT("General36"), ID_SETTER_GENERAL35, true, true, true}, - {wxT("General37"), ID_SETTER_GENERAL36, true, true, true}, - {wxT("General38"), ID_SETTER_GENERAL37, true, true, true}, - {wxT("General39"), ID_SETTER_GENERAL38, true, true, true}, - {wxT("General40"), ID_SETTER_GENERAL39, true, true, true}, - {wxT("General41"), ID_SETTER_GENERAL40, true, true, true}, - {wxT("General42"), ID_SETTER_GENERAL41, true, true, true}, - {wxT("General43"), ID_SETTER_GENERAL42, true, true, true}, - {wxT("General44"), ID_SETTER_GENERAL43, true, true, true}, - {wxT("General45"), ID_SETTER_GENERAL44, true, true, true}, - {wxT("General46"), ID_SETTER_GENERAL45, true, true, true}, - {wxT("General47"), ID_SETTER_GENERAL46, true, true, true}, - {wxT("General48"), ID_SETTER_GENERAL47, true, true, true}, - {wxT("General49"), ID_SETTER_GENERAL48, true, true, true}, - {wxT("General50"), ID_SETTER_GENERAL49, true, true, true}, - - {wxT("GeneralPrev"), ID_SETTER_GENERAL_PREV, true, true, false}, - {wxT("GeneralNext"), ID_SETTER_GENERAL_NEXT, true, true, false}, - - {wxT("PitchP1"), ID_SETTER_PITCH_P1, true, true, false}, - {wxT("PitchP10"), ID_SETTER_PITCH_P10, true, true, false}, - {wxT("PitchP100"), ID_SETTER_PITCH_P100, true, true, false}, - {wxT("PitchM1"), ID_SETTER_PITCH_M1, true, true, false}, - {wxT("PitchM10"), ID_SETTER_PITCH_M10, true, true, false}, - {wxT("PitchM100"), ID_SETTER_PITCH_M100, true, true, false}, - {wxT("TemperamentPrev"), ID_SETTER_TEMPERAMENT_PREV, true, true, false}, - {wxT("TemperamentNext"), ID_SETTER_TEMPERAMENT_NEXT, true, true, false}, - {wxT("TransposeDown"), ID_SETTER_TRANSPOSE_DOWN, true, true, false}, - {wxT("TransposeUp"), ID_SETTER_TRANSPOSE_UP, true, true, false}, - - {KEY_SAVE_SETTINGS, ID_SETTER_SAVE_SETTINGS, true, true, false}, - {KEY_ON_STATE, ID_SETTER_ON, false, true, false}, - - {wxT("CrescendoA"), ID_SETTER_CRESCENDO_A, true, true, false}, - {wxT("CrescendoB"), ID_SETTER_CRESCENDO_B, true, true, false}, - {wxT("CrescendoC"), ID_SETTER_CRESCENDO_C, true, true, false}, - {wxT("CrescendoD"), ID_SETTER_CRESCENDO_D, true, true, false}, - {wxT("CrescendoPrev"), ID_SETTER_CRESCENDO_PREV, true, true, false}, - {wxT("CrescendoCurrent"), ID_SETTER_CRESCENDO_CURRENT, true, true, false}, - {wxT("CrescendoNext"), ID_SETTER_CRESCENDO_NEXT, true, true, false}, + {wxT("Prev"), ID_SETTER_PREV, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Next"), ID_SETTER_NEXT, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Set"), ID_SETTER_SET, true, false, false, &MIDI_CONTEXT_SETTER}, + {wxT("M1"), ID_SETTER_M1, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("M10"), ID_SETTER_M10, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("M100"), ID_SETTER_M100, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("P1"), ID_SETTER_P1, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("P10"), ID_SETTER_P10, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("P100"), ID_SETTER_P100, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Current"), + ID_SETTER_CURRENT, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("Home"), ID_SETTER_HOME, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("GC"), ID_SETTER_GC, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L1"), ID_SETTER_L1, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L2"), ID_SETTER_L2, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L3"), ID_SETTER_L3, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L4"), ID_SETTER_L4, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L5"), ID_SETTER_L5, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L6"), ID_SETTER_L6, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L7"), ID_SETTER_L7, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L8"), ID_SETTER_L8, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L9"), ID_SETTER_L9, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("L0"), ID_SETTER_L0, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Regular"), + ID_SETTER_REGULAR, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("Scope"), ID_SETTER_SCOPE, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Scoped"), ID_SETTER_SCOPED, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Full"), ID_SETTER_FULL, true, false, false, &MIDI_CONTEXT_SETTER}, + {wxT("Insert"), ID_SETTER_INSERT, true, true, false, &MIDI_CONTEXT_SETTER}, + {wxT("Delete"), ID_SETTER_DELETE, true, true, false, &MIDI_CONTEXT_SETTER}, + {KEY_REFRESH_FILES, + ID_SETTER_REFRESH_FILES, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {KEY_PREV_FILE, + ID_SETTER_PREV_FILE, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {KEY_NEXT_FILE, + ID_SETTER_NEXT_FILE, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {KEY_LOAD_FILE, + ID_SETTER_LOAD_FILE, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {KEY_SAVE_FILE, + ID_SETTER_SAVE_FILE, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("General01"), + ID_SETTER_GENERAL00, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General02"), + ID_SETTER_GENERAL01, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General03"), + ID_SETTER_GENERAL02, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General04"), + ID_SETTER_GENERAL03, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General05"), + ID_SETTER_GENERAL04, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General06"), + ID_SETTER_GENERAL05, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General07"), + ID_SETTER_GENERAL06, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General08"), + ID_SETTER_GENERAL07, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General09"), + ID_SETTER_GENERAL08, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General10"), + ID_SETTER_GENERAL09, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General11"), + ID_SETTER_GENERAL10, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General12"), + ID_SETTER_GENERAL11, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General13"), + ID_SETTER_GENERAL12, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General14"), + ID_SETTER_GENERAL13, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General15"), + ID_SETTER_GENERAL14, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General16"), + ID_SETTER_GENERAL15, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General17"), + ID_SETTER_GENERAL16, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General18"), + ID_SETTER_GENERAL17, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General19"), + ID_SETTER_GENERAL18, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General20"), + ID_SETTER_GENERAL19, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General21"), + ID_SETTER_GENERAL20, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General22"), + ID_SETTER_GENERAL21, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General23"), + ID_SETTER_GENERAL22, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General24"), + ID_SETTER_GENERAL23, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General25"), + ID_SETTER_GENERAL24, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General26"), + ID_SETTER_GENERAL25, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General27"), + ID_SETTER_GENERAL26, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General28"), + ID_SETTER_GENERAL27, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General29"), + ID_SETTER_GENERAL28, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General30"), + ID_SETTER_GENERAL29, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General31"), + ID_SETTER_GENERAL30, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General32"), + ID_SETTER_GENERAL31, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General33"), + ID_SETTER_GENERAL32, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General34"), + ID_SETTER_GENERAL33, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General35"), + ID_SETTER_GENERAL34, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General36"), + ID_SETTER_GENERAL35, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General37"), + ID_SETTER_GENERAL36, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General38"), + ID_SETTER_GENERAL37, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General39"), + ID_SETTER_GENERAL38, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General40"), + ID_SETTER_GENERAL39, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General41"), + ID_SETTER_GENERAL40, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General42"), + ID_SETTER_GENERAL41, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General43"), + ID_SETTER_GENERAL42, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General44"), + ID_SETTER_GENERAL43, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General45"), + ID_SETTER_GENERAL44, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General46"), + ID_SETTER_GENERAL45, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General47"), + ID_SETTER_GENERAL46, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General48"), + ID_SETTER_GENERAL47, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General49"), + ID_SETTER_GENERAL48, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("General50"), + ID_SETTER_GENERAL49, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + + {wxT("GeneralPrev"), + ID_SETTER_GENERAL_PREV, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("GeneralNext"), + ID_SETTER_GENERAL_NEXT, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + + {wxT("PitchP1"), + ID_SETTER_PITCH_P1, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PitchP10"), + ID_SETTER_PITCH_P10, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PitchP100"), + ID_SETTER_PITCH_P100, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PitchM1"), + ID_SETTER_PITCH_M1, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PitchM10"), + ID_SETTER_PITCH_M10, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PitchM100"), + ID_SETTER_PITCH_M100, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("TemperamentPrev"), + ID_SETTER_TEMPERAMENT_PREV, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("TemperamentNext"), + ID_SETTER_TEMPERAMENT_NEXT, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("TransposeDown"), + ID_SETTER_TRANSPOSE_DOWN, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("TransposeUp"), + ID_SETTER_TRANSPOSE_UP, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + + {KEY_SAVE_SETTINGS, + ID_SETTER_SAVE_SETTINGS, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {KEY_ON_STATE, ID_SETTER_ON, false, true, false, &MIDI_CONTEXT_SETTER}, + + {wxT("CrescendoA"), + ID_SETTER_CRESCENDO_A, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoB"), + ID_SETTER_CRESCENDO_B, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoC"), + ID_SETTER_CRESCENDO_C, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoD"), + ID_SETTER_CRESCENDO_D, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoPrev"), + ID_SETTER_CRESCENDO_PREV, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoCurrent"), + ID_SETTER_CRESCENDO_CURRENT, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("CrescendoNext"), + ID_SETTER_CRESCENDO_NEXT, + true, + true, + false, + &MIDI_CONTEXT_SETTER}, {wxT("CrescendoOverride"), ID_SETTER_CRESCENDO_OVERRIDE, true, false, - false}, - {wxT("PanicButton"), ID_SETTER_AUDIO_PANIC, true, true, true}, - {wxT("ExitGO"), ID_SETTER_FILE_EXIT, true, true, true}, + false, + &MIDI_CONTEXT_SETTER}, + {wxT("PanicButton"), + ID_SETTER_AUDIO_PANIC, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, + {wxT("ExitGO"), + ID_SETTER_FILE_EXIT, + true, + true, + true, + &MIDI_CONTEXT_SETTER}, {wxT(""), -1, false, false, false}}; const struct GOElementCreator::ButtonDefinitionEntry *GOSetter:: diff --git a/src/grandorgue/control/GOElementCreator.cpp b/src/grandorgue/control/GOElementCreator.cpp index e90d64d32..2c236ca1f 100644 --- a/src/grandorgue/control/GOElementCreator.cpp +++ b/src/grandorgue/control/GOElementCreator.cpp @@ -1,6 +1,6 @@ /* * Copyright 2006 Milan Digital Audio LLC - * Copyright 2009-2023 GrandOrgue contributors (see AUTHORS) + * Copyright 2009-2025 GrandOrgue contributors (see AUTHORS) * License GPL-2.0 or later * (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). */ @@ -10,14 +10,17 @@ #include "GOCallbackButtonControl.h" void GOElementCreator::CreateButtons(GOOrganModel &organModel) { - const struct ButtonDefinitionEntry *entries = GetButtonDefinitionList(); - for (unsigned i = 0; - entries[i].name != wxEmptyString && entries[i].value >= 0; - i++) { - if (m_buttons.size() <= (unsigned)entries[i].value) - m_buttons.resize(entries[i].value + 1); - m_buttons[entries[i].value] = new GOCallbackButtonControl( - organModel, this, entries[i].is_pushbutton, entries[i].is_piston); + for (const ButtonDefinitionEntry *pEntry = GetButtonDefinitionList(); + !pEntry->name.IsEmpty() && pEntry->value; + pEntry++) { + const unsigned buttonIndex = (unsigned)pEntry->value; + GOCallbackButtonControl *pButton = new GOCallbackButtonControl( + organModel, this, pEntry->is_pushbutton, pEntry->is_piston); + + pButton->SetContext(pEntry->p_MidiContext); + if (m_buttons.size() <= buttonIndex) + m_buttons.resize(buttonIndex + 1); + m_buttons[buttonIndex] = pButton; } } diff --git a/src/grandorgue/control/GOElementCreator.h b/src/grandorgue/control/GOElementCreator.h index f52ca14f0..08dda4a11 100644 --- a/src/grandorgue/control/GOElementCreator.h +++ b/src/grandorgue/control/GOElementCreator.h @@ -1,6 +1,6 @@ /* * Copyright 2006 Milan Digital Audio LLC - * Copyright 2009-2023 GrandOrgue contributors (see AUTHORS) + * Copyright 2009-2025 GrandOrgue contributors (see AUTHORS) * License GPL-2.0 or later * (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). */ @@ -15,9 +15,10 @@ class GOButtonControl; class GOConfigReader; -class GOOrganModel; class GOEnclosure; class GOLabelControl; +class GOMidiObjectContext; +class GOOrganModel; class GOElementCreator : private GOButtonCallback { public: @@ -27,6 +28,7 @@ class GOElementCreator : private GOButtonCallback { bool is_public; bool is_pushbutton; bool is_piston; + const GOMidiObjectContext *p_MidiContext = nullptr; }; protected: diff --git a/src/grandorgue/midi/objects/GOMidiObject.cpp b/src/grandorgue/midi/objects/GOMidiObject.cpp index 0c70787d1..b2b2dca35 100644 --- a/src/grandorgue/midi/objects/GOMidiObject.cpp +++ b/src/grandorgue/midi/objects/GOMidiObject.cpp @@ -12,6 +12,8 @@ #include "midi/GOMidiReceiver.h" #include "model/GOOrganModel.h" +#include "GOMidiObjectContext.h" + GOMidiObject::GOMidiObject( GOOrganModel &organModel, const wxString &midiTypeCode, @@ -23,7 +25,8 @@ GOMidiObject::GOMidiObject( p_MidiSender(nullptr), p_MidiReceiver(nullptr), p_ShortcutReceiver(nullptr), - p_DivisionSender(nullptr) { + p_DivisionSender(nullptr), + p_context(nullptr) { r_OrganModel.RegisterSoundStateHandler(this); r_OrganModel.RegisterMidiObject(this); } @@ -34,6 +37,10 @@ GOMidiObject::~GOMidiObject() { r_OrganModel.UnRegisterSoundStateHandler(this); } +wxString GOMidiObject::GetContextTitle() const { + return GOMidiObjectContext::getFullTitle(p_context); +} + void GOMidiObject::InitMidiObject( GOConfigReader &cfg, const wxString &group, const wxString &name) { SetGroup(group); diff --git a/src/grandorgue/midi/objects/GOMidiObject.h b/src/grandorgue/midi/objects/GOMidiObject.h index 34616e1bc..7678cd711 100644 --- a/src/grandorgue/midi/objects/GOMidiObject.h +++ b/src/grandorgue/midi/objects/GOMidiObject.h @@ -17,6 +17,7 @@ #include "GOSaveableObject.h" class GOMidiMap; +class GOMidiObjectContext; class GOMidiReceiver; class GOMidiSender; class GOMidiShortcutReceiver; @@ -38,6 +39,8 @@ class GOMidiObject : public GOSoundStateHandler, public GOSaveableObject { GOMidiShortcutReceiver *p_ShortcutReceiver; GOMidiSender *p_DivisionSender; + const GOMidiObjectContext *p_context; + protected: GOMidiObject( GOOrganModel &organModel, @@ -80,6 +83,11 @@ class GOMidiObject : public GOSoundStateHandler, public GOSaveableObject { const wxString &GetName() const { return m_name; } void SetName(const wxString &name) { m_name = name; } + const GOMidiObjectContext *GetContext() const { return p_context; } + void SetContext(const GOMidiObjectContext *pContext) { p_context = pContext; } + + wxString GetContextTitle() const; + virtual void Init( GOConfigReader &cfg, const wxString &group, const wxString &name) { InitMidiObject(cfg, group, name); diff --git a/src/grandorgue/midi/objects/GOMidiObjectContext.cpp b/src/grandorgue/midi/objects/GOMidiObjectContext.cpp new file mode 100644 index 000000000..365155c34 --- /dev/null +++ b/src/grandorgue/midi/objects/GOMidiObjectContext.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2006 Milan Digital Audio LLC + * Copyright 2009-2025 GrandOrgue contributors (see AUTHORS) + * License GPL-2.0 or later + * (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). + */ + +#include "GOMidiObjectContext.h" + +const wxString WX_PATH_SEPARATOR = "/"; + +GOMidiObjectContext::GOMidiObjectContext( + const wxString &name, + const wxString &title, + const GOMidiObjectContext *pParent) + : m_name(name), m_title(title), p_parent(pParent) {} + +wxString GOMidiObjectContext::getFullTitle( + const GOMidiObjectContext *pContext) { + wxString path; + + for (; pContext; pContext = pContext->p_parent) { + if (!path.IsEmpty()) + path = WX_PATH_SEPARATOR + path; + path = pContext->m_title + path; + } + return path; +} diff --git a/src/grandorgue/midi/objects/GOMidiObjectContext.h b/src/grandorgue/midi/objects/GOMidiObjectContext.h new file mode 100644 index 000000000..666f27328 --- /dev/null +++ b/src/grandorgue/midi/objects/GOMidiObjectContext.h @@ -0,0 +1,42 @@ +/* + * Copyright 2006 Milan Digital Audio LLC + * Copyright 2009-2025 GrandOrgue contributors (see AUTHORS) + * License GPL-2.0 or later + * (https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). + */ + +#ifndef GOMIDIOBJECTCONTEXT_H +#define GOMIDIOBJECTCONTEXT_H + +#include + +/** + * This class is used for describing a place where a midi object is used. + * There is a hierarhial tree of contexts. For example, setter, manuals/1/stops, + * manuals/1/divisionals + */ + +class GOMidiObjectContext { +private: + // Name. Not translated. Used for exports + wxString m_name; + + // Title. Translated. Used in UI + wxString m_title; + + // Parent context + const GOMidiObjectContext *p_parent; + +public: + GOMidiObjectContext( + const wxString &name, + const wxString &title, + const GOMidiObjectContext *pParent = nullptr); + + const wxString &GetName() const { return m_name; } + const GOMidiObjectContext *GetParent() const { return p_parent; } + + static wxString getFullTitle(const GOMidiObjectContext *pContext); +}; + +#endif /* GOMIDIOBJECTCONTEXT_H */ diff --git a/src/grandorgue/model/GOManual.cpp b/src/grandorgue/model/GOManual.cpp index 908f9b538..d9b5e8d89 100644 --- a/src/grandorgue/model/GOManual.cpp +++ b/src/grandorgue/model/GOManual.cpp @@ -22,8 +22,12 @@ static const wxString WX_MIDI_TYPE_CODE = wxT("Manual"); static const wxString WX_MIDI_TYPE_NAME = _("Manual"); +static const wxString WX_MANUAL_NUM_FMT = wxT("%03u"); -GOManual::GOManual(GOOrganModel &organModel) +GOManual::GOManual( + GOOrganModel &organModel, + unsigned manualNumber, + const GOMidiObjectContext *pParentContext) : GOMidiObjectWithDivision( organModel, WX_MIDI_TYPE_CODE, @@ -36,7 +40,11 @@ GOManual::GOManual(GOOrganModel &organModel) m_Velocity(), m_DivisionState(), m_Velocities(), - m_manual_number(0), + m_manual_number(manualNumber), + m_MidiContext( + wxString::Format(WX_MANUAL_NUM_FMT, manualNumber), + wxString::Format(WX_MANUAL_NUM_FMT, manualNumber), + pParentContext), m_first_accessible_logical_key_nb(0), m_nb_logical_keys(0), m_first_accessible_key_midi_note_nb(0), @@ -51,6 +59,8 @@ GOManual::GOManual(GOOrganModel &organModel) m_ODFCouplerCount(0), m_displayed(false), m_DivisionalTemplate(organModel) { + SetContext(pParentContext); + SetInitialMidiIndex(manualNumber); // Used in LoadMidiObject SetReceiverKeyMap(&m_MidiKeyMap); m_InputCouplers.push_back(NULL); r_OrganModel.RegisterCombinationButtonSet(this); @@ -79,17 +89,15 @@ void GOManual::Resize() { void GOManual::Init( GOConfigReader &cfg, const wxString &group, - int manualNumber, unsigned firstMidi, unsigned keys) { - m_manual_number = manualNumber; m_MIDIInputNumber = 0; GOMidiReceivingSendingObject::Init( cfg, group, wxString::Format( _("Coupling manual %d"), - manualNumber - r_OrganModel.GetODFManualCount() + 1)); + m_manual_number - r_OrganModel.GetODFManualCount() + 1)); m_nb_logical_keys = keys; m_first_accessible_logical_key_nb = 1; m_first_accessible_key_midi_note_nb = firstMidi; @@ -113,10 +121,7 @@ void GOManual::Init( std::fill(m_KeyVelocity.begin(), m_KeyVelocity.end(), 0x00); } -void GOManual::Load( - GOConfigReader &cfg, const wxString &group, int manualNumber) { - m_manual_number = manualNumber; - SetInitialMidiIndex(manualNumber); // Used in LoadMidiObject +void GOManual::Load(GOConfigReader &cfg, const wxString &group) { m_MIDIInputNumber = cfg.ReadInteger( ODFSetting, group, wxT("MIDIInputNumber"), 0, 200, false, 0); GOMidiReceivingSendingObject::Load( diff --git a/src/grandorgue/model/GOManual.h b/src/grandorgue/model/GOManual.h index 2be9052e9..ef237ed7c 100644 --- a/src/grandorgue/model/GOManual.h +++ b/src/grandorgue/model/GOManual.h @@ -15,15 +15,16 @@ #include "combinations/control/GOCombinationButtonSet.h" #include "combinations/model/GOCombinationDefinition.h" #include "control/GOControl.h" +#include "midi/objects/GOMidiObjectContext.h" #include "midi/objects/GOMidiObjectWithDivision.h" class GOConfigReader; class GOCoupler; class GODivisionalButtonControl; +class GOOrganModel; class GOStop; class GOSwitch; class GOTremulant; -class GOOrganModel; class GOManual : public GOControl, public GOMidiObjectWithDivision, @@ -39,6 +40,7 @@ class GOManual : public GOControl, std::vector> m_Velocities; GOMidiReceiver::KeyMap m_MidiKeyMap; unsigned m_manual_number; + GOMidiObjectContext m_MidiContext; unsigned m_first_accessible_logical_key_nb; unsigned m_nb_logical_keys; unsigned m_first_accessible_key_midi_note_nb; @@ -79,7 +81,10 @@ class GOManual : public GOControl, GOButtonControl *buttonToLight, int manualIndexOnlyFor) override; public: - GOManual(GOOrganModel &organModel); + GOManual( + GOOrganModel &organModel, + unsigned manualNumber, + const GOMidiObjectContext *pParentContext = nullptr); ~GOManual(); unsigned GetManulNumber() const { return m_manual_number; } @@ -88,11 +93,10 @@ class GOManual : public GOControl, void Init( GOConfigReader &cfg, const wxString &group, - int manualNumber, unsigned firstMidi, unsigned keys); using GOMidiObject::Load; // avoiding a compilation warning - void Load(GOConfigReader &cfg, const wxString &group, int manualNumber); + void Load(GOConfigReader &cfg, const wxString &group); void LoadDivisionals(GOConfigReader &cfg); unsigned RegisterCoupler(GOCoupler *coupler); // send the key state to all outgoing couplers diff --git a/src/grandorgue/model/GOOrganModel.cpp b/src/grandorgue/model/GOOrganModel.cpp index 1477bd640..c16cfaeec 100644 --- a/src/grandorgue/model/GOOrganModel.cpp +++ b/src/grandorgue/model/GOOrganModel.cpp @@ -7,10 +7,13 @@ #include "GOOrganModel.h" +#include + #include "combinations/control/GOGeneralButtonControl.h" #include "config/GOConfig.h" #include "config/GOConfigReader.h" #include "control/GOPistonControl.h" +#include "midi/objects/GOMidiObjectContext.h" #include "modification/GOModificationListener.h" #include "GODivisionalCoupler.h" @@ -22,6 +25,9 @@ #include "GOTremulant.h" #include "GOWindchest.h" +static const GOMidiObjectContext MIDI_CONTEXT_MANUALS( + wxT("manuals"), _("manuals")); + GOOrganModel::GOOrganModel(GOConfig &config) : m_config(config), m_GeneralTemplate(*this), @@ -38,8 +44,6 @@ GOOrganModel::GOOrganModel(GOConfig &config) RegisterCombinationButtonSet(this); } -GOOrganModel::~GOOrganModel() {} - unsigned GOOrganModel::GetRecorderElementID(const wxString &name) { return m_config.GetMidiMap().GetElementByString(name); } @@ -75,10 +79,10 @@ void GOOrganModel::Load(GOConfigReader &cfg) { m_manuals.resize(0); m_manuals.resize(m_FirstManual); // Add empty slot for pedal, if necessary for (unsigned int i = m_FirstManual; i < m_ODFManualCount; i++) - m_manuals.push_back(new GOManual(*this)); + m_manuals.push_back(new GOManual(*this, i, &MIDI_CONTEXT_MANUALS)); for (unsigned int i = 0; i < 4; i++) - m_manuals.push_back(new GOManual(*this)); + m_manuals.push_back(new GOManual(*this, i, &MIDI_CONTEXT_MANUALS)); unsigned NumberOfEnclosures = cfg.ReadInteger(ODFSetting, WX_ORGAN, wxT("NumberOfEnclosures"), 0, 999); @@ -121,7 +125,7 @@ void GOOrganModel::Load(GOConfigReader &cfg) { // Switches must be loaded before manuals because manuals reference to // switches for (unsigned int i = m_FirstManual; i < m_ODFManualCount; i++) - m_manuals[i]->Load(cfg, wxString::Format(wxT("Manual%03d"), i), i); + m_manuals[i]->Load(cfg, wxString::Format(wxT("Manual%03d"), i)); unsigned min_key = 0xff, max_key = 0; for (unsigned i = GetFirstManualIndex(); i < GetODFManualCount(); i++) { @@ -138,7 +142,6 @@ void GOOrganModel::Load(GOConfigReader &cfg) { GetManual(i)->Init( cfg, wxString::Format(wxT("SetterFloating%03d"), i - GetODFManualCount() + 1), - i, min_key, max_key - min_key); diff --git a/src/grandorgue/model/GOOrganModel.h b/src/grandorgue/model/GOOrganModel.h index f87db0d78..c95314c29 100644 --- a/src/grandorgue/model/GOOrganModel.h +++ b/src/grandorgue/model/GOOrganModel.h @@ -102,7 +102,6 @@ class GOOrganModel : private GOCombinationButtonSet, public: GOOrganModel(GOConfig &config); - ~GOOrganModel(); const GOConfig &GetConfig() const { return m_config; } GOConfig &GetConfig() { return m_config; }