user3194972
user3194972

Reputation: 155

How to close a midi device?

How do i close a midi device in java? I have tried re-initialising the MidiHandler object, but the device stays open until the program terminates. Also, if i unplug my midi controller while the program is running, it wont send notes after it is reconnected, even after reinitialising. I have to, again, terminate and start the program anew, in order for it to work. I am very new to using midi, so i might be fundamentally misunderstanding the whole concept. Here is what i have so far:

public class MidiHandler {
MidiDevice device;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();

public MidiHandler() {

    for (int i = 0; i < infos.length; i++) {
        try {
            this.device = MidiSystem.getMidiDevice(this.infos[i]);
            // does the device have any transmitters?
            // if it does, add it to the device list
            System.out.println(this.infos[i]);

            // get all transmitters
            List<Transmitter> transmitters = this.device.getTransmitters();
            // and for each transmitter

            for (int j = 0; j < transmitters.size(); j++) {
                // create a new receiver
                transmitters.get(j).setReceiver(
                // using my own MidiInputReceiver
                        new MidiInputReceiver(this.device.getDeviceInfo()
                                .toString()));
            }

            Transmitter trans = this.device.getTransmitter();
            trans.setReceiver(new MidiInputReceiver(this.device.getDeviceInfo()
                    .toString()));
            this.device.open();
        } catch (MidiUnavailableException e) {
        }
    }

}

public void close() {

}

public String getInfos() {
    String infos = "";
    for(int i = 0; i < this.infos.length; i++) {
        infos += "\n" + this.infos[i] + " ";
    }
    return infos;
}

// tried to write my own class. I thought the send method handles an
// MidiEvents sent to it
public class MidiInputReceiver implements Receiver {
    Synthesizer synth;
    MidiChannel[] mc;
    Instrument[] instr;
    int instrument;
    int channel;

    public MidiInputReceiver(String name) {
        try
        {
            patcher p = new patcher();
            this.instrument = p.getInstrument();
            this.channel = p.getChannel();
            this.synth = MidiSystem.getSynthesizer();
            this.synth.open();
            this.mc = synth.getChannels();
            instr = synth.getDefaultSoundbank().getInstruments();
            this.synth.loadInstrument(instr[1]);
            mc[this.channel].programChange(0, this.instrument);
        }
        catch (MidiUnavailableException e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }

    public void send(MidiMessage msg, long timeStamp) {
        /*
         * Use to display midi message
         */ 
        for(int i = 0; i < msg.getMessage().length; i++) {
            System.out.print("[" + msg.getMessage()[i] + "] ");

        }
        System.out.println();

        if (msg.getMessage()[0] == -112) {
            mc[this.channel].noteOn(msg.getMessage()[1], msg.getMessage()[2]+1000);
        }

        if (msg.getMessage()[0] == -128) {
            mc[this.channel].noteOff(msg.getMessage()[1], msg.getMessage()[2]+1000);
        }

    }

    public void close() {
    }
}

The main class simply instantiates a MidiHandler and that works fine, except for the issues above.

Upvotes: 3

Views: 798

Answers (3)

dotrinh DM
dotrinh DM

Reputation: 1393

You can try:

midiDevice.close();
outputPort.close();
inputPort.close();

Upvotes: 0

Jordi Castilla
Jordi Castilla

Reputation: 26961

You can call MidiDevice::close()

explicit closing is done by calling close()

But the MIDI devices extends Autocloseable, so, according to the API, you have to close the Transmitter or Receiver.

In the API:

The device is closed after the last Receiver or Transmitter has been closed. On the other hand, calling getReceiver or getTransmitter on the device instance directly does not open the device implicitly. Closing these Transmitters and Receivers does not close the device implicitly.

Upvotes: 1

Troy
Troy

Reputation: 166

Have you checked out Oracle MIDI-messages?

Closing Connections

Once you're done with a connection, you can free up its resources by invoking the close method for each transmitter and receiver that you've obtained. The Transmitter and Receiver interfaces each have a close method. Note that invoking Transmitter.setReceiver doesn't close the transmitter's current receiver. The receiver is left open, and it can still receive messages from any other transmitter that's connected to it.

If you're also done with the devices, you can similarly make them available to other application programs by invoking MidiDevice.close(). Closing a device automatically closes all its transmitters and receivers.

Upvotes: 1

Related Questions