From bc280c7fc6d86ec29369238f504fa5245f4c8b87 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Tue, 25 Jul 2023 22:56:00 +0200 Subject: [PATCH] Added image viewer menu view --- Makefile | 1 + src/menu/menu.c | 8 +++ src/menu/menu_state.h | 2 + src/menu/views/browser.c | 13 ++++ src/menu/views/fragments/fragments.c | 12 ++++ src/menu/views/fragments/fragments.h | 1 + src/menu/views/image_viewer.c | 89 ++++++++++++++++++++++++++++ src/menu/views/load.c | 9 +-- src/menu/views/views.h | 3 + 9 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 src/menu/views/image_viewer.c diff --git a/Makefile b/Makefile index 02d6b7e1..9b5a8336 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ SRCS = \ menu/views/file_info.c \ menu/views/fragments/fragments.c \ menu/views/fragments/widgets.c \ + menu/views/image_viewer.c \ menu/views/load.c \ menu/views/music_player.c \ menu/views/startup.c \ diff --git a/src/menu/menu.c b/src/menu/menu.c index b0146400..c69ead36 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -112,6 +112,10 @@ void menu_run (boot_params_t *boot_params) { view_system_info_display(menu, display); break; + case MENU_MODE_IMAGE_VIEWER: + view_image_viewer_display(menu, display); + break; + case MENU_MODE_MUSIC_PLAYER: view_music_player_display(menu, display); break; @@ -158,6 +162,10 @@ void menu_run (boot_params_t *boot_params) { view_system_info_init(menu); break; + case MENU_MODE_IMAGE_VIEWER: + view_image_viewer_init(menu); + break; + case MENU_MODE_MUSIC_PLAYER: view_music_player_init(menu); break; diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index c4761ec3..4592540a 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -24,6 +24,7 @@ typedef enum { MENU_MODE_BROWSER, MENU_MODE_FILE_INFO, MENU_MODE_SYSTEM_INFO, + MENU_MODE_IMAGE_VIEWER, MENU_MODE_MUSIC_PLAYER, MENU_MODE_CREDITS, MENU_MODE_LOAD, @@ -37,6 +38,7 @@ typedef enum { ENTRY_TYPE_DIR, ENTRY_TYPE_ROM, ENTRY_TYPE_SAVE, + ENTRY_TYPE_IMAGE, ENTRY_TYPE_MUSIC, ENTRY_TYPE_OTHER, } entry_type_t; diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 34e45cd7..960da592 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -11,6 +11,7 @@ static const char *rom_extensions[] = { "z64", "n64", "v64", NULL }; static const char *save_extensions[] = { "sav", NULL }; +static const char *image_extensions[] = { "png", NULL }; static const char *music_extensions[] = { "mp3", NULL }; @@ -31,6 +32,10 @@ static int compare_entry (const void *pa, const void *pb) { return -1; } else if (b->type == ENTRY_TYPE_SAVE) { return 1; + } else if (a->type == ENTRY_TYPE_IMAGE) { + return -1; + } else if (b->type == ENTRY_TYPE_IMAGE) { + return 1; } else if (a->type == ENTRY_TYPE_MUSIC) { return -1; } else if (b->type == ENTRY_TYPE_MUSIC) { @@ -87,6 +92,8 @@ static bool load_directory (menu_t *menu) { entry->type = ENTRY_TYPE_ROM; } else if (file_has_extensions(info.fname, save_extensions)) { entry->type = ENTRY_TYPE_SAVE; + } else if (file_has_extensions(info.fname, image_extensions)) { + entry->type = ENTRY_TYPE_IMAGE; } else if (file_has_extensions(info.fname, music_extensions)) { entry->type = ENTRY_TYPE_MUSIC; } else { @@ -208,6 +215,9 @@ static void process (menu_t *menu) { case ENTRY_TYPE_ROM: menu->next_mode = MENU_MODE_LOAD; break; + case ENTRY_TYPE_IMAGE: + menu->next_mode = MENU_MODE_IMAGE_VIEWER; + break; case ENTRY_TYPE_MUSIC: menu->next_mode = MENU_MODE_MUSIC_PLAYER; break; @@ -324,6 +334,9 @@ static void draw (menu_t *menu, surface_t *d) { case ENTRY_TYPE_ROM: fragment_textf(text_x, text_y, "A: Load"); break; + case ENTRY_TYPE_IMAGE: + fragment_textf(text_x, text_y, "A: Show"); + break; case ENTRY_TYPE_MUSIC: fragment_textf(text_x, text_y, "A: Play"); break; diff --git a/src/menu/views/fragments/fragments.c b/src/menu/views/fragments/fragments.c index e682b8fb..13d3f87d 100644 --- a/src/menu/views/fragments/fragments.c +++ b/src/menu/views/fragments/fragments.c @@ -94,3 +94,15 @@ int fragment_textf (int x, int y, char *fmt, ...) { return layout.line_height; } + +void fragment_loader (surface_t *d) { + const color_t text_color = RGBA32(0xFF, 0xFF, 0xFF, 0xFF); + + const int offset_x = 248; + const int offset_y = 212; + const int text_offset_x = -39; + + widget_border(offset_x, offset_y, d->width - offset_x, d->height - offset_y, layout.border_thickness); + fragment_text_start(text_color); + fragment_textf((d->width / 2) + text_offset_x, (d->height / 2) - (layout.line_height / 2), "Loading…"); +} diff --git a/src/menu/views/fragments/fragments.h b/src/menu/views/fragments/fragments.h index 9c4170c6..1f9c45d3 100644 --- a/src/menu/views/fragments/fragments.h +++ b/src/menu/views/fragments/fragments.h @@ -51,6 +51,7 @@ void fragment_progressbar (surface_t *d, float progress); void fragment_text_start (color_t color); void fragment_text_set_color (color_t color); int fragment_textf (int x, int y, char *fmt, ...); +void fragment_loader (surface_t *d); /** @} */ /* view_fragments */ diff --git a/src/menu/views/image_viewer.c b/src/menu/views/image_viewer.c new file mode 100644 index 00000000..77ec99e0 --- /dev/null +++ b/src/menu/views/image_viewer.c @@ -0,0 +1,89 @@ +#include +#include + +#include "../png_decoder.h" +#include "fragments/fragments.h" +#include "views.h" + + +static surface_t *image; +static rspq_block_t *cached_image_dl; + + +static void process (menu_t *menu) { + if (menu->actions.back) { + menu->next_mode = MENU_MODE_BROWSER; + } +} + +static void draw (menu_t *menu, surface_t *d) { + rdpq_attach_clear(d, NULL); + + if (image == NULL) { + fragment_loader(d); + } else { + rspq_block_run(cached_image_dl); + } + + rdpq_detach_show(); +} + +static void deffered_image_load (menu_t *menu, surface_t *d) { + image = calloc(1, sizeof(surface_t)); + + if (image == NULL) { + menu->next_mode = MENU_MODE_ERROR; + return; + } + + path_t *path = path_clone(menu->browser.directory); + path_push(path, menu->browser.list[menu->browser.selected].name); + + if (png_decode(path_get(path), image, 640, 480) == PNG_OK) { + uint16_t x = (d->width / 2) - (image->width / 2); + uint16_t y = (d->height / 2) - (image->height / 2); + + rspq_block_begin(); + + rdpq_set_mode_copy(false); + rdpq_tex_blit(image, x, y, NULL); + + cached_image_dl = rspq_block_end(); + } else { + menu->next_mode = MENU_MODE_ERROR; + } + + path_free(path); +} + +static void dl_free (void *arg) { + rspq_block_free((rspq_block_t *) (arg)); +} + +static void deinit (menu_t *menu) { + if (image != NULL) { + rdpq_call_deferred(dl_free, cached_image_dl); + surface_free(image); + free(image); + } +} + + +void view_image_viewer_init (menu_t *menu) { + image = NULL; + cached_image_dl = NULL; +} + +void view_image_viewer_display (menu_t *menu, surface_t *display) { + process(menu); + + draw(menu, display); + + if (image == NULL) { + deffered_image_load(menu, display); + } + + if (menu->next_mode != MENU_MODE_IMAGE_VIEWER) { + deinit(menu); + } +} diff --git a/src/menu/views/load.c b/src/menu/views/load.c index c22f001d..d5de8171 100644 --- a/src/menu/views/load.c +++ b/src/menu/views/load.c @@ -207,14 +207,7 @@ static void draw (menu_t *menu, surface_t *d) { rdpq_clear(bg_color); if (load_pending) { - const int offset_x = 248; - const int offset_y = 212; - const int text_offset_x = -39; - - // Loading screen - widget_border(offset_x, offset_y, d->width - offset_x, d->height - offset_y, layout->border_thickness); - fragment_text_start(text_color); - fragment_textf((d->width / 2) + text_offset_x, (d->height / 2) - (layout->line_height / 2), "Loading…"); + fragment_loader(d); } else { // Layout fragment_borders(d); diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 4264c793..991a03d8 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -29,6 +29,9 @@ void view_system_info_display (menu_t *menu, surface_t *display); void view_file_info_init (menu_t *menu); void view_file_info_display (menu_t *menu, surface_t *display); +void view_image_viewer_init (menu_t *menu); +void view_image_viewer_display (menu_t *menu, surface_t *display); + void view_music_player_init (menu_t *menu); void view_music_player_display (menu_t *menu, surface_t *display);