diff --git a/src/app.c b/src/app.c index dd8dbcc..5075bb4 100644 --- a/src/app.c +++ b/src/app.c @@ -15,6 +15,7 @@ #define CHANNEL_BANNER_DURATION_MS 5000 #define CHANNEL_SWITCH_LOCK_DURATION_MS 7000 #define NUMERIC_INPUT_TIMEOUT_MS 1000 +#define GUIDE_PREVIEW_FRAME_INTERVAL_MS 83 static void configure_runtime_environment(void) { char runtime_dir[64]; @@ -66,6 +67,9 @@ static void destroy_video_texture(App *app) { app->texture_width = 0; app->texture_height = 0; } + if (app) { + app->last_guide_preview_update = 0; + } } static void begin_startup_handoff(App *app) { @@ -82,8 +86,25 @@ static int update_video_texture(App *app) { double sync_clock; double lead_tolerance; Uint64 now_ticks; + Uint32 update_ticks; + + if (!app) { + return -1; + } 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); 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_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) { app->startup_handoff_active = 0; app->startup_handoff_until = 0; diff --git a/src/app.h b/src/app.h index f8d6912..5207292 100644 --- a/src/app.h +++ b/src/app.h @@ -24,6 +24,7 @@ typedef struct App { int startup_handoff_active; int last_blackout_state; Uint32 startup_handoff_until; + Uint32 last_guide_preview_update; Uint32 channel_banner_until; Uint32 channel_switch_lock_until; time_t app_start_time; diff --git a/src/theme.h b/src/theme.h index f321b30..9a4b52f 100644 --- a/src/theme.h +++ b/src/theme.h @@ -110,8 +110,8 @@ static const SDL_Color COLOR_PILL_SHADOW = {0x00, 0x00, 0x00, 0x40}; #define GUIDE_VISIBLE_ROWS 5 #define TIMELINE_VISIBLE_SECONDS (90.0 * 60.0) #define GUIDE_INFO_WIDTH 390 -#define GUIDE_PREVIEW_WIDTH 430 -#define GUIDE_PREVIEW_HEIGHT 194 +#define GUIDE_PREVIEW_WIDTH 240 +#define GUIDE_PREVIEW_HEIGHT 135 #define GUIDE_STATUS_HEIGHT 42 #define GUIDE_GRID_TOP 212 #define GUIDE_FOOTER_HEIGHT 54 diff --git a/src/ui.c b/src/ui.c index 0ce6bc2..cb64546 100644 --- a/src/ui.c +++ b/src/ui.c @@ -503,8 +503,14 @@ static void draw_mini_status_bar(SDL_Renderer *renderer, const Channel *selected_channel, const SDL_Rect *rect, 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_Rect time_rect; + SDL_Rect channel_rect; + int time_width = 0; + int gap = 8; if (!rect) { return; @@ -519,17 +525,31 @@ static void draw_mini_status_bar(SDL_Renderer *renderer, blend_color(theme->status_bottom, theme->status_mid, 220)); stroke_rect(renderer, rect, theme->panel_border); - if (selected_channel) { - char clock_text[32]; - 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); - } else { - char clock_text[32]; - format_time_compact(clock_text, sizeof(clock_text), now_wall); - snprintf(status_text, sizeof(status_text), "Time %s", clock_text); + format_time_compact(clock_text, sizeof(clock_text), now_wall); + if (TTF_SizeUTF8(font, clock_text, &time_width, NULL) != 0) { + time_width = rect->w / 3; } - 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, @@ -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, const UiFonts *fonts, 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_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) { 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_scanline_overlay(renderer, window_width, window_height, theme); } void ui_render_theme_picker(SDL_Renderer *renderer,