Etape 5: Gestionnaires de messages personnalisés
Utilisation midiMessage est OK pour les cas simples, comme avoir le croquis à faire quelque chose, n’importe quelle note est envoyé, ou peut-être en sélectionnant comportement basé sur deux ou trois notes, mais si trouver votre code remplissant avec des longues if/then ou switch/case déclarations vous devriez se méfier. Ces types de structures peuvent devenir difficiles à maintenir.
Ce qui serait plus propre qu’un ensemble croissant d’instructions conditionnelles serait une façon d’appeler une méthode basée sur la valeur de note. Voici une façon de le faire :
void midiMessage(MidiMessage message, long timestamp, String bus_name) { int note = (int)(message.getMessage()[1] & 0xFF) ; int vel = (int)(message.getMessage()[2] & 0xFF); println("Bus " + bus_name + ": Note "+ note + ", vel " + vel); invokeNoteHandler(note, vel); } void invokeNoteHandler(int note, int velocity) { try { Class[] cls = new Class[1]; cls[0] = int.class; Method handler = this.getClass().getMethod( "onNote" + note, cls ); handler.invoke(this, velocity); } catch (Exception e) { e.printStackTrace(); } }
Lorsqu’un message MIDI arrive, midiMessage sort de la valeur de note et la vitesse. Il transmet ces valeurs sur invokeNoteHandler. C’est où le plaisir arrive.
Réflexion de Java permet au code de trouver des méthodes par nom (à l’aide de getMethod) et de les appeler. Nous voulons passer une valeur int à un mode de la forme onNote < SomeNoteValue > ; pour trouver une méthode, que vous devez à la fois le nom et un tableau des classes décrivant quels arguments cette méthode prend.
Une fois qu’une référence à une telle méthode est trouvée elle est appelée à l’aide de (surprise!) appeler.
Tout cela se passe à l’intérieur d’un bloc try/catch. Si quelque chose ne va pas (par exemple, la code essaie de trouver et appeler une méthode qui n’existe pas), l’exception est plus ou moins ignoré. L’idée ici est que nous aurons des méthodes pour certains ensembles de notes, et nous ne se soucient notes pour lesquelles il n’y a aucune méthode correspondante de la gestionnaire.
La dernière partie de cela est de définir une ou plusieurs méthodes pour faire quelque chose pour les notes spécifiques. Par exemple :
void onNote48(int vel) { if (vel > 0 ) { currentColor = vel*2; } } void onNote50(int vel) { if (vel > 0 ) { currentColor = vel*2; } }
Pas très imaginatif, mais que cela ne fait pas change de couleur d’écran limite à juste deux notes.
Voici peut-être un meilleur exemple :
Tout d’abord, changer le type de currentColor :
color currentColor = new color(0,0,0);
Maintenant ont les gestionnaires Remarque définir différentes couleurs :
void onNote48(int vel) { if (vel > 0 ) { currentColor = color(255, vel*2, vel*2); } } void onNote50(int vel) { if (vel > 0 ) { currentColor = color(vel*2, 255, vel*2 ); } } void onNote52(int vel) { if (vel > 0 ) { currentColor = color(vel*2, vel*2, 255); } }
Le point clé est que le comportement de n’importe quelle note donnée est encapsulé dans sa propre méthode au lieu d’être entassés dans une méthode de culture fourre-tout.
Nous pouvons rendre les choses plus propre mais en mettant toutes les méthodes de gestion note dans un fichier séparé (par exemple noteHandlers.pde) si vous savez exactement où regarder pour ajouter ou modifier quoi que ce soit.
Vos propres gestionnaires de messages peuvent être tout ce que vous voulez, et vous pouvez passer des autres paramètres, peut-être passer dans le message MIDI original lui-même. Toutefois, vous définissez il vous devez paramétrer votre version d’invokeNoteHandler afin qu’il localise des méthodes ayant la signature de paramètre correct.
Par exemple, si vous souhaitez utiliser des méthodes de gestionnaire qui prennent la vélocité de la note et le nom de bus, vous devez modifier le tableau de la classe utilisé avec getMethod pour indiquer les types de ces deux paramètres :
void invokeNoteHandler(int note, int velocity, String busName) { try { // An array of size 2 since we are looking for a method that // takes two arguments Class[] cls = new Class[2]; cls[0] = int.class; cls[1] = String.class; Method handler = this.getClass().getMethod( "onNote" + note, cls ); // Now call the located method with the two arguments handler.invoke(this, velocity, busName); } catch (Exception e) { e.printStackTrace(); } }