1 #ifndef AL_PARAMETERGUI_H
2 #define AL_PARAMETERGUI_H
45 #include "al/io/al_AudioIO.hpp"
46 #include "al/io/al_ControlNav.hpp"
47 #include "al/io/al_Imgui.hpp"
48 #include "al/scene/al_DynamicScene.hpp"
49 #include "al/scene/al_SynthRecorder.hpp"
50 #include "al/scene/al_SynthSequencer.hpp"
51 #include "al/ui/al_Parameter.hpp"
52 #include "al/ui/al_ParameterBundle.hpp"
53 #include "al/ui/al_ParameterMIDI.hpp"
54 #include "al/ui/al_PresetHandler.hpp"
55 #include "al/ui/al_PresetMIDI.hpp"
56 #include "al/ui/al_PresetSequencer.hpp"
57 #include "al/ui/al_SequenceRecorder.hpp"
61 class BundleGUIManager;
70 static inline void draw(
ParameterMeta *param) { drawParameterMeta(param); }
73 static void drawVectorParameters(std::vector<ParameterMeta *> params,
74 std::string suffix =
"");
75 static void drawParameterMeta(
ParameterMeta *param, std::string suffix =
"");
76 static void drawParameter(
Parameter *param, std::string suffix =
"");
78 std::string suffix =
"");
79 static void drawParameterInt(
ParameterInt *param, std::string suffix);
80 static void drawParameterBool(
ParameterBool *param, std::string suffix =
"");
81 static void drawParameterPose(
ParameterPose *param, std::string suffix =
"");
83 std::string suffix =
"");
84 static void drawMenu(
ParameterMenu *param, std::string suffix =
"");
85 static void drawChoice(
ParameterChoice *param, std::string suffix =
"");
86 static void drawVec3(
ParameterVec3 *param, std::string suffix =
"");
87 static void drawVec4(
ParameterVec4 *param, std::string suffix =
"");
88 static void drawTrigger(
Trigger *param, std::string suffix =
"");
90 static void drawSynthController(
PolySynth *param, std::string suffix =
"");
93 static void drawNav(
Nav *mNav, std::string suffix =
"");
94 static void drawDynamicScene(
DynamicScene *scene, std::string suffix =
"");
98 static void drawParameterMeta(std::vector<ParameterMeta *> params,
99 std::string suffix,
int index = 0);
100 static void drawParameter(std::vector<Parameter *> params, std::string suffix,
102 static void drawParameterString(std::vector<ParameterString *> params,
103 std::string suffix,
int index = 0);
104 static void drawParameterInt(std::vector<ParameterInt *> params,
105 std::string suffix,
int index = 0);
106 static void drawParameterBool(std::vector<ParameterBool *> params,
107 std::string suffix,
int index = 0);
108 static void drawParameterPose(std::vector<ParameterPose *> params,
109 std::string suffix,
int index = 0);
110 static void drawParameterColor(std::vector<ParameterColor *> params,
111 std::string suffix,
int index = 0);
112 static void drawMenu(std::vector<ParameterMenu *> params, std::string suffix,
114 static void drawChoice(std::vector<ParameterChoice *> params,
115 std::string suffix,
int index = 0);
116 static void drawVec3(std::vector<ParameterVec3 *> params, std::string suffix,
118 static void drawVec4(std::vector<ParameterVec4 *> params, std::string suffix,
120 static void drawTrigger(std::vector<Trigger *> params, std::string suffix,
126 std::string currentBank;
127 int currentBankIndex = 0;
128 std::vector<std::string> mapList;
129 int presetHandlerBank = 0;
131 std::string enteredText;
132 std::string newMapText;
133 bool storeButtonState{
false};
137 int presetColumns = 10,
140 int ¤tPresetSequencerItem);
145 static void drawAudioIO(
AudioIO &io) { drawAudioIO(&io); }
146 static void drawAudioIO(
AudioIO *io);
148 drawParameterMIDI(&midi);
150 static void drawParameterMIDI(ParameterMIDI *midi);
151 static void drawPresetMIDI(PresetMIDI *presetMidi);
153 static void drawBundleGroup(std::vector<ParameterBundle *> bundles,
154 std::string suffix,
int ¤tBundle,
156 static void drawBundle(ParameterBundle *bundle);
157 static void drawBundleManager(BundleGUIManager *manager);
159 static bool usingInput() {
return isImguiUsingInput(); }
160 static bool usingKeyboard() {
return isImguiUsingKeyboard(); }
163 static auto vector_getter(
void *vec,
int idx,
const char **out_text) {
164 auto &vector = *
static_cast<std::vector<std::string> *
>(vec);
165 if (idx < 0 || idx >=
static_cast<int>(vector.size())) {
168 *out_text = vector.at(idx).c_str();
172 static void beginPanel(std::string name,
float x = -1,
float y = -1,
173 float width = -1,
float height = -1,
174 ImGuiWindowFlags window_flags = 0) {
175 if (x >= 0 || y >= 0) {
176 ImGui::SetNextWindowPos(ImVec2(x, y));
179 if (width >= 0 || height >= 0) {
180 ImGui::SetNextWindowSize(ImVec2(width, height));
190 ImGui::Begin(name.c_str(),
nullptr, window_flags);
193 static void endPanel() { ImGui::End(); }
200 void drawBundleGUI() {
201 std::unique_lock<std::mutex> lk(mBundleLock);
202 std::string suffix =
"##_bundle_" + mName;
203 ParameterGUI::drawBundleGroup(mBundles, suffix, mCurrentBundle,
208 if (mName.size() == 0 || bundle.
name() == mName) {
209 std::unique_lock<std::mutex> lk(mBundleLock);
210 if (mName.size() == 0) {
211 mName = bundle.
name();
213 mBundles.push_back(&bundle);
215 std::cout <<
"Warning: bundle name mismatch. Bundle '" << bundle.
name()
216 <<
"' ingnored." << std::endl;
222 return registerParameterBundle(newBundle);
227 return registerParameterBundle(*newBundle);
230 std::string name() {
return mName; }
232 int ¤tBundle() {
return mCurrentBundle; }
233 bool &bundleGlobal() {
return mBundleGlobal; }
234 std::vector<ParameterBundle *> bundles() {
return mBundles; }
237 std::mutex mBundleLock;
238 std::vector<ParameterBundle *> mBundles;
240 int mCurrentBundle{0};
241 bool mBundleGlobal{
false};
249 mControlVoice.init();
250 for (
auto *param : mControlVoice.triggerParameters()) {
251 mPresetHandler << *param;
257 mName = demangle(
typeid(mControlVoice).name());
259 mPresetHandler.setRootPath(mName +
"-data");
260 mPresetSequencer << mPresetHandler;
261 mPresetSequenceRecorder << mPresetHandler;
263 mSequencer.setDirectory(mName +
"-data");
264 mRecorder.setDirectory(mName +
"-data");
266 mRecorder << mSequencer.synth();
269 mSequencer.synth().template registerSynthClass<VoiceType>(
270 demangle(
typeid(VoiceType).name()));
271 mSequencer.synth().template allocatePolyphony<VoiceType>(16);
274 std::string name() {
return mName; }
276 void drawSynthWidgets() {
278 drawAllNotesOffButton();
281 ImGui::Columns(2,
nullptr,
true);
282 if (ImGui::Selectable(
"Polyphonic", mCurrentTab == 1)) {
287 if (ImGui::Selectable(
"Static", mCurrentTab == 2)) {
289 synthSequencer().stopSequence();
296 if (mCurrentTab == 1) {
297 drawAllNotesOffButton();
298 drawSynthSequencer();
302 drawPresetSequencer();
303 drawPresetSequencerRecorder();
307 void setCurrentTab(
int tab) {
308 if (tab >= 1 && tab <= 2) {
311 std::cerr <<
"ERROR: Can't set tab for SynthGUIManager:" << tab
320 ParameterGUI::beginPanel(demangle(
typeid(mControlVoice).name()).c_str());
322 ParameterGUI::endPanel();
327 void render(Graphics &g) { synthSequencer().
render(g); }
329 void configureVoiceFromGui(VoiceType *voice) {
330 for (
size_t i = 0; i < mControlVoice.triggerParameters().size(); i++) {
331 voice->triggerParameters()[i]->set(mControlVoice.triggerParameters()[i]);
336 for (
auto *param : mControlVoice.triggerParameters()) {
337 ParameterGUI::drawParameterMeta(param);
341 void drawPresets(
int columns = 12,
int rows = 4) {
342 ParameterGUI::drawPresetHandler(&mPresetHandler, columns, rows);
345 void drawSynthSequencer() { ParameterGUI::drawSynthSequencer(&mSequencer); }
347 void drawSynthRecorder() { ParameterGUI::drawSynthRecorder(&mRecorder); }
349 void drawPresetSequencer() {
350 static int currentItem{0};
351 ParameterGUI::drawPresetSequencer(&mPresetSequencer, currentItem);
354 void drawPresetSequencerRecorder() {
355 ParameterGUI::drawSequenceRecorder(&mPresetSequenceRecorder);
358 void createBundle(uint8_t bundleSize) {
359 for (uint8_t i = 0; i < bundleSize; i++) {
360 auto voice = mSequencer.synth().template getVoice<VoiceType>();
361 auto bundle = std::make_shared<ParameterBundle>(
362 demangle(
typeid(mControlVoice).name()));
363 for (
auto *param : voice->triggerParameters()) {
366 mBundles.push_back(bundle);
367 mBundleGui << *bundle;
373 if (mBundles.size() > 0) {
374 mBundleGui.drawBundleGUI();
378 void drawTriggerButton() {
379 std::string buttonName =
380 mCurrentTriggerState ?
"Turn off##paramGUI" :
"Trigger##paramGUI";
381 if (ImGui::Button(buttonName.c_str(),
382 ImVec2(ImGui::GetWindowWidth(), 40))) {
383 if (!mCurrentTriggerState) {
391 void drawAllNotesOffButton() {
392 std::string buttonName =
"All notes off##paramGUI";
393 if (ImGui::Button(buttonName.c_str(), ImVec2(ImGui::GetWindowWidth(), 0))) {
405 if (!mCurrentTriggerState) {
407 mSequencer.synth().
triggerOn(&mControlVoice, 0, INT_MIN);
408 mCurrentTriggerState =
true;
411 VoiceType *voice = synth().template getVoice<VoiceType>();
412 configureVoiceFromGui(voice);
417 void triggerOff(
int id = INT_MIN) {
419 if (mCurrentTriggerState) {
420 mControlVoice.free();
421 while (mControlVoice.id() != -1) {
423 std::this_thread::sleep_for(std::chrono::milliseconds(10));
426 mCurrentTriggerState =
false;
433 bool triggerButtonState() {
return mCurrentTriggerState; }
435 VoiceType *voice() {
return &mControlVoice; }
437 void recallPreset(
int index) { mPresetHandler.
recallPreset(index); }
439 PresetSequencer &presetSequencer() {
return mPresetSequencer; }
440 PresetHandler &presetHandler() {
return mPresetHandler; }
442 PolySynth &synth() {
return mSequencer.synth(); }
443 SynthSequencer &synthSequencer() {
return mSequencer; }
444 SynthRecorder &synthRecorder() {
return mRecorder; }
448 VoiceType mControlVoice;
450 PresetHandler mPresetHandler;
451 PresetSequencer mPresetSequencer;
452 SequenceRecorder mPresetSequenceRecorder;
455 SynthSequencer mSequencer{TimeMasterMode::TIME_MASTER_AUDIO};
456 SynthRecorder mRecorder;
458 std::vector<std::shared_ptr<ParameterBundle>> mBundles;
459 BundleGUIManager mBundleGui;
461 bool mCurrentTriggerState{
false};
462 int mTriggerVoiceId{INT_MIN};
BundleGUIManager & operator<<(ParameterBundle *newBundle)
Register parameter using the streaming operator.
BundleGUIManager & operator<<(ParameterBundle &newBundle)
Register parameter using the streaming operator.
std::string name() const
get the name for this bundle
A parameter representing selected items from a list.
The ParameterMIDI class connects Parameter objects to MIDI messages.
A PolySynth manages polyphony and rendering of SynthVoice instances.
virtual void allNotesOff()
Turn off all notes immediately (without calling triggerOff() )
void triggerOff(int id)
trigger release of voice with id
int triggerOn(SynthVoice *voice, int offsetFrames=0, int id=-1, void *userData=nullptr)
trigger Puts voice in active voice lit and calls triggerOn() for it
bool popFreeVoice(SynthVoice *voice)
Remove voice from the free voice pool.
The PresetHandler class handles sorting and recalling of presets.
void recallPreset(std::string name)
Recall a preset by name.
The PresetSequencer class allows triggering presets from a PresetHandler over time.
The SequenceRecorder class records preset changes in a ".sequence" file.
void triggerOn(int id=INT_MIN)
Trigger a free voice. If no id provided the internal voice is triggered.
void drawSynthControlPanel()
Draws a panel with all the synth controls.
The SynthRecorder class records the events arriving at a PolySynth.
Event Sequencer triggering audio visual "notes".
void render(AudioIOData &io)
Insert this function within the audio callback.