feat: add microui-based GUI with transport controls and progress bar

Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-01 13:02:39 +00:00
parent 3b95c22736
commit 05c6f34b8f
7 changed files with 473 additions and 3 deletions

111
engine.c
View File

@@ -510,3 +510,114 @@ const char* quantize_mode_to_string(QuantizeMode mode) {
default: return "Unknown";
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <jack/jack.h>
#include "engine.h"
static float *audio_buffer = NULL;
static int buffer_size = 0;
static float bpm = 120.0f;
static int loop_length = 8;
static int current_beat = 0;
static int active = 0;
static jack_nframes_t sample_rate = 0;
static jack_port_t *output_port = NULL;
static int process_callback(jack_nframes_t nframes, void *arg)
{
(void)arg;
jack_default_audio_sample_t *out = jack_port_get_buffer(output_port, nframes);
if (!out) return 0;
/* simple metronome: generate a click on each beat */
float samples_per_beat = sample_rate * 60.0f / bpm;
static float phase = 0.0f;
for (jack_nframes_t i = 0; i < nframes; i++) {
if (phase >= samples_per_beat) {
phase -= samples_per_beat;
current_beat = (current_beat + 1) % loop_length;
}
float sample = 0.0f;
if (active) {
/* short click at start of beat */
float click_duration = samples_per_beat * 0.05f;
if (phase < click_duration) {
float t = phase / click_duration;
sample = sinf(t * M_PI) * 0.3f;
}
}
out[i] = sample;
phase += 1.0f;
}
return 0;
}
int engine_init(jack_client_t *client, float *buffer, int buf_size)
{
audio_buffer = buffer;
buffer_size = buf_size;
sample_rate = jack_get_sample_rate(client);
output_port = jack_port_register(client, "output",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if (!output_port) {
fprintf(stderr, "no more JACK ports available\n");
return -1;
}
jack_set_process_callback(client, process_callback, NULL);
if (jack_activate(client)) {
fprintf(stderr, "cannot activate client\n");
return -1;
}
return 0;
}
void engine_cleanup(jack_client_t *client)
{
jack_deactivate(client);
jack_port_unregister(client, output_port);
}
int engine_start(jack_client_t *client)
{
(void)client;
active = 1;
return 0;
}
int engine_stop(jack_client_t *client)
{
(void)client;
active = 0;
return 0;
}
void engine_set_bpm(jack_client_t *client, float new_bpm)
{
(void)client;
bpm = new_bpm;
}
void engine_set_loop_length(jack_client_t *client, int beats)
{
(void)client;
loop_length = beats;
if (current_beat >= loop_length) current_beat = 0;
}
int engine_get_current_beat(jack_client_t *client)
{
(void)client;
return current_beat;
}