From 95a7d05ca53ea917ad0db416fa34c1a640deae2f Mon Sep 17 00:00:00 2001 From: Loic Coenen Date: Sun, 17 May 2026 10:18:58 +0000 Subject: [PATCH] feat: add mock JACK test target and unit tests for carla host --- client/makefile | 15 +++- client/src/carla_host.c | 35 +++++++++- client/tests/test_carla_host_mock.c | 92 +++++++++++++++++++++++++ engine/looper | Bin 0 -> 72680 bytes engine/src/channel.c | 102 ++++++++++++++-------------- engine/src/channel.o | Bin 0 -> 18360 bytes engine/src/looper.c | 100 ++++++++++++++------------- engine/src/looper.o | Bin 0 -> 44408 bytes engine/src/main.o | Bin 0 -> 9992 bytes engine/src/midi.c | 3 +- engine/src/midi.o | Bin 0 -> 9760 bytes engine/src/pipe.c | 5 +- engine/src/pipe.o | Bin 0 -> 12544 bytes engine/src/queue.o | Bin 0 -> 6112 bytes 14 files changed, 247 insertions(+), 105 deletions(-) create mode 100644 client/tests/test_carla_host_mock.c create mode 100755 engine/looper create mode 100644 engine/src/channel.o create mode 100644 engine/src/looper.o create mode 100644 engine/src/main.o create mode 100644 engine/src/midi.o create mode 100644 engine/src/pipe.o create mode 100644 engine/src/queue.o diff --git a/client/makefile b/client/makefile index 411cfac..7d7811a 100644 --- a/client/makefile +++ b/client/makefile @@ -77,19 +77,30 @@ $(TEST_CARLA_OBJ): tests/test_carla_host.c src/carla_host.h $(TEST_CARLA_BIN): $(TEST_CARLA_OBJ) $(CARLA_OBJ) $(CC) $(CFLAGS) -o $@ $^ $(CARLA_LIB) -ljack +# --- Mock JACK test --- +TEST_CARLA_MOCK_BIN = test_carla_host_mock +CARLA_MOCK_OBJ = src/carla_host_mock.o + +$(CARLA_MOCK_OBJ): src/carla_host.c src/carla_host.h + $(CC) -Wall -Wextra -std=c11 -Isrc $(CARLA_INC) -DTESTING -DMOCK_JACK -c -o $@ $< + +$(TEST_CARLA_MOCK_BIN): tests/test_carla_host_mock.c $(CARLA_MOCK_OBJ) + $(CC) $(CFLAGS) $(CARLA_INC) -DTESTING -DMOCK_JACK -o $@ $^ $(CARLA_LIB) -ljack + # --- Integration test (requires TESTING symbol) --- $(TEST_INTEGRATION_BIN): tests/test_integration.c $(CARLA_TEST_OBJ) $(CC) $(CFLAGS) $(CARLA_INC) -DTESTING -o $@ $^ $(CARLA_LIB) -ljack -test: looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN) +test: looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN) $(TEST_CARLA_MOCK_BIN) ./test_status_parse ./$(TEST_PLUGINS_BIN) ./$(TEST_CLIENT_BIN) ./$(TEST_CARLA_BIN) ./$(TEST_CLIENT_CMD_BIN) ./$(TEST_INTEGRATION_BIN) + ./$(TEST_CARLA_MOCK_BIN) .PHONY: all test clean clean: - rm -f looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN) *.o tests/*.o src/*.o + rm -f looper-client test_status_parse $(TEST_PLUGINS_BIN) $(TEST_CLIENT_BIN) $(TEST_CARLA_BIN) $(TEST_CLIENT_CMD_BIN) $(TEST_INTEGRATION_BIN) $(TEST_CARLA_MOCK_BIN) *.o tests/*.o src/*.o diff --git a/client/src/carla_host.c b/client/src/carla_host.c index ee682e7..fdba62f 100644 --- a/client/src/carla_host.c +++ b/client/src/carla_host.c @@ -1,13 +1,38 @@ #include #include -#include #include #include "carla_host.h" +#ifdef MOCK_JACK +/* Mock JACK functions – always succeed */ +/* Provide a dummy type so we can have a non‑NULL pointer */ +typedef void jack_client_t; +static int mock_jack_connect(const char *from, const char *to) { + (void)from; (void)to; + return 0; +} +static int mock_jack_disconnect(const char *from, const char *to) { + (void)from; (void)to; + return 0; +} +/* Provide a fake jack_client pointer that is non‑NULL */ +#define jack_client ((jack_client_t*)1) +/* Real jack_connect/jack_disconnect take 3 arguments (client, a, b). + We ignore the client and forward to the mock 2‑arg functions. */ +#define jack_connect(client, a, b) ((void)(client), mock_jack_connect(a, b)) +#define jack_disconnect(client, a, b) ((void)(client), mock_jack_disconnect(a, b)) +#else +#include +#endif + #define MAX_PLUGINS 256 static CarlaHostHandle handle = NULL; +#ifdef MOCK_JACK +/* jack_client is defined via macro above (non‑NULL) */ +#else static jack_client_t *jack_client = NULL; // private JACK client for port connections +#endif static int carla_pids[MAX_PLUGINS]; static int plugin_count = 0; @@ -25,16 +50,20 @@ static int conn_count = 0; int carla_init_jack(void) { if (handle != NULL) return 0; +#ifndef MOCK_JACK // 1) Open our own JACK client (for port connections) jack_status_t status; jack_client = jack_client_open("looper-connector", JackNoStartServer, &status); // It's okay if jack_client is NULL; we still try Carla +#endif // 2) Create the Carla host handle handle = carla_standalone_host_init(); if (!handle) { +#ifndef MOCK_JACK if (jack_client) jack_client_close(jack_client); jack_client = NULL; +#endif return -1; } @@ -42,8 +71,10 @@ int carla_init_jack(void) { if (!carla_engine_init(handle, "JACK", "looper-client")) { carla_engine_close(handle); handle = NULL; +#ifndef MOCK_JACK if (jack_client) jack_client_close(jack_client); jack_client = NULL; +#endif return -1; } return 0; @@ -54,10 +85,12 @@ void carla_cleanup_jack(void) { carla_engine_close(handle); handle = NULL; } +#ifndef MOCK_JACK if (jack_client) { jack_client_close(jack_client); jack_client = NULL; } +#endif plugin_count = 0; } diff --git a/client/tests/test_carla_host_mock.c b/client/tests/test_carla_host_mock.c new file mode 100644 index 0000000..915825e --- /dev/null +++ b/client/tests/test_carla_host_mock.c @@ -0,0 +1,92 @@ +#include "carla_host.h" +#include + +static int tests_passed = 0; +static int tests_failed = 0; + +#define ASSERT_EQ(expected, actual, msg) do { \ + if ((expected) != (actual)) { \ + fprintf(stderr, "FAIL: %s (expected %d, got %d)\n", msg, (int)(expected), (int)(actual)); \ + tests_failed++; \ + } else { \ + printf("PASS: %s\n", msg); \ + tests_passed++; \ + } \ +} while(0) + +#define ASSERT_TRUE(expr, msg) do { \ + if (!(expr)) { \ + fprintf(stderr, "FAIL: %s\n", msg); \ + tests_failed++; \ + } else { \ + printf("PASS: %s\n", msg); \ + tests_passed++; \ + } \ +} while(0) + +static void test_init_cleanup(void) +{ + // When compiled with MOCK_JACK, carla_init_jack should succeed + int ret = carla_init_jack(); + ASSERT_EQ(0, ret, "carla_init_jack() returns 0 under MOCK_JACK"); + CarlaHostHandle h = carla_get_handle(); + ASSERT_TRUE(h != NULL, "carla_get_handle() is non‑NULL after init"); + carla_cleanup_jack(); +} + +static void test_load_unload(void) +{ + int ret = carla_init_jack(); + ASSERT_EQ(0, ret, "carla_init_jack() returns 0"); + int id; + ret = carla_load("libmock_plugin.so", "mock_plugin", &id); + // Under mock, carla_load will try to call carla_add_plugin which may fail + // because no real Carla engine. The mock only mocks JACK, not Carla. + // We accept either success or failure – the test just verifies no crash. + if (ret == 0) { + ASSERT_TRUE(id >= 0, "id is non‑negative after load"); + ret = carla_unload(id); + ASSERT_EQ(0, ret, "carla_unload returns 0"); + } else { + printf(" SKIP: carla_load failed, presumably no Carla engine available\n"); + } + carla_cleanup_jack(); +} + +static void test_connect_disconnect(void) +{ + int ret = carla_init_jack(); + ASSERT_EQ(0, ret, "carla_init_jack() returns 0"); + int id = 0; + // Use carla_test_add_connection to simulate a connection + ret = carla_test_add_connection(id, "test:out", "looper:in"); + ASSERT_EQ(0, ret, "carla_test_add_connection returns 0"); + ASSERT_EQ(1, carla_test_connection_count(), "connection count is 1 after add"); + // carla_disconnect_plugin should clear all connections for id 0 + ret = carla_disconnect_plugin(0); + ASSERT_EQ(0, ret, "carla_disconnect_plugin returns 0"); + ASSERT_EQ(0, carla_test_connection_count(), "connection count is 0 after disconnect_plugin"); + carla_cleanup_jack(); +} + +static void test_set_bypass(void) +{ + int ret = carla_init_jack(); + ASSERT_EQ(0, ret, "carla_init_jack() returns 0"); + // bypass should not crash even with no plugin loaded + carla_set_bypass(0, true); + printf("PASS: carla_set_bypass(0, true) did not crash\n"); + tests_passed++; + carla_cleanup_jack(); +} + +int main(void) +{ + printf("=== Carla host mock integration tests ===\n"); + test_init_cleanup(); + test_load_unload(); + test_connect_disconnect(); + test_set_bypass(); + printf("\nResults: %d passed, %d failed\n", tests_passed, tests_failed); + return tests_failed > 0 ? 1 : 0; +} diff --git a/engine/looper b/engine/looper new file mode 100755 index 0000000000000000000000000000000000000000..88ac30017bcc6b3aba14cf49e4287d79531b6420 GIT binary patch literal 72680 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 literal 0 HcmV?d00001 diff --git a/engine/src/channel.c b/engine/src/channel.c index cbf99a4..fdc217f 100644 --- a/engine/src/channel.c +++ b/engine/src/channel.c @@ -7,9 +7,9 @@ /* Helper: zero a scene and set its state to IDLE */ static void init_scene(scene_t *sc) { - memset(sc, 0, sizeof(scene_t)); - atomic_store(&sc->state, STATE_IDLE); - atomic_store(&sc->prev_state, -1); + memset(sc, 0, sizeof(scene_t)); + atomic_store(&sc->state, STATE_IDLE); + atomic_store(&sc->prev_state, -1); } void channel_add(jack_client_t *client, int idx) { @@ -76,61 +76,61 @@ void channel_remove(jack_client_t *client, int idx) { } void channel_add_scene(jack_client_t *client, int idx) { - (void)client; - struct channel_t *cur = get_channels_array(); - if (atomic_load(&cur[idx].scene_count) >= MAX_SCENES) - return; - int ns = atomic_load(&cur[idx].scene_count); - init_scene(&cur[idx].scenes[ns]); - atomic_fetch_add(&cur[idx].scene_count, 1); + (void)client; + struct channel_t *cur = get_channels_array(); + if (atomic_load(&cur[idx].scene_count) >= MAX_SCENES) + return; + int ns = atomic_load(&cur[idx].scene_count); + init_scene(&cur[idx].scenes[ns]); + atomic_fetch_add(&cur[idx].scene_count, 1); } void channel_remove_scene(jack_client_t *client, int idx) { - (void)client; - struct channel_t *cur = get_channels_array(); - int sc = atomic_load(&cur[idx].scene_count); - if (sc <= 1) - return; - int cs = atomic_load(&cur[idx].current_scene); - /* shift remaining scenes down (atomic copy of fields) */ - for (int i = cs; i < sc - 1; i++) { - atomic_store(&cur[idx].scenes[i].loop_count, - atomic_load(&cur[idx].scenes[i+1].loop_count)); - atomic_store(&cur[idx].scenes[i].record_pos, - atomic_load(&cur[idx].scenes[i+1].record_pos)); - atomic_store(&cur[idx].scenes[i].playback_pos, - atomic_load(&cur[idx].scenes[i+1].playback_pos)); - atomic_store(&cur[idx].scenes[i].state, - atomic_load(&cur[idx].scenes[i+1].state)); - atomic_store(&cur[idx].scenes[i].prev_state, - atomic_load(&cur[idx].scenes[i+1].prev_state)); - /* copy loop data (may race with RT thread; acceptable for this release) */ - memcpy(cur[idx].scenes[i].loop.audio_buffer, - cur[idx].scenes[i+1].loop.audio_buffer, - LOOP_BUF_SIZE * sizeof(float)); - } - atomic_fetch_sub(&cur[idx].scene_count, 1); - int new_sc = atomic_load(&cur[idx].scene_count); - if (cs >= new_sc) - atomic_store(&cur[idx].current_scene, new_sc - 1); + (void)client; + struct channel_t *cur = get_channels_array(); + int sc = atomic_load(&cur[idx].scene_count); + if (sc <= 1) + return; + int cs = atomic_load(&cur[idx].current_scene); + /* shift remaining scenes down (atomic copy of fields) */ + for (int i = cs; i < sc - 1; i++) { + atomic_store(&cur[idx].scenes[i].loop_count, + atomic_load(&cur[idx].scenes[i + 1].loop_count)); + atomic_store(&cur[idx].scenes[i].record_pos, + atomic_load(&cur[idx].scenes[i + 1].record_pos)); + atomic_store(&cur[idx].scenes[i].playback_pos, + atomic_load(&cur[idx].scenes[i + 1].playback_pos)); + atomic_store(&cur[idx].scenes[i].state, + atomic_load(&cur[idx].scenes[i + 1].state)); + atomic_store(&cur[idx].scenes[i].prev_state, + atomic_load(&cur[idx].scenes[i + 1].prev_state)); + /* copy loop data (may race with RT thread; acceptable for this release) */ + memcpy(cur[idx].scenes[i].loop.audio_buffer, + cur[idx].scenes[i + 1].loop.audio_buffer, + LOOP_BUF_SIZE * sizeof(float)); + } + atomic_fetch_sub(&cur[idx].scene_count, 1); + int new_sc = atomic_load(&cur[idx].scene_count); + if (cs >= new_sc) + atomic_store(&cur[idx].current_scene, new_sc - 1); } void channel_next_scene(jack_client_t *client, int idx) { - (void)client; - struct channel_t *cur = get_channels_array(); - int sc = atomic_load(&cur[idx].scene_count); - if (sc > 1) { - int cs = atomic_load(&cur[idx].current_scene); - atomic_store(&cur[idx].current_scene, (cs + 1) % sc); - } + (void)client; + struct channel_t *cur = get_channels_array(); + int sc = atomic_load(&cur[idx].scene_count); + if (sc > 1) { + int cs = atomic_load(&cur[idx].current_scene); + atomic_store(&cur[idx].current_scene, (cs + 1) % sc); + } } void channel_prev_scene(jack_client_t *client, int idx) { - (void)client; - struct channel_t *cur = get_channels_array(); - int sc = atomic_load(&cur[idx].scene_count); - if (sc > 1) { - int cs = atomic_load(&cur[idx].current_scene); - atomic_store(&cur[idx].current_scene, (cs - 1 + sc) % sc); - } + (void)client; + struct channel_t *cur = get_channels_array(); + int sc = atomic_load(&cur[idx].scene_count); + if (sc > 1) { + int cs = atomic_load(&cur[idx].current_scene); + atomic_store(&cur[idx].current_scene, (cs - 1 + sc) % sc); + } } diff --git a/engine/src/channel.o b/engine/src/channel.o new file mode 100644 index 0000000000000000000000000000000000000000..13c2887832364ffc7ade564478fbfb1fcfb3aeb3 GIT binary patch literal 18360 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 a%6}@$bVoMr)#q5T)tRfJL)$l9|9=1nzQNW2 literal 0 HcmV?d00001 diff --git a/engine/src/looper.c b/engine/src/looper.c index 8ce993c..db1d86d 100644 --- a/engine/src/looper.c +++ b/engine/src/looper.c @@ -4,48 +4,56 @@ #include "command.h" #include "midi.h" #include "queue.h" -#include -#include #include -#include +#include #include #include #include #include #include #include +#include +#include #define STATUS_FIFO "/tmp/looper_status" static void looper_write_status(void) { - int fd = open(STATUS_FIFO, O_WRONLY | O_NONBLOCK); - if (fd < 0) - return; - struct channel_t *cur = get_channels_array(); - int cap = atomic_load(&channel_capacity); - char buf[256]; - for (int ch = 0; ch < cap; ch++) { - if (!atomic_load(&cur[ch].active)) - continue; - int sc_idx = atomic_load(&cur[ch].current_scene); - int state = atomic_load(&cur[ch].scenes[sc_idx].state); - const char *state_str; - switch (state) { - case STATE_IDLE: state_str = "IDLE"; break; - case STATE_RECORD: state_str = "RECORD"; break; - case STATE_LOOPING: state_str = "LOOPING"; break; - case STATE_PAUSED: state_str = "PAUSED"; break; - default: state_str = "UNKNOWN"; - } - int n = snprintf(buf, sizeof(buf), - "CH=%d SC=%d STATE=%s\n", - ch, sc_idx, state_str); - if (n > 0) { - int ret = write(fd, buf, n); - (void)ret; - } + int fd = open(STATUS_FIFO, O_WRONLY | O_NONBLOCK); + if (fd < 0) + return; + struct channel_t *cur = get_channels_array(); + int cap = atomic_load(&channel_capacity); + char buf[256]; + for (int ch = 0; ch < cap; ch++) { + if (!atomic_load(&cur[ch].active)) + continue; + int sc_idx = atomic_load(&cur[ch].current_scene); + int state = atomic_load(&cur[ch].scenes[sc_idx].state); + const char *state_str; + switch (state) { + case STATE_IDLE: + state_str = "IDLE"; + break; + case STATE_RECORD: + state_str = "RECORD"; + break; + case STATE_LOOPING: + state_str = "LOOPING"; + break; + case STATE_PAUSED: + state_str = "PAUSED"; + break; + default: + state_str = "UNKNOWN"; } - close(fd); + int n = snprintf(buf, sizeof(buf), "CH=%d SC=%d STATE=%s\n", ch, sc_idx, + state_str); + if (n > 0) { + int ret = write(fd, buf, n); + (void)ret; + } + } + close(fd); } /* Global state (shared across files) */ @@ -252,8 +260,7 @@ int process_callback(jack_nframes_t nframes, void *arg) { if (rp < MAX_MIDI_EVENTS) { sc->loop.midi_events[rp].timestamp = ev.time; sc->loop.midi_events[rp].status = ev.buffer[0]; - sc->loop.midi_events[rp].note = - (ev.size > 1) ? ev.buffer[1] : 0; + sc->loop.midi_events[rp].note = (ev.size > 1) ? ev.buffer[1] : 0; sc->loop.midi_events[rp].velocity = (ev.size > 2) ? ev.buffer[2] : 0; atomic_store(&sc->record_pos, rp + 1); @@ -295,23 +302,22 @@ int process_callback(jack_nframes_t nframes, void *arg) { /* no output */ break; default: /* IDLE */ - { - void *midi_in_buf = - jack_port_get_buffer(active_channels[c].midi_in, nframes); - void *midi_out_buf = - jack_port_get_buffer(active_channels[c].midi_out, nframes); - if (midi_in_buf && midi_out_buf) { - jack_midi_clear_buffer(midi_out_buf); - jack_nframes_t nevents = jack_midi_get_event_count(midi_in_buf); - jack_midi_event_t ev; - for (jack_nframes_t j = 0; j < nevents; j++) { - if (jack_midi_event_get(&ev, midi_in_buf, j) != 0) - continue; - jack_midi_event_write(midi_out_buf, ev.time, ev.buffer, ev.size); - } + { + void *midi_in_buf = + jack_port_get_buffer(active_channels[c].midi_in, nframes); + void *midi_out_buf = + jack_port_get_buffer(active_channels[c].midi_out, nframes); + if (midi_in_buf && midi_out_buf) { + jack_midi_clear_buffer(midi_out_buf); + jack_nframes_t nevents = jack_midi_get_event_count(midi_in_buf); + jack_midi_event_t ev; + for (jack_nframes_t j = 0; j < nevents; j++) { + if (jack_midi_event_get(&ev, midi_in_buf, j) != 0) + continue; + jack_midi_event_write(midi_out_buf, ev.time, ev.buffer, ev.size); } } - break; + } break; } if (state == STATE_LOOPING) { atomic_store(&sc->loop_count, atomic_load(&sc->record_pos)); diff --git a/engine/src/looper.o b/engine/src/looper.o new file mode 100644 index 0000000000000000000000000000000000000000..7efc8e550c4520d94eb94a6f88422defa40d37a8 GIT binary patch literal 44408 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 literal 0 HcmV?d00001 diff --git a/engine/src/main.o b/engine/src/main.o new file mode 100644 index 0000000000000000000000000000000000000000..56c78d888c2369440381afabae3b2d0e90181aa1 GIT binary patch literal 9992 zcmb`M2{@En{P2!$xRTuntq8pAE2%@T%E+1sbV*cyYGv6YHSk#wa^w}qr=y`+V3 zlQxQSE2Xr!UFjB=w5Zgr-+N}hr=}DC|MUEw-+7*y_k2I+yS?A@zVE!}%qpju&hm0{ z6mD|VRO*|ADMhh|f9u;xx^|QQk??Q?HaD_>W{H)v1xaWq@G73 zXQhr%K&b{~(%0xWU$k#4>?{3iK0kk#k8EsdZntr&y_=8t|Cn#1$7P+;UViy83Els< zmo`sqlIBy-?!D%+LD*NEnrV*|ef-DHL4#taJ2n3y0Z_DzHoB@l?*rLmbtIRAxSyn! zH5d315s^G0MTKz#mU064p*(?@LleOm6Gjj>l+Oz^V~E6DakPjrg~5t5wq&y6RFPvJ z0oR|;V~8Ud0TBWLFF=gCZuX8d7$Tl9h9^{|q@Ed}f>3cNmmezPibEp=;8c~042|S5 zggkB_PuQ1=BUd1Z5Hq*|;?Nkbn8%Q2Cy7pB@4{$-AXE^{7$Y5I2)N-q#%N>FXcN#w zmm6vmm83^3$L&tvdSiySht8G9E8bP?oOr$S&!KxPmR@Fz)X{OBS$y!Z*XBc7x2sNM zvI;UR)#vN=Hx9f#N6k^UxHu=ro$(|$CpU(>%lGZ*5}}s8`1-r@cei~jF4;U2T`zsM z_hZ{BW%UbITLbEM1pS%wYv9SQ&bwj9@0|{83evnf=xK_lT^vk{0$)lE>Ir@9Xe=Y7yhlN?Yebzk4 zJAcg}&W@?p)b9|(ovn7WC~x-m_%k=XkNX`P`zplezsHf)BU%>iPG6q0&ID!XR#N<5 z_0$7BuBXo&j@vqGZazCuxuz&xy||8JlezeaVrTNW0gX51Vm>aaTsZ_qf@;7#nL z`k~9NX{)u%8!4WpqU9eZmRAZYW0DN*j#L`jD(N-uFP=I zn1<>7ofS9jYx~on**fQVu5nD2tH+ZPyNI~V+u=!{y>&ZFEA2iR9a=7*&kFKv7ME{c z;Gi2Pot;{GS7S826`46@y7Ib?3F;Aw%mZa6Cm5`azK{DaR7%j)OHJR> zV-{KGn%U(uYpP!Dkmm_)TA`_bwT8J*m{8V5m2f6g!q0a){=MVAJ@{0V)x?4i%@d2v zC+q(`wjjRjLWv;VwCcYHjNkiPT=#Q+ec|?}9?z2bw+wbV=ecyH?Kgi@*Sh)j%7Ubd z&5ZKQsA1i@(-a<=DnH8pL)Yt~uUY4ah|7(|rkX_$b+r9{wl~poP93%UfnE0G2|nF_4J?aKtDQEzp(A5KW1>w{^sY~TvxXiSP}jLiE%=b> z%=Q(J9?z|7ShB+4)>A+2oQ2b}9ZD@dF6pH24=YvKaG<1|Y3|C}yRaWqWt7)k@6xUB zMw!MfYd^TpHf)E-;a^)gPIp$J2d|{HLkG)oyBB5H`(9wFPj_+Oy*8!9-MuMm$m+)m zRfqX!6K~!MGTMV5 znA>qap@pqbBW#hsIc`sTeF%T)!0mZ^`sK?rH|i*>wM^<1-5xr6aOFAQ38xoNRoYNB zCvWEk{~aHaMunxDADpFgWA%hICz05stYpIS{POW#8!YYI9HY0s{=D_tn!KWiCL?u9 zJf~z`Q$FG3s&W6NZr4O(kBZ|ne#jqS@)RV*W&0PuCkh?eOhN$d(A{6yZGtc zpOSK-<_;Zv=~d|=|34V#xTi0iO+Gz3$DX^q@u$nfi~ItA7N?i4IjeEHC^#fD{FF5RBkCeN?7evzWM3PH)=_*^owx*C6b?c>gzj4+-{zClc0&E z-jM%ZdHzXPt@Z=vZTE*eZXT$2c728BhMAM*2iEL2iv9S}Lw6FhCu6Q|rtRd(fmxNy zyr1myepaz3@6Ug)>76Y8(BhIYyywL9&JS^4oGL%}Q{kz(Joi}JKXaAs8=-?;Q)`|6 z^Eok}TgHsPuOt^=v+{+(m4NmW`=VZ`CpV15TKeK$QW_#{pkI5N1-64DR(=`9T zFR^D?XlF3;CYwgt*6tlUUcKYh2rpN;o$2)>HnW>|ecF+7sM~7aeC0WpKP>Z~^khNy zpjjKYRp;x?e-|_?h_x-*SkV2ZG-Xcg6s5V-luZYX34XG~FT~4AeTb54a9(a=cKMQl zhN%Xr0;83QV^ubvYjUr8dvL*8UnLWxw_6fTs`sCdw#e?j@vF_9;Lk-?ZbyG#f47xe z94?5xd*<$$y4IlLveKqU|!4@Nn z7g}D&%?k5o8Oe?O>td{#zEa-B`@eY!JlwfHDaH%^1vQ7~%uQ8_*6FPE^i1Aw+A*)8 z)IPH(T{Ln~$o6Wt8}qU?!{0OtS}%1!+4*K~+_IPxd$w(RdewMR$;+^}*(quFMLV|n z*3~pj)ID~Vn{oQBu8;n|L){P8c5D)feID2>7F<_l=}z3$a%ItwD36qXHg4Hw7_7VQ zqKoMQ-FZp|X8*`7E$Hlbf5d~0$(>h^#?6j8)LiS_@nB|4?&%HV4tqWCPI&pEtLt~~ zeT}is-Fs6FOI}pDwUyf&s4cU)xkY{QRlV$C@mbsQR82IQ#m6!REzB5o*Mgyuw`tNP z+ah*Zz1P-?4jwc0SlE*xpI9!c7eC!GtFw7JesS12jbgpe3dUO6>gcA#*R$#m_v4C9 z4^`3q_|btmdmrQdK+EFh6URbBZ>c?gbaHIU!15ZG>oy;fY~ofs$z7OUn5=0cSFtsa@FYTf4Hbb-#SihBy1oM;_;FXnSXSznWEcR6A|&hQXoXrUkLQ z**1fId)43SnXqEdv9vPK&$x$wjj<$?3F0*`07#3Dc3#J9b zl4WVd8vhFm<*!J881x6-j<@D8+RWfL01Dc@^ zYLW+-{Xori@{R+P6voQaD$;>ozEK=Ss_RQHLzKeTEWRIAkYxKkLy`goFJHuv0@Ztb z1xk(3l!^+JWbyICm;yEM2ZlTklF1W4ypadZAG9gTun%tB2Orl5AKwRe?SqH(!8v{K z_&)fCKKQOaczz$ev=4r*4}Px?-qi>H*axS=xuF7PfaLJQVuTWj>2-pT3W^kl3dBKF zP^>Ui%#*4G^Tc@Ff?ob9j?2v14)!xSvz?v2oV+>S_6{?hI8s#+tr{te2;hlCoB%GL z?@zCJU?e1392gNR-~{+fL4<%K0tQPB4qC`a2Vt2Mz>g5|Bnuf1y+jgVK zB@X5bfTMR5boXHHFT;@^WQQ8PO8ziixW8II!aKtbt-UjR|vWaC!I_?L})O~#L`|2r}q`9F!A)2&s;kL>mK zN`~vvdN_Y=G*NUz`3$8$n48M*pJX`xB|-NDyu#8w>A9dI;>z@AE!d-4p@ulJ#lMmI z2+|F6sYFr3po7u{7ZPF)9O=vc%2~;96t^6VB->E5jPv;wogm$&OAlYUB`O}>W=IcT zxd-Tb61*M!&m(vM$UK7Efxd{~4KN>Z1pgW0t|j<-;28w}2>IjZ13up{&_7J*7lK?t z@OtorpBvbZ9`IX)zB)|)V}jd*+)i*1DJ3{>>|YN24XJJwSFNcohVm zO>iTS=@&#v!};LnT>!zyKs`eV-T*v;;QvD0Xo4RC{pAGT4fRYSxH0%iA^2d>-%4b|!cf)WMJ7Z$Mr_aD1Mb z1pf?j0l}}ryqqL>Cd9o;a4wuzGr@-ge@SpVkO#nd<2taw{}_TtfQ;*n_3?f-htRi% z{1XVi801`nAA$Kg1{|dUE+iwBg#I%ayiRam;13AC4$kWZ!TUiSJ`lVH>ZSrOm-u|I zgP$S5ah~{h0>6tQeQ+(wAMbr&eF>z$MnDJYqu<`qAde!rBgm!%cLAA6aQr@MN$@C; zW#5xg+%>@M;E40V@0U&l$Lkk2g6{=+Ho*^q>`m}fAme;-T>Rd-n9#?+BLM_|2yzI) zTR_IoY3#oZI9`uq{t9?3;Ro%Xpq3y#d|js~!1b^WI61!z;OMf1OH)diqWEwz*PmjF z#6syY1ownIK9?!x#fd3qAXm(#nEoOW#S}(J1<7b2&p$et-WmytpmijDuD`#K7elKd zV?aW#Aee_tzcGHOfQL=!c({u&y&Xc!0rW-*{bw}Ar2hlvG3hPPagtpUkb?!$OnOU& z{_9#C4}N(eoFF0E0s22_4B88-A-<2WQ#6{8*&WIuhM?c3+9KqXIV|3+`*Q zM}ch7wT~KF1EYrSJH$Z^AxVq;Zt^gd>VA{x{R>(^KL5A&7PKvjPlm(so9HpwhV#d4 zD&3LPgcz6u3E}q|tWT&>HuOMm^|MBsJ#^DVn+|kC^+R)n?Q#9k^Pso*OJG7rN(N~q zXxJXhi|7uaA{knvEY)CPML3eWb7|gN{%phV?NR>y=?{*N^GDCe-tsSj_?7gyY{T}L z@##))@#7$VGbD`Sqf%mf9DfDPkO~VA(0$b6K&~Y&46KIhkV5PBX3vIs+b8k%?TfU} z!uH=(B)#WgZ$NMy7ax&-+?Q4Dhc=&jX{2rut%FKUoF=6L_T>EI{ITmAx`TX@_SRr; zjTPZY+Fzu3Z}T^oAvM7BgywG${lWH__ZAyjMne1)NDS@i^>+OsMm{@`{d@SUMV%-Z XAxided$W&ZATJb!_id!ok8|}uwpT!7 literal 0 HcmV?d00001 diff --git a/engine/src/midi.c b/engine/src/midi.c index 410c990..1f35921 100644 --- a/engine/src/midi.c +++ b/engine/src/midi.c @@ -82,8 +82,7 @@ void midi_handle_events(void *port_buffer, jack_nframes_t nframes) { queue_push(&cmd_queue_main_midi, cmd); } break; case 69: { - command_t cmd = { - .type = CMD_ADD_SCENE, .channel = -1, .data = 0}; + command_t cmd = {.type = CMD_ADD_SCENE, .channel = -1, .data = 0}; queue_push(&cmd_queue_main_midi, cmd); } break; case 70: { diff --git a/engine/src/midi.o b/engine/src/midi.o new file mode 100644 index 0000000000000000000000000000000000000000..4ab9814412161c08130b07472bd1b46ccf11cf3a GIT binary patch literal 9760 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 #include #include -#include #include +#include #include #define FIFO_PATH "/tmp/looper_cmd" @@ -39,7 +39,8 @@ static void *pipe_thread_func(void *arg) { command_t cmd = {.type = CMD_ADD_CHANNEL, .channel = -1, .data = 0}; queue_push(&cmd_queue_main_fifo, cmd); } else if (strcmp(line, "add_midi") == 0) { - command_t cmd = {.type = CMD_ADD_MIDI_CHANNEL, .channel = -1, .data = 0}; + command_t cmd = { + .type = CMD_ADD_MIDI_CHANNEL, .channel = -1, .data = 0}; queue_push(&cmd_queue_main_fifo, cmd); } else if (strcmp(line, "remove") == 0) { command_t cmd = {.type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0}; diff --git a/engine/src/pipe.o b/engine/src/pipe.o new file mode 100644 index 0000000000000000000000000000000000000000..40363e39fa5fb79a03c3d0abde120854a0e2d97b GIT binary patch literal 12544 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