2023-05-12 20:26:09 +00:00
#!/bin/bash
change_preset_dialog( ) {
# This function will build a list of all systems compatible with a given preset, their current enable/disabled state and allow the user to change one or more
# USAGE: change_preset_dialog "$preset"
2024-11-13 15:10:07 +00:00
2024-11-13 15:08:09 +00:00
preset = " $1 "
pretty_preset_name = ${ preset //_/ } # Preset name prettification
pretty_preset_name = $( echo $pretty_preset_name | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1))substr($i,2)}}1' ) # Preset name prettification
current_preset_settings = ( )
local section_results = $( sed -n '/\[' " $preset " '\]/, /\[/{ /\[' " $preset " '\]/! { /\[/! p } }' $rd_conf | sed '/^$/d' )
2023-05-12 20:26:09 +00:00
2024-11-13 15:08:09 +00:00
while IFS = read -r config_line
do
system_name = $( get_setting_name " $config_line " "retrodeck" )
system_value = $( get_setting_value " $rd_conf " " $system_name " "retrodeck" " $preset " )
current_preset_settings = ( " ${ current_preset_settings [@] } " " $system_value " " $( make_name_pretty $system_name ) " " $system_name " )
done < <( printf '%s\n' " $section_results " )
2024-05-30 15:30:46 +00:00
2024-06-28 20:07:35 +00:00
choice = $( rd_zenity \
2024-05-30 15:30:46 +00:00
--list --width= 1200 --height= 720 \
--checklist \
--separator= "," \
--hide-column= 3 --print-column= 3 \
--text= " Enable $pretty_preset_name : " \
--column "Enabled" \
--column "Emulator" \
--column "internal_system_name" \
" ${ current_preset_settings [@] } " )
local rc = $?
if [ [ ! -z $choice || " $rc " = = 0 ] ] ; then
(
2024-11-14 13:39:51 +00:00
make_preset_changes " $1 " " $choice "
2024-05-30 15:30:46 +00:00
) |
2024-06-28 20:07:35 +00:00
rd_zenity --icon-name= net.retrodeck.retrodeck --progress --no-cancel --pulsate --auto-close \
2024-05-30 15:30:46 +00:00
--window-icon= "/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" \
--title "RetroDECK Configurator Utility - Presets Configuration" \
--text= "Setting up your presets, please wait..."
else
2024-06-29 19:38:16 +00:00
log i "No preset choices made"
2024-05-30 15:30:46 +00:00
fi
}
2025-02-06 04:26:52 +00:00
2024-05-30 15:30:46 +00:00
build_preset_list_options( ) {
2025-02-06 04:26:52 +00:00
# FUNCTION: build_preset_list_options
# DESCRIPTION: This function builds a list of all the systems available for a given preset.
# It generates the list into a Godot temp file and updates the variable $current_preset_settings.
# The function also builds several arrays (all_systems, changed_systems, etc.) that are used in the make_preset_changes() function.
# This function needs to be called in the same memory space as make_preset_changes() at least once.
2024-11-13 15:10:07 +00:00
# USAGE: build_preset_list_options "$preset"
2025-02-06 04:26:52 +00:00
# INPUT:
# - $1: The name of the preset.
# OUTPUT:
# - $godot_current_preset_settings: A Godot temp file containing the system values, pretty system names, and system names.
# - $current_preset_settings: An array containing the system values, pretty system names, and system names.
# - $current_enabled_systems: An array containing the names of systems that are enabled in the preset.
# - $current_disabled_systems: An array containing the names of systems that are disabled in the preset.
# - $changed_systems: An array that will be used to track systems that have changed.
# - $changed_presets: An array that will be used to track presets that have changed.
# - $all_systems: An array containing the names of all systems in the preset.
2024-05-30 15:30:46 +00:00
if [ [ -f " $godot_current_preset_settings " ] ] ; then
rm -f " $godot_current_preset_settings " # Godot data transfer temp files
fi
touch " $godot_current_preset_settings "
2024-05-31 13:34:53 +00:00
preset = " $1 "
2023-05-12 20:26:09 +00:00
pretty_preset_name = ${ preset //_/ } # Preset name prettification
pretty_preset_name = $( echo $pretty_preset_name | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1))substr($i,2)}}1' ) # Preset name prettification
2024-05-31 13:34:53 +00:00
current_preset_settings = ( )
current_enabled_systems = ( )
current_disabled_systems = ( )
changed_systems = ( )
changed_presets = ( )
2024-10-28 01:02:17 +00:00
all_systems = ( )
2023-05-12 20:26:09 +00:00
local section_results = $( sed -n '/\[' " $preset " '\]/, /\[/{ /\[' " $preset " '\]/! { /\[/! p } }' $rd_conf | sed '/^$/d' )
while IFS = read -r config_line
do
system_name = $( get_setting_name " $config_line " "retrodeck" )
all_systems = ( " ${ all_systems [@] } " " $system_name " )
system_value = $( get_setting_value " $rd_conf " " $system_name " "retrodeck" " $preset " )
if [ [ " $system_value " = = "true" ] ] ; then
current_enabled_systems = ( " ${ current_enabled_systems [@] } " " $system_name " )
elif [ [ " $system_value " = = "false" ] ] ; then
current_disabled_systems = ( " ${ current_disabled_systems [@] } " " $system_name " )
fi
2023-05-15 20:33:54 +00:00
current_preset_settings = ( " ${ current_preset_settings [@] } " " $system_value " " $( make_name_pretty $system_name ) " " $system_name " )
2024-05-30 15:30:46 +00:00
echo " $system_value " ^" $( make_name_pretty $system_name ) " ^" $system_name " >> " $godot_current_preset_settings "
2023-05-12 20:26:09 +00:00
done < <( printf '%s\n' " $section_results " )
2024-05-30 15:30:46 +00:00
}
2023-05-12 20:26:09 +00:00
2024-05-30 15:30:46 +00:00
make_preset_changes( ) {
2025-02-06 04:26:52 +00:00
# This function takes a preset name ($1) and a CSV list ($2) of system names.
# If a third parameter is provided (force_state), it forces the specified state (true/false)
# for only the systems in the CSV list. Otherwise, it toggles the current state.
#
# USAGE: make_preset_changes $preset $choice [force_state]
#
# Examples:
# Force "borders" to be true for gba:
# make_preset_changes "borders" "gba" true
# Force "borders" to be true for all supported systems:
# make_preset_changes "borders" "all" true
# Toggle gba in preset "borders", this will disable the enabled and vice versa:
# make_preset_changes "borders" "gba" true
# Toggle all in preset "borders":
# make_preset_changes "borders" "all"
log d "Fetching incompatible presets from JSON file"
2024-08-15 14:42:40 +00:00
incompatible_presets = $( jq -r '
2025-02-06 04:26:52 +00:00
.incompatible_presets | to_entries[ ] |
2024-08-15 14:42:40 +00:00
[
2025-02-06 04:26:52 +00:00
"\(.key):\(.value)" ,
2024-08-15 14:42:40 +00:00
"\(.value):\(.key)"
] | join( "\n" )
2025-02-06 04:26:52 +00:00
' " $features " )
2024-08-15 14:42:40 +00:00
2024-11-14 13:39:51 +00:00
preset = " $1 "
choice = " $2 "
2025-02-06 04:26:52 +00:00
force_state = " ${ 3 :- } "
2024-11-13 15:08:09 +00:00
2025-02-06 04:26:52 +00:00
log d " Building preset list options for preset: $preset "
2024-11-13 15:08:09 +00:00
build_preset_list_options " $preset "
2024-05-30 15:30:46 +00:00
IFS = "," read -ra choices <<< " $choice "
2025-02-06 04:26:52 +00:00
if [ [ " ${ choices [*] } " = = *" all " * ] ] ; then
log d " All systems selected for preset: $preset "
choices = ( " ${ all_systems [@] } " )
fi
# Use an associative array to store the new state for each emulator.
declare -A emulator_state
# Iterate only over the specified systems.
for emulator in " ${ choices [@] } " ; do
if [ [ -n " $force_state " ] ] ; then
new_state = " $force_state "
log d " Forcing $preset to state: $new_state for $emulator "
else
current_state = $( get_setting_value " $rd_conf " " $emulator " "retrodeck" " $preset " )
if [ [ " $current_state " = = "true" ] ] ; then
new_state = "false"
2025-02-06 05:21:43 +00:00
if [ [ $emulator = = "all" ] ] ; then
log i " Toggling off $preset for all systems "
else
log i " Toggling off $preset for system: $emulator "
fi
2025-02-06 04:26:52 +00:00
else
2025-02-06 05:21:43 +00:00
if [ [ $emulator = = "all" ] ] ; then
log i " Toggling on $preset for all systems "
else
new_state = "true"
log i " Toggling on $preset for system: $emulator "
fi
2023-05-12 20:26:09 +00:00
fi
2025-02-06 04:26:52 +00:00
fi
emulator_state[ " $emulator " ] = " $new_state "
changed_systems = ( " ${ changed_systems [@] } " " $emulator " )
[ [ ! " ${ changed_presets [*] } " = ~ " ${ preset } " ] ] && changed_presets = ( " ${ changed_presets [@] } " " $preset " )
set_setting_value " $rd_conf " " $emulator " " $new_state " "retrodeck" " $preset "
# If enabling the emulator, disable any conflicting presets.
if [ [ " $new_state " = = "true" ] ] ; then
while IFS = : read -r preset_being_checked known_incompatible_preset || [ [ -n " $preset_being_checked " ] ] ; do
if [ [ ! $preset_being_checked = ~ ^# ] ] && [ [ -n " $preset_being_checked " ] ] ; then
if [ [ " $preset " = = " $preset_being_checked " ] ] && [ [ $( get_setting_value " $rd_conf " " $emulator " "retrodeck" " $known_incompatible_preset " ) = = "true" ] ] ; then
log d " Disabling conflicting preset: $known_incompatible_preset for emulator: $emulator "
changed_presets = ( " ${ changed_presets [@] } " " $known_incompatible_preset " )
set_setting_value " $rd_conf " " $emulator " "false" "retrodeck" " $known_incompatible_preset "
fi
2023-05-12 20:26:09 +00:00
fi
2025-02-06 04:26:52 +00:00
done < <( echo " $incompatible_presets " )
fi
done
# Rebuild config for all changed systems.
for emulator in " ${ changed_systems [@] } " ; do
log d " Building preset config for changed emulator: $emulator "
if [ [ " ${ emulator_state [ $emulator ] } " = = "true" ] ] ; then
# When enabling, force a full config update (detailed settings applied).
build_preset_config " $emulator " " ${ changed_presets [*] } " true
else
build_preset_config " $emulator " " ${ changed_presets [*] } "
fi
done
2023-05-12 20:26:09 +00:00
}
2023-05-16 14:21:23 +00:00
build_preset_config( ) {
2023-05-12 20:26:09 +00:00
# This function will apply one or more presets for a given system, as listed in retrodeck.cfg
# USAGE: build_preset_config "system name" "preset class 1" "preset class 2" "preset class 3"
local system_being_changed = " $1 "
shift
local presets_being_changed = " $* "
2023-05-15 15:56:01 +00:00
for current_preset in $presets_being_changed
2023-05-12 20:26:09 +00:00
do
local preset_section = $( sed -n '/\[' " $current_preset " '\]/, /\[/{ /\[' " $current_preset " '\]/! { /\[/! p } }' $rd_conf | sed '/^$/d' )
while IFS = read -r system_line
do
local read_system_name = $( get_setting_name " $system_line " )
if [ [ " $read_system_name " = = " $system_being_changed " ] ] ; then
local read_system_enabled = $( get_setting_value " $rd_conf " " $read_system_name " "retrodeck" " $current_preset " )
2024-06-29 19:17:08 +00:00
while IFS = '^' read -r action read_preset read_setting_name new_setting_value section target_file defaults_file || [ [ -n " $action " ] ] ;
2023-05-12 20:26:09 +00:00
do
2024-06-29 19:31:05 +00:00
if [ [ ! $action = = "#" * ] ] && [ [ ! -z " $action " ] ] ; then
case " $action " in
2023-05-12 20:26:09 +00:00
2024-06-29 19:31:05 +00:00
"config_file_format" )
if [ [ " $read_preset " = = "retroarch-all" ] ] ; then
local retroarch_all = "true"
local read_config_format = "retroarch"
else
local read_config_format = " $read_preset "
2024-01-29 15:46:27 +00:00
fi
2024-06-29 19:31:05 +00:00
; ;
"change" )
if [ [ " $read_preset " = = " $current_preset " ] ] ; then
if [ [ " $target_file " = \$ * ] ] ; then # Read current target file and resolve if it is a variable
eval target_file = $target_file
2023-05-12 20:26:09 +00:00
fi
2024-06-29 19:31:05 +00:00
local read_target_file = " $target_file "
if [ [ " $defaults_file " = \$ * ] ] ; then #Read current defaults file and resolve if it is a variable
eval defaults_file = $defaults_file
fi
local read_defaults_file = " $defaults_file "
if [ [ " $read_system_enabled " = = "true" ] ] ; then
if [ [ " $new_setting_value " = \$ * ] ] ; then
eval new_setting_value = $new_setting_value
fi
if [ [ " $read_config_format " = = "retroarch" && ! " $retroarch_all " = = "true" ] ] ; then # If this is a RetroArch core, generate the override file
if [ [ ! -f " $read_target_file " ] ] ; then
create_dir " $( realpath " $( dirname " $read_target_file " ) " ) "
echo " $read_setting_name = \" " $new_setting_value "\"" > " $read_target_file "
2023-05-16 19:09:27 +00:00
else
2024-06-29 19:31:05 +00:00
if [ [ -z $( grep -o -P " ^ $read_setting_name \b " " $read_target_file " ) ] ] ; then
add_setting " $read_target_file " " $read_setting_name " " $new_setting_value " " $read_config_format " " $section "
else
set_setting_value " $read_target_file " " $read_setting_name " " $new_setting_value " " $read_config_format " " $section "
fi
fi
else
set_setting_value " $read_target_file " " $read_setting_name " " $new_setting_value " " $read_config_format " " $section "
2023-05-12 20:26:09 +00:00
fi
else
2024-06-29 19:31:05 +00:00
if [ [ " $read_config_format " = = "retroarch" && ! " $retroarch_all " = = "true" ] ] ; then
if [ [ -f " $read_target_file " ] ] ; then
delete_setting " $read_target_file " " $read_setting_name " " $read_config_format " " $section "
if [ [ -z $( cat " $read_target_file " ) ] ] ; then # If the override file is empty
rm -f " $read_target_file "
fi
if [ [ -z $( ls -1 " $( dirname " $read_target_file " ) " ) ] ] ; then # If the override folder is empty
rmdir " $( realpath " $( dirname " $read_target_file " ) " ) "
fi
2023-05-12 20:26:09 +00:00
fi
2024-06-29 19:31:05 +00:00
else
local default_setting_value = $( get_setting_value " $read_defaults_file " " $read_setting_name " " $read_config_format " " $section " )
set_setting_value " $read_target_file " " $read_setting_name " " $default_setting_value " " $read_config_format " " $section "
2023-05-12 20:26:09 +00:00
fi
fi
fi
2024-06-29 19:31:05 +00:00
; ;
2023-05-12 20:26:09 +00:00
2024-06-29 19:31:05 +00:00
"enable" )
if [ [ " $read_preset " = = " $current_preset " ] ] ; then
if [ [ " $read_system_enabled " = = "true" ] ] ; then
enable_file " $read_setting_name "
else
disable_file " $read_setting_name "
fi
2023-05-12 20:26:09 +00:00
fi
2024-06-29 19:31:05 +00:00
; ;
2023-05-12 20:26:09 +00:00
2024-06-29 19:31:05 +00:00
* )
2024-06-29 19:38:16 +00:00
log d " Other data: $action $read_preset $read_setting_name $new_setting_value $section " # DEBUG
2024-06-29 19:31:05 +00:00
; ;
2023-05-12 20:26:09 +00:00
2024-06-29 19:31:05 +00:00
esac
fi
2023-05-12 20:26:09 +00:00
done < <( cat " $presets_dir / $read_system_name " _presets.cfg)
fi
done < <( printf '%s\n' " $preset_section " )
done
}
2023-05-16 14:21:23 +00:00
build_retrodeck_current_presets( ) {
# This function will read the presets sections of the retrodeck.cfg file and build the default state
# This can also be used to build the "current" state post-update after adding new systems
# USAGE: build_retrodeck_current_presets
2024-06-29 19:17:08 +00:00
while IFS = read -r current_setting_line || [ [ -n " $current_setting_line " ] ] ; # Read the existing retrodeck.cfg
2023-05-16 14:21:23 +00:00
do
if [ [ ( ! -z " $current_setting_line " ) && ( ! " $current_setting_line " = = "#" *) && ( ! " $current_setting_line " = = "[]" ) ] ] ; then # If the line has a valid entry in it
if [ [ ! -z $( grep -o -P " ^\[.+?\] $" <<< " $current_setting_line " ) ] ] ; then # If the line is a section header
local current_section = $( sed 's^[][]^^g' <<< $current_setting_line ) # Remove brackets from section name
else
if [ [ ! ( " $current_section " = = "" || " $current_section " = = "paths" || " $current_section " = = "options" || " $current_section " = = "cheevos" || " $current_section " = = "cheevos_hardcore" ) ] ] ; then
local system_name = $( get_setting_name " $current_setting_line " "retrodeck" ) # Read the variable name from the current line
local system_enabled = $( get_setting_value " $rd_conf " " $system_name " "retrodeck" " $current_section " ) # Read the variables value from active retrodeck.cfg
if [ [ " $system_enabled " = = "true" ] ] ; then
build_preset_config " $system_name " " $current_section "
fi
fi
fi
fi
done < $rd_conf
}
2025-02-06 04:39:36 +00:00
fetch_all_presets( ) {
# This function fetches all possible presets from the presets directory
2025-02-06 05:00:12 +00:00
# USAGE: fetch_all_presets [--pretty] [system_name]
2025-02-06 04:39:36 +00:00
local presets_dir = " $config /retrodeck/presets "
local presets = ( )
local pretty_presets = ( )
local pretty_output = false
2025-02-06 05:00:12 +00:00
local system_name = ""
2025-02-06 04:39:36 +00:00
if [ [ " $1 " = = "--pretty" ] ] ; then
pretty_output = true
2025-02-06 05:00:12 +00:00
system_name = " $2 "
else
system_name = " $1 "
2025-02-06 04:39:36 +00:00
fi
2025-02-06 05:00:12 +00:00
if [ [ -n " $system_name " ] ] ; then
preset_file = " $presets_dir / ${ system_name } _presets.cfg "
if [ [ -f " $preset_file " ] ] ; then
while IFS = read -r line; do
if [ [ $line = ~ ^( change| enable ) \^ ( [ a-zA-Z0-9_] +) \^ ] ] ; then
preset = " ${ BASH_REMATCH [2] } "
if [ [ ! " ${ presets [*] } " = ~ " ${ preset } " ] ] ; then
presets += ( " $preset " )
if $pretty_output ; then
pretty_preset_name = ${ preset //_/ } # Preset name prettification
pretty_preset_name = $( echo $pretty_preset_name | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1))substr($i,2)}}1' ) # Preset name prettification
pretty_presets += ( " $pretty_preset_name " )
fi
2025-02-06 04:39:36 +00:00
fi
fi
2025-02-06 05:00:12 +00:00
done < " $preset_file "
fi
else
for preset_file in " $presets_dir " /*_presets.cfg; do
while IFS = read -r line; do
if [ [ $line = ~ ^change\^ ( [ a-zA-Z0-9_] +) \^ ] ] ; then
preset = " ${ BASH_REMATCH [1] } "
if [ [ ! " ${ presets [*] } " = ~ " ${ preset } " ] ] ; then
presets += ( " $preset " )
if $pretty_output ; then
pretty_preset_name = ${ preset //_/ } # Preset name prettification
pretty_preset_name = $( echo $pretty_preset_name | awk '{for(i=1;i<=NF;i++){$i=toupper(substr($i,1,1))substr($i,2)}}1' ) # Preset name prettification
pretty_presets += ( " $pretty_preset_name " )
fi
fi
fi
done < " $preset_file "
done
fi
2025-02-06 04:39:36 +00:00
if $pretty_output ; then
printf "%s\n" " ${ pretty_presets [@] } "
else
echo " ${ presets [@] } "
fi
}