MidiShare: Tutorials inicials II

De Wikijoan
Dreceres ràpides: navegació, cerca

SimpleMidiShareTest.java

important llegir Connectant_aplicacions_MidiShare:_síntesi

import grame.midishare.*;

/** Simple test for MidiShare/Java.  Sends Midi (does not receive Midi)

	Uses MidiShare's Java API (no JMSL at all).  
	Get this working before troubeshooting JMSL + MidiShare

	Open Midi, Send 12 chromatic noteons and noteoffs, close midi.

@author Nick Didkovsky, didkovn@mail.rockefeller.edu 7/12/01
*/

public class SimpleMidiShareTest {

	public static void main(String args[]) {
		// set these how you want them
		int outport = 0;
		int channel = 2;
		int pitch = 60;
		int vel = 120;

		int installed = 0;
		try {
			installed = Midi.Share();
		} catch (UnsatisfiedLinkError e) {
			e.printStackTrace();
			System.out.println(
				"\nMidiShare Java API probably not installed properly, grame.midishare.Midi.Share() barfed.\n" + e);
			System.exit(0);
		}

		System.out.println("installed = " + installed);
		int version = Midi.GetVersion();
		System.out.println("version = " + version);
		int numberOfAppl = Midi.CountAppls();
		System.out.println("numberOfAppl = " + numberOfAppl);
		int ourRefNum = Midi.Open("SimpleMidiShareTest");
		numberOfAppl = Midi.CountAppls();
		System.out.println("our ref #= " + ourRefNum + ", numberOfAppl = " + numberOfAppl);

		StringBuffer text = new StringBuffer();
		short i;
		int ref, n = Midi.CountAppls();
		text.append("List of MidiShare client applications\n");
		text.append("-------------------------------------\n");
		for (i = 1; i <= n; i++) {
			ref = Midi.GetIndAppl(i); // get the refnum form the order number
			text.append(String.valueOf(i));
			text.append(" : reference number ");
			text.append(String.valueOf(ref));
			text.append(" name : ");
			text.append(Midi.GetName(ref));
			text.append("\n");
		}
		text.append("-------------------------------------");
		System.out.println(text.toString());

		Midi.Connect(ourRefNum, 0, 1);
		int connected = Midi.IsConnected(ourRefNum, 0);
		System.out.println("Connected? " + connected);

		//connecto l'aplicació al fluidsynth, per poder escoltar
		int ref_fluidsynth;
		if ((ref_fluidsynth = Midi.GetNamedAppl("fluidsynth")) > 0) Midi.Connect (ourRefNum,ref_fluidsynth, 1);
		   
		for (int interval = 0; interval < 12; interval++) {
			int event = Midi.NewEv(Midi.typeKeyOn); // ask for a new note event
			if (event != 0) { // if the allocation was succesfull
				Midi.SetChan(event, channel); // set the Midi channel
				Midi.SetPort(event, outport); // set the destination port
				Midi.SetField(event, 0, pitch + interval); // set the pitch field
				Midi.SetField(event, 1, vel); // set the velocity field
				Midi.SendIm(ourRefNum, event);
			}
			System.out.println("Sent Midi note on " + (pitch + interval));
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
			}

			event = Midi.NewEv(Midi.typeKeyOff);

			if (event != 0) {
				Midi.SetChan(event, channel);
				Midi.SetPort(event, outport);
				Midi.SetField(event, 0, pitch + interval);
				Midi.SetField(event, 1, vel);
				Midi.SendIm(ourRefNum, event);
			}
			System.out.println("Sent Midi note off " + (pitch + interval));
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
			}
		}
		Midi.Close(ourRefNum);
	}
}

De l'aplicació original, per tal de poder escoltar, faig només el petit canvi de connectar l'aplicació al fluidsynth. La sortida de l'aplicació

installed = 1
version = 192
numberOfAppl = 5
our ref #= 5, numberOfAppl = 6
List of MidiShare client applications
-------------------------------------
1 : reference number 0 name : MidiShare
2 : reference number 1 name : msdisplay
3 : reference number 2 name : msconnect
4 : reference number 3 name : fluidsynth
5 : reference number 4 name : mscontrol
6 : reference number 5 name : SimpleMidiShareTest
-------------------------------------
Connected? 1
Sent Midi note on 60
Sent Midi note off 60
Sent Midi note on 61
Sent Midi note off 61
...

MidiShareIOTest.java

important llegir Connectant_aplicacions_MidiShare:_síntesi

Toca unes quantes notes (envia events MIDI), i escolta també els events MIDI que rep d'alguna aplicació origen que estigui connectada. Com es veu en el codi, necessito les aplicacions fluidsynth (per escoltar) i mscontrol (per produir sons). Connecto l'aplicació al fluidsynth (ja puc escoltar), i per rebre missatges he de connectar el mscontrol a la meva a aplicació.

No cal connectar mscontrol al fluidsynth, doncs per la propietat transitiva: mscontrol està connectat a l'aplicació, i l'aplicació està connectat al fluidsynth. Ara bé, en aquest cas, s'executa el codi del procediment:

