diff --git a/config.def.h b/config.def.h index 3ceef8ad7e..5a5cabcf4d 100644 --- a/config.def.h +++ b/config.def.h @@ -384,6 +384,8 @@ static unsigned menu_shader_pipeline = 2; static bool show_advanced_settings = false; static unsigned rgui_color_theme = RGUI_THEME_CLASSIC_GREEN; +static bool rgui_inline_thumbnails = false; +static bool rgui_swap_thumbnails = false; static unsigned rgui_thumbnail_downscaler = RGUI_THUMB_SCALE_POINT; static unsigned rgui_internal_upscale_level = RGUI_UPSCALE_NONE; static bool rgui_full_width_layout = true; diff --git a/configuration.c b/configuration.c index 02a7ed77d2..ad007934d0 100644 --- a/configuration.c +++ b/configuration.c @@ -1509,6 +1509,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("rgui_border_filler_thickness_enable", &settings->bools.menu_rgui_border_filler_thickness_enable, true, true, false); SETTING_BOOL("rgui_border_filler_enable", &settings->bools.menu_rgui_border_filler_enable, true, true, false); SETTING_BOOL("menu_rgui_full_width_layout", &settings->bools.menu_rgui_full_width_layout, true, rgui_full_width_layout, false); + SETTING_BOOL("rgui_inline_thumbnails", &settings->bools.menu_rgui_inline_thumbnails, true, rgui_inline_thumbnails, false); + SETTING_BOOL("rgui_swap_thumbnails", &settings->bools.menu_rgui_swap_thumbnails, true, rgui_swap_thumbnails, false); #endif #ifdef HAVE_XMB SETTING_BOOL("xmb_shadows_enable", &settings->bools.menu_xmb_shadows_enable, true, xmb_shadows_enable, false); diff --git a/configuration.h b/configuration.h index 75badb90cd..7d4728b9eb 100644 --- a/configuration.h +++ b/configuration.h @@ -172,6 +172,8 @@ typedef struct settings bool menu_rgui_border_filler_thickness_enable; bool menu_rgui_border_filler_enable; bool menu_rgui_full_width_layout; + bool menu_rgui_inline_thumbnails; + bool menu_rgui_swap_thumbnails; bool menu_xmb_shadows_enable; bool menu_xmb_vertical_thumbnails; bool menu_content_show_settings; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index e86bd83c77..4faa07bd24 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1133,6 +1133,10 @@ MSG_HASH(MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, "xmb_vertical_thumbnails") MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, "rgui_thumbnail_downscaler") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS, + "rgui_inline_thumbnails") +MSG_HASH(MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS, + "rgui_swap_thumbnails") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_DIRECTORY, "thumbnails_directory") MSG_HASH(MENU_ENUM_LABEL_THUMBNAILS_UPDATER_LIST, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 750eafe636..15b88d24ea 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2970,10 +2970,18 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_THUMBNAILS, "Thumbnails" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_THUMBNAILS_RGUI, + "Top Thumbnail" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS, "Left Thumbnails" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_RGUI, + "Bottom Thumbnail" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_OZONE, "Second Thumbnail" @@ -2982,13 +2990,29 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, "Thumbnails Vertical Disposition" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_RGUI_INLINE_THUMBNAILS, + "Show Playlist Thumbnails" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_RGUI_INLINE_THUMBNAILS, + "Enable display of inline downscaled thumbnails while viewing playlists. When disabled, 'Top Thumbnail' may still be toggled fullscreen by pressing RetroPad Y." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_MENU_RGUI_SWAP_THUMBNAILS, + "Swap Thumbnails" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_MENU_RGUI_SWAP_THUMBNAILS, + "Swaps the display positions of 'Top Thumbnail' and 'Bottom Thumbnail'." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_RGUI_THUMBNAIL_DOWNSCALER, "Thumbnail Downscaling Method" ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, - "Resampling method used when shrinking large thumbnails to fit the screen." + "Resampling method used when shrinking large thumbnails to fit the display." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_POINT, @@ -5751,10 +5775,18 @@ MSG_HASH( MENU_ENUM_SUBLABEL_THUMBNAILS, "Type of thumbnail to display." ) +MSG_HASH( + MENU_ENUM_SUBLABEL_THUMBNAILS_RGUI, + "Type of thumbnail to display at the top right of playlists. This thumbnail may be toggled fullscreen by pressing RetroPad Y." + ) MSG_HASH( MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS, "Type of thumbnail to display at the left." ) +MSG_HASH( + MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_RGUI, + "Type of thumbnail to display at the bottom right of playlists." + ) MSG_HASH( MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_OZONE, "Replace the content metadata panel by another thumbnail." diff --git a/menu/cbs/menu_cbs_scan.c b/menu/cbs/menu_cbs_scan.c index 9376a99a00..ae6ce51091 100644 --- a/menu/cbs/menu_cbs_scan.c +++ b/menu/cbs/menu_cbs_scan.c @@ -111,11 +111,17 @@ int action_switch_thumbnail(const char *path, if (settings->uints.menu_thumbnails == 0) { - settings->uints.menu_left_thumbnails++; - if (settings->uints.menu_left_thumbnails > 3) - settings->uints.menu_left_thumbnails = 1; - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); - menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + /* RGUI is a special case where thumbnail 'switch' corresponds to + * toggling thumbnail view on/off. For other menu drivers, we + * cycle through available thumbnail types. */ + if(!string_is_equal(settings->arrays.menu_driver, "rgui")) + { + settings->uints.menu_left_thumbnails++; + if (settings->uints.menu_left_thumbnails > 3) + settings->uints.menu_left_thumbnails = 1; + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_PATH, NULL); + menu_driver_ctl(RARCH_MENU_CTL_UPDATE_THUMBNAIL_IMAGE, NULL); + } } else { diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 522d316ac2..f60a588484 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -312,7 +312,9 @@ default_sublabel_macro(action_bind_sublabel_stdin_cmd_enable, MENU_ default_sublabel_macro(action_bind_sublabel_mouse_enable, MENU_ENUM_SUBLABEL_MOUSE_ENABLE) default_sublabel_macro(action_bind_sublabel_pointer_enable, MENU_ENUM_SUBLABEL_POINTER_ENABLE) default_sublabel_macro(action_bind_sublabel_thumbnails, MENU_ENUM_SUBLABEL_THUMBNAILS) +default_sublabel_macro(action_bind_sublabel_thumbnails_rgui, MENU_ENUM_SUBLABEL_THUMBNAILS_RGUI) default_sublabel_macro(action_bind_sublabel_left_thumbnails, MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS) +default_sublabel_macro(action_bind_sublabel_left_thumbnails_rgui, MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_RGUI) default_sublabel_macro(action_bind_sublabel_left_thumbnails_ozone, MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS_OZONE) default_sublabel_macro(action_bind_sublabel_timedate_enable, MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE) default_sublabel_macro(action_bind_sublabel_timedate_style, MENU_ENUM_SUBLABEL_TIMEDATE_STYLE) @@ -526,6 +528,8 @@ default_sublabel_macro(action_bind_sublabel_menu_linear_filter, default_sublabel_macro(action_bind_sublabel_menu_rgui_aspect_ratio_lock, MENU_ENUM_SUBLABEL_MENU_RGUI_ASPECT_RATIO_LOCK) default_sublabel_macro(action_bind_sublabel_rgui_menu_color_theme, MENU_ENUM_SUBLABEL_RGUI_MENU_COLOR_THEME) default_sublabel_macro(action_bind_sublabel_rgui_menu_theme_preset, MENU_ENUM_SUBLABEL_RGUI_MENU_THEME_PRESET) +default_sublabel_macro(action_bind_sublabel_menu_rgui_inline_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_INLINE_THUMBNAILS) +default_sublabel_macro(action_bind_sublabel_menu_rgui_swap_thumbnails, MENU_ENUM_SUBLABEL_MENU_RGUI_SWAP_THUMBNAILS) default_sublabel_macro(action_bind_sublabel_menu_rgui_thumbnail_downscaler, MENU_ENUM_SUBLABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER) default_sublabel_macro(action_bind_sublabel_content_runtime_log, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG) default_sublabel_macro(action_bind_sublabel_content_runtime_log_aggregate, MENU_ENUM_SUBLABEL_CONTENT_RUNTIME_LOG_AGGREGATE) @@ -1599,11 +1603,23 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_timedate_style); break; case MENU_ENUM_LABEL_THUMBNAILS: - BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_thumbnails); + settings = config_get_ptr(); + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_thumbnails_rgui); + } + else + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_thumbnails); + } break; case MENU_ENUM_LABEL_LEFT_THUMBNAILS: settings = config_get_ptr(); - if (string_is_equal(settings->arrays.menu_driver, "ozone")) + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_left_thumbnails_rgui); + } + else if (string_is_equal(settings->arrays.menu_driver, "ozone")) { BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_left_thumbnails_ozone); } @@ -2408,6 +2424,12 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_RGUI_MENU_THEME_PRESET: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_rgui_menu_theme_preset); break; + case MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_inline_thumbnails); + break; + case MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_swap_thumbnails); + break; case MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_rgui_thumbnail_downscaler); break; diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index c748d96a67..06e861cbf0 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -448,9 +448,11 @@ typedef struct rgui_colors_t colors; bool is_playlist; bool entry_has_thumbnail; - bool show_thumbnail; + bool entry_has_left_thumbnail; + bool show_fs_thumbnail; menu_thumbnail_path_data_t *thumbnail_path_data; uint32_t thumbnail_queue_size; + uint32_t left_thumbnail_queue_size; bool show_wallpaper; char theme_preset_path[PATH_MAX_LENGTH]; /* Must be a fixed length array... */ char menu_title[255]; /* Must be a fixed length array... */ @@ -463,8 +465,13 @@ typedef struct struct scaler_ctx image_scaler; } rgui_t; +static unsigned mini_thumbnail_max_width = 0; +static unsigned mini_thumbnail_max_height = 0; + typedef struct { + unsigned max_width; + unsigned max_height; unsigned width; unsigned height; bool is_valid; @@ -472,7 +479,29 @@ typedef struct uint16_t *data; } thumbnail_t; -static thumbnail_t thumbnail = { +static thumbnail_t fs_thumbnail = { + 0, + 0, + 0, + 0, + false, + NULL, + NULL +}; + +static thumbnail_t mini_thumbnail = { + 0, + 0, + 0, + 0, + false, + NULL, + NULL +}; + +static thumbnail_t mini_left_thumbnail = { + 0, + 0, 0, 0, false, @@ -678,33 +707,34 @@ static void process_wallpaper(rgui_t *rgui, struct texture_image *image) rgui->force_redraw = true; } -static bool request_thumbnail(rgui_t *rgui, const char *path) +static bool request_thumbnail(thumbnail_t *thumbnail, enum menu_thumbnail_id thumbnail_id, uint32_t *queue_size, const char *path) { /* Do nothing if current thumbnail path hasn't changed */ - if (!string_is_empty(path) && !string_is_empty(thumbnail.path)) + if (!string_is_empty(path) && !string_is_empty(thumbnail->path)) { - if (string_is_equal(thumbnail.path, path)) + if (string_is_equal(thumbnail->path, path)) return true; } /* 'Reset' current thumbnail */ - thumbnail.width = 0; - thumbnail.height = 0; - thumbnail.is_valid = false; - free(thumbnail.path); - thumbnail.path = NULL; + thumbnail->width = 0; + thumbnail->height = 0; + thumbnail->is_valid = false; + free(thumbnail->path); + thumbnail->path = NULL; /* Ensure that new path is valid... */ if (!string_is_empty(path)) { - thumbnail.path = strdup(path); + thumbnail->path = strdup(path); if (filestream_exists(path)) { /* Would like to cancel any existing image load tasks * here, but can't see how to do it... */ - if(task_push_image_load(thumbnail.path, menu_display_handle_thumbnail_upload, NULL)) + if(task_push_image_load(thumbnail->path, (thumbnail_id == MENU_THUMBNAIL_LEFT) ? + menu_display_handle_left_thumbnail_upload : menu_display_handle_thumbnail_upload, NULL)) { - rgui->thumbnail_queue_size++; + *queue_size = *queue_size + 1; return true; } } @@ -713,28 +743,29 @@ static bool request_thumbnail(rgui_t *rgui, const char *path) return false; } -static bool downscale_thumbnail(rgui_t *rgui, struct texture_image *image_src, struct texture_image *image_dst) +static bool downscale_thumbnail(rgui_t *rgui, unsigned max_width, unsigned max_height, + struct texture_image *image_src, struct texture_image *image_dst) { settings_t *settings = config_get_ptr(); /* Determine output dimensions */ - float display_aspect_ratio = (float)rgui_frame_buf.width / (float)rgui_frame_buf.height; + float display_aspect_ratio = (float)max_width / (float)max_height; float aspect_ratio = (float)image_src->width / (float)image_src->height; if (aspect_ratio > display_aspect_ratio) { - image_dst->width = rgui_frame_buf.width; - image_dst->height = image_src->height * rgui_frame_buf.width / image_src->width; + image_dst->width = max_width; + image_dst->height = image_src->height * max_width / image_src->width; /* Account for any possible rounding errors... */ image_dst->height = (image_dst->height < 1) ? 1 : image_dst->height; - image_dst->height = (image_dst->height > rgui_frame_buf.height) ? rgui_frame_buf.height : image_dst->height; + image_dst->height = (image_dst->height > max_height) ? max_height : image_dst->height; } else { - image_dst->height = rgui_frame_buf.height; - image_dst->width = image_src->width * rgui_frame_buf.height / image_src->height; + image_dst->height = max_height; + image_dst->width = image_src->width * max_height / image_src->height; /* Account for any possible rounding errors... */ image_dst->width = (image_dst->width < 1) ? 1 : image_dst->width; - image_dst->width = (image_dst->width > rgui_frame_buf.width) ? rgui_frame_buf.width : image_dst->width; + image_dst->width = (image_dst->width > max_width) ? max_width : image_dst->width; } /* Allocate pixel buffer */ @@ -805,7 +836,7 @@ static bool downscale_thumbnail(rgui_t *rgui, struct texture_image *image_src, s return true; } -static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) +static void process_thumbnail(rgui_t *rgui, thumbnail_t *thumbnail, uint32_t *queue_size, struct texture_image *image_src) { unsigned x, y; struct texture_image *image = NULL; @@ -818,25 +849,20 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) /* Ensure that we only process the most recently loaded * thumbnail image (i.e. don't waste CPU cycles processing - * old images if we have a backlog) - * > NB: After some testing, cannot seem to ever trigger a - * situation where rgui->thumbnail_queue_size is greater - * than 1, so perhaps image loading is synchronous after all. - * This probably makes the check redundant, but we'll leave - * it here for now... */ - if (rgui->thumbnail_queue_size > 0) - rgui->thumbnail_queue_size--; - if (rgui->thumbnail_queue_size > 0) + * old images if we have a backlog) */ + if (*queue_size > 0) + *queue_size = *queue_size - 1; + if (*queue_size > 0) return; /* Sanity check */ - if (!image_src->pixels || (image_src->width < 1) || (image_src->height < 1) || !thumbnail.data) + if (!image_src->pixels || (image_src->width < 1) || (image_src->height < 1) || !thumbnail->data) return; /* Downscale thumbnail if it exceeds maximum size limits */ - if ((image_src->width > rgui_frame_buf.width) || (image_src->height > rgui_frame_buf.height)) + if ((image_src->width > thumbnail->max_width) || (image_src->height > thumbnail->max_height)) { - if (!downscale_thumbnail(rgui, image_src, &image_resampled)) + if (!downscale_thumbnail(rgui, thumbnail->max_width, thumbnail->max_height, image_src, &image_resampled)) return; image = &image_resampled; } @@ -845,20 +871,20 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) image = image_src; } - thumbnail.width = image->width; - thumbnail.height = image->height; + thumbnail->width = image->width; + thumbnail->height = image->height; /* Copy image to thumbnail buffer, performing pixel format conversion */ - for (x = 0; x < thumbnail.width; x++) + for (x = 0; x < thumbnail->width; x++) { - for (y = 0; y < thumbnail.height; y++) + for (y = 0; y < thumbnail->height; y++) { - thumbnail.data[x + (y * thumbnail.width)] = - argb32_to_pixel_platform_format(image->pixels[x + (y * thumbnail.width)]); + thumbnail->data[x + (y * thumbnail->width)] = + argb32_to_pixel_platform_format(image->pixels[x + (y * thumbnail->width)]); } } - thumbnail.is_valid = true; + thumbnail->is_valid = true; /* Tell menu that a display update is required */ rgui->force_redraw = true; @@ -872,9 +898,10 @@ static void process_thumbnail(rgui_t *rgui, struct texture_image *image_src) static bool rgui_load_image(void *userdata, void *data, enum menu_image_type type) { - rgui_t *rgui = (rgui_t*)userdata; + rgui_t *rgui = (rgui_t*)userdata; + settings_t *settings = config_get_ptr(); - if (!rgui || !data) + if (!rgui || !data || !settings) return false; switch (type) @@ -888,7 +915,27 @@ static bool rgui_load_image(void *userdata, void *data, enum menu_image_type typ case MENU_IMAGE_THUMBNAIL: { struct texture_image *image = (struct texture_image*)data; - process_thumbnail(rgui, image); + + if (rgui->show_fs_thumbnail) + process_thumbnail(rgui, &fs_thumbnail, &rgui->thumbnail_queue_size, image); + else if (settings->bools.menu_rgui_inline_thumbnails) + process_thumbnail(rgui, &mini_thumbnail, &rgui->thumbnail_queue_size, image); + else + { + /* If user toggles settings rapidly on very slow systems, + * it is possible for a thumbnail to be requested without + * it ever being processed. In this case, we still have to + * decrement the thumbnail queue (otherwise image updates + * will get 'stuck') */ + if (rgui->thumbnail_queue_size > 0) + rgui->thumbnail_queue_size--; + } + } + break; + case MENU_IMAGE_LEFT_THUMBNAIL: + { + struct texture_image *image = (struct texture_image*)data; + process_thumbnail(rgui, &mini_left_thumbnail, &rgui->left_thumbnail_queue_size, image); } break; default: @@ -920,7 +967,7 @@ static bool rgui_render_wallpaper(void) return false; } -static void rgui_render_thumbnail(void) +static void rgui_render_fs_thumbnail(void) { size_t fb_pitch; unsigned fb_width, fb_height; @@ -929,7 +976,7 @@ static void rgui_render_thumbnail(void) unsigned thumb_x_offset, thumb_y_offset; unsigned width, height; - if (thumbnail.is_valid && rgui_frame_buf.data && thumbnail.data) + if (fs_thumbnail.is_valid && rgui_frame_buf.data && fs_thumbnail.data) { menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch); @@ -938,27 +985,27 @@ static void rgui_render_thumbnail(void) * cannot assume fb_width and fb_height are constant and * >= thumbnail.width and thumbnail.height (even though * they are...) */ - if (thumbnail.width <= fb_width) + if (fs_thumbnail.width <= fb_width) { thumb_x_offset = 0; - fb_x_offset = (fb_width - thumbnail.width) >> 1; - width = thumbnail.width; + fb_x_offset = (fb_width - fs_thumbnail.width) >> 1; + width = fs_thumbnail.width; } else { - thumb_x_offset = (thumbnail.width - fb_width) >> 1; + thumb_x_offset = (fs_thumbnail.width - fb_width) >> 1; fb_x_offset = 0; width = fb_width; } - if (thumbnail.height <= fb_height) + if (fs_thumbnail.height <= fb_height) { thumb_y_offset = 0; - fb_y_offset = (fb_height - thumbnail.height) >> 1; - height = thumbnail.height; + fb_y_offset = (fb_height - fs_thumbnail.height) >> 1; + height = fs_thumbnail.height; } else { - thumb_y_offset = (thumbnail.height - fb_height) >> 1; + thumb_y_offset = (fs_thumbnail.height - fb_height) >> 1; fb_y_offset = 0; height = fb_height; } @@ -969,7 +1016,65 @@ static void rgui_render_thumbnail(void) for (x = 0; x < width; x++) { rgui_frame_buf.data[(y + fb_y_offset) * (fb_pitch >> 1) + (x + fb_x_offset)] = - thumbnail.data[(x + thumb_x_offset) + ((y + thumb_y_offset) * thumbnail.width)]; + fs_thumbnail.data[(x + thumb_x_offset) + ((y + thumb_y_offset) * fs_thumbnail.width)]; + } + } + } +} + +static unsigned inline rgui_get_mini_thumbnail_fullwidth(void) +{ + unsigned width = mini_thumbnail.is_valid ? mini_thumbnail.width : 0; + unsigned left_width = mini_left_thumbnail.is_valid ? mini_left_thumbnail.width : 0; + return width >= left_width ? width : left_width; +} + +static void rgui_render_mini_thumbnail(thumbnail_t *thumbnail, enum menu_thumbnail_id thumbnail_id) +{ + settings_t *settings = config_get_ptr(); + size_t fb_pitch; + unsigned fb_width, fb_height; + unsigned term_width, term_height; + unsigned x, y; + unsigned fb_x_offset, fb_y_offset; + unsigned thumbnail_fullwidth = rgui_get_mini_thumbnail_fullwidth(); + + if (!thumbnail || !settings) + return; + + if (thumbnail->is_valid && rgui_frame_buf.data && thumbnail->data) + { + menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch); + + term_width = RGUI_TERM_WIDTH(fb_width) * FONT_WIDTH_STRIDE; + term_height = RGUI_TERM_HEIGHT(fb_height) * FONT_HEIGHT_STRIDE; + + /* Sanity check (this can never, ever happen, so just return + * instead of trying to crop the thumbnail image...) */ + if ((thumbnail_fullwidth > term_width) || (thumbnail->height > term_height)) + return; + + fb_x_offset = (RGUI_TERM_START_X(fb_width) + term_width) - + (thumbnail->width + ((thumbnail_fullwidth - thumbnail->width) >> 1)); + + if (((thumbnail_id == MENU_THUMBNAIL_RIGHT) && !settings->bools.menu_rgui_swap_thumbnails) || + ((thumbnail_id == MENU_THUMBNAIL_LEFT) && settings->bools.menu_rgui_swap_thumbnails)) + { + fb_y_offset = RGUI_TERM_START_Y(fb_height) + ((thumbnail->max_height - thumbnail->height) >> 1); + } + else + { + fb_y_offset = (RGUI_TERM_START_Y(fb_height) + term_height) - + (thumbnail->height + ((thumbnail->max_height - thumbnail->height) >> 1)); + } + + /* Copy thumbnail to framebuffer */ + for (y = 0; y < thumbnail->height; y++) + { + for (x = 0; x < thumbnail->width; x++) + { + rgui_frame_buf.data[(y + fb_y_offset) * (fb_pitch >> 1) + (x + fb_x_offset)] = + thumbnail->data[x + (y * thumbnail->width)]; } } } @@ -1359,8 +1464,8 @@ static void rgui_render_background(rgui_t *rgui) dst += pitch_in_pixels * 4; } - /* Skip drawing border if we are currently showing a thumbnail */ - if (!(rgui->show_thumbnail && rgui->entry_has_thumbnail && (thumbnail.is_valid || (rgui->thumbnail_queue_size > 0)))) + /* Skip drawing border if we are currently showing a fullscreen thumbnail */ + if (!(rgui->show_fs_thumbnail && rgui->entry_has_thumbnail && (fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0)))) { if (rgui_frame_buf.data) { @@ -1489,7 +1594,7 @@ static void rgui_render(void *data, bool is_idle) menu_animation_ctx_ticker_t ticker; static const char* const ticker_spacer = RGUI_TICKER_SPACER; unsigned x, y; - size_t i, end, fb_pitch, old_start; + size_t i, end, fb_pitch, old_start, new_start; unsigned fb_width, fb_height; int bottom; size_t entries_end = 0; @@ -1622,14 +1727,14 @@ static void rgui_render(void *data, bool is_idle) ticker.type_enum = (enum menu_animation_ticker_type)settings->uints.menu_ticker_type; ticker.spacer = ticker_spacer; - /* If thumbnails are enabled and we are viewing a playlist, - * switch to thumbnail view mode if either current thumbnail + /* If fullscreen thumbnails are enabled and we are viewing a playlist, + * switch to fullscreen thumbnail view mode if either current thumbnail * is valid or we are waiting for current thumbnail to load * (if load is pending we'll get a blank screen + title, but * this is better than switching back to the text playlist * view, which causes ugly flickering when scrolling quickly * through a list...) */ - if (rgui->show_thumbnail && rgui->entry_has_thumbnail && (thumbnail.is_valid || (rgui->thumbnail_queue_size > 0))) + if (rgui->show_fs_thumbnail && rgui->entry_has_thumbnail && (fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0))) { const char *thumbnail_title = NULL; char thumbnail_title_buf[255]; @@ -1637,7 +1742,7 @@ static void rgui_render(void *data, bool is_idle) thumbnail_title_buf[0] = '\0'; /* Draw thumbnail */ - rgui_render_thumbnail(); + rgui_render_fs_thumbnail(); /* Get thumbnail title */ if (menu_thumbnail_get_label(rgui->thumbnail_path_data, &thumbnail_title)) @@ -1665,11 +1770,40 @@ static void rgui_render(void *data, bool is_idle) } else { - /* No thumbnail - render usual text */ + /* Render usual text */ char title_buf[255]; unsigned timedate_x = (RGUI_TERM_START_X(fb_width) + (RGUI_TERM_WIDTH(fb_width) * FONT_WIDTH_STRIDE)) - (5 * FONT_WIDTH_STRIDE); unsigned core_name_len = ((timedate_x - RGUI_TERM_START_X(fb_width)) / FONT_WIDTH_STRIDE) - 3; + bool show_mini_thumbnails = rgui->is_playlist && settings->bools.menu_rgui_inline_thumbnails; + bool show_thumbnail = false; + bool show_left_thumbnail = false; + unsigned thumbnail_panel_width = 0; + unsigned term_mid_point = 0; + + /* Cache mini thumbnail related parameters, if required */ + if (show_mini_thumbnails) + { + /* Get whether each thumbnail type is enabled */ + show_thumbnail = rgui->entry_has_thumbnail && + (mini_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0)); + show_left_thumbnail = rgui->entry_has_left_thumbnail && + (mini_left_thumbnail.is_valid || (rgui->left_thumbnail_queue_size > 0)); + + /* Get maximum width of thumbnail 'panel' on right side + * of screen */ + thumbnail_panel_width = rgui_get_mini_thumbnail_fullwidth(); + + if ((rgui->entry_has_thumbnail && rgui->thumbnail_queue_size > 0) || + (rgui->entry_has_left_thumbnail && rgui->left_thumbnail_queue_size > 0)) + thumbnail_panel_width = mini_thumbnail_max_width; + + /* Index (relative to first displayed menu entry) of + * the vertical centre of RGUI's 'terminal' + * (required to determine whether a particular entry + * is adjacent to the 'right' or 'left' thumbnail) */ + term_mid_point = (unsigned)((RGUI_TERM_HEIGHT(fb_height) * 0.5f) + 0.5f) - 1; + } /* Print title */ title_buf[0] = '\0'; @@ -1694,9 +1828,9 @@ static void rgui_render(void *data, bool is_idle) x = RGUI_TERM_START_X(fb_width); y = RGUI_TERM_START_Y(fb_height); - menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i); + menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &new_start); - for (; i < end; i++, y += FONT_HEIGHT_STRIDE) + for (i = new_start; i < end; i++, y += FONT_HEIGHT_STRIDE) { char entry_value[255]; char message[255]; @@ -1727,9 +1861,45 @@ static void rgui_render(void *data, bool is_idle) entry_path = menu_entry_get_rich_label(&entry); menu_entry_get_value(&entry, entry_value, sizeof(entry_value)); - /* Get base width of entry title field */ + /* Get base length of entry title field */ entry_title_max_len = RGUI_TERM_WIDTH(fb_width) - (1 + 2); + /* If showing mini thumbnails, reduce title field length accordingly */ + if (show_mini_thumbnails) + { + unsigned term_offset = settings->bools.menu_rgui_swap_thumbnails ? + (RGUI_TERM_HEIGHT(fb_height) - (i - new_start) - 1) : (i - new_start); + unsigned thumbnail_width = 0; + + /* Note: + * - 'Right' thumbnail is drawn at the top + * - 'Left' thumbnail is drawn at the bottom + * ...unless thumbnail postions are swapped. + * (legacy naming, unfortunately...) */ + + /* An annoyance - cannot assume terminal will have a + * standard layout (even though it always will...), + * so have to check whether there are an odd or even + * number of entries... */ + if((RGUI_TERM_HEIGHT(fb_height) & 1) == 0) + { + /* Even number of entries */ + if ((show_thumbnail && (term_offset <= term_mid_point)) || + (show_left_thumbnail && (term_offset > term_mid_point))) + thumbnail_width = thumbnail_panel_width; + } + else + { + /* Odd number of entries (will always be the case) */ + if ((show_thumbnail && (term_offset < term_mid_point)) || + (show_left_thumbnail && (term_offset > term_mid_point)) || + ((show_thumbnail || show_left_thumbnail) && (term_offset == term_mid_point))) + thumbnail_width = thumbnail_panel_width; + } + + entry_title_max_len -= (thumbnail_width / FONT_WIDTH_STRIDE) + 1; + } + /* Determine whether entry has a value component */ if (!string_is_empty(entry_value)) { @@ -1799,6 +1969,16 @@ static void rgui_render(void *data, bool is_idle) free(entry_path); } + /* Draw mini thumbnails, if required */ + if (show_mini_thumbnails) + { + if (show_thumbnail) + rgui_render_mini_thumbnail(&mini_thumbnail, MENU_THUMBNAIL_RIGHT); + + if (show_left_thumbnail) + rgui_render_mini_thumbnail(&mini_left_thumbnail, MENU_THUMBNAIL_LEFT); + } + /* Print menu sublabel/core name (if required) */ if (settings->bools.menu_show_sublabels && !string_is_empty(rgui->menu_sublabel)) { @@ -1899,19 +2079,24 @@ static void rgui_framebuffer_free(void) rgui_frame_buf.data = NULL; } -static void rgui_thumbnail_free(void) +static void rgui_thumbnail_free(thumbnail_t *thumbnail) { - thumbnail.width = 0; - thumbnail.height = 0; - thumbnail.is_valid = false; + if (!thumbnail) + return; - if (!string_is_empty(thumbnail.path)) - free(thumbnail.path); - thumbnail.path = NULL; + thumbnail->max_width = 0; + thumbnail->max_height = 0; + thumbnail->width = 0; + thumbnail->height = 0; + thumbnail->is_valid = false; - if (thumbnail.data) - free(thumbnail.data); - thumbnail.data = NULL; + if (!string_is_empty(thumbnail->path)) + free(thumbnail->path); + thumbnail->path = NULL; + + if (thumbnail->data) + free(thumbnail->data); + thumbnail->data = NULL; } static void rgui_wallpaper_free(void) @@ -2060,7 +2245,9 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) settings_t *settings = config_get_ptr(); rgui_framebuffer_free(); - rgui_thumbnail_free(); + rgui_thumbnail_free(&fs_thumbnail); + rgui_thumbnail_free(&mini_thumbnail); + rgui_thumbnail_free(&mini_left_thumbnail); rgui_wallpaper_free(); /* Cache new aspect ratio */ @@ -2135,9 +2322,29 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update) rgui_term_layout.start_y = (rgui_frame_buf.height - (rgui_term_layout.height * FONT_HEIGHT_STRIDE)) / 2; /* Allocate thumbnail buffer */ - thumbnail.data = (uint16_t*)calloc( - rgui_frame_buf.width * rgui_frame_buf.height, sizeof(uint16_t)); - if (!thumbnail.data) + fs_thumbnail.max_width = rgui_frame_buf.width; + fs_thumbnail.max_height = rgui_frame_buf.height; + fs_thumbnail.data = (uint16_t*)calloc( + fs_thumbnail.max_width * fs_thumbnail.max_height, sizeof(uint16_t)); + if (!fs_thumbnail.data) + return false; + + /* Allocate mini thumbnail buffers */ + mini_thumbnail_max_width = ((rgui_term_layout.width - 4) > 19 ? 19 : (rgui_term_layout.width - 4)) * FONT_WIDTH_STRIDE; + mini_thumbnail_max_height = (unsigned)((rgui_term_layout.height * FONT_HEIGHT_STRIDE) * 0.5f) - 2; + + mini_thumbnail.max_width = mini_thumbnail_max_width; + mini_thumbnail.max_height = mini_thumbnail_max_height; + mini_thumbnail.data = (uint16_t*)calloc( + mini_thumbnail.max_width * mini_thumbnail.max_height, sizeof(uint16_t)); + if (!mini_thumbnail.data) + return false; + + mini_left_thumbnail.max_width = mini_thumbnail_max_width; + mini_left_thumbnail.max_height = mini_thumbnail_max_height; + mini_left_thumbnail.data = (uint16_t*)calloc( + mini_left_thumbnail.max_width * mini_left_thumbnail.max_height, sizeof(uint16_t)); + if (!mini_left_thumbnail.data) return false; /* Allocate wallpaper buffer */ @@ -2223,14 +2430,17 @@ static void *rgui_init(void **userdata, bool video_is_threaded) goto error; rgui->thumbnail_queue_size = 0; - /* Ensure that we start with thumbnails disabled */ - rgui->show_thumbnail = false; + rgui->left_thumbnail_queue_size = 0; + /* Ensure that we start with fullscreen thumbnails disabled */ + rgui->show_fs_thumbnail = false; return menu; error: rgui_framebuffer_free(); - rgui_thumbnail_free(); + rgui_thumbnail_free(&fs_thumbnail); + rgui_thumbnail_free(&mini_thumbnail); + rgui_thumbnail_free(&mini_left_thumbnail); rgui_wallpaper_free(); if (menu) free(menu); @@ -2259,7 +2469,9 @@ static void rgui_free(void *data) menu_display_set_font_data_init(fb_font_inited); rgui_framebuffer_free(); - rgui_thumbnail_free(); + rgui_thumbnail_free(&fs_thumbnail); + rgui_thumbnail_free(&mini_thumbnail); + rgui_thumbnail_free(&mini_left_thumbnail); rgui_wallpaper_free(); if (rgui_upscale_buf.data) @@ -2442,21 +2654,50 @@ static void rgui_set_thumbnail_system(void *userdata, char *s, size_t len) static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui) { - rgui->entry_has_thumbnail = false; + settings_t *settings = config_get_ptr(); - if (rgui->show_thumbnail && rgui->is_playlist) + if (!settings) + return; + + rgui->entry_has_thumbnail = false; + rgui->entry_has_left_thumbnail = false; + + if ((rgui->show_fs_thumbnail || settings->bools.menu_rgui_inline_thumbnails) && rgui->is_playlist) { if (menu_thumbnail_set_content_playlist(rgui->thumbnail_path_data, playlist_get_cached(), menu_navigation_get_selection())) { - if (menu_thumbnail_update_path(rgui->thumbnail_path_data, MENU_THUMBNAIL_RIGHT)) + if (menu_thumbnail_is_enabled(MENU_THUMBNAIL_RIGHT)) { - const char *thumbnail_path = NULL; - - if (menu_thumbnail_get_path(rgui->thumbnail_path_data, - MENU_THUMBNAIL_RIGHT, &thumbnail_path)) + if (menu_thumbnail_update_path(rgui->thumbnail_path_data, MENU_THUMBNAIL_RIGHT)) { - rgui->entry_has_thumbnail = request_thumbnail(rgui, thumbnail_path); + const char *thumbnail_path = NULL; + + if (menu_thumbnail_get_path(rgui->thumbnail_path_data, + MENU_THUMBNAIL_RIGHT, &thumbnail_path)) + { + if (rgui->show_fs_thumbnail) + rgui->entry_has_thumbnail = request_thumbnail( + &fs_thumbnail, MENU_THUMBNAIL_RIGHT, &rgui->thumbnail_queue_size, thumbnail_path); + else + rgui->entry_has_thumbnail = request_thumbnail( + &mini_thumbnail, MENU_THUMBNAIL_RIGHT, &rgui->thumbnail_queue_size, thumbnail_path); + } + } + } + + if (settings->bools.menu_rgui_inline_thumbnails && menu_thumbnail_is_enabled(MENU_THUMBNAIL_LEFT)) + { + if (menu_thumbnail_update_path(rgui->thumbnail_path_data, MENU_THUMBNAIL_LEFT)) + { + const char *left_thumbnail_path = NULL; + + if (menu_thumbnail_get_path(rgui->thumbnail_path_data, + MENU_THUMBNAIL_LEFT, &left_thumbnail_path)) + { + rgui->entry_has_left_thumbnail = request_thumbnail( + &mini_left_thumbnail, MENU_THUMBNAIL_LEFT, &rgui->left_thumbnail_queue_size, left_thumbnail_path); + } } } } @@ -2465,11 +2706,37 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui) static void rgui_update_thumbnail_image(void *userdata) { - rgui_t *rgui = (rgui_t*)userdata; - if (!rgui) + rgui_t *rgui = (rgui_t*)userdata; + settings_t *settings = config_get_ptr(); + if (!rgui || !settings) return; - rgui->show_thumbnail = !rgui->show_thumbnail; + rgui->show_fs_thumbnail = !rgui->show_fs_thumbnail; + + /* It is possible that we are waiting for a 'right' thumbnail + * image to load at this point. If so, and we are displaying + * inline thumbnails, then 'fs_thumbnail' and 'mini_thumbnail' + * can get mixed up. To avoid this, we simply 'reset' the + * currently inactive right thumbnail. */ + if (settings->bools.menu_rgui_inline_thumbnails) + { + if (rgui->show_fs_thumbnail) + { + mini_thumbnail.width = 0; + mini_thumbnail.height = 0; + mini_thumbnail.is_valid = false; + free(mini_thumbnail.path); + mini_thumbnail.path = NULL; + } + else + { + fs_thumbnail.width = 0; + fs_thumbnail.height = 0; + fs_thumbnail.is_valid = false; + free(fs_thumbnail.path); + fs_thumbnail.path = NULL; + } + } rgui_scan_selected_entry_thumbnail(rgui); } @@ -2590,8 +2857,7 @@ static void rgui_populate_entries(void *data, /* Check whether we are currently viewing a playlist */ rgui->is_playlist = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_LIST)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY)) || - string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST)) || - string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_IMAGES_LIST)); + string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST)); /* Set menu title */ menu_entries_get_title(rgui->menu_title, sizeof(rgui->menu_title)); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index d4bd92dfe8..9437e5d562 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -6211,6 +6211,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist MENU_ENUM_LABEL_MENU_USE_PREFERRED_SYSTEM_COLOR_THEME, PARSE_ONLY_BOOL, false) == 0) count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS, + PARSE_ONLY_BOOL, false) == 0) + count++; if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_THUMBNAILS, PARSE_ONLY_UINT, false) == 0) @@ -6223,6 +6227,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, PARSE_ONLY_BOOL, false) == 0) count++; + if (menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS, + PARSE_ONLY_BOOL, false) == 0) + count++; if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_MENU_RGUI_THUMBNAIL_DOWNSCALER, PARSE_ONLY_UINT, false) == 0) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index c0bbabde1e..e574986ef2 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -9345,13 +9345,65 @@ static bool setting_append_list( general_read_handler, SD_FLAG_ADVANCED); + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_inline_thumbnails, + MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_INLINE_THUMBNAILS, + rgui_inline_thumbnails, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_rgui_swap_thumbnails, + MENU_ENUM_LABEL_MENU_RGUI_SWAP_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_MENU_RGUI_SWAP_THUMBNAILS, + rgui_swap_thumbnails, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); + } + if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone") || string_is_equal(settings->arrays.menu_driver, "rgui")) { + enum msg_hash_enums thumbnails_label_value; + enum msg_hash_enums left_thumbnails_label_value; + + if (string_is_equal(settings->arrays.menu_driver, "rgui")) + { + thumbnails_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS_RGUI; + left_thumbnails_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_RGUI; + } + else if (string_is_equal(settings->arrays.menu_driver, "ozone")) + { + thumbnails_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS; + left_thumbnails_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_OZONE; + } + else + { + thumbnails_label_value = MENU_ENUM_LABEL_VALUE_THUMBNAILS; + left_thumbnails_label_value = MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS; + } + CONFIG_UINT( list, list_info, &settings->uints.menu_thumbnails, MENU_ENUM_LABEL_THUMBNAILS, - MENU_ENUM_LABEL_VALUE_THUMBNAILS, + thumbnails_label_value, menu_thumbnails_default, &group_info, &subgroup_info, @@ -9362,6 +9414,40 @@ static bool setting_append_list( (*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_uint_menu_thumbnails; menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + + CONFIG_UINT( + list, list_info, + &settings->uints.menu_left_thumbnails, + MENU_ENUM_LABEL_LEFT_THUMBNAILS, + left_thumbnails_label_value, + menu_left_thumbnails_default, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_uint_menu_left_thumbnails; + menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); + } + + if (string_is_equal(settings->arrays.menu_driver, "xmb")) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_xmb_vertical_thumbnails, + MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, + xmb_vertical_thumbnails, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE); } if (string_is_equal(settings->arrays.menu_driver, "rgui")) @@ -9383,45 +9469,6 @@ static bool setting_append_list( menu_settings_list_current_add_range(list, list_info, 0, RGUI_THUMB_SCALE_LAST-1, 1, true, true); } - if (string_is_equal(settings->arrays.menu_driver, "xmb") || string_is_equal(settings->arrays.menu_driver, "ozone")) - { - bool is_ozone = string_is_equal(settings->arrays.menu_driver, "ozone"); - enum msg_hash_enums label = is_ozone ? - MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS_OZONE : MENU_ENUM_LABEL_VALUE_LEFT_THUMBNAILS; - - CONFIG_UINT( - list, list_info, - &settings->uints.menu_left_thumbnails, - MENU_ENUM_LABEL_LEFT_THUMBNAILS, - label, - menu_left_thumbnails_default, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler); - (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; - (*list)[list_info->index - 1].get_string_representation = - &setting_get_string_representation_uint_menu_left_thumbnails; - menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true); - - if (!is_ozone) - CONFIG_BOOL( - list, list_info, - &settings->bools.menu_xmb_vertical_thumbnails, - MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, - MENU_ENUM_LABEL_VALUE_XMB_VERTICAL_THUMBNAILS, - xmb_vertical_thumbnails, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_NONE); - } - CONFIG_BOOL( list, list_info, &settings->bools.menu_timedate_enable, diff --git a/msg_hash.h b/msg_hash.h index 8562efeaa0..e4bc2b0ccf 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -901,9 +901,13 @@ enum msg_hash_enums MENU_LABEL(CONTENT_SHOW_PLAYLISTS), MENU_LABEL(XMB_RIBBON_ENABLE), MENU_LABEL(THUMBNAILS), + MENU_LABEL(THUMBNAILS_RGUI), MENU_LABEL(LEFT_THUMBNAILS), + MENU_LABEL(LEFT_THUMBNAILS_RGUI), MENU_LABEL(LEFT_THUMBNAILS_OZONE), MENU_LABEL(XMB_VERTICAL_THUMBNAILS), + MENU_LABEL(MENU_RGUI_INLINE_THUMBNAILS), + MENU_LABEL(MENU_RGUI_SWAP_THUMBNAILS), MENU_LABEL(MENU_RGUI_THUMBNAIL_DOWNSCALER), MENU_LABEL(TIMEDATE_ENABLE), MENU_LABEL(TIMEDATE_STYLE),