Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
automation_view.h
1/*
2 * Copyright (c) 2023 Sean Ditny
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include "gui/views/clip_view.h"
22#include "hid/button.h"
23#include "model/clip/instrument_clip_minder.h"
24#include "model/mod_controllable/mod_controllable_audio.h"
25#include "model/note/note_row.h"
26#include "modulation/automation/copied_param_automation.h"
27
28class Action;
29class CopiedNoteRow;
30class Drum;
31class Editor;
32class AudioClip;
33class Instrument;
34class InstrumentClip;
35class MidiInstrument;
36class ModControllable;
41class Note;
42class NoteRow;
43class ParamCollection;
45class ParamNode;
46class PatchCableSet;
47class Sound;
48class SoundDrum;
49
50class AutomationView final : public ClipView, public InstrumentClipMinder {
51public:
52 AutomationView();
53 bool opened() override;
54 void initializeView();
55 void openedInBackground();
56 void focusRegained() override;
57
58 // called by ui_timer_manager - might need to revise this routine for automation clip view since it references notes
59 void graphicsRoutine() override;
60
61 // ui
62 UIType getUIType() override { return UIType::AUTOMATION; }
63 AutomationSubType getAutomationSubType();
64
65 // rendering
66 bool possiblyRefreshAutomationEditorGrid(Clip* clip, deluge::modulation::params::Kind paramKind, int32_t paramID);
67 bool renderMainPads(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
68 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true) override;
69 bool renderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
70 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]) override;
71 void renderDisplay(int32_t knobPosLeft = kNoSelection, int32_t knobPosRight = kNoSelection,
72 bool modEncoderAction = false);
73 void displayAutomation(bool padSelected = false, bool updateDisplay = true);
74
75 void renderOLED(deluge::hid::display::oled_canvas::Canvas& canvas) override {
76 InstrumentClipMinder::renderOLED(canvas);
77 }
78
79 // button action
80 ActionResult buttonAction(deluge::hid::Button b, bool on, bool inCardRoutine) override;
81
82 // pad action
83 ActionResult padAction(int32_t x, int32_t y, int32_t velocity) override;
84
85 // horizontal encoder action
86 ActionResult horizontalEncoderAction(int32_t offset) override;
87 uint32_t getMaxLength() override;
88 uint32_t getMaxZoom() override;
89 [[nodiscard]] int32_t getNavSysId() const override;
90 int32_t navSysId;
91
92 // vertical encoder action
93 ActionResult verticalEncoderAction(int32_t offset, bool inCardRoutine) override;
94 ActionResult scrollVertical(int32_t scrollAmount);
96
97 // mod encoder action
98 void modEncoderAction(int32_t whichModEncoder, int32_t offset) override;
99 void modEncoderButtonAction(uint8_t whichModEncoder, bool on) override;
100 CopiedParamAutomation copiedParamAutomation;
101
102 // Select encoder action
103 void selectEncoderAction(int8_t offset) override;
104 void getLastSelectedParamShortcut(Clip* clip); // public so menu can access it
105 void getLastSelectedParamArrayPosition(Clip* clip); // public so menu can access it
106 bool multiPadPressSelected; // public so menu can access it
107
108 // called by melodic_instrument.cpp or kit.cpp
109 void noteRowChanged(InstrumentClip* clip, NoteRow* noteRow) override;
110
111 // called by playback_handler.cpp
112 void notifyPlaybackBegun() override;
113
114 // used to identify the UI as a clip UI or not.
116 return getAutomationSubType() == AutomationSubType::ARRANGER ? nullptr : this;
117 }
118
119 void setAutomationParamType();
120
121 bool onAutomationOverview();
122 bool inAutomationEditor();
123 bool inNoteEditor();
124
125 bool interpolation;
126 bool interpolationBefore;
127 bool interpolationAfter;
128
129 // public to midi follow can access it
131 getModelStackWithParamForClip(ModelStackWithTimelineCounter* modelStack, Clip* clip,
133 deluge::modulation::params::Kind paramKind = deluge::modulation::params::Kind::NONE);
134
135 // public so instrument clip view can access it
136 void initParameterSelection(bool updateDisplay = true);
137 bool onArrangerView;
138
139 // public so uiTimerManager can access it
140 void blinkInterpolationShortcut();
141 void blinkPadSelectionShortcut();
142
143 // public so menu can access it
144 bool onMenuView;
145 UI* previousUI; // previous UI so you can swap back UI after exiting menu
146 int32_t getAutomationParameterKnobPos(ModelStackWithAutoParam* modelStack, uint32_t pos);
147 void setAutomationKnobIndicatorLevels(ModelStackWithAutoParam* modelStack, int32_t knobPosLeft,
148 int32_t knobPosRight);
149 void resetInterpolationShortcutBlinking();
150 void resetPadSelectionShortcutBlinking();
151 AutomationParamType automationParamType;
152 bool getAffectEntire() override;
153
154 // public so action logger can access it
155 void resetShortcutBlinking();
156
157private:
158 // button action functions
159 void handleSessionButtonAction(Clip* clip, bool on);
160 void handleKeyboardButtonAction(bool on);
161 void handleClipButtonAction(bool on, bool isAudioClip);
162 void handleCrossScreenButtonAction(bool on);
163 void handleKitButtonAction(OutputType outputType, bool on);
164 void handleSynthButtonAction(OutputType outputType, bool on);
165 void handleMidiButtonAction(OutputType outputType, bool on);
166 void handleCVButtonAction(OutputType outputType, bool on);
167 bool handleHorizontalEncoderButtonAction(bool on, bool isAudioClip);
168 bool handleBackAndHorizontalEncoderButtonComboAction(Clip* clip, bool on);
169 void handleVerticalEncoderButtonAction(bool on);
170 void handleSelectEncoderButtonAction(bool on);
171 void handleAffectEntireButtonAction(bool on);
172
173 // edit pad action
174 ActionResult handleEditPadAction(ModelStackWithAutoParam* modelStackWithParam,
175 ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow, Clip* clip,
176 Output* output, OutputType outputType, int32_t effectiveLength, int32_t x,
177 int32_t y, int32_t velocity, SquareInfo& squareInfo);
178 bool shortcutPadAction(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, Output* output,
179 OutputType outputType, int32_t effectiveLength, int32_t x, int32_t y, int32_t velocity,
180 int32_t xScroll, int32_t xZoom, SquareInfo& squareInfo);
183 bool toggleAutomationPadSelectionMode(ModelStackWithAutoParam* modelStackWithParam, int32_t effectiveLength,
184 int32_t xScroll, int32_t xZoom);
185 void handleParameterSelection(Clip* clip, Output* output, OutputType outputType, int32_t xDisplay,
186 int32_t yDisplay);
187 void noteEditPadAction(ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow, InstrumentClip* clip,
188 int32_t x, int32_t y, int32_t velocity, int32_t effectiveLength, SquareInfo& squareInfo);
189 void velocityPadSelectionAction(ModelStackWithNoteRow* modelStackWithNoteRow, InstrumentClip* clip, int32_t x,
190 int32_t y, int32_t velocity, SquareInfo& squareInfo);
191 void velocityEditPadAction(ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow, InstrumentClip* clip,
192 int32_t x, int32_t y, int32_t velocity, int32_t effectiveLength, SquareInfo& squareInfo);
193 int32_t getVelocityFromY(int32_t y);
194 int32_t getYFromVelocity(int32_t velocity);
195 void addNoteWithNewVelocity(int32_t x, int32_t velocity, int32_t newVelocity);
196 void adjustNoteVelocity(ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow, int32_t x, int32_t velocity,
197 int32_t newVelocity, uint8_t squareType);
198 void setVelocity(ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow, int32_t x, int32_t newVelocity);
199 void setVelocityRamp(ModelStackWithNoteRow* modelStackWithNoteRow, NoteRow* noteRow,
200 SquareInfo rowSquareInfo[kDisplayWidth], int32_t velocityIncrement);
201 void recordNoteEditPadAction(int32_t x, int32_t velocity);
202 void automationEditPadAction(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, int32_t xDisplay,
203 int32_t yDisplay, int32_t velocity, int32_t effectiveLength, int32_t xScroll,
204 int32_t xZoom);
205 bool recordAutomationSinglePadPress(int32_t xDisplay, int32_t yDisplay);
206
207 // mute pad action
208 ActionResult handleMutePadAction(ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
209 InstrumentClip* instrumentClip, Output* output, OutputType outputType, int32_t y,
210 int32_t velocity);
211
212 // audition pad action
213 ActionResult handleAuditionPadAction(InstrumentClip* instrumentClip, Output* output, OutputType outputType,
214 int32_t y, int32_t velocity);
215 void auditionPadAction(int32_t velocity, int32_t yDisplay, bool shiftButtonDown);
216
217 // Automation View Render Functions
218 void performActualRender(RGB image[][kDisplayWidth + kSideBarWidth],
219 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xScroll, uint32_t xZoom,
220 int32_t renderWidth, int32_t imageWidth, bool drawUndefinedArea = true);
221 void renderAutomationOverview(ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
222 ModelStackWithThreeMainThings* modelStackWithThreeMainThings, Clip* clip,
223 OutputType outputType, RGB image[][kDisplayWidth + kSideBarWidth],
224 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xDisplay,
225 bool isMIDICVDrum);
226 void renderAutomationEditor(ModelStackWithAutoParam* modelStackWithParam, Clip* clip,
227 RGB image[][kDisplayWidth + kSideBarWidth],
228 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t renderWidth,
229 int32_t xScroll, uint32_t xZoom, int32_t effectiveLength, int32_t xDisplay,
230 bool drawUndefinedArea, deluge::modulation::params::Kind kind, bool isBipolar);
231 void renderAutomationColumn(ModelStackWithAutoParam* modelStackWithParam,
232 RGB image[][kDisplayWidth + kSideBarWidth],
233 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t lengthToDisplay,
234 int32_t xDisplay, bool isAutomated, int32_t xScroll, int32_t xZoom,
235 deluge::modulation::params::Kind kind, bool isBipolar);
236 void renderAutomationBipolarSquare(RGB image[][kDisplayWidth + kSideBarWidth],
237 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xDisplay,
238 int32_t yDisplay, bool isAutomated, deluge::modulation::params::Kind kind,
239 int32_t knobPos);
240 void renderAutomationUnipolarSquare(RGB image[][kDisplayWidth + kSideBarWidth],
241 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xDisplay,
242 int32_t yDisplay, bool isAutomated, int32_t knobPos);
243 void renderNoteEditor(ModelStackWithNoteRow* modelStackWithNoteRow, InstrumentClip* clip,
244 RGB image[][kDisplayWidth + kSideBarWidth],
245 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t renderWidth, int32_t xScroll,
246 uint32_t xZoom, int32_t effectiveLength, int32_t xDisplay, bool drawUndefinedArea,
247 SquareInfo& squareInfo);
248 void renderNoteColumn(ModelStackWithNoteRow* modelStackWithNoteRow, InstrumentClip* clip,
249 RGB image[][kDisplayWidth + kSideBarWidth],
250 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xDisplay, int32_t xScroll,
251 int32_t xZoom, SquareInfo& squareInfo);
252 void renderNoteSquare(RGB image[][kDisplayWidth + kSideBarWidth],
253 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t xDisplay, int32_t yDisplay,
254 uint8_t squareType, int32_t value);
255 void renderUndefinedArea(int32_t xScroll, uint32_t xZoom, int32_t lengthToDisplay,
256 RGB image[][kDisplayWidth + kSideBarWidth],
257 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], int32_t imageWidth,
258 TimelineView* timelineView, bool tripletsOnHere, int32_t xDisplay);
259 void renderDisplayOLED(Clip* clip, Output* output, OutputType outputType, int32_t knobPosLeft = kNoSelection,
260 int32_t knobPosRight = kNoSelection);
261 void renderAutomationOverviewDisplayOLED(deluge::hid::display::oled_canvas::Canvas& canvas, Output* output,
262 OutputType outputType);
263 void renderAutomationEditorDisplayOLED(deluge::hid::display::oled_canvas::Canvas& canvas, Clip* clip,
264 OutputType outputType, int32_t knobPosLeft, int32_t knobPosRight);
265 void renderNoteEditorDisplayOLED(deluge::hid::display::oled_canvas::Canvas& canvas, InstrumentClip* clip,
266 OutputType outputType, int32_t knobPosLeft, int32_t knobPosRight);
267 void renderDisplay7SEG(Clip* clip, Output* output, OutputType outputType, int32_t knobPosLeft = kNoSelection,
268 bool modEncoderAction = false);
269 void renderAutomationOverviewDisplay7SEG(Output* output, OutputType outputType);
270 void renderAutomationEditorDisplay7SEG(Clip* clip, OutputType outputType, int32_t knobPosLeft,
271 bool modEncoderAction);
272 void renderNoteEditorDisplay7SEG(InstrumentClip* clip, OutputType outputType, int32_t knobPosLeft);
273
274 // Horizontal Encoder Action
275 void shiftAutomationHorizontally(ModelStackWithAutoParam* modelStackWithParam, int32_t offset,
276 int32_t effectiveLength);
277
278 // Mod Encoder Action
279 bool automationModEncoderActionForSelectedPad(ModelStackWithAutoParam* modelStackWithParam, int32_t whichModEncoder,
280 int32_t offset, int32_t effectiveLength);
281 void automationModEncoderActionForUnselectedPad(ModelStackWithAutoParam* modelStackWithParam,
282 int32_t whichModEncoder, int32_t offset, int32_t effectiveLength);
283
284 // Mod Encoder Button Action
285 void copyAutomation(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, int32_t xScroll, int32_t xZoom);
286 void pasteAutomation(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, int32_t effectiveLength,
287 int32_t xScroll, int32_t xZoom);
288
289 // Select Encoder Action
290 void selectGlobalParam(int32_t offset, Clip* clip);
291 void selectNonGlobalParam(int32_t offset, Clip* clip);
292 bool selectPatchCable(int32_t offset, Clip* clip);
293 bool selectPatchCableAtIndex(Clip* clip, PatchCableSet* set, int32_t patchCableIndex, bool& foundCurrentPatchCable);
294 void selectMIDICC(int32_t offset, Clip* clip);
295 int32_t getNextSelectedParamArrayPosition(int32_t offset, int32_t lastSelectedParamArrayPosition,
296 int32_t numParams);
297 void getLastSelectedNonGlobalParamArrayPosition(Clip* clip);
298 void getLastSelectedGlobalParamArrayPosition(Clip* clip);
299
300 // Automation Lanes Functions
301 void initPadSelection();
302 void initInterpolation();
303 ParamManagerForTimeline* getParamManagerForClip(Clip* clip);
304 int32_t getEffectiveLength(ModelStackWithTimelineCounter* modelStack);
305 uint32_t getSquareWidth(int32_t square, int32_t effectiveLength, int32_t xScroll, int32_t xZoom);
306 uint32_t getMiddlePosFromSquare(int32_t xDisplay, int32_t effectiveLength, int32_t xScroll, int32_t xZoom);
307
308 void getAutomationParameterName(Clip* clip, OutputType outputType, StringBuf& parameterName);
309
310 bool getAutomationNodeInterpolation(ModelStackWithAutoParam* modelStack, int32_t pos, bool reversed);
311 void setAutomationParameterValue(ModelStackWithAutoParam* modelStack, int32_t knobPos, int32_t squareStart,
312 int32_t xDisplay, int32_t effectiveLength, int32_t xScroll, int32_t xZoom,
313 bool modEncoderAction = false);
314 void updateAutomationModPosition(ModelStackWithAutoParam* modelStack, uint32_t squareStart,
315 bool updateDisplay = true, bool updateIndicatorLevels = true);
316
317 void handleAutomationSinglePadPress(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, int32_t xDisplay,
318 int32_t yDisplay, int32_t effectiveLength, int32_t xScroll, int32_t xZoom);
319 void handleAutomationParameterChange(ModelStackWithAutoParam* modelStackWithParam, Clip* clip,
320 OutputType outputType, int32_t xDisplay, int32_t yDisplay,
321 int32_t effectiveLength, int32_t xScroll, int32_t xZoom);
322 int32_t calculateAutomationKnobPosForPadPress(ModelStackWithAutoParam* modelStackWithParam, OutputType outputType,
323 int32_t yDisplay);
324 int32_t calculateAutomationKnobPosForMiddlePadPress(deluge::modulation::params::Kind kind, int32_t yDisplay);
325 int32_t calculateAutomationKnobPosForSinglePadPress(deluge::modulation::params::Kind kind, int32_t yDisplay);
326
327 void handleAutomationMultiPadPress(ModelStackWithAutoParam* modelStackWithParam, Clip* clip, int32_t firstPadX,
328 int32_t firstPadY, int32_t secondPadX, int32_t secondPadY,
329 int32_t effectiveLength, int32_t xScroll, int32_t xZoom,
330 bool modEncoderAction = false);
331 void renderAutomationDisplayForMultiPadPress(ModelStackWithAutoParam* modelStackWithParam, Clip* clip,
332 int32_t effectiveLength, int32_t xScroll, int32_t xZoom,
333 int32_t xDisplay = kNoSelection, bool modEncoderAction = false);
334
335 int32_t calculateAutomationKnobPosForModEncoderTurn(ModelStackWithAutoParam* modelStackWithParam, int32_t knobPos,
336 int32_t offset);
337
338 void blinkShortcuts();
339 void resetParameterShortcutBlinking();
340
341 bool parameterShortcutBlinking;
342
343 bool interpolationShortcutBlinking;
344 bool padSelectionShortcutBlinking;
345
346 bool padSelectionOn;
347 bool multiPadPressActive;
348 bool middlePadPressSelected;
349 int32_t leftPadSelectedX;
350 int32_t leftPadSelectedY;
351 int32_t rightPadSelectedX;
352 int32_t rightPadSelectedY;
353 int32_t lastPadSelectedKnobPos;
354 int32_t numNotesSelected;
355 int32_t selectedPadPressed;
356
357 bool playbackStopped;
358
359 // grid sized array to assign midi cc values to each pad on the grid
360 void initMIDICCShortcutsForAutomation();
361 uint32_t midiCCShortcutsForAutomation[kDisplayWidth][kDisplayHeight];
362 bool midiCCShortcutsLoaded;
363
364 bool probabilityChanged;
365 uint32_t timeSelectKnobLastReleased;
366};
367
368extern AutomationView automationView;
Definition action.h:75
Definition audio_clip.h:35
Definition automation_view.h:50
void potentiallyVerticalScrollToSelectedDrum(InstrumentClip *clip, Output *output)
Definition automation_view.cpp:4027
bool toggleAutomationInterpolation()
toggle automation interpolation on / off
Definition automation_view.cpp:2536
void renderNoteSquare(RGB image[][kDisplayWidth+kSideBarWidth], uint8_t occupancyMask[][kDisplayWidth+kSideBarWidth], int32_t xDisplay, int32_t yDisplay, uint8_t squareType, int32_t value)
render column for note parameter
Definition automation_view.cpp:1151
void renderNoteColumn(ModelStackWithNoteRow *modelStackWithNoteRow, InstrumentClip *clip, RGB image[][kDisplayWidth+kSideBarWidth], uint8_t occupancyMask[][kDisplayWidth+kSideBarWidth], int32_t xDisplay, int32_t xScroll, int32_t xZoom, SquareInfo &squareInfo)
render each square in each column of the note editor grid
Definition automation_view.cpp:1134
bool toggleVelocityPadSelectionMode(SquareInfo &squareInfo)
toggle velocity pad selection mode on / off
Definition automation_view.cpp:2554
void renderAutomationColumn(ModelStackWithAutoParam *modelStackWithParam, RGB image[][kDisplayWidth+kSideBarWidth], uint8_t occupancyMask[][kDisplayWidth+kSideBarWidth], int32_t lengthToDisplay, int32_t xDisplay, bool isAutomated, int32_t xScroll, int32_t xZoom, deluge::modulation::params::Kind kind, bool isBipolar)
render each square in each column of the automation editor grid
Definition automation_view.cpp:971
bool shortcutPadAction(ModelStackWithAutoParam *modelStackWithParam, Clip *clip, Output *output, OutputType outputType, int32_t effectiveLength, int32_t x, int32_t y, int32_t velocity, int32_t xScroll, int32_t xZoom, SquareInfo &squareInfo)
Definition automation_view.cpp:2482
ClipMinder * toClipMinder() override
Definition automation_view.h:115
void renderAutomationUnipolarSquare(RGB image[][kDisplayWidth+kSideBarWidth], uint8_t occupancyMask[][kDisplayWidth+kSideBarWidth], int32_t xDisplay, int32_t yDisplay, bool isAutomated, int32_t knobPos)
render column for unipolar params (e.g. not pan, pitch, or patch cables)
Definition automation_view.cpp:1079
void renderAutomationBipolarSquare(RGB image[][kDisplayWidth+kSideBarWidth], uint8_t occupancyMask[][kDisplayWidth+kSideBarWidth], int32_t xDisplay, int32_t yDisplay, bool isAutomated, deluge::modulation::params::Kind kind, int32_t knobPos)
render column for bipolar params - e.g. pan, pitch, patch cable
Definition automation_view.cpp:992
bool toggleAutomationPadSelectionMode(ModelStackWithAutoParam *modelStackWithParam, int32_t effectiveLength, int32_t xScroll, int32_t xZoom)
toggle automation pad selection mode on / off
Definition automation_view.cpp:2588
Definition clip_minder.h:23
Definition clip.h:46
Definition copied_note_row.h:23
Definition copied_param_automation.h:28
Definition drum.h:44
Definition instrument_clip.h:48
Definition instrument.h:45
Definition mod_controllable.h:40
Definition model_stack.h:269
Definition model_stack.h:189
Definition model_stack.h:231
Definition model_stack.h:129
Definition note_row.h:98
Definition note.h:24
Definition output.h:81
Definition param_collection.h:39
Definition param_manager.h:174
Definition param_node.h:23
Definition patch_cable_set.h:41
This class represents the colour format most used by the Deluge globally.
Definition rgb.h:14
Definition sound_drum.h:28
Definition sound.h:71
Definition d_string.h:106
Definition timeline_view.h:27
Definition ui.h:92
Kind
Definition param.h:42
constexpr uint32_t kNoParamID
Magic number which represents an invalid or missing param type.
Definition param.h:296
Definition note_row.h:58