public void ReceiveAlarm(int ev) {

que em permet tractar el event que rebo, i si vull escoltar la nota, l'he de reenviar per tal que el fluidsynth el faci sonar:

Midi.SendIm(this.refnum, ev);

en comptes de

Midi.FreeEv(ev);

Així, doncs, el codi queda:

import java.awt.*;
import java.awt.event.*;

import grame.midishare.*;

/** Test for MidiShare's Java API.  Sends Midi and receives Midi, printing message types of incoming MIDI.
*
* Uses MidiShare's Java API (no JMSL at all). 
* Get this working before troubeshooting JMSL + MidiShare
*
* IMPORTANT: Change inport and output values in main() for your system !!!!!!!!!!
*
* @author Nick Didkovsky, didkovn@mail.rockefeller.edu 4/15/04
*/

public class MidiShareIOTest extends MidiAppl {

    int inport;
    int outport;

    public MidiShareIOTest(int inport, int outport) {
        this.inport = inport;
        this.outport = outport;
    }

    public void Open(String name) throws MidiException {
        super.Open(name);
        configureFilter();
    }

    /* kill active sensing */
    void configureFilter() {
        int i;
        for (i = 0; i < 256; i++) {
            //Midi.AcceptPort(filter, i, 1);
            Midi.AcceptPort(filter, i, 0);
            Midi.AcceptType(filter, i, 1);
        }

        for (i = 0; i < 16; i++) {
            Midi.AcceptChan(filter, i, 1);
        }
        Midi.AcceptPort(filter, inport, 1);
        Midi.AcceptType(filter, Midi.typeActiveSens, 0);
        //    Midi.AcceptType(filter, Midi.typeSysEx, 0);
        //    System.out.println("MidiShare configureFilter() filter#" + filter);
    }

    /** Simply notify that an input event occurred, print what kind */
    public void ReceiveAlarm(int ev) {
        switch (Midi.GetType(ev)) {
            case Midi.typeNote :
                System.out.println("MidiShareIOTest, received typeNote");
                break;
            case Midi.typeKeyOn :
                System.out.println("MidiShareIOTest, received typeKeyOn");
                break;
            case Midi.typeKeyOff :
                System.out.println("MidiShareIOTest, received typeKeyOff");
                break;
            case Midi.typeKeyPress :
                System.out.println("MidiShareIOTest, received typeKeyPress");
                break;
            case Midi.typeCtrlChange :
                System.out.println("MidiShareIOTest, typeCtrlChange");
                break;
            case Midi.typeProgChange :
                System.out.println("MidiShareIOTest, received typeProgChange");
                break;
            case Midi.typeChanPress :
                System.out.println("MidiShareIOTest, received typeChanPress");
                break;
            case Midi.typePitchWheel :
                System.out.println("MidiShareIOTest, received typePitchWheel");
                break;
            case Midi.typeSysEx :
                System.out.println("MidiShareIOTest, received typeSysEx");
                break;
            default :
                break;
        }
        //Midi.FreeEv(ev);
        Midi.SendIm(this.refnum, ev);
    }

    void playNotes() {
        int channel = 1;
        int pitch = 60;
        int vel = 80;
        for (int interval = 0; interval < 4; interval++) {
            int event = Midi.NewEv(Midi.typeKeyOn); // ask for a new note event
            if (event != 0) { // if the allocation was succesfull
                Midi.SetChan(event, channel); // set the Midi channel
                Midi.SetPort(event, outport); // set the destination port
                Midi.SetField(event, 0, pitch + interval); // set the pitch field
                Midi.SetField(event, 1, vel); // set the velocity field
                Midi.SendIm(refnum, event);
            }
            System.out.println("Sent Midi note on " + (pitch + interval));
            try {
                Thread.sleep(200);
            }
            catch (InterruptedException e) {
            }

            event = Midi.NewEv(Midi.typeKeyOff);

            if (event != 0) {
                Midi.SetChan(event, channel);
                Midi.SetPort(event, outport);
                Midi.SetField(event, 0, pitch + interval);
                Midi.SetField(event, 1, vel);
                Midi.SendIm(refnum, event);
            }
            System.out.println("Sent Midi note off " + (pitch + interval));
            try {
                Thread.sleep(200);
            }
            catch (InterruptedException e) {
            }
        }
    }

    public static void main(String args[]) {
        // set these how you want them
        int inport = 0;
        int outport = 1;

        int installed = 0;
        try {
            installed = Midi.Share();
        }
        catch (UnsatisfiedLinkError e) {
            e.printStackTrace();
            System.out.println(
                "\nMidiShare Java API probably not installed properly, grame.midishare.Midi.Share() barfed.\n" + e);
            System.exit(0);
        }

        System.out.println("installed = " + installed);
        int version = Midi.GetVersion();
        System.out.println("version = " + version);
        int numberOfAppl = Midi.CountAppls();
        System.out.println("numberOfAppl = " + numberOfAppl);

        final MidiShareIOTest midiHandler = new MidiShareIOTest(inport, outport);

        Frame f = new Frame("Watch console for incoming midi messages. Close this frame to quit");

        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.out.println("Closing Midi, byebye");
                midiHandler.Close();
                System.exit(0);
            }
        });
        Button playButton = new Button("play notes");
        f.add(playButton);
        playButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                midiHandler.playNotes();
            }
        });
        f.setSize(600, 100);
        f.setVisible(true);

        try {
            midiHandler.Open("MidiShareIOTest");
            Midi.Connect(midiHandler.refnum, 0, 1);
            Midi.Connect(0, midiHandler.refnum, 1);
            // Check output connection
            int connected = Midi.IsConnected(midiHandler.refnum, 0);
            System.out.println("Connected for input? " + connected);

            // Check input connection
            connected = Midi.IsConnected(0, midiHandler.refnum);
            System.out.println("Connected for output? " + connected);

            //em connecto a fluidsynth
            int ref_fluidsynth;
            if ((ref_fluidsynth = Midi.GetNamedAppl("fluidsynth")) > 0) Midi.Connect (midiHandler.refnum,ref_fluidsynth, 1);
            //em connecto al mscontrol
            int ref_mscontrol;
            if ((ref_mscontrol = Midi.GetNamedAppl("mscontrol")) > 0) Midi.Connect (ref_mscontrol,midiHandler.refnum, 1);
            
            StringBuffer text = new StringBuffer();
            short i;
            int ref, n = Midi.CountAppls();
            text.append("List of MidiShare client applications\n");
            text.append("-------------------------------------\n");
            for (i = 1; i <= n; i++) {
                ref = Midi.GetIndAppl(i); // get the refnum from the order number
                text.append(String.valueOf(i));
                text.append(" : reference number ");
                text.append(String.valueOf(ref));
                text.append(" name : ");
                text.append(Midi.GetName(ref));
                text.append("\n");
            }
            text.append("-------------------------------------");
            System.out.println(text.toString());
        }
        catch (MidiException e1) {
            System.out.println("Error opening MidiShareIOTest: " + e1);
            e1.printStackTrace();
        }

    }
}

