Deluge Firmware 1.3.0
Build date: 2025.07.05
Loading...
Searching...
No Matches
session_view.h
1/*
2 * Copyright © 2014-2023 Synthstrom Audible Limited
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_navigation_timeline_view.h"
22#include "hid/button.h"
23#include "model/song/song.h"
24#include "storage/flash_storage.h"
25
26class Editor;
27class InstrumentClip;
28class AudioClip;
29class Clip;
30class ModelStack;
32
33enum SessionGridMode : uint8_t {
34 SessionGridModeEdit,
35 SessionGridModeLaunch,
36 SessionGridModeMacros,
37 SessionGridModeMaxElement // Keep as boundary
38};
39
40extern float getTransitionProgress();
41
42constexpr uint32_t kGridHeight = kDisplayHeight;
43
44class SessionView final : public ClipNavigationTimelineView {
45public:
46 SessionView();
47 bool getGreyoutColsAndRows(uint32_t* cols, uint32_t* rows) override;
48 bool opened() override;
49 void focusRegained() override;
50
51 ActionResult buttonAction(deluge::hid::Button b, bool on, bool inCardRoutine) override;
52 ActionResult clipCreationButtonPressed(hid::Button i, bool on, bool routine);
53 ActionResult padAction(int32_t x, int32_t y, int32_t velocity) override;
54 ActionResult horizontalEncoderAction(int32_t offset) override;
55 ActionResult verticalEncoderAction(int32_t offset, bool inCardRoutine) override;
56 bool renderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
57 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]) override;
58 void removeClip(Clip* clip);
59 void redrawClipsOnScreen(bool doRender = true);
60 uint32_t getMaxZoom() override;
61 void cloneClip(uint8_t yDisplayFrom, uint8_t yDisplayTo);
62 bool renderRow(ModelStack* modelStack, uint8_t yDisplay, RGB thisImage[kDisplayWidth + kSideBarWidth],
63 uint8_t thisOccupancyMask[kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true);
64 void graphicsRoutine() override;
65 int32_t displayLoopsRemainingPopup(bool ephemeral = false);
66 void potentiallyRenderClipLaunchPlayhead(bool reallyNoTickSquare, int32_t sixteenthNotesRemaining);
67 void requestRendering(UI* ui, uint32_t whichMainRows = 0xFFFFFFFF, uint32_t whichSideRows = 0xFFFFFFFF);
68
69 int32_t getClipPlaceOnScreen(Clip* clip);
70 void drawStatusSquare(uint8_t yDisplay, RGB thisImage[]);
71 void drawSectionSquare(uint8_t yDisplay, RGB thisImage[]);
72 bool calculateZoomPinSquares(uint32_t oldScroll, uint32_t newScroll, uint32_t newZoom, uint32_t oldZoom) override;
73 uint32_t getMaxLength() override;
74 bool setupScroll(uint32_t oldScroll) override;
75 uint32_t getClipLocalScroll(Clip* loopable, uint32_t overviewScroll, uint32_t xZoom);
76 void flashPlayRoutine();
77
78 void modEncoderButtonAction(uint8_t whichModEncoder, bool on) override;
79 void modButtonAction(uint8_t whichButton, bool on) override;
80 void selectEncoderAction(int8_t offset) override;
81 ActionResult timerCallback() override;
82 void noteRowChanged(InstrumentClip* clip, NoteRow* noteRow) override;
83 void setLedStates();
84 void editNumRepeatsTilLaunch(int32_t offset);
85 uint32_t getGreyedOutRowsNotRepresentingOutput(Output* output) override;
86 bool renderMainPads(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
87 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true) override;
88 void midiLearnFlash() override;
89
90 void transitionToViewForClip(Clip* clip = nullptr);
91 void transitionToSessionView();
92 void finishedTransitioningHere();
93 void playbackEnded() override;
94 void clipNeedsReRendering(Clip* clip) override;
95 void sampleNeedsReRendering(Sample* sample) override;
96 Clip* getClipOnScreen(int32_t yDisplay);
97 Output* getOutputFromPad(int32_t x, int32_t y);
98 void modEncoderAction(int32_t whichModEncoder, int32_t offset) override;
99 ActionResult verticalScrollOneSquare(int32_t direction);
100
101 void renderOLED(deluge::hid::display::oled_canvas::Canvas& canvas) override;
102
103 // 7SEG only
104 void redrawNumericDisplay();
105 void clearNumericDisplay();
106 void displayRepeatsTilLaunch();
107
108 uint32_t selectedClipTimePressed;
109 uint8_t selectedClipYDisplay; // Where the clip is on screen
110 uint8_t selectedClipPressYDisplay; // Where the user's finger actually is on screen
111 uint8_t selectedClipPressXDisplay;
112 bool clipWasSelectedWithShift; // Whether shift was held when clip pad started to be held
113 bool performActionOnPadRelease;
114 bool performActionOnSectionPadRelease; // Keep this separate from the above one because we don't want a mod encoder
115 // action to set this to false
116 uint8_t sectionPressed;
117 uint8_t masterCompEditMode;
118 int8_t selectedMacro = -1;
119
120 Clip* getClipForLayout();
121 int32_t getClipIndexForLayout();
122
123 void copyClipName(Clip* source, Clip* target, Output* targetOutput);
124
125 // Members for grid layout
126 inline bool gridFirstPadActive() { return (gridFirstPressedX != -1 && gridFirstPressedY != -1); }
127 ActionResult gridHandlePads(int32_t x, int32_t y, int32_t on);
128 ActionResult gridHandleScroll(int32_t offsetX, int32_t offsetY);
129
130 // ui
131 UIType getUIType() override { return UIType::SESSION; }
132 UIModControllableContext getUIModControllableContext() override { return UIModControllableContext::SONG; }
133
134 Clip* createNewClip(OutputType outputType, int32_t yDisplay);
135 bool createClip{false};
136 OutputType lastTypeCreated{OutputType::NONE};
137
138 // Grid macros config mode
139 void enterMacrosConfigMode();
140 void exitMacrosConfigMode();
141 char const* getMacroKindString(SessionMacroKind kind);
142
143 // Midi learn mode
144 void enterMidiLearnMode();
145 void exitMidiLearnMode();
146
147 // display tempo
148 void displayPotentialTempoChange(UI* ui);
149 void displayTempoBPM(deluge::hid::display::oled_canvas::Canvas& canvas, StringBuf& tempoBPM, bool clearArea);
150 float lastDisplayedTempo = 0;
151
152 // display root note and scale name
153 void displayCurrentRootNoteAndScaleName(deluge::hid::display::oled_canvas::Canvas& canvas,
154 StringBuf& rootNoteAndScaleName, bool clearArea);
155 int16_t lastDisplayedRootNote = 0;
156
157 // convert instrument clip to audio clip
158 void replaceInstrumentClipWithAudioClip(Clip* clip);
159
160 // pulse selected clip in grid view
161 void gridPulseSelectedClip();
162
163private:
164 // These and other (future) commandXXX methods perform actions triggered by HID, but contain
165 // no dispatch logic.
166 //
167 // selectEncoderAction() triggered commands
168 void commandChangeSectionRepeats(int8_t offset);
169 void commandChangeClipPreset(int8_t offset);
170 void commandChangeCurrentSectionRepeats(int8_t offset);
171 void commandChangeLayout(int8_t offset);
172
173private:
174 void renderViewDisplay();
175 void sectionPadAction(uint8_t y, bool on);
176 void clipPressEnded();
177 void drawSectionRepeatNumber();
178 void beginEditingSectionRepeatsNum();
179 void goToArrangementEditor();
180 void rowNeedsRenderingDependingOnSubMode(int32_t yDisplay);
181 void setCentralLEDStates();
182
183 Clip* createNewAudioClip(int32_t yDisplay);
184 Clip* createNewInstrumentClip(OutputType outputType, int32_t yDisplay);
185
186 bool createNewTrackForAudioClip(AudioClip* newClip);
187 bool createNewTrackForInstrumentClip(OutputType type, InstrumentClip* clip, bool copyDrumsFromClip);
188
189 bool insertAndResyncNewClip(Clip* newClip, int32_t yDisplay);
190 void resyncNewClip(Clip* newClip, ModelStackWithTimelineCounter* modelStackWithTimelineCounter);
191
192 // Members regarding rendering different layouts
193private:
194 void selectLayout(int8_t offset);
195 void renderLayoutChange(bool displayPopup = true);
196 void selectSpecificLayout(SessionLayoutType layout);
197 SessionLayoutType previousLayout;
198 SessionGridMode previousGridModeActive;
199
200 bool sessionButtonActive = false;
201 bool sessionButtonUsed = false;
202 bool horizontalEncoderPressed = false;
203 bool viewingRecordArmingActive = false;
204 // Members for grid layout
205private:
206 bool gridRenderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
207 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]);
208 void gridRenderActionModes(int32_t y, RGB image[][kDisplayWidth + kSideBarWidth],
209 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]);
210 bool gridRenderMainPads(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
211 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true);
212
213 RGB gridRenderClipColor(Clip* clip, int32_t x, int32_t y, bool renderPulse = true);
214
215 ActionResult gridHandlePadsEdit(int32_t x, int32_t y, int32_t on, Clip* clip);
216 ActionResult gridHandlePadsLaunch(int32_t x, int32_t y, int32_t on, Clip* clip);
217 ActionResult gridHandlePadsLaunchImmediate(int32_t x, int32_t y, int32_t on, Clip* clip);
218 ActionResult gridHandlePadsLaunchWithSelection(int32_t x, int32_t y, int32_t on, Clip* clip);
219 void gridHandlePadsWithMidiLearnPressed(int32_t x, int32_t on, Clip* clip);
220 ActionResult gridHandlePadsMacros(int32_t x, int32_t y, int32_t on, Clip* clip);
221 void gridHandlePadsLaunchToggleArming(Clip* clip, bool immediate);
222
223 void gridTransitionToSessionView();
224 void gridTransitionToViewForClip(Clip* clip);
225
226 SessionGridMode gridModeSelected = SessionGridModeEdit;
227 SessionGridMode gridModeActive = SessionGridModeEdit;
228 bool gridActiveModeUsed = false;
229
230 int32_t gridFirstPressedX = -1;
231 int32_t gridFirstPressedY = -1;
232 int32_t gridSecondPressedX = -1;
233 int32_t gridSecondPressedY = -1;
234 inline bool gridSecondPadInactive() { return (gridSecondPressedX == -1 && gridSecondPressedY == -1); }
235
236 inline void gridResetPresses(bool first = true, bool second = true) {
237 if (first) {
238 gridFirstPressedX = -1;
239 gridFirstPressedY = -1;
240 }
241 if (second) {
242 gridSecondPressedX = -1;
243 gridSecondPressedY = -1;
244 }
245 }
246
247 Clip* gridCloneClip(Clip* sourceClip);
248 Clip* gridCreateClipInTrack(Output* targetOutput);
249 AudioClip* gridCreateAudioClipWithNewTrack();
250 InstrumentClip* gridCreateInstrumentClipWithNewTrack(OutputType type);
251 Clip* gridCreateClip(uint32_t targetSection, Output* targetOutput = nullptr, Clip* sourceClip = nullptr);
252 void gridClonePad(uint32_t sourceX, uint32_t sourceY, uint32_t targetX, uint32_t targetY);
253 void setupNewClip(Clip* newClip);
254
255 void gridStartSection(uint32_t section, bool instant);
256 void gridToggleClipPlay(Clip* clip, bool instant);
257
258 [[nodiscard]] const size_t gridTrackCount() const;
259 uint32_t gridClipCountForTrack(Output* track);
260 uint32_t gridTrackIndexFromTrack(Output* track, uint32_t maxTrack);
261 Output* gridTrackFromIndex(uint32_t trackIndex, uint32_t maxTrack);
262 int32_t gridYFromSection(uint32_t section);
263 int32_t gridSectionFromY(uint32_t y);
264 int32_t gridXFromTrack(uint32_t trackIndex);
265 int32_t gridTrackIndexFromX(uint32_t x, uint32_t maxTrack);
266 Output* gridTrackFromX(uint32_t x, uint32_t maxTrack);
267 Clip* gridClipFromCoords(uint32_t x, uint32_t y);
268 int32_t gridClipIndexFromCoords(uint32_t x, uint32_t y);
269 Cartesian gridXYFromClip(Clip& clip);
270
271 void gridSetDefaultMode() {
272 switch (FlashStorage::defaultGridActiveMode) {
273 case GridDefaultActiveModeGreen: {
274 gridModeSelected = SessionGridModeLaunch;
275 break;
276 }
277 case GridDefaultActiveModeBlue: {
278 gridModeSelected = SessionGridModeEdit;
279 break;
280 }
281 // explicit fallthrough cases
282 case GridDefaultActiveModeSelection: // handled outside
283 case GridDefaultActiveModeMaxElement:;
284 }
285 }
286
287 void setupTrackCreation() const;
288 void exitTrackCreation();
289
290 // selected clip pulsing in grid view
291
294
297
299 void gridSelectClipForPulsing(Clip& clip);
300
303
304 bool gridSelectedClipPulsing = false; // are we doing any pulsing
305 Clip* selectedClipForPulsing = nullptr; // selected clip we are pulsing
306 RGB gridSelectedClipRenderedColour; // last pulse colour we rendered
307 bool blendDirection = false; // direction we're blending towards
308 int32_t progress = 0; // pulse blend slider position
309
310 static constexpr int32_t kMinProgress = 1; // min position to reach in blend slider
311 static constexpr int32_t kMaxProgressFull = (65535 / 100) * 60; // max position to reach for unmuted clip
312 static constexpr int32_t kMaxProgressDim = 1000; // max position to reach for muted clip
313 static constexpr int32_t kPulseRate = 50; // speed of timer in ms
314 static constexpr int32_t kBlendRate = 60; // speed of blending colours
315 static constexpr int32_t kBlendOffsetFull = kPulseRate * kBlendRate; // amount to move slider for unmuted clip
316 static constexpr int32_t kBlendOffsetDim = kPulseRate; // amount to move slider for muted clip
317};
318
319extern SessionView sessionView;
Definition audio_clip.h:35
Definition clip.h:46
Definition instrument_clip.h:48
Definition model_stack.h:129
Definition model_stack.h:123
Definition note_row.h:98
Definition output.h:81
This class represents the colour format most used by the Deluge globally.
Definition rgb.h:14
Definition sample.h:49
Definition session_view.h:44
UIType getUIType() override
What type of UI is this? e.g. UIType::ARRANGER.
Definition session_view.h:131
void renderViewDisplay()
render session view display on opening
Definition session_view.cpp:2029
UIModControllableContext getUIModControllableContext() override
What mod controllable context is this UI using? E.g. Automation View can use the Song ModControllable...
Definition session_view.h:132
int32_t displayLoopsRemainingPopup(bool ephemeral=false)
display number of bars or quarter notes remaining until a launch event
Definition session_view.cpp:2372
bool gridCheckForPulseStop()
check if we should stop pulsing
Definition session_view.cpp:4771
void gridResetSelectedClipPulseProgress()
reset blend position for pulse
Definition session_view.cpp:4757
void gridSelectClipForPulsing(Clip &clip)
render pulse for selected clip
Definition session_view.cpp:4764
void gridStopSelectedClipPulsing()
disable selected clip pulsing
Definition session_view.cpp:4749
Definition ui.h:92