Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
launch_a_script [2023/10/21 05:52] – rephrase some parts, remove outdated script examples, rename new headers to make more sense atarilaunch_a_script [2025/11/05 22:37] (current) – [Table] beter formatting lbrpdx
Line 38: Line 38:
  
 ==== custom: Last during startup, first after shutdown ==== ==== custom: Last during startup, first after shutdown ====
 +
 +<WRAP center round important>
 +While [[#custom.sh (deprecated)|custom.sh]] still works in **v40**, it's deprecated since **v38** and and may be removed in a later version. (See [[https://batocera.org/changelog|changelog]].)
 +The recommended way to do custom scripting in Batocera now is the [[#services|services]] method detailed below.
 +</WRAP>
 +
 +=== custom.sh (deprecated) ===
  
 Sometimes you just want to fire up one script after successfully booting, for example when you want [[:vpn_client|to start up a VPN]] or other after-boot tasks. In order to do this, create a script text file at ''/userdata/system/custom.sh''. Be aware that the script will be executed independently of the executable (''x'') attribute being set to the script file or not! Sometimes you just want to fire up one script after successfully booting, for example when you want [[:vpn_client|to start up a VPN]] or other after-boot tasks. In order to do this, create a script text file at ''/userdata/system/custom.sh''. Be aware that the script will be executed independently of the executable (''x'') attribute being set to the script file or not!
Line 47: Line 54:
 </WRAP> </WRAP>
  
-=== A simple custom script as an example ===+== A simple custom script as an example ==
  
 <code bash| custom.sh> <code bash| custom.sh>
Line 84: Line 91:
  
 exit $? exit $?
 +</code>
 +
 +=== services ===
 +
 +You should replace ''/userdata/system/custom.sh'' with ''/userdata/system/services/myservice''.
 +
 +Important notes:
 +  * Make sure that the filename is without the ''.sh'' extension.
 +  * To debug your services, use: ''bash -x batocera-services list''
 +
 +Additional benefits of this system over ''custom.sh'':
 +  * You can now have more than one service running.
 +  * You can enable and disable them individually, from the command line (''batocera-services'') or through the UI in EmulationStation (System settings -> Services).
 +
 +**Disabling** services (with ''batocera-services disable'') doesn't **stop** them. That needs to be done manually with ''batocera-services stop''. Disabling them only means that they wil not be automatically started after the next system startup.
 +
 +**Enabling** them (with ''batocera-services enable'') works the same. To actually **start** a service, enable it first, then restart Batocera or use ''batocera-services start''.
 +
 +Enabling or disabling the service in the EmulationStation user interface will also start or stop the service immediately.
 +
 +== Sample service ==
 +
 +<code bash| myservice>
 +#!/bin/bash
 +
 +case "$1" in
 +    start)
 +        echo "I've started."
 +        ;;
 +    stop)
 +        echo "I've stopped."
 +        ;;
 +    status)
 +        echo "This is my status."
 +        ;;
 +esac
 </code> </code>
  
Line 176: Line 219:
 </WRAP> </WRAP>
  
-^ Event name           ^ Arguments ^ Notes ^ +^ Event name                   ^ Arguments                                                                          ^ Notes                                                                                                                                                                     
-| ''game-start''       | ROM name ''rom'', ROM path ''basename'' | When a game starts. Nearly identical to Batocera's ''gameStart'', however this doesn't include as much information and only triggers when it's ES itself that starts it. | +| ''game-start''               | ROM name ''rom'', ROM path ''basename'' (arguments described below)                | When a game starts. Nearly identical to Batocera's ''gameStart'', however this doesn't include as much information and only triggers when it's ES itself that starts it.  
-| ''game-end''         | N/A | When a game ends. Nearly identical to Batocera's ''gameStop'', however this only triggers when it's ES itself that ends it. | +| ''game-end''                 | N/A                                                                                | When a game ends. Nearly identical to Batocera's ''gameStop'', however this only triggers when it's ES itself that ends it.                                               
-| ''game-selected''    | ''getSourceFileData()->getSystem()->getName()'', ''getPath()'', ''getName()'' | New to Batocera **v33**. Whichever game is currently being hovered over. Includes games shown during the screensaver. | +| ''game-selected''            | ''getSourceFileData()->getSystem()->getName()'', ''getPath()'', ''getName()''      | New to Batocera **v33**. Whichever game is currently being hovered over. Includes games shown during the screensaver.                                                     
-| ''system-selected''  | System ''getSelected()->getName()'' | New to Batocera **v33**. Whichever system is currently being hovered over in the system list. | +| ''system-selected''          | System ''getSelected()->getName()''                                                | New to Batocera **v33**. Whichever system is currently being hovered over in the system list.                                                                             
-| ''theme-changed''    | Theme being switched to ''theme_set->getSelected()'', Previous theme ''oldTheme'' | When a different theme is selected. Mostly used for theme/element reloading. | +| ''theme-changed''            | Theme being switched to ''theme_set->getSelected()'', Previous theme ''oldTheme''  | When a different theme is selected. Mostly used for theme/element reloading.                                                                                              
-| ''settings-changed'' | N/A | When a system setting is saved. | +| ''settings-changed''         | N/A                                                                                | When a system setting is saved.                                                                                                                                           
-| ''controls-changed'' | N/A | When a controller mapping is saved from the **CONTROLLER MAPPING** menu. | +| ''controls-changed''         | N/A                                                                                | When a controller mapping is saved from the **CONTROLLER MAPPING** menu.                                                                                                  
-| ''config-changed''   | N/A | Whenever any configuration, be it system settings or controller mappings, is changed. | +| ''config-changed''           | N/A                                                                                | Whenever any configuration, be it system settings or controller mappings, is changed.                                                                                     
-| ''quit''             | N/A | When the system is told to do a regular shutdown. | +| ''quit''                     | N/A                                                                                | When the system is told to do a regular shutdown.                                                                                                                         
-| ''reboot''           | N/A | When the system is told to do a reboot. | +| ''reboot''                   | N/A                                                                                | When the system is told to do a reboot.                                                                                                                                   
-| ''shutdown''         | N/A | When the system is told to do a fast shutdown. | +| ''shutdown''                 | N/A                                                                                | When the system is told to do a fast shutdown.                                                                                                                            
-| ''sleep''            | N/A | When the system is told to sleep. | +| ''sleep''                    | N/A                                                                                | When the system is told to sleep.                                                                                                                                         
-| ''wake''             | N/A | When the system is told to wake from sleep. |+| ''wake''                     | N/A                                                                                | When the system is told to wake from sleep.                                                                                                                               | 
 +| ''achievements''             | with arguments described below                                                     | When a RetroAchievement is unlocked - new to Batocera **v38**                                                                                                             | 
 +| ''screensaver-start''        | N/A                                                                                | When the screensaver starts                                                                                                                                               | 
 +| ''screensaver-stop''         | N/A                                                                                | When the screensaver stops (waken up by user)                                                                                                                             | 
 +| ''suspend''                  | N/A                                                                                | When the system is told to sleep (but triggered by  ''/etc/pm/sleep.d/99es_scripts_runner'' instead of ''sleep''                                                        | 
 +| ''resume''                   | N/A                                                                                | When waken up by keyboard action ( triggered by  ''/etc/pm/sleep.d/99es_scripts_runner''                                                                                | 
 +| ''controller-connected''     | device being added to the Batocera machine                                         | New to Batocera **v43**, triggered when a device ''/dev/input/js*'' is connected                                                                                          | 
 +| ''controller-disconnected''  | device being disconnected                                                          | New to Batocera **v43**, triggered when a device ''/dev/input/js*'' is disconnected                                                                                       |
  
 EmulationStation sends different arguments to these scripts based on the event type. For game-related events: EmulationStation sends different arguments to these scripts based on the event type. For game-related events:
Line 262: Line 312:
 ifconfig eth1 down ifconfig eth1 down
 </file> </file>
 +
 +==== Shut down Batocera after 1 hour of idleness ====
 +
 +In that example, we want the Batocera system to shutdown one hour after the screensaver is launched (so that the system shuts down itself automatically after being idle).
 +
 +To do so, you will need to add two scripts: 
 +  * ''/userdata/system/configs/emulationstation/scripts/screensaver-start/shutdown-trigger.sh'' that is launched when the screensaver starts, and will start a 1 hour timer (see in the script the 3rd line where you can tune that with options possible through the ''date'' command).
 +  * ''/userdata/system/configs/emulationstation/scripts/screensaver-stop/shutdown-cancel.sh'' that cancels the automatic shutdown, triggered when you touch the controller.
 +
 +The script to put in the directory ''/userdata/system/configs/emulationstation/scripts/screensaver-start/'' is:
 +<file bash shutdown-trigger.sh>
 +#!/bin/sh
 +TRG=/tmp/shutdown.screensaver
 +date -d "+1 hour" +"%s" > "$TRG"
 +while true; do
 +    now=$(date +"%s")
 +    [ -f "$TRG" ] || break
 +    trg=$(cat "$TRG")
 +    if [ "$now" -ge "$trg" ]; then
 +        shutdown -h now
 + rm "$TRG"
 +    fi
 +    sleep 5
 +done
 +</file>
 +
 +And the script to put in the directory ''/userdata/system/configs/emulationstation/scripts/screensaver-stop/'' is:
 +<file bash shutdown-cancel.sh>
 +#!/bin/sh
 +TRG=/tmp/shutdown.screensaver
 +rm "$TRG"
 +</file>
 +
 +
  
 ==== Batocera event watcher scripts ==== ==== Batocera event watcher scripts ====
Line 376: Line 460:
         # Toggle the audio mute.         # Toggle the audio mute.
         batocera-audio setSystemVolume mute-toggle         batocera-audio setSystemVolume mute-toggle
 +</file>
 +
 +* Watch for controller inactivity and do X when inactive
 +<file bash controller-inactivity-checker.sh>
 +#!/bin/bash
 +
 +LOCK="/var/run/controller-inactivity-checker.lock"
 +if [ -f "$LOCK" ]; then
 +    exit 1
 +fi
 +
 +trap 'rm -f "$LOCK"; exit 0' SIGTERM EXIT
 +touch "$LOCK"
 +
 +STATE="active"
 +JS_DEVICES=()
 +
 +TIMER="$(/usr/bin/batocera-settings-get system.controllerinactivitytimer)"
 +if [[ -z "$TIMER" || ! "$TIMER" =~ ^[0-9]+$ || "$TIMER" -le 60 ]]; then
 +    TIMER="900" # default in seconds
 +    /usr/bin/batocera-settings-set system.controllerinactivitytimer "$TIMER"
 +fi
 +
 +js_update() {
 +    JS_DEVICES=()
 +    for js_device in /dev/input/js*; do
 +        if [ -e "$js_device" ]; then
 +            JS_DEVICES+=("$js_device")
 +        fi
 +    done
 +}
 +
 +do_inactivity() {
 +    STATE="inactive"
 +    # your code here
 +}
 +
 +do_activity() {
 +    STATE="active"
 +    # your code here
 +}
 +
 +monitor_controllers() {
 +    local JS_REFRESH_INTERVAL=10 # Number of loops before controller refresh (by default 1 loop per second)
 +    LOOP_COUNT=0 # This should always be 0
 +
 +    while true; do
 +        if (( LOOP_COUNT % JS_REFRESH_INTERVAL == 0 )); then
 +            js_update
 +        fi
 +
 +        for i in "${!JS_DEVICES[@]}"; do
 +            js="${JS_DEVICES[$i]}"
 +
 +        if [ -e "$js" ]; then
 +            if timeout 1 jstest --event "$js" | tail -n +25 | grep -q "Event"; then
 +                LOOP_COUNT=0
 +                JS_DEVICES=("$js" "${JS_DEVICES[@]:0:$i}" "${JS_DEVICES[@]:$((i + 1))}")
 +                if [ "$STATE" = "inactive" ]; then
 +                    do_activity
 +                fi
 +                break
 +            fi
 +        fi
 +        done
 +
 +        ((LOOP_COUNT++))
 +        if (( LOOP_COUNT >= TIMER )); then
 +            if [ "$STATE" = "active" ]; then
 +                do_inactivity
 +            fi
 +        fi
 +    done
 +}
 +
 +js_update
 +monitor_controllers
 +
 +exit 0
 +
 </file> </file>
  
  • launch_a_script.1697867537.txt.gz
  • Last modified: 3 years ago
  • by atari