More minimal preview view in the top right corner

This commit is contained in:
markmental 2026-03-30 12:23:19 -04:00
commit fe5fccbd02
4 changed files with 60 additions and 20 deletions

View file

@ -15,6 +15,7 @@
#define CHANNEL_BANNER_DURATION_MS 5000 #define CHANNEL_BANNER_DURATION_MS 5000
#define CHANNEL_SWITCH_LOCK_DURATION_MS 7000 #define CHANNEL_SWITCH_LOCK_DURATION_MS 7000
#define NUMERIC_INPUT_TIMEOUT_MS 1000 #define NUMERIC_INPUT_TIMEOUT_MS 1000
#define GUIDE_PREVIEW_FRAME_INTERVAL_MS 83
static void configure_runtime_environment(void) { static void configure_runtime_environment(void) {
char runtime_dir[64]; char runtime_dir[64];
@ -66,6 +67,9 @@ static void destroy_video_texture(App *app) {
app->texture_width = 0; app->texture_width = 0;
app->texture_height = 0; app->texture_height = 0;
} }
if (app) {
app->last_guide_preview_update = 0;
}
} }
static void begin_startup_handoff(App *app) { static void begin_startup_handoff(App *app) {
@ -82,8 +86,25 @@ static int update_video_texture(App *app) {
double sync_clock; double sync_clock;
double lead_tolerance; double lead_tolerance;
Uint64 now_ticks; Uint64 now_ticks;
Uint32 update_ticks;
if (!app) {
return -1;
}
now_ticks = SDL_GetTicks64(); now_ticks = SDL_GetTicks64();
update_ticks = (Uint32) now_ticks;
if (app->mode == MODE_GUIDE &&
app->video_texture &&
update_ticks - app->last_guide_preview_update < GUIDE_PREVIEW_FRAME_INTERVAL_MS) {
if (app->startup_handoff_active && app->startup_handoff_until != 0 && SDL_GetTicks() >= app->startup_handoff_until) {
app->startup_handoff_active = 0;
app->startup_handoff_until = 0;
}
return 0;
}
sync_clock = player_get_sync_clock(&app->player, now_ticks); sync_clock = player_get_sync_clock(&app->player, now_ticks);
lead_tolerance = app->startup_handoff_active ? 0.240 : 0.060; lead_tolerance = app->startup_handoff_active ? 0.240 : 0.060;
@ -119,6 +140,10 @@ static int update_video_texture(App *app) {
frame.pitch_v); frame.pitch_v);
frame_data_free(&frame); frame_data_free(&frame);
if (app->mode == MODE_GUIDE) {
app->last_guide_preview_update = update_ticks;
}
if (app->startup_handoff_active && app->startup_handoff_until != 0 && SDL_GetTicks() >= app->startup_handoff_until) { if (app->startup_handoff_active && app->startup_handoff_until != 0 && SDL_GetTicks() >= app->startup_handoff_until) {
app->startup_handoff_active = 0; app->startup_handoff_active = 0;
app->startup_handoff_until = 0; app->startup_handoff_until = 0;

View file

@ -24,6 +24,7 @@ typedef struct App {
int startup_handoff_active; int startup_handoff_active;
int last_blackout_state; int last_blackout_state;
Uint32 startup_handoff_until; Uint32 startup_handoff_until;
Uint32 last_guide_preview_update;
Uint32 channel_banner_until; Uint32 channel_banner_until;
Uint32 channel_switch_lock_until; Uint32 channel_switch_lock_until;
time_t app_start_time; time_t app_start_time;

View file

@ -110,8 +110,8 @@ static const SDL_Color COLOR_PILL_SHADOW = {0x00, 0x00, 0x00, 0x40};
#define GUIDE_VISIBLE_ROWS 5 #define GUIDE_VISIBLE_ROWS 5
#define TIMELINE_VISIBLE_SECONDS (90.0 * 60.0) #define TIMELINE_VISIBLE_SECONDS (90.0 * 60.0)
#define GUIDE_INFO_WIDTH 390 #define GUIDE_INFO_WIDTH 390
#define GUIDE_PREVIEW_WIDTH 430 #define GUIDE_PREVIEW_WIDTH 240
#define GUIDE_PREVIEW_HEIGHT 194 #define GUIDE_PREVIEW_HEIGHT 135
#define GUIDE_STATUS_HEIGHT 42 #define GUIDE_STATUS_HEIGHT 42
#define GUIDE_GRID_TOP 212 #define GUIDE_GRID_TOP 212
#define GUIDE_FOOTER_HEIGHT 54 #define GUIDE_FOOTER_HEIGHT 54

View file

@ -503,8 +503,14 @@ static void draw_mini_status_bar(SDL_Renderer *renderer,
const Channel *selected_channel, const Channel *selected_channel,
const SDL_Rect *rect, const SDL_Rect *rect,
time_t now_wall) { time_t now_wall) {
char status_text[256]; char clock_text[32];
char channel_text[192];
char fitted_channel_text[192];
SDL_Color text_color; SDL_Color text_color;
SDL_Rect time_rect;
SDL_Rect channel_rect;
int time_width = 0;
int gap = 8;
if (!rect) { if (!rect) {
return; return;
@ -519,17 +525,31 @@ static void draw_mini_status_bar(SDL_Renderer *renderer,
blend_color(theme->status_bottom, theme->status_mid, 220)); blend_color(theme->status_bottom, theme->status_mid, 220));
stroke_rect(renderer, rect, theme->panel_border); stroke_rect(renderer, rect, theme->panel_border);
if (selected_channel) {
char clock_text[32];
format_time_compact(clock_text, sizeof(clock_text), now_wall); format_time_compact(clock_text, sizeof(clock_text), now_wall);
snprintf(status_text, sizeof(status_text), "Time %s | Channel %s %d", clock_text, selected_channel->name, selected_channel->number); if (TTF_SizeUTF8(font, clock_text, &time_width, NULL) != 0) {
} else { time_width = rect->w / 3;
char clock_text[32];
format_time_compact(clock_text, sizeof(clock_text), now_wall);
snprintf(status_text, sizeof(status_text), "Time %s", clock_text);
} }
draw_text_clipped(renderer, font, status_text, rect, rect->x + 10, rect->y + 4, text_color); time_rect = (SDL_Rect){rect->x + 8, rect->y, SDL_min(time_width + 4, rect->w - 16), rect->h};
draw_text_clipped(renderer, font, clock_text, &time_rect, time_rect.x, rect->y + 4, text_color);
if (selected_channel) {
channel_rect = (SDL_Rect){time_rect.x + time_rect.w + gap,
rect->y,
rect->x + rect->w - (time_rect.x + time_rect.w + gap) - 8,
rect->h};
if (channel_rect.w > 0) {
snprintf(channel_text, sizeof(channel_text), "%d %s", selected_channel->number, selected_channel->name);
fit_text_with_ellipsis(font, channel_text, channel_rect.w, fitted_channel_text, sizeof(fitted_channel_text));
draw_text_clipped(renderer,
font,
fitted_channel_text,
&channel_rect,
channel_rect.x,
rect->y + 4,
text_color);
}
}
} }
static void draw_info_panel(SDL_Renderer *renderer, static void draw_info_panel(SDL_Renderer *renderer,
@ -661,13 +681,6 @@ static void draw_footer_legend(SDL_Renderer *renderer,
} }
} }
static void draw_scanline_overlay(SDL_Renderer *renderer, int width, int height, const GuideTheme *theme) {
(void) renderer;
(void) width;
(void) height;
(void) theme;
}
static void draw_channel_status_banner(SDL_Renderer *renderer, static void draw_channel_status_banner(SDL_Renderer *renderer,
const UiFonts *fonts, const UiFonts *fonts,
const GuideTheme *theme, const GuideTheme *theme,
@ -946,6 +959,8 @@ void ui_render_guide(SDL_Renderer *renderer,
double guide_view_end_seconds = guide_view_start_seconds + TIMELINE_VISIBLE_SECONDS; double guide_view_end_seconds = guide_view_start_seconds + TIMELINE_VISIBLE_SECONDS;
double guide_focus_seconds = channel_schedule_elapsed_seconds(app_start_time, guide_focus_time); double guide_focus_seconds = channel_schedule_elapsed_seconds(app_start_time, guide_focus_time);
(void) active_channel;
if (channels && channels->count > 0 && selected_channel >= 0 && selected_channel < channels->count) { if (channels && channels->count > 0 && selected_channel >= 0 && selected_channel < channels->count) {
selected_channel_ptr = &channels->items[selected_channel]; selected_channel_ptr = &channels->items[selected_channel];
} }
@ -1145,7 +1160,6 @@ void ui_render_guide(SDL_Renderer *renderer,
} }
draw_footer_legend(renderer, fonts, theme, window_width, window_height, cache->logo_texture); draw_footer_legend(renderer, fonts, theme, window_width, window_height, cache->logo_texture);
draw_scanline_overlay(renderer, window_width, window_height, theme);
} }
void ui_render_theme_picker(SDL_Renderer *renderer, void ui_render_theme_picker(SDL_Renderer *renderer,