summaryrefslogtreecommitdiff
path: root/src/fruits/cmc/ui
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-08-26 17:58:15 -0400
committerAndrew Opalach <andrew@akon.city> 2026-08-26 17:58:15 -0400
commitb112da5b9825262b3b779bd699a4cf4bca8b6d01 (patch)
tree7742d66d3aac6bc007c638377f81da738e9886be /src/fruits/cmc/ui
parent197d41a3e23cab35848f623c6133baccc62aacbe (diff)
downloadcamu-b112da5b9825262b3b779bd699a4cf4bca8b6d01.tar.gz
camu-b112da5b9825262b3b779bd699a4cf4bca8b6d01.tar.bz2
camu-b112da5b9825262b3b779bd699a4cf4bca8b6d01.zip
Rough cmc UI tweaking
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/fruits/cmc/ui')
-rw-r--r--src/fruits/cmc/ui/panes/list.c57
-rw-r--r--src/fruits/cmc/ui/ui.c8
-rw-r--r--src/fruits/cmc/ui/util/waveform.c34
-rw-r--r--src/fruits/cmc/ui/widgets/now_playing.c42
4 files changed, 113 insertions, 28 deletions
diff --git a/src/fruits/cmc/ui/panes/list.c b/src/fruits/cmc/ui/panes/list.c
index b599cc5..388e22f 100644
--- a/src/fruits/cmc/ui/panes/list.c
+++ b/src/fruits/cmc/ui/panes/list.c
@@ -226,11 +226,36 @@ void cmc_list_pane_clear(struct cmc_list_pane *lp)
cmc_now_playing_clear(&lp->np);
}
+static u32 count_headers(struct cmc_list *list)
+{
+ struct cmc_list_entry *entry;
+ str header = AL_STR_EMPTY;
+ u32 count = 0;
+ al_array_foreach(list->entries, i, entry) {
+ u32 rslash = al_str_rfind(&entry->brief, '/');
+ str remain = al_str_substr(&entry->brief, 0, rslash);
+ rslash = al_str_rfind(&remain, '/');
+ str new_header;
+ if (rslash != AL_STR_NO_POS) {
+ new_header = al_str_substr(&remain, rslash + 1, remain.length);
+ } else {
+ new_header = remain;
+ }
+ if (al_str_is_empty(&header) || !al_str_eq(&header, &new_header)) {
+ header = new_header;
+ count++;
+ }
+ }
+ return count;
+}
+
static void render_list_entries(struct cmc_list_pane *lp, struct cmc_list_tab *tab, s32 max_height)
{
struct cmc_list *list = tab->list;
struct ncplane *n = lp->n;
s32 tracked = tab->move.active ? tab->move.selected + tab->move.offset : tab->selected;
+ u32 headers = count_headers(list);
+ max_height -= headers;
s32 count = (s32)list->entries.count;
s32 midpoint = max_height / 2;
s32 rounded = (max_height + 1) / 2;
@@ -245,6 +270,9 @@ static void render_list_entries(struct cmc_list_pane *lp, struct cmc_list_tab *t
top = tracked - midpoint;
end = tracked + rounded;
}
+ str header = AL_STR_EMPTY;
+ s32 last_y = 0;
+ s32 y_offset = 0;
s32 index;
struct cmc_list_entry *entry;
for (s32 i = top; i < end; i++) {
@@ -258,14 +286,39 @@ static void render_list_entries(struct cmc_list_pane *lp, struct cmc_list_tab *t
}
}
entry = al_array_at(list->entries, index);
+ u32 rslash = al_str_rfind(&entry->brief, '/');
+ str part;
+ if (rslash != AL_STR_NO_POS) {
+ part = al_str_substr(&entry->brief, rslash + 1, entry->brief.length);
+ } else {
+ part = entry->brief;
+ }
+ str remain = al_str_substr(&entry->brief, 0, rslash);
+ rslash = al_str_rfind(&remain, '/');
+ str new_header;
+ if (rslash != AL_STR_NO_POS) {
+ new_header = al_str_substr(&remain, rslash + 1, remain.length);
+ } else {
+ new_header = remain;
+ }
+ if (al_str_is_empty(&header) || !al_str_eq(&header, &new_header)) {
+ header = new_header;
+ char *c_str = al_str_to_c_str(&header);
+ ncplane_set_styles(n, NCSTYLE_BOLD);
+ ncplane_putstr_yx(n, last_y, 0, c_str);
+ ncplane_set_styles(n, NCSTYLE_NONE);
+ al_free(c_str);
+ y_offset++;
+ }
bool on_current = list->current >= 0 && index == list->current;
bool styled = i == tracked;
if (styled) {
ncplane_set_styles(n, NCSTYLE_BOLD);
ncplane_set_fg_palindex(n, 4);
}
- s32 y = i - top;
- char *c_str = al_str_to_c_str(&entry->brief);
+ s32 y = i - top + y_offset;
+ last_y = y + 1;
+ char *c_str = al_str_to_c_str(&part);
if (tab->move.active && i == tracked) {
ncplane_putstr_yx(n, y, 0, c_str);
} else if (on_current) {
diff --git a/src/fruits/cmc/ui/ui.c b/src/fruits/cmc/ui/ui.c
index b51ec53..55441e9 100644
--- a/src/fruits/cmc/ui/ui.c
+++ b/src/fruits/cmc/ui/ui.c
@@ -176,9 +176,9 @@ static bool relayout(struct cmc_ui *ui, struct ncplane *stdplane)
if (ui->n) ncplane_destroy(ui->n);
struct ncplane_options nopts = { 0 };
nopts.x = 1;
- nopts.y = 1;
+ nopts.y = 0;
nopts.margin_r = 2;
- nopts.margin_b = 1;
+ nopts.margin_b = 0;
nopts.flags = NCPLANE_OPTION_MARGINALIZED;
ui->n = ncplane_create(stdplane, &nopts);
@@ -223,7 +223,7 @@ static s32 log_callback(void *userdata, u8 level, char *message)
{
struct cmc_ui *ui = (struct cmc_ui *)userdata;
(void)level;
- cmc_log_pane_push_message(&ui->log, message);
+ cmc_log_pane_push_message(&ui->log, strdup(message));
return al_strnlen(message, AL_LOG_MESSAGE_SIZE);
}
@@ -263,7 +263,7 @@ bool cmc_ui_init(struct cmc_ui *ui, struct nn_event_loop *loop, struct cmc *c)
nn_poll_start(&ui->input_poll, ui->loop);
nn_timer_init(&ui->render_timer, ui->loop, render_timer_callback, ui);
- nn_timer_set_repeat(&ui->render_timer, NNWT_TS_FROM_USEC(200000));
+ nn_timer_set_repeat(&ui->render_timer, NNWT_TS_FROM_USEC(40000));
nn_timer_again(&ui->render_timer);
return true;
diff --git a/src/fruits/cmc/ui/util/waveform.c b/src/fruits/cmc/ui/util/waveform.c
index 624069e..f43890d 100644
--- a/src/fruits/cmc/ui/util/waveform.c
+++ b/src/fruits/cmc/ui/util/waveform.c
@@ -1,18 +1,21 @@
#include <al/log.h>
#include <al/math.h>
+#include "../../util/color_palette.h"
+
#include "waveform.h"
#define WITHIN_RMS(low, high, rms) \
((low >= 0 && low <= rms) || (high < 0 && high >= -rms) || (low < 0 && high > 0 && rms > 0))
-//#define OUTPUT_WAVEFORM_PNG
+#define OUTPUT_WAVEFORM_PNG
//#define WAVEFORM_REFERENCE_MODE
#ifdef OUTPUT_WAVEFORM_PNG
#include <nnwt/file.h>
#include <nnwt/net.h>
+#include <nnwt/time.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include <stb_image_write.h>
+//#include <stb_image_write.h>
// min/max: #BC615E, #F4EAE0
// rms: #FF928F, #E4CAAF
@@ -21,9 +24,10 @@
// rms: #f44f7a, #c84064
// extra: #f6ac7f, #F5F4FA, #5b524b
// left channel: n == 0, right channel: n == 1.
-#define COLOR_FOR_PIXEL(n, rms) rms ? \
- n == 0 ? nn_htonl(0xe4caaf99) : nn_htonl(0xff928fff) : \
- n == 0 ? nn_htonl(0xf4eae099) : nn_htonl(0xbc615eff)
+static u32 color1, color2, color3, color4;
+#define COLOR_FOR_PIXEL(n, rms) ((rms) ? \
+ ((n == 0) ? color1 : color3) : \
+ ((n == 0) ? color2 : color4))
// ss: current sample, ns: next sample.
#define HIT_WAVE(low, high, ss, ns) \
@@ -33,6 +37,11 @@ static void test_write_bitmap(struct cmc_list_entry *entry, u32 width, u32 heigh
{
f64 start = nn_get_tick();
+ color1 = nn_htonl((global_color_palette.colors[CAMU_COLOR5] << 8) | 0xFF);
+ color2 = nn_htonl((global_color_palette.colors[CAMU_COLOR2] << 8) | 0xFF);
+ color3 = nn_htonl((global_color_palette.colors[CAMU_COLOR3] << 8) | 0xFF);
+ color4 = nn_htonl((global_color_palette.colors[CAMU_COLOR1] << 8) | 0xFF);
+
*rgba = al_calloc(width * height, 4);
u32 channels = entry->raw.fmt.channel_count;
@@ -72,7 +81,12 @@ static void test_write_bitmap(struct cmc_list_entry *entry, u32 width, u32 heigh
for (u32 j = 0; j < height; j++) {
low = steps[j + 1], high = steps[j];
if (low < max && high >= min) {
- (*rgba)[j * width + i] = COLOR_FOR_PIXEL(n, WITHIN_RMS(low, high, rms));
+ bool in_rms = WITHIN_RMS(low, high, rms);
+ u32 *out = *rgba + (j * width + i);
+ if (n == 1 && *out == COLOR_FOR_PIXEL(0, true) && !in_rms) {
+ continue;
+ }
+ *out = COLOR_FOR_PIXEL(n, in_rms);
}
}
#else
@@ -82,7 +96,12 @@ static void test_write_bitmap(struct cmc_list_entry *entry, u32 width, u32 heigh
for (u32 j = 0; j < height; j++) {
low = steps[j + 1], high = steps[j];
if (HIT_WAVE(low, high, ss, ns)) {
- (*rgba)[j * width + i] = COLOR_FOR_PIXEL(n, WITHIN_RMS(low, high, rms));
+ bool in_rms = WITHIN_RMS(low, high, rms);
+ u32 *out = *rgba + (j * width + i);
+ if (n == 1 && *out == COLOR_FOR_PIXEL(0, true) && !in_rms) {
+ continue;
+ }
+ *out = COLOR_FOR_PIXEL(n, in_rms);
}
}
}
@@ -93,7 +112,6 @@ static void test_write_bitmap(struct cmc_list_entry *entry, u32 width, u32 heigh
log_info("generating waveform took: %.2fs.", nn_get_tick() - start);
//stbi_write_png("./waveform.png", width, height, 4, *rgba, width * 4);
-
/*
struct nn_file file;
nn_file_open(&file, &al_str_c("./raw_samples.raw"), NNWT_FILE_CREATE);
diff --git a/src/fruits/cmc/ui/widgets/now_playing.c b/src/fruits/cmc/ui/widgets/now_playing.c
index 9edf6ca..56405b3 100644
--- a/src/fruits/cmc/ui/widgets/now_playing.c
+++ b/src/fruits/cmc/ui/widgets/now_playing.c
@@ -140,32 +140,46 @@ void cmc_now_playing_render(struct cmc_now_playing *np, struct cmc_list_entry *e
ncplane_set_fg_default(np->n);
char timestr[16] = { 0 }; // max = 829128280:01:49\0
- s32 offset = camu_print_time(timestr, sizeof(timestr), pos, true, 4);
+ s32 width1 = camu_print_time(timestr, sizeof(timestr), pos, true, 3);
ncplane_putstr_yx(np->n, 1, 4, timestr);
- ncplane_putstr_yx(np->n, 1, 4 + offset, "⎹");
-
- if (entry) {
- char *c_str = al_str_to_c_str(&entry->brief);
- ncplane_putnstr_yx(np->n, 1, 6 + offset, MIN(al_strlen(c_str), (size_t)60), c_str);
- al_free(c_str);
- }
+ ncplane_putstr_yx(np->n, 1, 4 + width1, "⎹");
+ s32 width2;
bool show_remaining = false;
if (show_remaining) {
- offset = camu_print_time(timestr, sizeof(timestr), remaining, true, 4);
+ width2 = camu_print_time(timestr, sizeof(timestr), remaining, true, 3);
} else {
- offset = camu_print_time(timestr, sizeof(timestr), duration, true, 4);
+ width2 = camu_print_time(timestr, sizeof(timestr), duration, true, 3);
}
- ncplane_putstr_yx(np->n, 1, width - 4 - offset, "⎸");
+ s32 x1 = width - 4 - width2;
+ ncplane_putstr_yx(np->n, 1, x1, "⎸");
// "=" Duration, "+" Segment, "-" Remaining.
if (show_remaining) {
- ncplane_putstr_yx(np->n, 1, width - 3 - offset, "-");
+ ncplane_putstr_yx(np->n, 1, x1 + 1, "-");
} else {
- ncplane_putstr_yx(np->n, 1, width - 3 - offset, "=");
+ ncplane_putstr_yx(np->n, 1, x1 + 1, "=");
}
- ncplane_putstr_yx(np->n, 1, width - 2 - offset, timestr);
+ ncplane_putstr_yx(np->n, 1, x1 + 2, timestr);
if (entry) {
+ u32 rslash = al_str_rfind(&entry->brief, '/');
+ str part;
+ if (rslash != AL_STR_NO_POS) {
+ part = al_str_substr(&entry->brief, rslash + 1, entry->brief.length);
+ } else {
+ part = entry->brief;
+ }
+ char *c_str = al_str_to_c_str(&part);
+ s32 x2 = 6 + width1;
+ // @TODO: Can mid be negative.
+ s32 mid = x1 - x2;
+ ncplane_putnstr_yx(np->n, 1, x2, MIN(al_strlen(c_str), (size_t)mid), c_str);
+ if (part.length >= mid) {
+ ncplane_putnstr_yx(np->n, 1, x2 + mid - 1, 1, ".");
+ ncplane_putnstr_yx(np->n, 1, x2 + mid - 2, 1, ".");
+ }
+ al_free(c_str);
+
bool visual_cached = false;
struct cmc_now_playing_visual *visual;
al_array_foreach_ptr(np->visuals, i, visual) {