feat: add rack mode, colon commands, and client command parser

This commit is contained in:
Loic Coenen
2026-05-16 23:15:07 +00:00
committed by Loic Coenen (aider)
parent c7df02d37c
commit 9fda1b2669
10 changed files with 560 additions and 43 deletions

View File

@@ -10,6 +10,9 @@
#include <sys/stat.h>
#include <math.h>
#include "carla_host.h"
#include "client_cmd.h"
#include "plugins.h"
#include <CarlaHost.h>
/* ---------- FIFO command helper ---------- */
int send_command(const char *cmd) {
@@ -54,6 +57,8 @@ enum {
static int selected_row = 0, selected_col = 0;
static int selected_grid = 0;
static bool show_help = false;
static bool rack_mode = false;
static int rack_selected = 0;
/* Visual mode, marks, yank buffer keep but only local state */
static int marks[26];
@@ -118,7 +123,41 @@ static void draw_cell(int grid, int row, int col, bool selected) {
attroff(COLOR_PAIR(color));
}
static void draw_rack(void) {
clear();
attron(A_BOLD);
mvprintw(0,0,"Rack View - Plugins");
attroff(A_BOLD);
CarlaHostHandle h = carla_get_handle();
if (!h) {
mvprintw(2,0,"Carla host not initialised");
refresh();
return;
}
uint32_t count = carla_get_current_plugin_count(h);
if (count == 0) {
mvprintw(2,0,"No plugins loaded");
refresh();
return;
}
for (uint32_t i=0; i<count; ++i) {
const CarlaPluginInfo *info = carla_get_plugin_info(h, i);
if (!info) continue;
if ((int)i == rack_selected)
attron(A_REVERSE);
mvprintw(2+i,0,"%u: %s", i, info->name ? info->name : "(unnamed)");
if ((int)i == rack_selected)
attroff(A_REVERSE);
}
mvprintw(2+count+1,0,"[B] bypass [D] delete [X] disconnect [R] grid [Esc] back");
refresh();
}
static void draw_grid(void) {
if (rack_mode) {
draw_rack();
return;
}
clear();
attron(A_BOLD);
mvprintw(0,0,"JACK Looper - Client (FIFO only)");
@@ -130,7 +169,7 @@ static void draw_grid(void) {
selected_grid, selected_row, selected_col);
if (show_help) {
attron(COLOR_PAIR(COLOR_HELP));
mvprintw(GRID_ROWS*CELL_HEIGHT+4, 0, "Help: h/j/k/l navigate, t record, d/D stop, s/S scene, a add, A add_midi, r remove, b bind, u unbind, ? help, Esc/Q quit");
mvprintw(GRID_ROWS*CELL_HEIGHT+4, 0, "Help: h/j/k/l navigate, t record, d/D stop, s/S scene, a add, A add_midi, r remove, b bind, u unbind, R rack, ? help, Esc/Q quit");
attroff(COLOR_PAIR(COLOR_HELP));
}
refresh();
@@ -157,6 +196,10 @@ void tui_init(void) {
}
/* ---------- TUI run ---------- */
static char colon_buf[256];
static int colon_len = 0;
static bool in_colon = false;
void tui_run(void) {
draw_grid();
while (1) {
@@ -185,7 +228,45 @@ void tui_run(void) {
}
close(fd);
}
if (in_colon) {
int chc = getch();
if (chc == '\n') {
colon_buf[colon_len] = '\0';
colon_len = 0;
in_colon = false;
int dummy_id;
handle_client_command(colon_buf, &dummy_id);
draw_grid();
continue;
} else if (chc == 27) {
colon_len = 0;
in_colon = false;
draw_grid();
continue;
} else if (chc == KEY_BACKSPACE || chc == 127) {
if (colon_len > 0) colon_len--;
} else if (chc >= 32 && chc < 127 && colon_len < 255) {
colon_buf[colon_len++] = chc;
}
mvprintw(LINES-1, 0, ":%s", colon_buf);
clrtoeol();
move(LINES-1, colon_len+1);
refresh();
continue;
}
int chc = getch();
if (chc == ':') {
in_colon = true;
colon_len = 0;
colon_buf[0] = '\0';
mvprintw(LINES-1, 0, ":");
clrtoeol();
move(LINES-1, 1);
refresh();
continue;
}
switch (chc) {
case 'h': case KEY_LEFT: selected_col = (selected_col-1+GRID_COLS)%GRID_COLS; break;
case 'j': case KEY_DOWN: selected_row = (selected_row+1)%GRID_ROWS; break;
@@ -225,8 +306,51 @@ void tui_run(void) {
send_command("unbind\n");
break;
case '?': show_help = !show_help; break;
case 27: case 'Q': return;
default: break;
case 'R':
rack_mode = !rack_mode;
rack_selected = 0;
break;
case 27: case 'Q':
if (rack_mode) {
rack_mode = false;
break;
}
return;
default:
if (rack_mode) {
switch (chc) {
case 'j': case KEY_DOWN:
{
CarlaHostHandle h = carla_get_handle();
uint32_t cnt = h ? carla_get_current_plugin_count(h) : 0;
if (cnt > 0) rack_selected = (rack_selected + 1) % cnt;
}
break;
case 'k': case KEY_UP:
{
CarlaHostHandle h = carla_get_handle();
uint32_t cnt = h ? carla_get_current_plugin_count(h) : 0;
if (cnt > 0) rack_selected = (rack_selected - 1 + cnt) % cnt;
}
break;
case 'b': case 'B':
plugin_set_bypass(rack_selected, true);
// toggle would be better, but for now just enable bypass
break;
case 'd': case 'D':
plugin_unload(rack_selected);
rack_selected = 0;
break;
case 'x': case 'X':
carla_disconnect_plugin(rack_selected);
mvprintw(LINES-1,0,"Disconnected plugin %d", rack_selected);
clrtoeol();
refresh();
napms(500);
break;
}
}
break;
}
draw_grid();
}