Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MIDI OUT transmitter not available

Tags:

java

midi

I've been banging my head on this all day, read everything I can find, followed the JDK source around, no luck in finding out the gory details about HOW or WHERE java looks to obtain data on a midi device and determines what's what.

I'm trying to capture midi messages through my NI Audio 8 DJ MIDI IN port, but, java isn't "seeing" the MIDI IN port, only the out, which I have successfully used to send midi with. I also get the same results with an M-Audio USB UNO midi device: MidiSystem.getMidiDeviceInfo() only "sees" the output port.

I have verified the operation of the MIDI IN port with:

amidi -p hw:2,0 -d

and sending it some signals. Works fine.

getMaxTransmitters() returns zero. MidiSystem.getMidiDeviceInfo() shows only one entry for both devices: Audio8DJ [hw:2,0] or Interface [hw:2,0]

The code below works fine for a Receiver and I think is only the bits I need to verify that getTransmitter() grabs the port, since it just works for the other and everything works fine, up I get a MidiUnavailableException / Transmitter not available exception.

I've even taken the getMaxReceivers() trap out because I was just trying to see if the device only offered up the one entry and sorted it out, but no.

public static Transmitter getMidiIn () {
    if (midiIn == null){
        devices = MidiSystem.getMidiDeviceInfo();
        for(MidiDevice.Info info: devices){
            System.out.println("device class " + info.getClass());
            MidiDevice device;
            try{
                device = MidiSystem.getMidiDevice(info);
                if (info.toString().equals("Audio8DJ [hw:2,0]")){

                    if (device.getMaxTransmitters() != 0){
                        try{
                            device.open();
                            System.out.println("max transmitters:" + device.getMaxTransmitters());
                            midiIn = device.getTransmitter();
                            System.out.println("Found a transmitter: "+ midiIn);
                            break;
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            } catch (MidiUnavailableException e1){
                e1.printStackTrace();

            }
        }
    }
    return midiIn;
}

So the thing that's getting me here is this: alsa lists only one entry in amidi -l and when I specify that as a port to dump, it works fine. Java gets that same text entry and can't sort out the MIDI IN, assigning it the com.sun.media.sound.MidiOutDeviceProvider class so it leaves me wondering just how does, or where does Java figure out what a device has to offer and why isn't it seeing the input port that alsa is seeing.

I'm coding with eclipse Version: 3.8.1 IDE with JDK1.6, on a linux mint OS, .

I'll be happy to provide anything asked for. Thanks for reading!

like image 647
Daniel Sevelt Avatar asked Oct 19 '22 18:10

Daniel Sevelt


1 Answers

The solution to java seeing the transmitter was in the version of JDK being used, though unfortunately at this time, I do not have an answer as to why for the failure, just that one version worked and suits my needs for the time being. If I find that answer, I will edit this answer.

Of the three versions I was switching between for testing, jdk1.8.0_60, jdk1.7.0_80, jdk1.6.0_45, 1.7 did not experience the error and successfully obtained a transmitter from my device. I found this out, and that privileges were not the cause of my specific issue, by compiling and running some code I found suitable for command line execution that attempts to obtain the transmitter, prints out midi data sent to it, and modified it a little ...

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;

public class MidiInputTest {

    public MidiDevice       input;
    public MidiDevice       output;

    public static void main(String[] args) {
        new MidiInputTest().start();
    } 


    public void start() {
        init();  // initialize your midi input device
                 // system dependent


        try {
            output.open(); // From midi device
            MyReceiver myrcvr = new MyReceiver();
            MidiSystem.getTransmitter().setReceiver(myrcvr);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }

    }

    private class MyReceiver implements Receiver  {
        Receiver rcvr;
        public MyReceiver() {
            try {
                this.rcvr = MidiSystem.getReceiver();
            } catch (MidiUnavailableException mue) {
                mue.printStackTrace();
            }
        }

        @Override
        public void send(MidiMessage message, long timeStamp) {
            byte[] b = message.getMessage();
            if (b[0] != (byte)254) {
                System.out.println((b[0] & 0xff) + " " + (b[1] & 0xff));
            }
            //rcvr.send(message, timeStamp); // will send out what ever you receive
        }

        @Override
        public void close() {
            rcvr.close();
        }
    } 
    public void init() {

        MidiDevice.Info[] devices;

        devices = MidiSystem.getMidiDeviceInfo();
        try{

            for (MidiDevice.Info info: devices) {
                MidiDevice device;
                device = MidiSystem.getMidiDevice(info);
                System.out.println("MidiDevice.Info="+info + "\n" + "maxTransmitters="+device.getMaxTransmitters());

                // I put the specific device I want to connect to behind an if gate here to avoid connecting to something I do not

                if (info.toString().equals("Interface [hw:2,0,0]") && device.getMaxTransmitters() != 0) { 
                    System.out.println(" Name: " + info.toString() +
                            ", Decription: " +
                            info.getDescription() +
                            ", Vendor: " +
                            info.getVendor());

                    output = MidiSystem.getMidiDevice(info);

                   if (! output.isOpen()) {
                        output.open();
                   }
                }
            }
        } catch (MidiUnavailableException mue) {
                    mue.printStackTrace();
        }
    }
}

To run this from the command line choose a version of JDK you have installed, compile and run it with those specific versions substituting jdk1.7.0_80 for the distro you wish to test.

/opt/java-jdk/jdk1.7.0_80/bin/javac MidiInputTest.java
/opt/java-jdk/jdk1.7.0_80/bin/java -cp . MidiInputTest

Though I haven't been able to verify it, Java Sound is apparently responsible for figuring out what is available for java's use from your MIDI architecture.

Thank you Mike Harris for sending me down the right path of testing on the command line, and jim829 over at java-forums.org for the example code for the command line.

like image 63
Daniel Sevelt Avatar answered Nov 02 '22 11:11

Daniel Sevelt