Dernière mise à jour : Thu Jan 9 15:40:58 CET 2014
Ce logiciel est une expérimentation pas vraiment terminée, mais je le trouve assez prometteur : il permet de piloter un périphérique MIDI à partir d'une manette de jeu USB. Pour le moment, il n'est testé que sous Linux, mais dès que les principes généraux seront en place, il sera (peut-être) porté dans le poisson piquant.
Il ne connait actuellement que les boutons binaires, c'est à dire que les croix directionelles et les sticks analogiques ne sont pas utilisables. Ce léger inconvénient n'est que provisoire. Il ne peut piloter qu'un seul synthé MIDI sur un seul canal. Ce léger inconvénient n'est pas plus provisoire que le précédent.
L'interactivité n'est pas encore au rendez-vous, sauf pour les vieux qui considèrent que _tout_ peut se faire avec vim. Pratiquement tout le machin se règle par des fichiers de configurations textuels, garantis sans la moindre tache gluante de XML. Il existe plusieurs catégories de fichier, qui sont détaillées plus loin.
Qaund le premier prototype sera opérationnel, je rajouterais la possiblité de surcharger les valeurs déclarées dans ces fichiers par des options de la cli et/ou des variables d'environnement.
Quelques règles fluctuantes mais néammoins générales : par défaut, les fichiers sont placés dans $HOME/.tth/joymidi/. L'option -i /un/chemin permet de choisir un autre endroit. Cet emplacement pourra peut-être être surchargé par la variable shell JOYMIDI_RC_DIR (si ça marche un jour). Le caractère # introduit les commentaires, si ils sont au début de la ligne. Les lignes vides sont ignorées. Tout le système est case sensitive. Les valeurs numériques peuvent être introduites en décimal, octal ou hexadécimal : 42 042 0x42. Les lignes ne doivent pas dépasser (en gros) 200 caractères.
Nous avons trois (ou plus) catégories de fichiers : le fichier maitre, qui contrôle les aspects généraux du système (son nom est fixé (par dddd) : context.init), les fichiers de description des manettes, et, pour finir, les "pilotes de synthés".
Une des plus grosses difficultés que j'ai rencontré lors de la création de cet engin a été, justement, l'organisation de ces fichiers de configuration. Nous devons prendre en compte plusieurs catégories de choses : le contexte général tout d'abord, puis les manettes de jeu, les synthétiseurs, et les connections entre ces manettes et ces machines à bruit. Je peux vous garantir que ce n'est pas simple, surtout quand on est seul à réfléchir sur la chose\dots.
Ce fichier contient les réglages généraux du bouzin. Il définit tout un paquet de choses essentielles : comment accéder au baton, par quel moyen causer aux machines cibles,
Voyons un exemple :
# -------------------------------- # primary initialisation file # -------------------------------- joydevice /dev/input/js0 midiout /dev/midi alsaname joymidi # warning: numbering of midi channel start at ONE ! midichannel 10 buttonsnames thrustmaster.init translation drumtracks.init
Dans le cas où midiout et alsaname sont tous deux présents, (en principe) c'est le dernier rencontré qui décide de la sortie à utiliser.
D'autres informations de contrôle vont peut-être arriver un de ces jours dans ce fichier, par exemple le volume général envoyé avec chaque note on, ou bien une transposition de toutes les notes... La limite est l'imagination.
Comme vu précedemment, les boutons sont identifiés par des numéros. Ce n'est pas très facile à manipuler, nous allons donc associer un nom à chacun de ces codes. Ces noms devront être constitués uniquement de lettres, de chiffres et du _, en tenant compte de la casse. Les codes numériques des boutons peuvent être trouvés avec le dumpeur adéquat. Voyons rapidement un petit exemple :
# les boutons du gadget button wtf 1 button omg 2 65 button osef 3 %50 # la croix directionnelle axis up_down 5 axis left_right 4
Le premier champ est le type de bouton : button désigne un bouton binaire (on/off) et axis désigne un bouton analogique. Le second champ est le nom que vous allez assigner à ce bouton ou ce valuateur. Le troisième est le numéro par lequel le bouton est connu du système. Il y a un outil pour découvrir ces numéros.
Les éventuels champs supplémentaires n'ont pas encore de destination précise. Je pense, entre autre, au volume. Dans cet exemple, il peut être absolu et dans l'intervalle [0..127], ou, si précédé d'un %, le pourcentage du volume par défaut (actuellement figé à 127 par dddd). A ce jour (19 mai 2010), ce n'est pas implémenté.
Actuellement, le format de ce(s) fichier(s) est en pleine crise d'incertitude quasi quantique. Comme le reste. Le 7 mai, j'ai rajouté la description des chargements de sysex sur la machine cible. Et à partir de maintenant, l'ordre des instructions dans ce fichier aura une importance. La seconde version est donc de ce genre :
# configuration du machin MIDI quelconque asciiupload sysex-tx81z.ascii # translation pour un machin MIDI quelconque keys wtf 0x55 omg 42 6 51 osef 88 c=12 .
La première section contient des instructions pour éventuellement changer la configuration du synthé au bout du fil, par exemple pour splitter un tx81z (au hasard :) en 8 sons monophoniques. J'envisage plusieurs options possibles : fichiers sysex en ascii ou en binaire, ordres MIDI en program change, setup du volume, du pitch-bend; vous voyez le genre, et en prime, la description de ces ordres :
La seconde section débute par le mot clef keys et se termine par un . seul sur sa ligne. Rassurez-vous, ça va être plus simple qu'un sendmail.cf (loulz). Le premier champ est soit un nom de touche tel que déclaré dans buttons.conf, soit un numéro de touche qu'il faut détecter avec dump_my_joy. Le second champ est le code MIDI de la note, exprimée en décimal, en octal (0nnn) ou en hexadécimal (0xnn), qui sera éventuellement modifié quand la fonctionnalité detune sera implémentée. Quand à l'éventuel troisième champ, il permettra par exemple de surcharger le numéro de canal déclaré dans context.init.
Je vais essayer de fournir, dans la mesure des machines que j'ai sous la main, ou dont j'ai la documentation, des exemples crédibles de fichier de branchement directement utilisables.
Certaines des machines que nous joystickons peuvent être configurées à distance. Il juste suffit de leur envoyer les bons octets : changement de programme, sysex, que sais-je encore ?
Pendant que je confectionne le code, je vais tenter de mettre au point un exemple pour le tx81z : avoir plusieurs sons différents, ce qui va probablement impliquer de pouvoir envoyer les noteon/off sur plusieurs canaux différents ?
# nous allons supposer (dddd) que la tx81z est sur le canal 1, et lui # envoyer un 'program change' pour le 109 (qui pulse bien) 0xc0 109
Ah oui, mais non..., ça ne va pas marcher ;( car quand le soft démarre, on n'a pas encore fait le aconnect 128:0 24:0 qui 'branche' le joystick sur la machine. Big L00z3, et là, sur le coup, je ne vois aucun moyen de régler le problème, à part passer directement par le lien physique ? Ou alors, peut-être il y a ce qu'il faut dans ALSA pour qu'une application détecte qu'un client s'est mis à l'écoute. Piste à creuser.
C'est très rudimentaire : il faut lire le Makefile, essayer de le comprendre, taper des commandes ésotériques dans le xterm, interpréter les messages d'erreur, toussa... Mais dans l'ensemble, sur un Linux classique, ça passe comme un spam au smtp. À condition d'avoir une installation complète d'alsa, avec tout ce qu'il faut pour compiler & linker un programme. Les bubuntistes comprendront.
Dans le Makefile, il y a quelques indications complémentaires sur ce qu'il est possible de modifier à la compilation, eg: le niveau de verbosité des messages de debug. Vous avez aussi un README.txt qui contient des explications approximatives.
L'étape suivante est l'identification des codes que la kernelle vous renvoie à chaque fois que vous appuyez sur la gachette. Pour ça, le petit proggy dump_my_joy peut vous aider. Compilez le, lancez le, et essayez de comprendre les chiffres. Vous allez voir, c'est assez simple. Chaque action sur votre bouton de joie est décodée par la kernelle (merci Ingrid) et renvoyée au logiciel sous la forme d'un assemblage de chiffres, décrits de cette façon :
struct js_event { __u32 time; /* event timestamp in milliseconds */ __s16 value; /* value */ __u8 type; /* event type */ __u8 number; /* axis/button number */ };
Tout cela semble diablement technique (recette !), et assez éloigné du MIDI. Détrompez vous : il y a quelques analogies, qui sont en fait à l'origine de ce merveilleux progiciel.
Après compilation par un trivial make dump_my_joy, vous pouvez le lancer dans un xterm avec l'option -n. Il va commencer par analyser une partie des fichiers de configuration, puis se mettre à lire votre manette et afficher ce qu'il en pense.
Tout d'abord, on voit défiler quelques lignes de technobabage racontant l'initialisation du bouzin, et ensuite, quand vous tripotez la manette, arrive un truc dans ce genre :
time type numbt value 252205792 1 4 1 252205912 1 4 0 252206400 1 6 1 252207104 1 4 1 252207632 1 9 1 252208056 1 8 1 252209904 1 8 0 252209904 1 9 0 252209936 1 4 0 252209936 1 6 0
Le time
, pour le moment, osef.
Le type
indique sur quel genre de contrôle vous venez
d'agir : la valeur 1 est celle qui nous intéresse, elle correspond
à un bouton. Un 2 indiquera une croix directionnelle ou un stick
analogique, non traités dans cette première version.
Le numbt
est le numéro du bouton concerné, et finalement
la value
, elle, nous indique ce qui vient de se passer. :
1 signifie "enfoncé" et 0, "relaché". Ça y est,
vous saisissez l'analogie avec noteon/noteoff du MIDI ?
Tout cela n'est pas très clair ? Essayez donc d'enlever l'option -n, et recommencez l'expérience. Voici un affichage qui vous permettra de debbuger facilement votre fichier joypad.init. Pour découvrir les autres options c'est simplement -h.
N'y songez même pas pour le moment : ya que des bugs. Je ne sais tellement pas comment construire la chose, que le code est en permanente fluctuation. Par contre, les remarques (même désobligeantes) et les suggestions (même trollisantes) sont acceptables; ceux qui savent sauront comment me joindre.
Il y a quand même les classiques fichiers README, BUGS, TODO et CHANGES. Ah, mais... il y a aussi un Makefile, aussi gruik que le reste ! Peut-être un volontaire pour écrire les manpages ?
Première méthode :
lancer joymidi avec les bonnes options, puis utiliser
aseqdumap -l pour repérer le port utilisé.
Ensuite, aseqdump -p nnn:0 décode ce qui sort du machin :
tth@lol:~/Devel/MIDI/JoyMidi$ aseqdump -l | grep tth 128:0 joymidi tth was here ! tth@lol:~/Devel/MIDI/JoyMidi$ aseqdump -p 128:0 Waiting for data. Press Ctrl+C to end. Source_ Event_________________ Ch _Data__ 128:0 Note on 0 70 100 128:0 Note on 0 67 100 128:0 Note off 0 70 0 128:0 Note off 0 67 0
Bien entendu, aseqdump -p joymidi fera (en principe), la même chose, si vous n'utilisez pas le potentiel surchargement du nom.
Deuxième méthode :
La première méthode a quand même un biais: aseqdump interprète ce qu'envoie
joymidi, et peut éventuellement rater quelques octets mal sentis. Un autre
outil du kit ALSA, amidi, peut en théorie montrer
exactement ce qui arrive. Mais son utilisation est moins immédiate. Première
etape : lancer amidi dans un xterm avec les bonnes options.
xtermA$ amidi -p virtual -d
Deuxième étape : faire la connexion entre joymidi et amidi grace à aconnect. (C'est là que ça n'est pas encore évident pour moi ;)
xtermB$ aconnect -io client 128: 'joymidi' [type=user] 0 'tth was here ! ' client 129: 'Client-129' [type=user] 0 'Virtual RawMIDI ' xtermB$ aconnect 128 129
Et maintenant, dans le premier xterm, on peut contempler les octets envoyés par votre glorieux baton de joie :
90 46 64 80 46 00 90 43 64 80 43 00 90 44 64 80 44 00 90 45 64 80 45 00
Voilà, j'espère avoir fait le tour des méthodes de debugging appliqués à la manette de jeu qui se prend pour un clavier MIDI.
Ce gadget de musimatique propose deux binaires utilisables à partir de la cli. Chacun d'entre eux prend des options sur la ligne, et j'essaye de garder une bonne cohérence entre les deux. Demander gentiment avec -h vous donnera quelque chose dans ce genre :
tth@lol:~/Devel/MIDI/JoyMidi$ ./dump_my_joy -h dump_my_joy options: -v : increment verbose level -h : get more help (if available) -i : set the locations of init files -d : use an alternate joy device -n : display just the numbers
Voyons cela plus en détails pour certains de ces demandes :
Vous avez peut-être remarqué que le chemin vers le joypad change parfois
selon la prise USB sur laquelle il est branché.
Il est probablement possible de
régler ce léger souci par une règle udev bien sentie.
D'autre part, est-il possible d'utiliser joymidi avec plusieurs
manettes ? Oui, je pense, il doit suffire de construire plusieurs
répertoires avec les bons fichiers et de lancer deux instances de
joymidi avec l'option -i foo/ ou -i bar/.
Pas encore testé.
Please add more doc here...
Tout nouveau, tout pas beau. Je ne suis qu'un noobz en programmation ALSA, et la doc est, comment dire, plutôt faite pour ceux qui savent déja. Ceci dit, avec les exemples fournis, et les trucs qu'on trouve dans le grand Ternet mondial, on s'en sort à peu près.
tth@lol:~/Devel/MIDI/JoyMidi$ aseqdump -l Port Client name Port name 0:0 System Timer 0:1 System Announce 14:0 Midi Through Midi Through Port-0 16:0 SB Live 5.1 EMU10K1 MPU-401 (UART) 24:0 UM-3EX UM-3EX MIDI 1 24:1 UM-3EX UM-3EX MIDI 2 24:2 UM-3EX UM-3EX MIDI 3 24:3 UM-3EX UM-3EX Control 128:0 joymidi tth was here !
Donc voilà, si tout est correctement configuré, notre manette apparait bien dans la liste des périphériques ALSA. Bonne nouvelle, puisque nous allons pouvoir examiner le code MIDI généré. Hop, voilà ce que ça donne :
tth@lol:~/Devel/MIDI/JoyMidi$ aseqdump -p joymidi Waiting for data. Press Ctrl+C to end. Source_ Event_________________ Ch _Data__ 128:0 Note on 0 68 100 128:0 Note off 0 68 0 128:0 Note on 0 67 100 128:0 Note off 0 67 0 128:0 Note on 0 33 100 128:0 Note on 0 67 100 128:0 Note off 0 67 0 128:0 Note off 0 33 0
Ne soyez pas impatient, le code est en train de se mettre en place, et le tarball contient déja un peu de grain à moudre. Rappelons toutefois que c'est un brouillon que vous êtes en train de lire. Néammoins, aller jeter un petit regard salace sur contexte.h peut vous apprendre plein de choses.
Ensuite, je prépare calmement un bon hack hardware, que je vous proposerais bientôt, pour brancher un machin élégant (ou steampunk ?) en amont de ce logiciel. Actuellement, j'en suis à l'erreur 404. Et pour finir, quelques exemples d'utilisation avec midish sont en train de voir le jour.
Donc voilà, il reste un gazillion de choses à faire pour que joymidi soit enfin prêt pour le primetime. En attendant, les dinos ayant tous les droits, je vous recolle la somptueuse gif animée :
Ce logiciel est généreusement offert par le dino reconnu tth à tous les gens qui aiment faire librement du bruit avec des machines du siècle dernier. La license (must legalize) sera probablement un truc dans le genre de la dwtfywl; ou pire. Les costumes sont de Paul Boyé et les décors de Donald Portnawak.