diff --git a/config.def.keybinds.h b/config.def.keybinds.h index 5271b3a068..eb16c5aac4 100644 --- a/config.def.keybinds.h +++ b/config.def.keybinds.h @@ -71,7 +71,11 @@ static const struct retro_keybind retro_keybinds_1[] = { { true, RARCH_LOAD_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#ifdef HAVE_LAKKA + { true, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#else { true, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#endif { true, RARCH_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_REWIND, MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND, RETROK_UNKNOWN, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, @@ -235,7 +239,11 @@ static const struct retro_keybind retro_keybinds_1[] = { { true, RARCH_LOAD_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY, RETROK_F4, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY, RETROK_F2, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY, RETROK_f, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#ifdef HAVE_LAKKA + { true, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY, RETROK_ESCAPE, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#else { true, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, RETROK_ESCAPE, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, +#endif { true, RARCH_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS, RETROK_F7, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS, RETROK_F6, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, { true, RARCH_REWIND, MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND, RETROK_r, NO_BTN, NO_BTN, 0, AXIS_NONE, AXIS_NONE, AXIS_NONE, NULL, NULL }, diff --git a/intl/.gitignore b/intl/.gitignore new file mode 100644 index 0000000000..1d6146afdd --- /dev/null +++ b/intl/.gitignore @@ -0,0 +1,3 @@ +*.json +crowdin.yaml +crowdin.yml diff --git a/intl/README.md b/intl/README.md new file mode 100644 index 0000000000..13721d9ad7 --- /dev/null +++ b/intl/README.md @@ -0,0 +1,23 @@ +# Internationalization Workflow (Draft) + +## Steps + +- Developers update strings in `msg_hash_us.h`. +- Developers (can set a cron job) run `./h2json.py msg_hash_us.h` to generate `msg_hash_us.json`. It is just a convenient format that is supported by Weblate/Crowdin/Transifex and doesn't need to be inversion control. +- Developers (can set a cron job) upload `msg_hash_us.json` to Weblate/Crowdin/Transifex. +- Translators translate strings on Weblate/Crowdin/Transifex. +- Developers (can set a cron job) download `msg_hash_xx.json` files. +- Developers (can set a cron job) run `./json2h.py msg_hash_xx.json` to generate `msg_hash_xx.h`. + +## Pros + +- No new dependencies. +- No performance impact. +- Don't require translators to know how to use Git, how to read C code and how to create Pull Request. +- Translators will be informed whenever a source string changes. + +## Cron job setup + +1. [Install crowdin cli tool](https://support.crowdin.com/cli-tool/) +2. Get the `intl/crowdin.yaml` file from someone who have crowdin admin accounts +3. Add cron job `cd path/to/retroarch/intl && ./crowin_sync.sh` diff --git a/intl/crowdin_sync.sh b/intl/crowdin_sync.sh new file mode 100755 index 0000000000..084834bb3a --- /dev/null +++ b/intl/crowdin_sync.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Update source code +git pull + +# Convert source *.h to *.json +./h2json.py msg_hash_us.h + +# Upload source file +crowdin upload sources + +# Crowdin need some time to process data +sleep 1m + +# Download translation files +crowdin download translations + +# Convert translation *.json to *.h +for f in *.json +do + ./json2h.py $f +done + +# Commit new translations +git add . +git commit -m "Synchronize translations" +git push diff --git a/intl/h2json.py b/intl/h2json.py new file mode 100755 index 0000000000..eb986cb063 --- /dev/null +++ b/intl/h2json.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +# Convert *.h to *.json +# Usage: ./h2json.py msg_has_us.h + +import re +import sys +import json + +try: + h_filename = sys.argv[1] + json_filename = h_filename.replace('.h', '.json') +except IndexError: + print("Usage: ./h2json.py msg_has_us.h") + sys.exit(1) + +p = re.compile('MSG_HASH\(\s*[A-Z0-9_]+,\s*\".*\"\s*\)') + +header = """#if defined(_MSC_VER) && !defined(_XBOX) && (_MSC_VER >= 1500 && _MSC_VER < 1900) +#if (_MSC_VER >= 1700) +/* https://support.microsoft.com/en-us/kb/980263 */ +#pragma execution_character_set("utf-8") +#endif +#pragma warning(disable:4566) +#endif +""" + + +def parse_message(message): + key_start = message.find('(') + 1 + key_end = message.find(',') + key = message[key_start:key_end].strip() + value_start = message.find('"') + 1 + value_end = message.rfind('"') + value = message[value_start:value_end].strip() + return key, value + + +try: + with open(h_filename, 'r+') as h_file: + text = h_file.read() + result = p.findall(text) + seen = set() + messages = {} + for msg in result: + key, val = parse_message(msg) + messages[key] = val + if key not in seen: + seen.add(key) + else: + print("Duplicate key: " + key) + with open(json_filename, 'w') as json_file: + json.dump(messages, json_file, indent=2) +except EnvironmentError: + print('Cannot read/write ' + h_filename) diff --git a/intl/json2h.py b/intl/json2h.py new file mode 100755 index 0000000000..1b4ea13372 --- /dev/null +++ b/intl/json2h.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +# Convert *.json to *.h +# Usage: ./json2h.py msg_hash_fr.json + +import re +import sys +import json + +try: + json_filename = sys.argv[1] + h_filename = json_filename.replace('.json', '.h') +except IndexError: + print("Usage: ./template.py ") + sys.exit(1) + +if json_filename == 'msg_hash_us.json': + print("Skip") + sys.exit(0) + +p = re.compile('MSG_HASH\(\s*[A-Z0-9_]+,\s*\".*\"\s*\)') + + +def parse_message(message): + key_start = message.find('(') + 1 + key_end = message.find(',') + key = message[key_start:key_end].strip() + value_start = message.find('"') + 1 + value_end = message.rfind('"') + value = message[value_start:value_end].strip() + return key, value + + +def parse_messages(text): + result = p.findall(text) + seen = set() + msg_list = [] + for msg in result: + key, val = parse_message(msg) + item = {'key': key, 'val': val, 'msg': msg} + msg_list.append(item) + if key not in seen: + seen.add(key) + else: + print("Duplicate key: " + key) + + return msg_list + + +def update(messages, template): + new_translation = template + template_messages = parse_messages(template) + for tp_msg in template_messages: + if tp_msg['key'] in messages: + tp_msg_val = tp_msg['val'] + tl_msg_val = messages[tp_msg['key']] + old_msg = tp_msg['msg'] + new_msg = old_msg.replace(tp_msg_val, tl_msg_val) + new_translation = new_translation.replace(old_msg, new_msg) + return new_translation + + +with open('msg_hash_us.h', 'r') as template_file: + template = template_file.read() + try: + with open(json_filename, 'r+') as json_file: + messages = json.load(json_file) + new_translation = update(messages, template) + with open(h_filename, 'w') as h_file: + h_file.seek(0) + h_file.write(new_translation) + h_file.truncate() + except EnvironmentError: + print('Cannot read/write ' + json_filename) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index a1fda62dba..a1e2a6dfb6 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1,3 +1,11 @@ +#if defined(_MSC_VER) && !defined(_XBOX) && (_MSC_VER >= 1500 && _MSC_VER < 1900) +#if (_MSC_VER >= 1700) +/* https://support.microsoft.com/en-us/kb/980263 */ +#pragma execution_character_set("utf-8") +#endif +#pragma warning(disable:4566) +#endif + #ifdef HAVE_LAKKA_SWITCH MSG_HASH( MENU_ENUM_LABEL_VALUE_SWITCH_GPU_PROFILE, @@ -1466,17 +1474,14 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_PAUSE_TOGGLE, "Pause toggle" ) -#ifdef HAVE_LAKKA MSG_HASH( - MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, + MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY, "Restart RetroArch" ) -#else MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, "Quit RetroArch" ) -#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_RESET, "Reset game" @@ -2567,12 +2572,6 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_MIDI_SETTINGS, "MIDI" ) -#ifdef HAVE_LAKKA -MSG_HASH( - MENU_ENUM_LABEL_VALUE_QUIT_RETROARCH, - "Restart RetroArch" - ) -#else MSG_HASH( MENU_ENUM_LABEL_VALUE_QUIT_RETROARCH, "Quit RetroArch" @@ -2581,7 +2580,6 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_RESTART_RETROARCH, "Restart RetroArch" ) -#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_RDB_ENTRY_DETAIL, "Database Entry" @@ -2732,15 +2730,14 @@ MSG_HASH( ) #ifdef HAVE_LAKKA_SWITCH MSG_HASH( - MENU_ENUM_LABEL_VALUE_REBOOT, + MENU_ENUM_LABEL_VALUE_REBOOT_RCM, "Reboot into RCM" ) -#else +#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_REBOOT, "Reboot" ) -#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_RECORDING_CONFIG_DIRECTORY, "Recording Config" @@ -6037,12 +6034,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_SYSTEM_INFORMATION, "Show information specific to the device." ) -#ifdef HAVE_LAKKA -MSG_HASH( - MENU_ENUM_SUBLABEL_QUIT_RETROARCH, - "Restart the program." - ) -#else MSG_HASH( MENU_ENUM_SUBLABEL_QUIT_RETROARCH, "Quit the program." @@ -6051,7 +6042,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_RESTART_RETROARCH, "Restart the program." ) -#endif MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_WINDOW_WIDTH, "Set the custom width for the display window." @@ -7335,16 +7325,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_MENU_SHOW_HELP, "Show/hide the 'Help' option." ) -#ifdef HAVE_LAKKA -MSG_HASH( - MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, - "Show Restart RetroArch" - ) -MSG_HASH( - MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, - "Show/hide the 'Restart RetroArch' option." - ) -#else MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, "Show Quit RetroArch" @@ -7361,7 +7341,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_MENU_SHOW_RESTART_RETROARCH, "Show/hide the 'Restart RetroArch' option." ) -#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_SHOW_REBOOT, "Show Reboot" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 9a4a43173c..bb31d502c8 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -72,7 +72,7 @@ static int menu_action_sublabel_file_browser_core(file_list_t *list, unsigned ty unsigned j; for (j = 0; j < core_list->count; j++) { - if (string_is_equal(path_basename(core_list->list[j].path), + if (string_is_equal(path_basename(core_list->list[j].path), path)) { if (core_list->list[j].licenses_list) @@ -305,7 +305,11 @@ default_sublabel_macro(action_bind_sublabel_content_special, MENU_ default_sublabel_macro(action_bind_sublabel_load_content_history, MENU_ENUM_SUBLABEL_LOAD_CONTENT_HISTORY) default_sublabel_macro(action_bind_sublabel_network_information, MENU_ENUM_SUBLABEL_NETWORK_INFORMATION) default_sublabel_macro(action_bind_sublabel_system_information, MENU_ENUM_SUBLABEL_SYSTEM_INFORMATION) +#ifdef HAVE_LAKKA +default_sublabel_macro(action_bind_sublabel_quit_retroarch, MENU_ENUM_SUBLABEL_RESTART_RETROARCH) +#else default_sublabel_macro(action_bind_sublabel_quit_retroarch, MENU_ENUM_SUBLABEL_QUIT_RETROARCH) +#endif default_sublabel_macro(action_bind_sublabel_restart_retroarch, MENU_ENUM_SUBLABEL_RESTART_RETROARCH) default_sublabel_macro(action_bind_sublabel_menu_widgets, MENU_ENUM_SUBLABEL_MENU_WIDGETS_ENABLE) default_sublabel_macro(action_bind_sublabel_video_window_width, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_WIDTH) @@ -1053,7 +1057,7 @@ static int action_bind_sublabel_playlist_entry( settings_t *settings = config_get_ptr(); playlist_t *playlist = NULL; const struct playlist_entry *entry = NULL; - + if (!settings->bools.playlist_show_sublabels || string_is_equal(settings->arrays.menu_driver, "ozone")) return 0; @@ -1065,19 +1069,19 @@ static int action_bind_sublabel_playlist_entry( if (i >= playlist_get_size(playlist)) return 0; - + /* Read playlist entry */ playlist_get_index(playlist, i, &entry); - + /* Only add sublabel if a core is currently assigned */ if (string_is_empty(entry->core_name) || string_is_equal(entry->core_name, "DETECT")) return 0; - + /* Add core name */ strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PLAYLIST_SUBLABEL_CORE), len); strlcat(s, " ", len); strlcat(s, entry->core_name, len); - + /* Get runtime info *if* required runtime log is enabled * *and* this is a valid playlist type */ if (((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_PER_CORE) && @@ -1085,7 +1089,7 @@ static int action_bind_sublabel_playlist_entry( ((settings->uints.playlist_sublabel_runtime_type == PLAYLIST_RUNTIME_AGGREGATE) && !settings->bools.content_runtime_log_aggregate)) return 0; - + /* Note: This looks heavy, but each string_is_equal() call will * return almost immediately */ if (!string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY)) && @@ -1095,17 +1099,17 @@ static int action_bind_sublabel_playlist_entry( !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_HORIZONTAL_MENU))) return 0; - + /* Check whether runtime info should be loaded from log file */ if (entry->runtime_status == PLAYLIST_RUNTIME_UNKNOWN) runtime_update_playlist(playlist, i); - + /* Check whether runtime info is valid */ if (entry->runtime_status == PLAYLIST_RUNTIME_VALID) { int n = 0; char tmp[64]; - + tmp[0 ] = '\n'; tmp[1 ] = '\0'; @@ -1113,18 +1117,18 @@ static int action_bind_sublabel_playlist_entry( tmp[n ] = '\n'; tmp[n+1] = '\0'; - + /* Runtime/last played strings are now cached in the * playlist, so we can add both in one go */ n = strlcat(tmp, entry->last_played_str, sizeof(tmp)); - + if ((n < 0) || (n >= 64)) n = 0; /* Silence GCC warnings... */ - + if (!string_is_empty(tmp)) strlcat(s, tmp, len); } - + return 0; } diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 07d8c415fd..495e0013db 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -277,7 +277,7 @@ struct string_options_entry (*a)[b->index - 1].enum_idx = c #define MENU_SETTINGS_LIST_CURRENT_ADD_ENUM_VALUE_IDX(a, b, c) \ - (*a)[b->index - 1].enum_value_idx = c + (*a)[b->index - 1].enum_value_idx = c static void menu_input_st_uint_cb(void *userdata, const char *str) { @@ -631,7 +631,7 @@ int setting_uint_action_left_default( overflowed = step > *setting->value.target.unsigned_integer; if (!overflowed) - *setting->value.target.unsigned_integer = + *setting->value.target.unsigned_integer = *setting->value.target.unsigned_integer - step; if (setting->enforce_minrange) @@ -662,7 +662,7 @@ int setting_uint_action_right_default( return -1; max = setting->max; - step = + step = recalc_step_based_on_length_of_action(setting); *setting->value.target.unsigned_integer = @@ -4185,7 +4185,7 @@ static void setting_get_string_representation_uint_xmb_menu_color_theme( msg_hash_to_str( MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME_SUNBEAM), len); - break; + break; } } #endif @@ -4358,7 +4358,7 @@ static void setting_get_string_representation_crt_switch_resolution_super( else if (*setting->value.target.unsigned_integer == 1) strlcpy(s, "DYNAMIC", len); else - snprintf(s, len, "%d", *setting->value.target.unsigned_integer); + snprintf(s, len, "%d", *setting->value.target.unsigned_integer); } static void setting_get_string_representation_uint_playlist_sublabel_runtime_type( @@ -5888,7 +5888,7 @@ rarch_setting_t *menu_setting_find_enum(enum msg_hash_enums enum_idx) return NULL; for (; setting_get_type(setting) != ST_NONE; (*list = *list + 1)) { - if ( setting->enum_idx == enum_idx && + if ( setting->enum_idx == enum_idx && setting_get_type(setting) <= ST_GROUP) { const char *short_description = setting->short_description; @@ -6570,7 +6570,7 @@ void general_write_handler(rarch_setting_t *setting) video_driver_set_rotation( (*setting->value.target.unsigned_integer + system->rotation) % 4); - + /* Update Custom Aspect Ratio values */ video_driver_get_viewport_info(&vp); custom->x = 0; @@ -7081,7 +7081,7 @@ static bool setting_append_list_input_player_options( "%s %u", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_SPLIT_JOYCON), user + 1); snprintf(label[user], sizeof(label[user]), - "%s", + "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_DEVICE_INDEX)); snprintf(label_type[user], sizeof(label_type[user]), "%s", @@ -7093,13 +7093,13 @@ static bool setting_append_list_input_player_options( "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_BIND_ALL)); snprintf(label_bind_defaults[user], sizeof(label_bind_defaults[user]), - "%s", + "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_BIND_DEFAULT_ALL)); snprintf(label_bind_all_save_autoconfig[user], sizeof(label_bind_all_save_autoconfig[user]), - "%s", + "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG)); snprintf(label_mouse_index[user], sizeof(label_mouse_index[user]), - "%s", + "%s", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX)); CONFIG_UINT_ALT( @@ -7675,6 +7675,15 @@ static bool setting_append_list( #endif #if !defined(IOS) /* Apple rejects iOS apps that let you forcibly quit them. */ +#ifdef HAVE_LAKKA + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_QUIT_RETROARCH, + MENU_ENUM_LABEL_VALUE_RESTART_RETROARCH, + &group_info, + &subgroup_info, + parent_group); +#else CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_QUIT_RETROARCH, @@ -7682,6 +7691,7 @@ static bool setting_append_list( &group_info, &subgroup_info, parent_group); +#endif menu_settings_list_current_add_cmd(list, list_info, CMD_EVENT_QUIT); #endif @@ -7713,6 +7723,15 @@ static bool setting_append_list( &subgroup_info, parent_group); #endif +#ifdef HAVE_LAKKA_SWITCH + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_REBOOT, + MENU_ENUM_LABEL_VALUE_REBOOT_RCM, + &group_info, + &subgroup_info, + parent_group); +#else CONFIG_ACTION( list, list_info, MENU_ENUM_LABEL_REBOOT, @@ -7720,6 +7739,7 @@ static bool setting_append_list( &group_info, &subgroup_info, parent_group); +#endif menu_settings_list_current_add_cmd(list, list_info, CMD_EVENT_REBOOT); CONFIG_ACTION( @@ -10143,7 +10163,7 @@ static bool setting_append_list( (*list)[list_info->index - 1].action_ok = setting_bool_action_left_with_refresh; (*list)[list_info->index - 1].action_left = setting_bool_action_left_with_refresh; (*list)[list_info->index - 1].action_right = setting_bool_action_right_with_refresh; - + CONFIG_UINT( list, list_info, &settings->uints.video_hard_sync_frames, @@ -13267,6 +13287,22 @@ static bool setting_append_list( general_read_handler, SD_FLAG_LAKKA_ADVANCED); +#ifdef HAVE_LAKKA + CONFIG_BOOL( + list, list_info, + &settings->bools.menu_show_quit_retroarch, + MENU_ENUM_LABEL_MENU_SHOW_QUIT_RETROARCH, + MENU_ENUM_LABEL_VALUE_MENU_SHOW_RESTART_RETROARCH, + menu_show_quit_retroarch, + 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); +#else CONFIG_BOOL( list, list_info, &settings->bools.menu_show_quit_retroarch, @@ -13281,6 +13317,7 @@ static bool setting_append_list( general_write_handler, general_read_handler, SD_FLAG_NONE); +#endif #ifdef HAVE_LAKKA CONFIG_BOOL( @@ -13676,7 +13713,7 @@ static bool setting_append_list( general_read_handler); (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; menu_settings_list_current_add_range(list, list_info, 0.0, 1.0, 0.010, true, true); - (*list)[list_info->index - 1].ui_type + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_FLOAT_SLIDER_AND_SPINBOX; */ } diff --git a/msg_hash.h b/msg_hash.h index d67859f1d6..41d41e14ce 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -793,6 +793,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY, + MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_BSV_RECORD_TOGGLE, diff --git a/retroarch.c b/retroarch.c index cada7d3922..ec1a957603 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2659,7 +2659,7 @@ bool menu_input_dialog_start_search(void) sizeof(menu_input_dialog_keyboard_label)); input_keyboard_ctl(RARCH_INPUT_KEYBOARD_CTL_LINE_FREE, NULL); - + #ifdef HAVE_ACCESSIBILITY if (is_accessibility_enabled()) accessibility_speak_priority((char*) @@ -3432,7 +3432,11 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = { DECLARE_META_BIND(1, load_state, RARCH_LOAD_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY), DECLARE_META_BIND(1, save_state, RARCH_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY), DECLARE_META_BIND(2, toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY), +#ifdef HAVE_LAKKA + DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY), +#else DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY), +#endif DECLARE_META_BIND(2, state_slot_increase, RARCH_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS), DECLARE_META_BIND(2, state_slot_decrease, RARCH_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS), DECLARE_META_BIND(1, rewind, RARCH_REWIND, MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND), @@ -4541,7 +4545,7 @@ static void handle_translation_cb( } i++; } - + if (string_is_equal(error_string, "No text found.")) { RARCH_LOG("No text found...\n"); @@ -4549,14 +4553,14 @@ static void handle_translation_cb( { text_string = (char*)malloc(15); } - + strlcpy(text_string, error_string, 15); #ifdef HAVE_MENU_WIDGETS if (menu_widgets_paused) { /* In this case we have to unpause and then repause for a frame */ menu_widgets_ai_service_overlay_set_state(2); - command_event(CMD_EVENT_UNPAUSE, NULL); + command_event(CMD_EVENT_UNPAUSE, NULL); } #endif } @@ -4589,7 +4593,7 @@ static void handle_translation_cb( { image_type = IMAGE_TYPE_BMP; } - else if (raw_image_file_data[1] == 'P' && + else if (raw_image_file_data[1] == 'P' && raw_image_file_data[2] == 'N' && raw_image_file_data[3] == 'G') image_type = IMAGE_TYPE_PNG; @@ -4598,11 +4602,11 @@ static void handle_translation_cb( RARCH_LOG("Invalid image type returned from server.\n"); goto finish; } - + ai_res = menu_widgets_ai_service_overlay_load( - raw_image_file_data, (unsigned) new_image_size, + raw_image_file_data, (unsigned) new_image_size, image_type); - + if (!ai_res) { RARCH_LOG("Video driver not supported for AI Service."); @@ -4619,7 +4623,7 @@ static void handle_translation_cb( command_event(CMD_EVENT_UNPAUSE, NULL); } } - else + else #endif /* Can't use menu widget overlays, so try writing to video buffer */ { @@ -4640,8 +4644,8 @@ static void handle_translation_cb( ((uint32_t) ((uint8_t)raw_image_file_data[23]) << 8) + ((uint32_t) ((uint8_t)raw_image_file_data[22]) << 0); raw_image_data = (void*)malloc(image_width*image_height*3*sizeof(uint8_t)); - memcpy(raw_image_data, - raw_image_file_data+54*sizeof(uint8_t), + memcpy(raw_image_data, + raw_image_file_data+54*sizeof(uint8_t), image_width*image_height*3*sizeof(uint8_t)); } else if (raw_image_file_data[1] == 'P' && raw_image_file_data[2] == 'N' && @@ -4660,7 +4664,7 @@ static void handle_translation_cb( ((uint32_t) ((uint8_t)raw_image_file_data[22])<<8)+ ((uint32_t) ((uint8_t)raw_image_file_data[23])<<0); rpng = rpng_alloc(); - + if (!rpng) { error = "Can't allocate memory."; @@ -4701,7 +4705,7 @@ static void handle_translation_cb( { RARCH_LOG("Output from URL not a valid file type, or is not supported.\n"); goto finish; - } + } scaler = (struct scaler_ctx*)calloc(1, sizeof(struct scaler_ctx)); if (!scaler) @@ -4756,7 +4760,7 @@ static void handle_translation_cb( video_driver_frame(raw_output_data, image_width, image_height, pitch); } } - + #ifdef HAVE_AUDIOMIXER if (raw_sound_data) { @@ -5007,9 +5011,9 @@ static const char *ai_service_get_str(enum translation_lang id) To make your own server, it must listen for a POST request, which will consist of a JSON body, with the "image" field as a base64 - encoded string of a 24bit-BMP/PNG that the will be translated. - The server must output the translated image in the form of a - JSON body, with the "image" field also as a base64 encoded + encoded string of a 24bit-BMP/PNG that the will be translated. + The server must output the translated image in the form of a + JSON body, with the "image" field also as a base64 encoded 24bit-BMP, or as an alpha channel png. */ static bool run_translation_service(void) @@ -5044,7 +5048,7 @@ static bool run_translation_service(void) char* system_label = NULL; core_info_t *core_info = NULL; -#ifdef HAVE_MENU_WIDGETS +#ifdef HAVE_MENU_WIDGETS if (menu_widgets_ai_service_overlay_get_state() != 0) { /* For the case when ai service pause is disabled. */ @@ -5071,7 +5075,7 @@ static bool run_translation_service(void) { const char *system_id = core_info->system_id ? core_info->system_id : "core"; - + const struct playlist_entry *entry = NULL; playlist_t *current_playlist = playlist_get_cached(); @@ -5232,7 +5236,7 @@ static bool run_translation_service(void) memcpy(json_buffer, (const void*)rf1, 11*sizeof(uint8_t)); memcpy(json_buffer+11, bmp64_buffer, (out_length)*sizeof(uint8_t)); if (rf3) - memcpy(json_buffer+11+out_length, (const void*)rf3, (16+strlen(system_label))*sizeof(uint8_t)); + memcpy(json_buffer+11+out_length, (const void*)rf3, (16+strlen(system_label))*sizeof(uint8_t)); else memcpy(json_buffer+11+out_length, (const void*)rf2, 3*sizeof(uint8_t)); RARCH_LOG("Request size: %d\n", out_length); @@ -5311,7 +5315,7 @@ static bool run_translation_service(void) if (use_overlay) mode_chr = "image,png,png-a,sound,wav"; else - mode_chr = "image,png,sound,wav"; + mode_chr = "image,png,sound,wav"; break; default: break; @@ -6550,13 +6554,13 @@ bool command_event(enum event_command cmd, void *data) #endif command_event(CMD_EVENT_UNPAUSE, NULL); } - } + } else { /* Don't pause - useful for Text-To-Speech since * the audio can't currently play while paused. * Also useful for cases when users don't want the - * core's sound to stop while translating. */ + * core's sound to stop while translating. */ command_event(CMD_EVENT_AI_SERVICE_CALL, NULL); } #endif @@ -8004,7 +8008,7 @@ static void global_free(void) void main_exit(void *args) { settings_t *settings = configuration_settings; - + if (cached_video_driver[0]) { strlcpy(settings->arrays.video_driver, cached_video_driver, @@ -9813,7 +9817,7 @@ static bool rarch_environment_cb(unsigned cmd, void *data) video_driver_get_hw_context_internal(); RARCH_LOG("[Environ]: SET_HW_RENDER.\n"); - + if (!dynamic_request_hw_context( cb->context_type, cb->version_minor, cb->version_major)) return false; @@ -10313,7 +10317,7 @@ static bool rarch_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT: #ifdef HAVE_LIBNX - /* TODO/FIXME - Force this off for now for Switch + /* TODO/FIXME - Force this off for now for Switch * until shared HW context can work there */ return false; #else @@ -13963,7 +13967,7 @@ static int16_t input_state_device( */ if (settings->uints.input_turbo_mode == 1) { - /* Pressing turbo button toggles turbo mode on or off. + /* Pressing turbo button toggles turbo mode on or off. * Holding the button will * pass through, else the pressed state will be modulated by a * periodic pulse defined by the configured duty cycle. @@ -14006,7 +14010,7 @@ static int16_t input_state_device( { uint16_t enable_new; input_driver_turbo_btns.turbo_pressed[port] |= 1 << id; - /* Toggle turbo for pressed button but make + /* Toggle turbo for pressed button but make * sure at least one button has turbo */ enable_new = input_driver_turbo_btns.enable[port] ^ (1 << id); if (enable_new) @@ -16853,7 +16857,7 @@ void input_keyboard_event(bool down, unsigned code, static bool deferred_wait_keys; #ifdef HAVE_ACCESSIBILITY #ifdef HAVE_MENU - if (menu_input_dialog_get_display_kb() + if (menu_input_dialog_get_display_kb() && down && is_accessibility_enabled()) { if (code != 303 && code != 0) @@ -20141,7 +20145,7 @@ static bool hw_render_context_is_gl(enum retro_hw_context_type type) bool *video_driver_get_threaded(void) { -#if defined(__MACH__) && defined(__APPLE__) +#if defined(__MACH__) && defined(__APPLE__) /* TODO/FIXME - force threaded video to disabled on Apple for now * until NSWindow/UIWindow concurrency issues are taken care of */ video_driver_threaded = false; @@ -20151,7 +20155,7 @@ bool *video_driver_get_threaded(void) void video_driver_set_threaded(bool val) { -#if defined(__MACH__) && defined(__APPLE__) +#if defined(__MACH__) && defined(__APPLE__) /* TODO/FIXME - force threaded video to disabled on Apple for now * until NSWindow/UIWindow concurrency issues are taken care of */ video_driver_threaded = false; @@ -21752,7 +21756,7 @@ static void video_driver_frame(const void *data, unsigned width, frame_cache_width = width; frame_cache_height = height; frame_cache_pitch = pitch; - + if ( video_driver_scaler_ptr && data @@ -28590,7 +28594,7 @@ unsigned int retroarch_get_rotation(void) bool is_input_keyboard_display_on(void) -{ +{ #ifdef HAVE_MENU return menu_input_dialog_get_display_kb(); #else @@ -28599,6 +28603,7 @@ bool is_input_keyboard_display_on(void) } #ifdef HAVE_ACCESSIBILITY + bool accessibility_speak_priority(const char* speak_text, int priority) { RARCH_LOG("Spoke: %s\n", speak_text); @@ -28613,11 +28618,11 @@ bool accessibility_speak_priority(const char* speak_text, int priority) RARCH_LOG("Platform not supported for accessibility.\n"); /* The following method is a fallback for other platforms to use the AI Service url to do the TTS. However, since the playback is done - via the audio mixer, which only processes the audio while the + via the audio mixer, which only processes the audio while the core is running, this playback method won't work. When the audio - mixer can handle playing streams while the core is paused, then + mixer can handle playing streams while the core is paused, then we can use this. */ - /* + /* #if defined(HAVE_NETWORKING) return accessibility_speak_ai_service(speak_text, voice, priority); #endif @@ -28640,7 +28645,7 @@ static bool is_narrator_running(void) static bool accessibility_startup_message(void) { - /* State that the narrator is on, and also include the first menu + /* State that the narrator is on, and also include the first menu item we're on at startup. */ accessibility_speak_priority( "RetroArch accessibility on. Main Menu Load Core.",