Implement full screen
This commit is contained in:
parent
b84a3060c1
commit
c840dc0134
6 changed files with 73 additions and 25 deletions
33
src/app.c
33
src/app.c
|
|
@ -137,6 +137,21 @@ static void tune_relative(App *app, int delta) {
|
|||
player_tune(&app->player, next_index);
|
||||
}
|
||||
|
||||
static void toggle_fullscreen(App *app) {
|
||||
Uint32 flags;
|
||||
|
||||
if (!app || !app->window) {
|
||||
return;
|
||||
}
|
||||
|
||||
flags = app->is_fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
if (SDL_SetWindowFullscreen(app->window, flags) == 0) {
|
||||
app->is_fullscreen = !app->is_fullscreen;
|
||||
} else {
|
||||
fprintf(stderr, "Fullscreen toggle failed: %s\n", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_event(App *app, const SDL_Event *event) {
|
||||
if (event->type == SDL_QUIT) {
|
||||
app->running = 0;
|
||||
|
|
@ -158,6 +173,9 @@ static void handle_event(App *app, const SDL_Event *event) {
|
|||
case SDLK_TAB:
|
||||
app->mode = app->mode == MODE_FULLSCREEN ? MODE_GUIDE : MODE_FULLSCREEN;
|
||||
break;
|
||||
case SDLK_f:
|
||||
toggle_fullscreen(app);
|
||||
break;
|
||||
case SDLK_UP:
|
||||
tune_relative(app, -1);
|
||||
break;
|
||||
|
|
@ -243,6 +261,8 @@ void app_run(App *app) {
|
|||
|
||||
while (app->running) {
|
||||
int in_blackout;
|
||||
int output_width = WINDOW_WIDTH;
|
||||
int output_height = WINDOW_HEIGHT;
|
||||
Uint64 now_ticks;
|
||||
time_t now_wall;
|
||||
|
||||
|
|
@ -255,6 +275,11 @@ void app_run(App *app) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (SDL_GetRendererOutputSize(app->renderer, &output_width, &output_height) != 0) {
|
||||
output_width = WINDOW_WIDTH;
|
||||
output_height = WINDOW_HEIGHT;
|
||||
}
|
||||
|
||||
in_blackout = player_is_in_blackout(&app->player);
|
||||
now_ticks = SDL_GetTicks64();
|
||||
now_wall = time(NULL);
|
||||
|
|
@ -266,7 +291,7 @@ void app_run(App *app) {
|
|||
app->last_blackout_state = in_blackout;
|
||||
|
||||
if (app->channels.count == 0) {
|
||||
ui_render_no_media(app->renderer, &app->ui_cache);
|
||||
ui_render_no_media(app->renderer, &app->ui_cache, output_width, output_height);
|
||||
} else if (app->mode == MODE_GUIDE) {
|
||||
if (!in_blackout) {
|
||||
player_resume_audio(&app->player);
|
||||
|
|
@ -275,6 +300,8 @@ void app_run(App *app) {
|
|||
in_blackout ? NULL : app->video_texture,
|
||||
app->texture_width,
|
||||
app->texture_height,
|
||||
output_width,
|
||||
output_height,
|
||||
&app->fonts,
|
||||
&app->ui_cache,
|
||||
&app->channels,
|
||||
|
|
@ -289,7 +316,9 @@ void app_run(App *app) {
|
|||
ui_render_fullscreen(app->renderer,
|
||||
in_blackout ? NULL : app->video_texture,
|
||||
app->texture_width,
|
||||
app->texture_height);
|
||||
app->texture_height,
|
||||
output_width,
|
||||
output_height);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(app->renderer);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ typedef struct App {
|
|||
int texture_height;
|
||||
AppMode mode;
|
||||
int running;
|
||||
int is_fullscreen;
|
||||
int startup_handoff_active;
|
||||
int last_blackout_state;
|
||||
Uint32 startup_handoff_until;
|
||||
|
|
|
|||
BIN
src/app.o
BIN
src/app.o
Binary file not shown.
53
src/ui.c
53
src/ui.c
|
|
@ -481,16 +481,21 @@ static void draw_scanline_overlay(SDL_Renderer *renderer, int width, int height)
|
|||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache) {
|
||||
SDL_Rect full = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache, int window_width, int window_height) {
|
||||
SDL_Rect full = {0, 0, window_width, window_height};
|
||||
fill_rect(renderer, &full, COLOR_NAVY_DARK);
|
||||
draw_cached_text(renderer, &cache->no_media_title, 58, 80);
|
||||
draw_cached_text(renderer, &cache->no_media_body, 58, 136);
|
||||
draw_cached_text(renderer, &cache->no_media_hint, 58, 176);
|
||||
}
|
||||
|
||||
void ui_render_fullscreen(SDL_Renderer *renderer, SDL_Texture *video_texture, int texture_width, int texture_height) {
|
||||
SDL_Rect window = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
void ui_render_fullscreen(SDL_Renderer *renderer,
|
||||
SDL_Texture *video_texture,
|
||||
int texture_width,
|
||||
int texture_height,
|
||||
int window_width,
|
||||
int window_height) {
|
||||
SDL_Rect window = {0, 0, window_width, window_height};
|
||||
fill_rect(renderer, &window, COLOR_BLACK);
|
||||
draw_video(renderer, video_texture, texture_width, texture_height, window);
|
||||
}
|
||||
|
|
@ -499,6 +504,8 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
SDL_Texture *video_texture,
|
||||
int texture_width,
|
||||
int texture_height,
|
||||
int window_width,
|
||||
int window_height,
|
||||
const UiFonts *fonts,
|
||||
UiCache *cache,
|
||||
const ChannelList *channels,
|
||||
|
|
@ -506,14 +513,18 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
Uint64 app_start_ticks,
|
||||
Uint64 now_ticks,
|
||||
time_t now_wall) {
|
||||
SDL_Rect full = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
SDL_Rect info_panel = {0, 0, GUIDE_INFO_WIDTH, GUIDE_INFO_HEIGHT};
|
||||
SDL_Rect preview = {WINDOW_WIDTH - GUIDE_PREVIEW_WIDTH, 0, GUIDE_PREVIEW_WIDTH, GUIDE_PREVIEW_HEIGHT};
|
||||
SDL_Rect status_bar = {GUIDE_INFO_WIDTH, 0, WINDOW_WIDTH - GUIDE_INFO_WIDTH, GUIDE_STATUS_HEIGHT};
|
||||
SDL_Rect header_row = {0, GUIDE_GRID_TOP - GUIDE_STATUS_HEIGHT, WINDOW_WIDTH, GUIDE_STATUS_HEIGHT};
|
||||
SDL_Rect grid = {0, GUIDE_GRID_TOP, WINDOW_WIDTH, WINDOW_HEIGHT - GUIDE_GRID_TOP - GUIDE_FOOTER_HEIGHT};
|
||||
double scale_x = (double) window_width / WINDOW_WIDTH;
|
||||
double scale_y = (double) window_height / WINDOW_HEIGHT;
|
||||
int guide_x_start = (int) (GUIDE_X_START * scale_x);
|
||||
int sidebar_width = (int) (GUIDE_SIDEBAR_WIDTH * scale_x);
|
||||
SDL_Rect full = {0, 0, window_width, window_height};
|
||||
SDL_Rect info_panel = {0, 0, (int) (GUIDE_INFO_WIDTH * scale_x), (int) (GUIDE_INFO_HEIGHT * scale_y)};
|
||||
SDL_Rect preview = {window_width - (int) (GUIDE_PREVIEW_WIDTH * scale_x), 0, (int) (GUIDE_PREVIEW_WIDTH * scale_x), (int) (GUIDE_PREVIEW_HEIGHT * scale_y)};
|
||||
SDL_Rect status_bar = {info_panel.w, 0, window_width - info_panel.w, (int) (GUIDE_STATUS_HEIGHT * scale_y)};
|
||||
SDL_Rect header_row = {0, (int) ((GUIDE_GRID_TOP - GUIDE_STATUS_HEIGHT) * scale_y), window_width, (int) (GUIDE_STATUS_HEIGHT * scale_y)};
|
||||
SDL_Rect grid = {0, (int) (GUIDE_GRID_TOP * scale_y), window_width, window_height - (int) (GUIDE_GRID_TOP * scale_y) - (int) (GUIDE_FOOTER_HEIGHT * scale_y)};
|
||||
int row_height = grid.h / GUIDE_VISIBLE_ROWS;
|
||||
int timeline_w = WINDOW_WIDTH - GUIDE_X_START - 20;
|
||||
int timeline_w = window_width - guide_x_start - (int) (20 * scale_x);
|
||||
int start_index = active_channel - 2;
|
||||
const Channel *selected_channel = NULL;
|
||||
double pixels_per_minute = timeline_w / 90.0;
|
||||
|
|
@ -554,9 +565,9 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
|
||||
for (int row = 0; row < GUIDE_VISIBLE_ROWS; ++row) {
|
||||
int channel_index = start_index + row;
|
||||
SDL_Rect row_rect = {0, grid.y + row * row_height, WINDOW_WIDTH, row_height};
|
||||
SDL_Rect sidebar = {0, row_rect.y, GUIDE_SIDEBAR_WIDTH, row_height};
|
||||
SDL_Rect timeline_rect = {GUIDE_X_START, row_rect.y + 6, timeline_w, row_height - 12};
|
||||
SDL_Rect row_rect = {0, grid.y + row * row_height, window_width, row_height};
|
||||
SDL_Rect sidebar = {0, row_rect.y, sidebar_width, row_height};
|
||||
SDL_Rect timeline_rect = {guide_x_start, row_rect.y + (int) (6 * scale_y), timeline_w, row_height - (int) (12 * scale_y)};
|
||||
SDL_Rect clip = timeline_rect;
|
||||
int is_selected = channel_index == active_channel;
|
||||
SDL_Rect inset = {row_rect.x + 4, row_rect.y + 3, row_rect.w - 8, row_rect.h - 6};
|
||||
|
|
@ -588,9 +599,9 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
const ProgramEntry *program = channel_resolve_program(channel, app_start_ticks, now_ticks, &program_seek, NULL);
|
||||
time_t guide_view_start_time = now_wall - (30 * 60);
|
||||
time_t program_start_time = now_wall - (time_t) live_position;
|
||||
int block_x = GUIDE_X_START;
|
||||
int block_x = guide_x_start;
|
||||
int block_w = 48;
|
||||
SDL_Rect block = {GUIDE_X_START, timeline_rect.y + 4, 48, timeline_rect.h - 8};
|
||||
SDL_Rect block = {guide_x_start, timeline_rect.y + 4, 48, timeline_rect.h - 8};
|
||||
SDL_Rect title_rect = {block.x + 8, block.y + 8, block.w - 16, block.h - 16};
|
||||
char title[128];
|
||||
|
||||
|
|
@ -599,7 +610,7 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
}
|
||||
live_position = channel_live_position_precise(channel, app_start_ticks, now_ticks);
|
||||
program_start_time = now_wall - (time_t) program_seek;
|
||||
block_x = GUIDE_X_START + (int) (((double) (program_start_time - guide_view_start_time)) / 60.0 * pixels_per_minute);
|
||||
block_x = guide_x_start + (int) (((double) (program_start_time - guide_view_start_time)) / 60.0 * pixels_per_minute);
|
||||
block_w = (int) ((program->duration_seconds / 60.0) * pixels_per_minute);
|
||||
block = (SDL_Rect){block_x, timeline_rect.y + 4, SDL_max(block_w, 48), timeline_rect.h - 8};
|
||||
title_rect = (SDL_Rect){block.x + 8, block.y + 8, block.w - 16, block.h - 16};
|
||||
|
|
@ -642,13 +653,13 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
}
|
||||
|
||||
if (selected_channel && active_channel >= 0 && start_index <= active_channel && active_channel < start_index + GUIDE_VISIBLE_ROWS) {
|
||||
SDL_Rect highlight = {0, grid.y + (active_channel - start_index) * row_height, WINDOW_WIDTH, row_height};
|
||||
SDL_Rect highlight = {0, grid.y + (active_channel - start_index) * row_height, window_width, row_height};
|
||||
draw_selection_glow(renderer, &highlight);
|
||||
draw_selection_glow(renderer, &(SDL_Rect){GUIDE_X_START, highlight.y + 6, timeline_w, row_height - 12});
|
||||
draw_selection_glow(renderer, &(SDL_Rect){guide_x_start, highlight.y + (int) (6 * scale_y), timeline_w, row_height - (int) (12 * scale_y)});
|
||||
}
|
||||
|
||||
draw_footer_legend(renderer, cache, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
draw_scanline_overlay(renderer, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
draw_footer_legend(renderer, cache, window_width, window_height);
|
||||
draw_scanline_overlay(renderer, window_width, window_height);
|
||||
}
|
||||
|
||||
int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts, const ChannelList *channels) {
|
||||
|
|
|
|||
11
src/ui.h
11
src/ui.h
|
|
@ -46,11 +46,18 @@ typedef struct UiCache {
|
|||
int channel_count;
|
||||
} UiCache;
|
||||
|
||||
void ui_render_fullscreen(SDL_Renderer *renderer, SDL_Texture *video_texture, int texture_width, int texture_height);
|
||||
void ui_render_fullscreen(SDL_Renderer *renderer,
|
||||
SDL_Texture *video_texture,
|
||||
int texture_width,
|
||||
int texture_height,
|
||||
int window_width,
|
||||
int window_height);
|
||||
void ui_render_guide(SDL_Renderer *renderer,
|
||||
SDL_Texture *video_texture,
|
||||
int texture_width,
|
||||
int texture_height,
|
||||
int window_width,
|
||||
int window_height,
|
||||
const UiFonts *fonts,
|
||||
UiCache *cache,
|
||||
const ChannelList *channels,
|
||||
|
|
@ -58,7 +65,7 @@ void ui_render_guide(SDL_Renderer *renderer,
|
|||
Uint64 app_start_ticks,
|
||||
Uint64 now_ticks,
|
||||
time_t now_wall);
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache);
|
||||
void ui_render_no_media(SDL_Renderer *renderer, const UiCache *cache, int window_width, int window_height);
|
||||
int ui_load_fonts(UiFonts *fonts);
|
||||
void ui_destroy_fonts(UiFonts *fonts);
|
||||
int ui_cache_init(UiCache *cache, SDL_Renderer *renderer, const UiFonts *fonts, const ChannelList *channels);
|
||||
|
|
|
|||
BIN
src/ui.o
BIN
src/ui.o
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue