| Both sides previous revision Previous revision Next revision | Previous revision |
| launch_a_script [2023/10/20 17:37] – S99custom to S99userservices crcerror | launch_a_script [2025/11/05 22:37] (current) – [Table] beter formatting lbrpdx |
|---|
| ====== Batocera scripts ====== | ====== Batocera scripts ====== |
| | |
| | <WRAP center round tip> |
| | If you are looking for how scripts behaved in **v37** and below, refer to the [[:launch_a_script_legacy|legacy scripts page]]. |
| | </WRAP> |
| |
| You can opt to have scripts launched at various points in Batocera. This will change the location you save the script to and how it opens. | You can opt to have scripts launched at various points in Batocera. This will change the location you save the script to and how it opens. |
| |
| ===== Scripts during /etc/init.d/ start-stop event ===== | ===== Scripts during boot/shutdown ===== |
| |
| In Batoceras boot process, there are three possibilites to set your own scripts for different purposes. | When booting and shutting down, Batocera checks for scripts three times at different stages in the boot/shutdown process: |
| - [[#S99userservices: Last during startup, first after shutdown|custom.sh]] is the prefered method for most usecases (but is the last script executed) | * [[#boot-custom: First during startup, last after shutdown|/boot/boot-custom.sh]], a special case if you need scripts executed very early in the boot process |
| - [[#S00bootcustom: First during startup, last after shutdown|boot-custom.sh]] is a special case if you need scripts executed very early in the boot process | * [[#postshare: First after mounting userdata mount, last before userdata gets unmounted|/boot/postshare.sh]], to launch scripts right after userdata is mounted |
| - [[#S12populateshare: First after /userdata mount, last before /userdata gets unmounted|postshare.sh]] is a special event if you need scripts right after ''/userdata'' was mounted | * [[#custom: Last during startup, first after shutdown|/userdata/system/custom.sh]], after EmulationStation has loaded, the preferred method for most use-cases |
| |
| ==== Events for init.d-scripts ==== | When these scripts are executed, Batocera sends the first argument to the script as ''start'' when Batocera is booting and ''stop'' when Batocera is shutting down. Putting code into cases or other checks for these argument values will cause that code to only be executed when booting or shutting down, otherwise code will be executed on both boot and shutdown. |
| |
| To distinguish between different events, the first argument parsed in the script will change: | ==== boot-custom: First during startup, last after shutdown ==== |
| |
| * ''start'' Only when Batocera is booting. | In Batocera **v32** and higher, scripts can be launched early in the boot process, before much of Batocera has even begun loading. This is done by storing the script in the boot partition at ''/boot/boot-custom.sh''. Keep in mind that this script will be limited to more basic commands/modules, as most things have not loaded yet. The filename must be ''boot-custom.sh'' otherwise it will not be checked. |
| * ''stop'' Only when Batocera is shutting down. | |
| |
| Putting code outside of cases which check these arguments will always be executed on both boot and shutdown. | <WRAP center round info> |
| | Precisely, this is the first thing executed once //init.d// has begun. This is before the //network/share// population/IR remote daemon have even loaded so capabilities are limited. Check ''/etc/init.d'' to see the exact order of all the modules have been loaded in (''S00bootcustom'' is when the ''/boot/boot-custom.sh'' is executed). |
| | </WRAP> |
| | |
| | This can be used to effectively patch and/or override the modules loaded by Batocera. Here are some examples that are only possible with this method: |
| | * Customize or disable ''S33disablealtfn'' to allow a certain text mode console on a particular TTY session. |
| | * Tinker with hwclock to [[:troubleshooting#changing_batocera_to_use_windows_local_time_instead|save local time instead of universal time to RTC]]. |
| | * Run ''fsck -a'' or ''e2fsck -p'' to harden the file system against data corruption in the case of a power cut/disconnection. |
| | |
| | ==== postshare: First after mounting userdata mount, last before userdata gets unmounted ==== |
| | |
| | In Batocera **v35** and higher, scripts can also be launched after ''/userdata'' is mounted in the boot process, before the splash video plays (and before Emulationstation has begun loading). It has to be placed to ''/boot/postshare.sh'' and is executed directly by the bash interpreter (no executable flag required). |
| | |
| | <WRAP center round important> |
| | This is the only init.d scripts that doesn't execute in background. So if you use a sleep timer for example, the script will halt till the time from sleep command is up! Be aware of endless do-while loops! Get familiar with shell commands and the usage of the ampersand m( **&** |
| | </WRAP> |
| | |
| | ==== 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> |
| |
| ==== S99userservices: Last during startup, first after shutdown ==== | === 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! |
| |
| This script is the very last one that will be invoked by Batocera at boot time after EmulationStation has launched (check ''/etc/init.d/'' to see all the modules that are loaded before then, ''S99userservices'' (''S99custom'' was renamed since Batocera **v38**) is when the user script is launched). The filename must be ''custom.sh'' otherwise it will not be checked. | This script is the very last one that will be invoked by Batocera at boot time after EmulationStation has launched (check ''/etc/init.d/'' to see all the modules that are loaded before then, ''S99userservices'' (previously ''S99custom'' in Batocera **v38** and below) is when the user script is launched). The filename must be ''custom.sh'' otherwise it will not be checked. |
| |
| <WRAP center round important> | <WRAP center round important> |
| </WRAP> | </WRAP> |
| |
| -->A simple custom script as an example# | == A simple custom script as an example == |
| |
| <code bash| custom.sh> | <code bash| custom.sh> |
| exit $? | exit $? |
| </code> | </code> |
| <-- | |
| ==== S00bootcustom: First during startup, last after shutdown ==== | |
| |
| In Batocera **v32** and higher, scripts can also be launched early in the boot process, before much of Batocera has even begun loading. This is done by storing the script in the boot partition at ''/boot/boot-custom.sh''. Keep in mind that this script will be limited to more basic commands/modules, as most things have not loaded yet. The filename must be ''boot-custom.sh'' otherwise it will not be checked. | === services === |
| |
| <WRAP center round info> | You should replace ''/userdata/system/custom.sh'' with ''/userdata/system/services/myservice''. |
| Precisely, this is the first thing executed once //init.d// has begun. This is before the //network/share// population/IR remote daemon have even loaded so capabilities are limited. Check ''/etc/init.d'' to see the exact order of all the modules have been loaded in (''S00bootcustom'' is when the ''/boot/boot-custom.sh'' is executed). | |
| </WRAP> | |
| |
| This can be used to effectively patch and/or override the modules loaded by Batocera. Here are some examples that are only possible with this method: | Important notes: |
| * Customize or disable ''S33disablealtfn'' to allow a certain text mode console on a particular TTY session. | * Make sure that the filename is without the ''.sh'' extension. |
| * Tinker with hwclock to [[:troubleshooting#changing_batocera_to_use_windows_local_time_instead|save local time instead of universal time to RTC]]. | * To debug your services, use: ''bash -x batocera-services list'' |
| * Run ''fsck -a'' or ''e2fsck -p'' to harden the file system against data corruption in the case of a power cut/disconnection. | |
| |
| This script is triggered by the same [[#events|events]] and follows the same rules as it. | 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). |
| |
| ==== S12populateshare: First after /userdata mount, last before /userdata gets unmounted ==== | **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. |
| |
| In Batocera **v35** and higher, scripts can also be launched after ''/userdata'' is mounted in the boot process, just before Batocera plays the internal video and of course before Emulationstation has even begun loading. It has to be placed to ''/boot/postshare.sh'' and is executed directly by bash interpreter without using the executable flag. This script is triggered by the same [[#events|events]] and follows the same rules as all init.d-scripts. | **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''. |
| |
| <WRAP center round important> | Enabling or disabling the service in the EmulationStation user interface will also start or stop the service immediately. |
| This is the only init.d scripts that doesn't execute in background. So if you use a sleep timer for example, the script will halt till the time from sleep command is up! \\ | |
| Be aware of endless do-while loops! Get familiar with shell commands and the usage of the ampersand m( **&** | == Sample service == |
| </WRAP> | |
| | <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> |
| |
| ===== Watch for a game start/stop event ===== | ===== Watch for a game start/stop event ===== |
| ==== Simple game start/stop script as an example ==== | ==== Simple game start/stop script as an example ==== |
| |
| At first create the directory where the scripts need to be set up. [[access_the_batocera_via_ssh|Connect through SSH]] and type ''mkdir /userdata/system/scripts''. After this we can set up our first script by typing ''nano /userdata/system/scripts/first_script.sh''. The filename can be anything readable by bash. | At first create the directory where the scripts need to be set up. [[:access_the_batocera_via_ssh|Connect through SSH]] and type ''mkdir /userdata/system/scripts''. After this we can set up our first script by typing ''nano /userdata/system/scripts/first_script.sh''. The filename can be anything readable by bash. |
| |
| Here's the template script: | Here's the template script: |
| </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: |
| |
| ===== Real use cases ===== | ===== Real use cases ===== |
| | |
| | <WRAP center round tip> |
| | Friendly reminder that older examples have now been moved to the [[:launch_a_script_legacy|legacy scripts page]]. |
| | </WRAP> |
| | |
| |
| ==== Batocera after boot scripts ==== | ==== Batocera after boot scripts ==== |
| 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 ==== |
| echo "ROM: $(basename "$3")" >> $testfile | echo "ROM: $(basename "$3")" >> $testfile |
| [[ "$4" == "libretro" ]] && echo "You are free!" >> $testfile || echo "No hotkey is pure hell eh??" >> $testfile | [[ "$4" == "libretro" ]] && echo "You are free!" >> $testfile || echo "No hotkey is pure hell eh??" >> $testfile |
| </file> | |
| |
| * [[https://wiki.batocera.org/doku.php?id=method_to_not_lose_srm_states_and_other_meta-_data|Method to not lose SRM and other meta-data]] | |
| <file bash custom.sh> | |
| #!/bin/bash | |
| # custom.sh - place to /userdata/system | |
| # by cyperghost 23/11/19 | |
| # | |
| | |
| if [[ $1 == stop ]]; then | |
| batocera-es-swissknife --emukill | |
| fi | |
| |
| </file> | |
| |
| * Splash video during game load (x86/x86_64) (credit to @algernon) | |
| <file bash videolaunchx86.sh> | |
| #!/bin/bash | |
| |
| # Adds system specific loading screen videos to x86 builds of batocera via VLC | |
| # Add your .mp4 videos to /userdata/loadingscreens naming them each with the same as in your roms folder i.e named snes.mp4 to play a video before for each snes game. | |
| # Add this script in /userdata/system/scripts then chmod+x /userdata/system/scripts/videolaunchx86.sh in terminal to give this script permissions to run | |
| |
| do_videostart () | |
| { | |
| video="$1" | |
| vlc play --fullscreen --no-video-title-show --play-and-exit $video | |
| } | |
| |
| # Comment out the above phrase and uncomment this one to enable playing loading videos concurrently with emulator launch instead of before (experimental) | |
| #do_videostart () | |
| #{ | |
| # video="$1" | |
| # vlc_opt="play --fullscreen --no-video-title-show --play-and-exit" | |
| # vlc $vlc_opt $video & | |
| # PID=$! | |
| #} | |
| |
| videopath="/userdata/loadingscreens" | |
| |
| if [[ "$1" == "gameStart" && -n "$2" ]]; then | |
| video="${videopath}/$2.mp4" | |
| [[ -f "$video" ]] || exit 1 | |
| else | |
| exit 1 | |
| fi | |
| |
| do_videostart "$video" | |
| #wait $PID | |
| exit 0 | |
| |
| |
| # Replace or comment out all the other code above except for the first bash line then uncomment the following phrase to enable a single loading splash for all systems. It should be named default.mp4 in the same folder as above. | |
| #default="/userdata/loadingscreens/default.mp4" | |
| #case $1 in | |
| # gameStart) | |
| # vlc play --fullscreen --no-video-title-show --play-and-exit $default | |
| # ;; | |
| # | |
| #esac | |
| # | |
| #exit 0 | |
| |
| </file> | |
| |
| * [[https://forum.batocera.org/d/3391-system-splash-screens-during-roms-are-loading|Splash video during game load (Raspberry Pi)]] | |
| <file bash videolaunchpi.sh> | |
| #!/bin/bash | |
| do_videostart () | |
| { | |
| video="$1" | |
| # Launch the video | |
| omx_fnt="--font=/usr/share/fonts/dejavu/DejaVuSans-BoldOblique.ttf" | |
| omx_opt="--no-keys --layer=10000 --aspect-mode=fill" | |
| omx_srt="--no-ghost-box --lines=1 --align=left $omx_fnt --font-size=20 --subtitles=/usr/share/batocera/splash/splash.srt" | |
| |
| # Disable sound | |
| omx_nosound="-n -1" | |
| # -911 = Volume set to 35% (On omxplayer) | |
| # 1/(10^(911/2000)) = 0.35034828830157 | |
| |
| /usr/bin/omxplayer -o both --vol -2500 $omx_opt $omx_srt $omx_nosound $video & | |
| PID=$! | |
| } | |
| |
| |
| videopath="/userdata/videoloadingscreens" | |
| |
| if [[ "$1" == "gameStart" && -n "$2" ]]; then | |
| video="${videopath}/$2.mp4" | |
| # Filecheck | |
| [[ -f "$video" ]] || exit 1 | |
| else | |
| exit 1 | |
| fi | |
| |
| do_videostart "$video" | |
| #wait $PID | |
| exit 0 | |
| |
| </file> | |
| |
| * [[https://archive.org/details/ogstcase-4batocera|OGST Screen Support]] ([[https://forum.batocera.org/d/1481-ogst-screen-support/43|original post]]) | |
| <file bash OGST_screen.sh> | |
| #!/bin/bash | |
| # Install videos of ZIP file to /userdata/OGST/ | |
| # Install scripts to /userdata/system/custom.sh and /userdata/system/scripts/OGST_screen.sh to use this script. | |
| |
| logo_folder='/userdata/OGST' | |
| default_logo='start.mp4' | |
| logo_file="" | |
| loop=false | |
| default_logo_loop=false | |
| cache_file='/userdata/system/.cache/ffmpeg_PID' | |
| |
| clean_cache () { | |
| if [ -f $cache_file ]; then | |
| rm -f $cache_file | |
| fi | |
| } | |
| |
| case "$1" in | |
| |
| start) | |
| # init TFT screen | |
| [ `/sbin/lsmod | grep -c spi_s3c64xx` -ge 1 ] && rmmod spi_s3c64xx | |
| modprobe spi_s3c64xx force32b=1 | |
| modprobe fbtft_device name=hktft9340 busnum=1 rotate=270 force32b=1 | |
| |
| # wait fb1 loaded | |
| N=0 | |
| while ! test -e /dev/fb1 -o $N -gt 15; do | |
| sleep 1 | |
| let N++ | |
| done | |
| |
| # rename fb1 to fb_ (trick to ovoid conflics with some emulators like reicast...) | |
| mv /dev/fb1 /dev/fb_ | |
| |
| clean_cache | |
| logo_file=$default_logo && loop=default_logo_loop | |
| ;; | |
| |
| stop) | |
| clean_cache | |
| logo_file='stop.mp4' && loop=false | |
| ;; | |
| |
| gameStop) | |
| logo_file=$default_logo && loop=default_logo_loop | |
| ;; | |
| |
| gameStart) | |
| logo_file=$default_logo && loop=default_logo_loop | |
| case "$2" in | |
| 3do) logo_file='3do/video.mp4' && loop=true ;; | |
| amiga) logo_file='amiga/video.mp4' && loop=true ;; | |
| amigacd32) logo_file='amigacd32/video.mp4' && loop=true ;; | |
| amstradcpc) logo_file='amstradcpc/video.mp4' && loop=true ;; | |
| apple2) logo_file='apple2/video.mp4' && loop=true ;; | |
| atari800) logo_file='atari800/video.mp4' && loop=true ;; | |
| atari2600) logo_file='atari2600/video.mp4' && loop=true ;; | |
| atari5200) logo_file='atari5200/video.mp4' && loop=true ;; | |
| atari7800) logo_file='atari7800/video.mp4' && loop=true ;; | |
| atarist) logo_file='atarist/video.mp4' && loop=true ;; | |
| atomiswave) logo_file='atomiswave/video.mp4' && loop=true ;; | |
| c64) logo_file='c64/video.mp4' && loop=true ;; | |
| cavestory) logo_file='cavestory/video.mp4' && loop=true ;; | |
| colecovision) logo_file='colecovision/video.mp4' && loop=true ;; | |
| dreamcast) logo_file='dreamcast/video.mp4' && loop=true ;; | |
| fba) logo_file='fba/video.mp4' && loop=true ;; | |
| fds) logo_file='fds/video.mp4' && loop=true ;; | |
| gameandwatch) logo_file='gameandwatch/video.mp4' && loop=true ;; | |
| gamegear) logo_file='gamegear/video.mp4' && loop=true ;; | |
| gb) logo_file='gb/video.mp4' && loop=true ;; | |
| gba) logo_file='gba/video.mp4' && loop=true ;; | |
| gbc) logo_file='gbc/video.mp4' && loop=true ;; | |
| gx4000) logo_file='gx4000/video.mp4' && loop=true ;; | |
| intellivision) logo_file='intellivision/video.mp4' && loop=true ;; | |
| jaguar) logo_file='jaguar/video.mp4' && loop=true ;; | |
| lynx) logo_file='lynx/video.mp4' && loop=true ;; | |
| mame) logo_file='mame/video.mp4' && loop=true ;; | |
| mastersystem) logo_file='mastersystem/video.mp4' && loop=true ;; | |
| megadrive) logo_file='megadrive/video.mp4' && loop=true ;; | |
| msx) logo_file='msx/video.mp4' && loop=true ;; | |
| n64) logo_file='n64/video.mp4' && loop=true ;; | |
| naomi) logo_file='naomi/video.mp4' && loop=true ;; | |
| neogeo) logo_file='neogeo/video.mp4' && loop=true ;; | |
| neogeocd) logo_file='neogeocd/video.mp4' && loop=true ;; | |
| nes) logo_file='nes/video.mp4' && loop=true ;; | |
| ngp) logo_file='ngp/video.mp4' && loop=true ;; | |
| ngpc) logo_file='ngpc/video.mp4' && loop=true ;; | |
| o2em) logo_file='o2em/video.mp4' && loop=true ;; | |
| pcenginecd) logo_file='pcenginecd/video.mp4' && loop=true ;; | |
| pcengine) logo_file='pcengine/video.mp4' && loop=true ;; | |
| pcfx) logo_file='pcfx/video.mp4' && loop=true ;; | |
| pokemini) logo_file='pokemini/video.mp4' && loop=true ;; | |
| prboom) logo_file='prboom/video.mp4' && loop=true ;; | |
| psp) logo_file='psp/video.mp4' && loop=true ;; | |
| psx) logo_file='psx/video.mp4' && loop=true ;; | |
| satellaview) logo_file='satellaview/video.mp4' && loop=true ;; | |
| saturn) logo_file='saturn/video.mp4' && loop=true ;; | |
| scummvm) logo_file='scummvm/video.mp4' && loop=true ;; | |
| sega32x) logo_file='sega32x/video.mp4' && loop=true ;; | |
| segacd) logo_file='segacd/video.mp4' && loop=true ;; | |
| sg1000) logo_file='sg1000/video.mp4' && loop=true ;; | |
| snes) logo_file='snes/video.mp4' && loop=true ;; | |
| sufami) logo_file='sufami/video.mp4' && loop=true ;; | |
| supergrafx) logo_file='supergrafx/video.mp4' && loop=true ;; | |
| thomson) logo_file='thomson/video.mp4' && loop=true ;; | |
| vectrex) logo_file='vectrex/video.mp4' && loop=true ;; | |
| virtualboy) logo_file='virtualboy/video.mp4' && loop=true ;; | |
| wswan) logo_file='wswan/video.mp4' && loop=true ;; | |
| wswanc) logo_file='atari800/video.mp4' && loop=true ;; | |
| x68000) logo_file='x68000/video.mp4' && loop=true ;; | |
| zx81) logo_file='zx81/video.mp4' && loop=true ;; | |
| zxspectrum) logo_file='zxspectrum/video.mp4' && loop=true ;; | |
| *) | |
| esac | |
| ;; | |
| esac | |
| |
| draw_logo () { | |
| loop=0 | |
| if [ $3 = true ]; then loop=-1; fi | |
| dd if=/dev/zero of=/dev/fb_ 2>/dev/null >/dev/null #clear before draw | |
| ffmpeg -hide_banner -re -stream_loop $loop -i $1/$2 -c:v rawvideo -pix_fmt rgb565le -f fbdev /dev/fb_ 2>/dev/null >/dev/null & | |
| echo $! > $cache_file | |
| } | |
| |
| # draw logo | |
| if [ "$logo_file" != "" ]; then | |
| # kill last played video if running | |
| if [ -s $cache_file ] ; then | |
| kill -9 $(cat $cache_file) | |
| fi | |
| # draw | |
| draw_logo $logo_folder $logo_file $loop | |
| fi | |
| |
| exit 1 | |
| |
| </file> | </file> |
| |
| # 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> |
| |