La sortida del programa és:

installed = 1
version = 192
numberOfAppl = 4
Connected for input? 1
Connected for output? 1
List of MidiShare client applications
-------------------------------------
1 : reference number 0 name : MidiShare
2 : reference number 1 name : msdisplay
3 : reference number 2 name : mscontrol
4 : reference number 3 name : fluidsynth
5 : reference number 4 name : MidiShareIOTest
-------------------------------------
Sent Midi note on 60
Sent Midi note off 60
Sent Midi note on 61
Sent Midi note off 61
Sent Midi note on 62
Sent Midi note off 62
Sent Midi note on 63
Sent Midi note off 63
Sent Midi note on 64
Sent Midi note off 64
Sent Midi note on 65
Sent Midi note off 65
Sent Midi note on 66
Sent Midi note off 66
Sent Midi note on 67
Sent Midi note off 67
MidiShareIOTest, received typeNote
MidiShareIOTest, received typeNote
MidiShareIOTest, received typeNote
MidiShareIOTest, received typeNote
Closing Midi, byebye

Compilació i execució des de la consola

cd /home/joan/workspace/MidiShareIOTest/src

la classe MidiAppl ja està compilada en el sistema: /usr/src/midishare/lang/java/native/grame/midishare/MidiAppl.class

Si no està compilada, l'hauré de compilar manualment:

$ cd /usr/src/midishare/lang/java/native/grame/midishare
$ sudo javac -classpath /usr/src/midishare/lang/java/native -d /usr/src/midishare/lang/java/native/grame/midishare MidiAppl.java

D'aquesta manera compilem MidiAppl.java i obtenim les classes en el mateix directori: MidiAppl.class, DriverInfos.class, MidiApplImpl.class, Midi.class, MidiPollingThread.class, ReadEvInfo.class, SmpteLoc.class, WriteEvInfo.class, MidiApplPolling.class, MidiException.class, MidiTask.class, SlotInfos.class, SyncInfo.class

Com a norma, el destí per a les class serà /bin. De manera que de la carpeta del projecte penjarand dos carpetes: /src i /bin. En la línia de comandes això s'especifica amb l'opció -d.

$ sudo javac -classpath /usr/src/midishare/lang/java/native -d /home/joan/workspace/MidiShareIOTest/bin MidiShareIOTest.java
$ java -classpath /usr/src/midishare/lang/java/native:/home/joan/workspace/MidiShareIOTest/bin MidiShareIOTest

En el classpath he de ficar la ruta on es troben les classes. Això en el Eclipse no cal fer-ho perquè quan es crea un projecte et pregunta quin serà el destí de les classes, i aleshores quan compila les fica allà i quan executa les espera trobar allà.

Eines de l'usuari
Espais de noms
Variants
Accions
Navegació
Institut Jaume Balmes
Màquines recreatives
CNC
Informàtica musical
joanillo.org Planet
Eines