feat: add scene-based recording, e2e tests, and improved TUI state indicators

This commit is contained in:
Loic Coenen
2026-05-22 17:52:13 +00:00
committed by Loic Coenen (aider)
parent f2993eac80
commit 7c289e1496
11 changed files with 1024 additions and 37 deletions

View File

@@ -15,6 +15,7 @@
#include "plugins.h"
#include "script.h"
#include <CarlaHost.h>
#include "log.h"
/* ---------- engine alive indicator ---------- */
static bool engine_running = false;
@@ -40,7 +41,15 @@ int send_command(const char *cmd) {
/* ---------- Stub functions (no engine) ---------- */
// Clip states dummy values used as placeholders
typedef enum { CLIP_EMPTY, CLIP_RECORDING, CLIP_LOOPING, CLIP_STOPPED } ClipState;
static const char *clip_state_string(ClipState s) { (void)s; return "?"; }
static const char *clip_state_string(ClipState s) {
switch (s) {
case CLIP_EMPTY: return " ";
case CLIP_RECORDING: return "R";
case CLIP_LOOPING: return "L";
case CLIP_STOPPED: return "P";
default: return "?";
}
}
/* Grid dimensions */
#define GRID_ROWS 8
@@ -131,6 +140,17 @@ static void draw_cell(int grid, int row, int col, bool selected) {
mvaddch(y+dy, x+dx, ' ');
mvprintw(y+1, x+1, "%2d", grid*GRID_ROWS*GRID_COLS + row*GRID_COLS + col);
attroff(COLOR_PAIR(color));
/* Draw state indicator character below the number, centered */
const char state_char = (s == STATE_RECORD) ? 'R' :
(s == STATE_LOOPING) ? 'L' :
(s == STATE_PAUSED) ? 'P' : '.';
int state_color = (s == STATE_RECORD) ? COLOR_RECORDING :
(s == STATE_LOOPING) ? COLOR_LOOPING :
(s == STATE_PAUSED) ? COLOR_STOPPED : COLOR_EMPTY;
attron(COLOR_PAIR(state_color));
mvaddch(y+2, x + CELL_WIDTH / 2, state_char);
attroff(COLOR_PAIR(state_color));
}
static void draw_rack(void) {
@@ -187,6 +207,7 @@ static void draw_grid(void) {
/* ---------- TUI init ---------- */
void tui_init(void) {
log_init();
initscr();
cbreak(); noecho(); keypad(stdscr, TRUE); curs_set(0);
debug_mode = (getenv("LOOPER_DEBUG") != NULL);
@@ -231,8 +252,15 @@ void tui_run(void) {
int ch, sc;
ChannelState st;
if (parse_status_line(line, &ch, &sc, &st)) {
if (ch >= 0 && ch < GRID_ROWS * GRID_COLS)
cell_state[ch] = st;
int idx = sc * GRID_COLS + ch;
if (idx >= 0 && idx < GRID_ROWS * GRID_COLS) {
log_msg("DIAG status: line=\"%s\" ch=%d sc=%d st=%d idx=%d", line, ch, sc, (int)st, idx);
cell_state[idx] = st;
} else {
log_msg("DIAG status out of range: line=\"%s\" ch=%d sc=%d idx=%d", line, ch, sc, idx);
}
} else {
log_msg("DIAG status parse failed: \"%s\"", line);
}
if (nl) {
*nl = '\n';
@@ -268,6 +296,9 @@ void tui_run(void) {
close(nfd);
}
/* Immediately redraw the grid so status changes appear without waiting for next keypress */
draw_grid();
if (in_colon) {
int chc = getch();
if (chc == '\n') {
@@ -326,8 +357,14 @@ void tui_run(void) {
case 'l': case KEY_RIGHT: selected_col = (selected_col+1)%GRID_COLS; break;
case 't': {
char cmd[32];
log_msg("DIAG t pressed: selected_row=%d selected_col=%d", selected_row, selected_col);
// channel = col, scene = row
snprintf(cmd, sizeof(cmd), "set_scene %d %d\n", selected_col, selected_row);
send_command(cmd);
log_msg("DIAG sent: %s", cmd);
snprintf(cmd, sizeof(cmd), "record %d\n", selected_col);
send_command(cmd);
log_msg("DIAG sent: %s", cmd);
break;
}
case 's':
@@ -350,6 +387,9 @@ void tui_run(void) {
break;
case 'b': {
char cmd[16];
// channel = col, scene = row
snprintf(cmd, sizeof(cmd), "set_scene %d %d\n", selected_col, selected_row);
send_command(cmd);
snprintf(cmd, sizeof(cmd), "bind %d\n", selected_col);
send_command(cmd);
break;