« Trucs » partagés

Comme tous les « trucs » possibles et envisageables ne peuvent pas être gérés par la bibliothèque de base, il est nécessaire d'avoir un mécanisme permettant de les faire gérer par un programme dédié, et de les partager aux autres programmes. Il y a d'ailleurs un programme dédié à exposer quelques « trucs » usuels, et chaque appli peut ensuite définir les siens.

Tout « truc » non-prédéfini dont le chemin ne contient pas de caractères trop spéciaux est considéré comme un « truc » partagé. Son contenu est lu depuis $TARGETSHM/things (s'il n'y a aucun fichier correspondant, on considère que le « truc » est vide et n'existe pas). Le contenu précis en termes de clefs/états/etc. dépend donc à chaque fois du programme partageant le « truc ». Cette section décrit le cas de base, mais il existe aussi des « trucs » partagés spécialisés comme les manettes (voir ci-dessous) ou les lecteurs média (à venir).

L'objet « control » d'un truc partagé fournit d'abord les méthodes « share » et « unshare » et « owned ». La première permet de créer la socket principale à l'adresse $TARGETSHM/things/CHEMIN/status et d'y connecter les bons écouteurs. C'est cette socket qui sera utilisée pour lire les informations (clefs, états, etc.) sur le truc, et pour lui envoyer des requêtes. La méthode « unshare » permet de fermer cette socket et de nettoyer le répertoire complet (ce qui sera fait automatiquement à la fermeture du programme). Les trucs partagés sont ajoutées comme des tâches pour la boucle principale. La méthode owned renvoie vrai si le programme en cours contrôle la socket, faux si c'est un autre programme qui le fait, et None si cette socket n'existe pas ou est injoignable. Par défaut, la méthode « share » ne fonctionne que si owned renvoie None, et la méthode « unshare » seulement si elle renvoie vrai. Un paramètre booléen optionnel permet de forcer leur utilisation dans d'autres cas.

$TARGETSHM/things/CHEMIN étant un répertoire, il est possible de l'utiliser pour stocker d'autres fichiers. Chaque programme exposant des trucs partagés peut choisir quel fichier y ranger : la seule structure prédéfinie est que le fichier « content » sera, s'il existe, utilisé par les méthodes « read » et « stream » pour tenter d'accéder au contenu du truc. Si le truc possède l'état « writable », la méthode « write » enverra également le contenu désiré vers ce fichier. L'objet control possède une méthode « file » permettant de récupérer le chemin absolu vers le répertoire demandé. C'est également cet objet control qui permet de modifier le contenu actuel du truc, grâce aux méthodes et attributs suivants :

Par défaut, chacun de ces changements est propagé immédiatement, et déclenche donc un appel aux différentes fonctions d'écoute. Pour gérer plusieurs modifications simultanées, il est possible d'utiliser un bloc with avec l'objet control, auquel cas tous les changements sont mis en attente et envoyés d'un coup une fois que le bloc se termine, ce qui ne fait donc qu'un seul appel aux fonctions d'écoute.

Manettes de jeu

J'ai beaucoup hésité à faire gérer les manettes de jeu directement par la bibliothèque de base, pour éviter d'avoir à faire tourner un programme qui leur est dédié. J'ai néanmoins fini par décider d'en faire uniquement des trucs partagés, pour notamment les raisons suivantes :

Donc, ceci fait que les manettes de jeu sont des trucs partagés (même si un peu particuliers). On les identifie par les chemins « joypadX », où X est généralement un numéro (du moins, pour les manettes physiques). Le stuff « joypad » permet donc de toutes les récupérer d'un coup. Une manette présente toujours au moins deux clefs : « buttons », tuple contenant des booléens indiquant l'état de chaque bouton, et « sticks », tuple contenant des nombres flottants indiquant l'état de chaque joystick. Il est aussi possible d'accéder à l'information précise de chaque bouton/joystick indépendamment avec les clefs « buttonX » (ou « bX ») et « stickX » (ou « sX »), où X est le numéro correspondant, mais seule les clefs sur les tuples sont listées, et elles permettent de compter le nombre de boutons et de sticks disponibles. D'autres informations peuvent être fournies, selon le programme qui partage (et la bibliothèque utilisée). Comme pour le clavier et le pointeur, une manette reçoit l'état « active » dès lors que l'un au moins de ses boutons est enfoncé, ou que l'un au moins de ses sticks n'est pas en position 0.

Puisqu'une manette n'a a priori ni contenu ni enfant, et que le répertoire ne contiendrait a priori rien de plus que la socket principale, j'ai décidé de ne pas faire de répertoire pour les manettes : leur socket est donc directement le fichier $TARGETSHM/things/joypadX. À voir à l'usage s'il y a des avantages et/ou des inconvénients. L'objet control fournit en tout cas les méthodes « moveby » et « moveto » pour déplacer les sticks, et « press », « release » et « toggle » pour les boutons, qui ne fonctionnent cependant (comme le reste des modifications de trucs partagés) que pour le programme ayant partagé le truc en question. Cet objet control est par ailleurs lui-même écoutable, pour suivre directement l'utilisation de la manette. Ses fonctions d'écoute reçoivent deux paramètres : le premier est le numéro du bouton ou du joystick, et le second est un booléen indiquant le nouvel état pour un bouton, et un nombre flottant indiquant la nouvelle position pour un joystick.

Il pourrait d'ailleurs potentiellement être intéressant d'ajouter les requêtes correspondantes, pour permettre à tout programme de générer de « faux » événements, comme c'est faisable pour le clavier et la souris. La limite étant ici que ça ne pourrait, en l'état, être propagé que pour les applis utilisant cette bibliothèque (tandis que les « faux » événement X fonctionnent partout), sauf à trouver une manière de générer de faux événements manette. C'est de toute façon au programme qui partage une manette de définir à quelles requêtes elles doivent répondre.