Skip to content

Commit

Permalink
SESSION MACROS
Browse files Browse the repository at this point in the history
  • Loading branch information
bfredl committed Mar 21, 2024
1 parent 73af9db commit f0a0962
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
171 changes: 171 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,171 @@
/*
* 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 "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) {
uint8_t brightness = 1;
uint8_t otherChannels = 0;

int32_t num = currentSong->sessionClips.getNumElements();

for (int32_t y = 0; y < kDisplayHeight; ++y) {
switch (macros[y].kind) {
case CLIP_LAUNCH:
if (macros[y].clip->activeIfNoSolo) {
image[y][column] = {0, 255, 0};
} else {
image[y][column] = {255, 0, 0};
}

break;
case OUTPUT_CYCLE:
image[y][column] = {0, 64, 255};
break;
case SECTION:
image[y][column] = {255, 0, 128};
break;
case NO_MACRO:
image[y][column] = {0, 0, 0};
}

}
}

bool SessionColumn::handleVerticalEncoder(int8_t pad, int32_t offset) {
SessionMacro &m = macros[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;

switch (m.kind) {
case CLIP_LAUNCH:
m.clip = getCurrentClip();
break;

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

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

default:
break;
}

return true;
};

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

SessionMacro &m = macros[pad.y];
switch (m.kind) {
case CLIP_LAUNCH:
if (pad.active) {
session.toggleClipStatus(m.clip, nullptr, Buttons::isShiftButtonPressed(), kInternalButtonPressLatency);
}
else if (!pad.padPressHeld) {
}
else {
}
break;

case OUTPUT_CYCLE:
handleOutput(m, pad);
break;

case SECTION:
// TODO: we can do really fancy stuff like registering a section+output combo
if (!pad.active) {
session.armSection(m.section, kInternalButtonPressLatency);
}

default:
break;
}
};

Clip *SessionColumn::findNextClipForOutput(SessionMacro &m, PressedPad pad) {
int last_active = -1;
for (int i = 0; i < currentSong->sessionClips.getNumElements(); i++) {
Clip* clip = currentSong->sessionClips.getClipAtIndex(i);
if (clip->output == m.output) {
if (last_active == -1) {
if(clip->activeIfNoSolo) {
last_active = i;
}
}
else {
return clip;
}
}
}

// might need to cycle around to find the next clip
for (int i = 0; i < last_active; i++) {
Clip* clip = currentSong->sessionClips.getClipAtIndex(i);
if (clip->output == m.output) {
return clip;
}
}


if (m.clip && m.clip->output == m.output) {
return m.clip;
}

return nullptr;
}

void SessionColumn::handleOutput(SessionMacro &m, PressedPad pad) {
if (pad.active) {
}
else if (!pad.padPressHeld) {
Clip *nextClip = findNextClipForOutput(m, pad);
if (nextClip) {
session.toggleClipStatus(nextClip, nullptr, Buttons::isShiftButtonPressed(), kInternalButtonPressLatency);
}
}
else {
// long press: mute if possible, otherwise do the same.
Clip *curClip = currentSong->getClipWithOutput(m.output, true, nullptr);
if (!curClip) {
curClip = findNextClipForOutput(m, pad);
}
if (curClip) {
session.toggleClipStatus(curClip, nullptr, Buttons::isShiftButtonPressed(), kInternalButtonPressLatency);
}
}

}

} // namespace deluge::gui::ui::keyboard::controls
54 changes: 54 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,54 @@
/*
* 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"

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

enum SessionMacroKind : int8_t {
NO_MACRO = 0,
CLIP_LAUNCH,
OUTPUT_CYCLE,
SECTION,
NUM_KINDS,
};

struct SessionMacro {
SessionMacroKind kind;
Clip *clip;
Output *output;
uint8_t section;
};

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 handlePad(ModelStackWithTimelineCounter* modelStackWithTimelineCounter, PressedPad pad,
KeyboardLayout* layout) override;

void handleOutput(SessionMacro &m, PressedPad pad);
Clip *findNextClipForOutput(SessionMacro &m, PressedPad pad);
private:
SessionMacro macros[8];
};

} // namespace deluge::gui::ui::keyboard::controls
3 changes: 3 additions & 0 deletions src/deluge/gui/ui/keyboard/layout/column_controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const char* functionNames[][2] = {
/* CHORD */ {"CHRD", "Chords"},
/* CHORD_MEM */ {"CMEM", "Chord Memory"},
/* SCALE_MODE */ {"SMOD", "Scales"},
/* SESSION */ {"SESS", "Session parts"},
/* BEAT_REPEAT */ {"BEAT", "Beat Repeat"},
};

Expand Down Expand Up @@ -148,6 +149,8 @@ ControlColumn* ColumnControlsKeyboard::getColumnForFunc(ColumnControlFunction fu
return &chordMemColumn;
case SCALE_MODE:
return &scaleModeColumn;
case SESSION:
return &sessionColumn;
}
return nullptr;
}
Expand Down
3 changes: 3 additions & 0 deletions src/deluge/gui/ui/keyboard/layout/column_controls.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "gui/ui/keyboard/column_controls/chord_mem.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/velocity.h"
#include "gui/ui/keyboard/layout.h"

Expand All @@ -38,6 +39,7 @@ enum ColumnControlFunction : int8_t {
CHORD,
CHORD_MEM,
SCALE_MODE,
SESSION,
// BEAT_REPEAT,
COL_CTRL_FUNC_MAX,
};
Expand Down Expand Up @@ -90,6 +92,7 @@ class ColumnControlsKeyboard : public KeyboardLayout {
ChordColumn chordColumn{};
ChordMemColumn chordMemColumn{};
ScaleModeColumn scaleModeColumn{};
SessionColumn sessionColumn{};

void renderColumnBeatRepeat(RGB image[][kDisplayWidth + kSideBarWidth], int32_t column);

Expand Down

0 comments on commit f0a0962

Please sign in to comment.