Merge pull request #9513 from guoyunhe/translation-update-script

Add translation update scripts to integrate with localization platforms
This commit is contained in:
Twinaphex 2020-02-15 02:39:31 +01:00 committed by GitHub
commit 1c031466fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 312 additions and 96 deletions

View File

@ -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 },

3
intl/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.json
crowdin.yaml
crowdin.yml

23
intl/README.md Normal file
View File

@ -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`

27
intl/crowdin_sync.sh Executable file
View File

@ -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

55
intl/h2json.py Executable file
View File

@ -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)

74
intl/json2h.py Executable file
View File

@ -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 <language_postfix>")
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)

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
*/
}

View File

@ -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,

View File

@ -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.",