Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sidebar: session macros in keyboard #1545

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/community_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,10 @@ Here is a list of features that have been added to the firmware as a list, group
- Track color can be changed by holding any populated clip in a column and rotating `▼︎▲︎`. For fine changes
to the color press `▼︎▲︎` while turning it.
- Section pads (left sidebar column) will allow changing repeat count while held
- `Purple mode`
- [Song macros](#419---song-macros) can be set up. First select a macro slot in the left sidebar and then press a clip to
put it in the slot. press the same clip multiple times to switch between macro kinds (i e affect the entire
output or section for the clip)
- ([#970]) Streamline recording new clips while Deluge is playing
- This assumes the Deluge is in Grid mode, you are in Green mode, the Deluge is Playing, and Recording is enabled.
- To use this feature you will need to enable it in the menu:
Expand Down Expand Up @@ -480,6 +484,23 @@ Here is a list of features that have been added to the firmware as a list, group
- y1 = -26.4 to -22.1
- y0 = -30.8 to -26.5

### 4.1.9 - Song macros

Macros are a way to quickly switch playing clips without needing to go into song view.
Within grid view, purple mode is used to edit macros. There are 8 macro slots
shown in the left sidebar. To assign a macro,
first select a macro slot and then press a clip in the grid. Pressing the same clip multiple
time cycles though different modes:

- clip macro: Launch or mute the clip
- output macro: cycle though all clips for this particular output
- section macro: Launch all clips for this section

Inside a clip timeline view, hold SONG button and press the left sidebar to launch a macro.
In keyboard view, macros are available as a sidebar control.
SHIFT makes the launch immediate just like in song view. AFFECT ENTIRE + clip macro can be
used to jump to edit the clip.

### 4.2 - Clip View - General Features (Instrument and Audio Clips)

#### 4.2.1 - Filters
Expand Down Expand Up @@ -950,6 +971,8 @@ to each individual note onset. ([#1978])
pads will default to the first 7 scale modes, but you can change any pad to any scale by
holding it down and turning the vertical encoder. If the scale that is going to be set
can't fit/transpose the existing notes from your clips, screen will show `Can't`.
- **`Song Macro Mode (SONG - various):`** Activate [Song macros](#419---song-macros).

- ([#2174]) With the addition of the new Keyboard Sidebar Controls, the default behaviour of being able to immediately exit the menu by pressing a sidebar pad while in Keyboard View was removed. To accomodate users that still wish to be able to exit the menus immediately by pressing a sidebar pad, a new community feature toggle has been added (`Enable KB View Sidebar Menu Exit (EXIT)`) which will enable you to immediately exit the menu using the top left sidebar pad if you are in the `SETTINGS` or `SOUND` menu for `KEYBOARD VIEW`.

#### 4.4.2 - Scales
Expand Down
2 changes: 1 addition & 1 deletion src/definitions_cxx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ enum GridMode : uint8_t {
Unassigned1,
Unassigned2,
Unassigned3,
Unassigned4,
MAGENTA,
YELLOW,
BLUE,
GREEN,
Expand Down
86 changes: 86 additions & 0 deletions src/deluge/gui/ui/keyboard/column_controls/session.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright © 2016-2024 Synthstrom Audible Limited
*
* This file is part of The Synthstrom Audible Deluge Firmware.
*
* The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/

#include "session.h"
#include "gui/ui/keyboard/layout/column_controls.h"
#include "gui/views/session_view.h"
#include "gui/views/view.h"
#include "hid/buttons.h"
#include "playback/mode/session.h"

using namespace deluge::gui::ui::keyboard::layout;

namespace deluge::gui::ui::keyboard::controls {

void SessionColumn::renderColumn(RGB image[][kDisplayWidth + kSideBarWidth], int32_t column) {
bool armed = false;
for (int32_t y = 0; y < kDisplayHeight; ++y) {
armed |= view.renderMacros(column, y, -1, image, nullptr);
}
if (armed) {
view.flashPlayEnable();
}
}

bool SessionColumn::handleVerticalEncoder(int8_t pad, int32_t offset) {
SessionMacro& m = currentSong->sessionMacros[pad];
int kindIndex = (int32_t)m.kind + offset;
if (kindIndex >= SessionMacroKind::NUM_KINDS) {
kindIndex = 0;
}
else if (kindIndex < 0) {
kindIndex = SessionMacroKind::NUM_KINDS - 1;
}

m.kind = (SessionMacroKind)kindIndex;
m.clip = nullptr;
m.output = nullptr;
m.section = 0;

switch (m.kind) {
case CLIP_LAUNCH:
m.clip = getCurrentClip();
bfredl marked this conversation as resolved.
Show resolved Hide resolved
break;

case OUTPUT_CYCLE:
m.output = getCurrentOutput();
break;

case SECTION:
m.section = getCurrentClip()->section;

default:
break;
}

return true;
};

void SessionColumn::handleLeavingColumn(ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
KeyboardLayout* layout){};

void SessionColumn::handlePad(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, PressedPad pad,
KeyboardLayout* layout) {

if (pad.active) {}
else {
view.activateMacro(pad.y);
}
view.flashPlayEnable();
};

} // namespace deluge::gui::ui::keyboard::controls
42 changes: 42 additions & 0 deletions src/deluge/gui/ui/keyboard/column_controls/session.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright © 2016-2024 Synthstrom Audible Limited
*
* This file is part of The Synthstrom Audible Deluge Firmware.
*
* The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "gui/ui/keyboard/column_controls/control_column.h"
#include "model/song/song.h"

namespace deluge::gui::ui::keyboard::controls {

class SessionColumn : public ControlColumn {
public:
SessionColumn() = default;

void renderColumn(RGB image[][kDisplayWidth + kSideBarWidth], int32_t column) override;
bool handleVerticalEncoder(int8_t pad, int32_t offset) override;
void handleLeavingColumn(ModelStackWithTimelineCounter* modelStackWithTimelineCounter,
KeyboardLayout* layout) override;
void handlePad(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, PressedPad pad,
KeyboardLayout* layout) override;

void handleOutput(SessionMacro& m, PressedPad pad);
Clip* findNextClipForOutput(SessionMacro& m, PressedPad pad);

private:
};

} // namespace deluge::gui::ui::keyboard::controls
3 changes: 3 additions & 0 deletions src/deluge/gui/ui/keyboard/layout/column_control_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "gui/ui/keyboard/column_controls/dx.h"
#include "gui/ui/keyboard/column_controls/mod.h"
#include "gui/ui/keyboard/column_controls/scale_mode.h"
#include "gui/ui/keyboard/column_controls/session.h"
#include "gui/ui/keyboard/column_controls/song_chord_mem.h"
#include "gui/ui/keyboard/column_controls/velocity.h"

Expand All @@ -35,6 +36,7 @@ enum ColumnControlFunction : int8_t {
CHORD_MEM,
SCALE_MODE,
DX,
SESSION,
// BEAT_REPEAT,
COL_CTRL_FUNC_MAX,
};
Expand All @@ -50,6 +52,7 @@ struct ColumnControlState {
ChordMemColumn chordMemColumn{};
ScaleModeColumn scaleModeColumn{};
DXColumn dxColumn{};
SessionColumn sessionColumn{};

ColumnControlFunction leftColFunc = VELOCITY;
ColumnControlFunction rightColFunc = MOD;
Expand Down
8 changes: 8 additions & 0 deletions src/deluge/gui/ui/keyboard/layout/column_controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const char* functionNames[][2] = {
/* CHORD_MEM */ {"CCME", "Clip Chord Memory"},
/* SCALE_MODE */ {"SMOD", "Scales"},
/* DX */ {"DX", "DX operators"},
/* SESSION */ {"SONG", "song macros"},
/* BEAT_REPEAT */ {"BEAT", "Beat Repeat"},
};

Expand Down Expand Up @@ -204,6 +205,8 @@ ControlColumn* ColumnControlState::getColumnForFunc(ColumnControlFunction func)
return &scaleModeColumn;
case DX:
return &dxColumn;
case SESSION:
return &sessionColumn;
}
return nullptr;
}
Expand All @@ -224,6 +227,8 @@ const char* columnFunctionToString(ColumnControlFunction func) {
return "scale_mode";
case DX:
return "dx";
case SESSION:
return "session";
}
return "";
}
Expand All @@ -250,6 +255,9 @@ ColumnControlFunction stringToColumnFunction(char const* string) {
else if (!strcmp(string, "dx")) {
return DX;
}
else if (!strcmp(string, "session")) {
return SESSION;
}
else {
return VELOCITY; // unknown column, just pick the default
}
Expand Down
1 change: 1 addition & 0 deletions src/deluge/gui/ui/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ extern bool pendingUIRenderingLock;
#define UI_MODE_HOLDING_STATUS_PAD 62
#define UI_MODE_IMPLODE_ANIMATION 63
#define UI_MODE_STEM_EXPORT 64
#define UI_MODE_HOLDING_SONG_BUTTON 65

#define EXCLUSIVE_UI_MODES_MASK ((uint32_t)255)

Expand Down
5 changes: 1 addition & 4 deletions src/deluge/gui/ui_timer_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,7 @@ void UITimerManager::routine() {
break;

case TimerName::PLAY_ENABLE_FLASH: {
RootUI* rootUI = getRootUI();
if ((rootUI == &sessionView) || (rootUI == &performanceSessionView)) {
sessionView.flashPlayRoutine();
}
view.flashPlayRoutine();
break;
}
case TimerName::DISPLAY:
Expand Down
39 changes: 38 additions & 1 deletion src/deluge/gui/views/audio_clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,18 @@ bool AudioClipView::renderSidebar(uint32_t whichRows, RGB image[][kDisplayWidth
return true;
}

int32_t macroColumn = kDisplayWidth;
m-m-adams marked this conversation as resolved.
Show resolved Hide resolved
bool armed = false;
for (int32_t y = 0; y < kDisplayHeight; y++) {
RGB* const start = &image[y][kDisplayWidth];
std::fill(start, start + kSideBarWidth, colours::black);

if (isUIModeActive(UI_MODE_HOLDING_SONG_BUTTON)) {
armed |= view.renderMacros(macroColumn, y, -1, image, occupancyMask);
}
}
if (armed) {
view.flashPlayEnable();
}

return true;
Expand Down Expand Up @@ -282,10 +291,27 @@ ActionResult AudioClipView::buttonAction(deluge::hid::Button b, bool on, bool in

// Song view button
if (b == SESSION_VIEW) {
if (on && currentUIMode == UI_MODE_NONE) {
if (on) {
if (currentUIMode == UI_MODE_NONE) {
currentUIMode = UI_MODE_HOLDING_SONG_BUTTON;
timeSongButtonPressed = AudioEngine::audioSampleTimer;
indicator_leds::setLedState(IndicatorLED::SESSION_VIEW, true);
uiNeedsRendering(this, 0, 0xFFFFFFFF);
}
}
else {
if (!isUIModeActive(UI_MODE_HOLDING_SONG_BUTTON)) {
return ActionResult::DEALT_WITH;
}
if (inCardRoutine) {
return ActionResult::REMIND_ME_OUTSIDE_CARD_ROUTINE;
}
exitUIMode(UI_MODE_HOLDING_SONG_BUTTON);
if ((int32_t)(AudioEngine::audioSampleTimer - timeSongButtonPressed) > kShortPressTime) {
uiNeedsRendering(this, 0, 0xFFFFFFFF);
indicator_leds::setLedState(IndicatorLED::SESSION_VIEW, false);
return ActionResult::DEALT_WITH;
}

uiTimerManager.unsetTimer(TimerName::UI_SPECIFIC);

Expand Down Expand Up @@ -502,6 +528,17 @@ ActionResult AudioClipView::padAction(int32_t x, int32_t y, int32_t on) {
}
}
}
else if (x == kDisplayWidth) {
if (isUIModeActive(UI_MODE_HOLDING_SONG_BUTTON)) {
if (sdRoutineLock) {
return ActionResult::REMIND_ME_OUTSIDE_CARD_ROUTINE;
}
if (!on) {
view.activateMacro(y);
}
return ActionResult::DEALT_WITH;
}
}

return ActionResult::DEALT_WITH;
}
Expand Down
1 change: 1 addition & 0 deletions src/deluge/gui/views/audio_clip_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class AudioClipView final : public ClipView, public ClipMinder {
const char* getName() { return "audio_clip_view"; }

private:
uint32_t timeSongButtonPressed;
void needsRenderingDependingOnSubMode();
int32_t lastTickSquare;
bool mustRedrawTickSquares;
Expand Down
Loading
Loading