3

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.

user3194972
  • 145
  • 1
  • 6

3 Answers3

1

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.

Community
  • 1
  • 1
Troy
  • 146
  • 4
1

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.

Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • i have tried calling this.device.close() in MidiHandler, the program is still transmitting and playing sound though. – user3194972 Apr 15 '15 at 19:57
  • Closing `MidiHandler` won't affect. In your `MidiHandler`, you set `Tansmitter`s and `Receiver`s for the device. **you have to close them to stop the device**. Also note, if you sent a long order, sound may not stop inmediately. – Jordi Castilla Apr 16 '15 at 07:24
0

You can try:

midiDevice.close();
outputPort.close();
inputPort.close();
dotrinh PM
  • 903
  • 1
  • 7
  • 19