L'interface de Recalbox peut lancer vos scripts (ou publier des messages MQTT) à chacun de ses événements : démarrage, sélection d'un système, lancement d'un jeu, scrape… De quoi piloter un écran secondaire, un marquee de borne, des LED, ou n'importe quelle action externe.
C'est principalement sur Raspberry Pi et autres machines à GPIO que cette fonctionnalité révèle tout son potentiel — mais elle fonctionne partout.
À chaque événement, l'interface écrit aussi un fichier d'état complet que vos scripts peuvent exploiter.
Pour lancer des scripts à la demande depuis un menu, voyez plutôt les Scripts utilisateur.
La liste des événements, le moment où ils sont déclenchés, et le paramètre supplémentaire éventuellement transmis aux scripts :
| Événement | Quand ? | Paramètre |
|---|---|---|
start |
Démarrage ou redémarrage de l'interface | Nombre de démarrages |
stop |
Arrêt de l'interface | Nombre de démarrages |
shutdown |
Arrêt complet du système | fast ou normal |
reboot |
Redémarrage du système | fast ou normal |
quit |
Arrêt de l'interface suite à une requête externe (bouton on/off d'un GPi Case par exemple) | quitrequested ou fatalerror |
relaunch |
Redémarrage de l'interface (gamelist.xml modifiée de l'extérieur, mise à jour des listes de jeux…) | |
systembrowsing |
Un nouveau système vient d'être sélectionné dans la liste des systèmes | Nom court du système |
gamelistbrowsing |
Un nouveau jeu (ou dossier) vient d'être sélectionné dans une liste de jeux | Chemin de la rom |
rungame |
Un jeu va être lancé | Chemin de la rom |
rundemo |
Un jeu va être lancé en mode démo | Chemin de la rom |
endgame |
Un jeu vient de se terminer | Chemin de la rom |
enddemo |
La démo d'un jeu vient de se terminer | Chemin de la rom |
sleep |
Démarrage de l'économiseur d'écran | Durée d'inactivité (ms) |
wakeup |
Sortie de l'économiseur d'écran | Durée d'inactivité (ms) |
scrapstart |
Une session de scrape multi-jeux démarre | |
scrapstop |
Une session de scrape multi-jeux se termine | Nombre de jeux scrapés |
scrapgame |
Un jeu vient d'être scrapé | Chemin de la rom |
startgameclip |
Un clip vidéo va être lancé | Chemin de la rom |
stopgameclip |
Un clip vidéo vient de se terminer | |
runkodi |
Kodi va être lancé | |
configurationchanged |
Quelque chose a changé dans la configuration | Fichier de configuration modifié |
Les scripts sont à placer directement dans /recalbox/share/userscripts (ou \\RECALBOX\share\userscripts par le réseau) — les sous-répertoires ne sont pas parcourus, et le sous-dossier manual/ est réservé aux Scripts utilisateur.
L'interface choisit elle-même le lanceur en fonction de l'extension :
.sh : lancé par sh ;.ash : lancé par ash (le shell optimisé de busybox) ;.py : lancé par python (python3 sur Recalbox) ;.py3 : lancé explicitement par python3.Les fichiers sans extension sont considérés comme des exécutables et lancés directement.
Chaque script est lancé avec les arguments suivants :
script -action <action> -statefile <statefile> [-param <paramètre>]
<action> : le nom de l'événement, en minuscules (première colonne du tableau ci-dessus) ;<statefile> : le chemin du fichier d'état (/tmp/es_state.inf) ;<paramètre> : le paramètre de l'événement. S'il n'y en a pas, -param est absent.Par défaut, un script est lancé pour chaque événement. Pour le limiter à certains événements, indiquez-les dans le nom du fichier, entre crochets et séparés par des virgules (la casse est indifférente) :
marquee[start,stop].sh — lancé uniquement au démarrage et à l'arrêt de l'interface ;gamesinfo[gamelistbrowsing,rungame,rundemo,scrapgame].sh — lancé uniquement pour les événements liés aux jeux (pour afficher les informations du jeu sur un écran secondaire, par exemple).Par défaut, les scripts sont lancés en asynchrone : l'interface continue son exécution pendant que le script tourne en parallèle.
Ajoutez (sync) dans le nom du fichier pour un lancement synchrone : l'interface attend la fin du script avant de continuer. C'est indispensable pour les scripts déclenchés à l'arrêt ou au redémarrage du système, qui doivent se terminer avant que la machine ne s'éteigne :
backup[reboot,shutdown](sync).sh — exécuté à l'arrêt ou au redémarrage, en bloquant la procédure jusqu'à la fin du script.Ajoutez (permanent) dans le nom du fichier pour que le script soit lancé une seule fois au démarrage de l'interface et tourne en continu — typiquement pour écouter les messages MQTT. Si l'interface redémarre, les scripts permanents déjà actifs ne sont pas relancés.
Recalbox embarque un serveur MQTT (Mosquitto) qui permet de faire du publish/subscribe. À chaque événement, l'interface publie :
Recalbox/EmulationStation/Event ;Recalbox/EmulationStation/EventJson.Le broker écoute sur le port 1883 (et en MQTT sur websockets sur le port 18833), y compris depuis votre réseau local — pratique pour piloter un écran ou un automatisme externe.
Mosquitto fournit deux petits exécutables, mosquitto_pub et mosquitto_sub, pour publier ou attendre un message. Dans un script permanent, vous pouvez ainsi attendre les événements en boucle :
event=$(mosquitto_sub -h 127.0.0.1 -p 1883 -q 0 -t Recalbox/EmulationStation/Event -C 1)
Cette commande bloque jusqu'à la publication d'un événement, puis le renvoie dans la variable event.
On comprend vite l'intérêt des scripts permanents : plutôt que de lancer un processus à chaque événement, un seul script permanent intercepte tout, pour un coût processeur quasi nul.
À chaque événement, l'interface écrit /tmp/es_state.inf (en RAM), un fichier de type ini (clé=valeur), avant de lancer les scripts et de publier le message MQTT.
Les clés toujours présentes :
| Clé | Valeur |
|---|---|
Version |
version du format (2.0) |
Action |
le nom de l'événement qui a généré l'écriture du fichier |
ActionData |
le paramètre de l'événement (peut être vide) |
System / SystemId |
nom complet / nom court du système concerné (peuvent être vides) |
Game / GamePath |
nom / chemin complet du jeu concerné (peuvent être vides) |
ImagePath |
chemin de l'image du jeu (peut être vide) |
State |
playing (un jeu est en cours), demo (démo en cours) ou selected (tous les autres cas) |
Les clés supplémentaires quand un jeu est concerné (gamelistbrowsing, rungame, rundemo, endgame, enddemo, scrapgame) :
| Clé | Valeur |
|---|---|
IsFolder |
1 si un dossier est sélectionné, 0 pour un jeu |
Emulator / Core |
émulateur et core utilisés pour lancer ce jeu |
BoxPath / VideoPath |
chemins du boîtier et de la vidéo du jeu (*) |
Developer / Publisher |
développeur / éditeur (*) |
Players |
nombre de joueurs (*) |
Region / Genre / GenreId |
région, genre et identifiant de genre (*) |
Favorite / Hidden / Adult |
1 ou 0 selon les métadonnées (*) |
(*) Ces informations proviennent des métadonnées du jeu : elles peuvent être vides si le jeu n'a pas été scrapé.
Et quand un système est concerné (systembrowsing) :
| Clé | Valeur |
|---|---|
DefaultEmulator / DefaultCore |
émulateur et core par défaut du système |
Certains événements sont très rapprochés : le fichier peut avoir été réécrit par un second événement au moment où votre script le lit. Vérifiez donc la clé
Action, et ne présumez jamais qu'une clé optionnelle sera présente ou qu'une clé fixe aura une valeur.
Lancer des scripts à chaque événement a un coût : ralentissements, lags en jeu ou dans le son, démarrage des jeux plus lent… Quelques conseils :
(sync) sauf nécessité réelle (phase d'arrêt) ;mosquitto_sub plutôt qu'un lancement par événement.