Deluge Firmware 1.3.0
Build date: 2025.04.16
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
133 Clip* createNewClip(OutputType outputType, int32_t yDisplay);
134 bool createClip{false};
135 OutputType lastTypeCreated{OutputType::NONE};
136
137 // Grid macros config mode
138 void enterMacrosConfigMode();
139 void exitMacrosConfigMode();
140 char const* getMacroKindString(SessionMacroKind kind);
141
142 // Midi learn mode
143 void enterMidiLearnMode();
144 void exitMidiLearnMode();
145
146 // display tempo
147 void displayPotentialTempoChange(UI* ui);
148 void displayTempoBPM(deluge::hid::display::oled_canvas::Canvas& canvas, StringBuf& tempoBPM, bool clearArea);
149 float lastDisplayedTempo = 0;
150
151 // display root note and scale name
152 void displayCurrentRootNoteAndScaleName(deluge::hid::display::oled_canvas::Canvas& canvas,
153 StringBuf& rootNoteAndScaleName, bool clearArea);
154 int16_t lastDisplayedRootNote = 0;
155
156 // convert instrument clip to audio clip
157 void replaceInstrumentClipWithAudioClip(Clip* clip);
158
159 // pulse selected clip in grid view
160 void gridPulseSelectedClip();
161
162private:
163 // These and other (future) commandXXX methods perform actions triggered by HID, but contain
164 // no dispatch logic.
165 //
166 // selectEncoderAction() triggered commands
167 void commandChangeSectionRepeats(int8_t offset);
168 void commandChangeClipPreset(int8_t offset);
169 void commandChangeCurrentSectionRepeats(int8_t offset);
170 void commandChangeLayout(int8_t offset);
171
172private:
173 void renderViewDisplay();
174 void sectionPadAction(uint8_t y, bool on);
175 void clipPressEnded();
176 void drawSectionRepeatNumber();
177 void beginEditingSectionRepeatsNum();
178 void goToArrangementEditor();
179 void rowNeedsRenderingDependingOnSubMode(int32_t yDisplay);
180 void setCentralLEDStates();
181
182 Clip* createNewAudioClip(int32_t yDisplay);
183 Clip* createNewInstrumentClip(OutputType outputType, int32_t yDisplay);
184
185 bool createNewTrackForAudioClip(AudioClip* newClip);
186 bool createNewTrackForInstrumentClip(OutputType type, InstrumentClip* clip, bool copyDrumsFromClip);
187
188 bool insertAndResyncNewClip(Clip* newClip, int32_t yDisplay);
189 void resyncNewClip(Clip* newClip, ModelStackWithTimelineCounter* modelStackWithTimelineCounter);
190
191 // Members regarding rendering different layouts
192private:
193 void selectLayout(int8_t offset);
194 void renderLayoutChange(bool displayPopup = true);
195 void selectSpecificLayout(SessionLayoutType layout);
196 SessionLayoutType previousLayout;
197 SessionGridMode previousGridModeActive;
198
199 bool sessionButtonActive = false;
200 bool sessionButtonUsed = false;
201 bool horizontalEncoderPressed = false;
202 bool viewingRecordArmingActive = false;
203 // Members for grid layout
204private:
205 bool gridRenderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
206 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]);
207 void gridRenderActionModes(int32_t y, RGB image[][kDisplayWidth + kSideBarWidth],
208 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth]);
209 bool gridRenderMainPads(uint32_t whichRows, RGB image[][kDisplayWidth + kSideBarWidth],
210 uint8_t occupancyMask[][kDisplayWidth + kSideBarWidth], bool drawUndefinedArea = true);
211
212 RGB gridRenderClipColor(Clip* clip, int32_t x, int32_t y, bool renderPulse = true);
213
214 ActionResult gridHandlePadsEdit(int32_t x, int32_t y, int32_t on, Clip* clip);
215 ActionResult gridHandlePadsLaunch(int32_t x, int32_t y, int32_t on, Clip* clip);
216 ActionResult gridHandlePadsLaunchImmediate(int32_t x, int32_t y, int32_t on, Clip* clip);
217 ActionResult gridHandlePadsLaunchWithSelection(int32_t x, int32_t y, int32_t on, Clip* clip);
218 void gridHandlePadsWithMidiLearnPressed(int32_t x, int32_t on, Clip* clip);
219 ActionResult gridHandlePadsMacros(int32_t x, int32_t y, int32_t on, Clip* clip);
220 void gridHandlePadsLaunchToggleArming(Clip* clip, bool immediate);
221
222 void gridTransitionToSessionView();
223 void gridTransitionToViewForClip(Clip* clip);
224
225 SessionGridMode gridModeSelected = SessionGridModeEdit;
226 SessionGridMode gridModeActive = SessionGridModeEdit;
227 bool gridActiveModeUsed = false;
228
229 int32_t gridFirstPressedX = -1;
230 int32_t gridFirstPressedY = -1;
231 int32_t gridSecondPressedX = -1;
232 int32_t gridSecondPressedY = -1;
233 inline bool gridSecondPadInactive() { return (gridSecondPressedX == -1 && gridSecondPressedY == -1); }
234
235 inline void gridResetPresses(bool first = true, bool second = true) {
236 if (first) {
237 gridFirstPressedX = -1;
238 gridFirstPressedY = -1;
239 }
240 if (second) {
241 gridSecondPressedX = -1;
242 gridSecondPressedY = -1;
243 }
244 }
245
246 Clip* gridCloneClip(Clip* sourceClip);
247 Clip* gridCreateClipInTrack(Output* targetOutput);
248 AudioClip* gridCreateAudioClipWithNewTrack();
249 InstrumentClip* gridCreateInstrumentClipWithNewTrack(OutputType type);
250 Clip* gridCreateClip(uint32_t targetSection, Output* targetOutput = nullptr, Clip* sourceClip = nullptr);
251 void gridClonePad(uint32_t sourceX, uint32_t sourceY, uint32_t targetX, uint32_t targetY);
252 void setupNewClip(Clip* newClip);
253
254 void gridStartSection(uint32_t section, bool instant);
255 void gridToggleClipPlay(Clip* clip, bool instant);
256
257 [[nodiscard]] const size_t gridTrackCount() const;
258 uint32_t gridClipCountForTrack(Output* track);
259 uint32_t gridTrackIndexFromTrack(Output* track, uint32_t maxTrack);
260 Output* gridTrackFromIndex(uint32_t trackIndex, uint32_t maxTrack);
261 int32_t gridYFromSection(uint32_t section);
262 int32_t gridSectionFromY(uint32_t y);
263 int32_t gridXFromTrack(uint32_t trackIndex);
264 int32_t gridTrackIndexFromX(uint32_t x, uint32_t maxTrack);
265 Output* gridTrackFromX(uint32_t x, uint32_t maxTrack);
266 Clip* gridClipFromCoords(uint32_t x, uint32_t y);
267 int32_t gridClipIndexFromCoords(uint32_t x, uint32_t y);
268 Cartesian gridXYFromClip(Clip& clip);
269
270 void gridSetDefaultMode() {
271 switch (FlashStorage::defaultGridActiveMode) {
272 case GridDefaultActiveModeGreen: {
273 gridModeSelected = SessionGridModeLaunch;
274 break;
275 }
276 case GridDefaultActiveModeBlue: {
277 gridModeSelected = SessionGridModeEdit;
278 break;
279 }
280 // explicit fallthrough cases
281 case GridDefaultActiveModeSelection: // handled outside
282 case GridDefaultActiveModeMaxElement:;
283 }
284 }
285
286 void setupTrackCreation() const;
287 void exitTrackCreation();
288
289 // selected clip pulsing in grid view
290
293
296
298 void gridSelectClipForPulsing(Clip& clip);
299
302
303 bool gridSelectedClipPulsing = false; // are we doing any pulsing
304 Clip* selectedClipForPulsing = nullptr; // selected clip we are pulsing
305 RGB gridSelectedClipRenderedColour; // last pulse colour we rendered
306 bool blendDirection = false; // direction we're blending towards
307 int32_t progress = 0; // pulse blend slider position
308
309 static constexpr int32_t kMinProgress = 1; // min position to reach in blend slider
310 static constexpr int32_t kMaxProgressFull = (65535 / 100) * 60; // max position to reach for unmuted clip
311 static constexpr int32_t kMaxProgressDim = 1000; // max position to reach for muted clip
312 static constexpr int32_t kPulseRate = 50; // speed of timer in ms
313 static constexpr int32_t kBlendRate = 60; // speed of blending colours
314 static constexpr int32_t kBlendOffsetFull = kPulseRate * kBlendRate; // amount to move slider for unmuted clip
315 static constexpr int32_t kBlendOffsetDim = kPulseRate; // amount to move slider for muted clip
316};
317
318extern 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:50
Definition session_view.h:44
void renderViewDisplay()
render session view display on opening
Definition session_view.cpp:2034
int32_t displayLoopsRemainingPopup(bool ephemeral=false)
display number of bars or quarter notes remaining until a launch event
Definition session_view.cpp:2377
bool gridCheckForPulseStop()
check if we should stop pulsing
Definition session_view.cpp:4773
void gridResetSelectedClipPulseProgress()
reset blend position for pulse
Definition session_view.cpp:4759
void gridSelectClipForPulsing(Clip &clip)
render pulse for selected clip
Definition session_view.cpp:4766
void gridStopSelectedClipPulsing()
disable selected clip pulsing
Definition session_view.cpp:4751
Definition d_string.h:106
Definition ui.h:92