MIDI OUT 发送器不可用

MIDI OUT transmitter not available

我一整天都在为这件事苦思冥想,阅读我能找到的所有东西,跟着 JDK 来源,没能找到关于 HOW[= 的血淋淋的细节44=] 或 WHERE java 寻找 midi 设备上的数据并确定什么是什么。

我试图通过我的 NI Audio 8 DJ MIDI IN 端口捕获 MIDI 消息,但是,java 不是 "seeing" MIDI IN 端口,只有输出,我已经成功了用于发送 midi。我在 M-Audio USB UNO midi 设备上也得到了相同的结果:MidiSystem.getMidiDeviceInfo() 仅 "sees" 输出端口。

我已经验证了 MIDI IN 端口的操作:

amidi -p hw:2,0 -d

并向它发送一些信号。工作正常。

getMaxTransmitters() returns 零。 MidiSystem.getMidiDeviceInfo() 只显示两个设备的一个条目:Audio8DJ [hw:2,0]Interface [hw:2,0]

下面的代码适用于接收器,我认为这只是我需要验证 getTransmitter() 获取端口的位,因为它适用于另一个并且一切正常,我得到一个MidiUnavailableException / 发送器不可用异常。

我什至排除了 getMaxReceivers() 陷阱,因为我只是想看看设备是否只提供了一个条目并将其整理出来,但没有。

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;
}

所以让我来到这里的是:alsa 在 amidi -l 中仅列出一个条目,当我将其指定为要转储的端口时,它工作正常。 Java 获取相同的文本条目,无法整理 MIDI IN,将其分配给 com.sun.media.sound.MidiOutDeviceProvider class 所以这让我想知道 Java 是怎么做的,或者在哪里弄清楚设备必须提供什么以及为什么它没有看到 alsa 看到的输入端口。

我正在使用 eclipse 版本:3.8.1 IDE 和 JDK1.6 在 linux mint OS 上进行编码。

我很乐意提供任何要求。感谢阅读!

java 看到发射器的解决方案是使用 JDK 的版本,但不幸的是,此时我没有关于 为什么 失败了,暂时只有一个版本可以用,适合我的需要。如果我找到那个答案,我会编辑这个答案。

我在测试的三个版本中,jdk1.8.0_60、jdk1.7.0_80、jdk1.6.0_45、1.7没体验错误并成功地从我的设备获得了一个发射器。我发现了这一点,并且特权不是我的特定问题的原因,通过编译和 运行 宁一些代码我 found 适合命令行执行尝试获取发射器,打印出 midi 数据发送给它,并对其进行了一些修改...

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();
        }
    }
}

为了 运行 从命令行选择一个你安装的 JDK 版本,编译并 运行 用那些特定版本替换 jdk1.7.0_80 对于您要测试的发行版。

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

虽然我无法验证它,Java Sound 显然负责从您的 MIDI 架构中找出可供 java 使用的内容。

感谢 Mike Harris 让我在命令行上进行正确的测试,并感谢 jim829 在 java-forums.org 提供命令行的示例代码。

我遇到了这个问题,它是由 MidiSystem.getMidiDeviceInfo() 返回的同名设备信息的多个实例引起的。基本上当你调用 MidiSystem.getMidiDevice(Info) 时,如果你不走运,它会 return 那个没有发射器的。我不确定它为什么这样做,但只有一个实例有发射器,(我认为一个可能用于进出,但不确定)。通过首先只获取具有发射器的设备,然后从这些设备中选择所需的信息,它对我有用。希望有帮助

public ArrayList<MidiDevice> getTransmitterDevices() {
    MidiDevice.Info[] deviceInfo = MidiSystem.getMidiDeviceInfo();

    ArrayList<MidiDevice> transmitterDevices = new ArrayList<>();
        for(int i=0;i<deviceInfo.length;i++) {
            try {
                MidiDevice device = MidiSystem.getMidiDevice(deviceInfo[i]);
                if(device.getMaxTransmitters()!=0) {
                    transmitterDevices.add(device);
                }
            } catch (MidiUnavailableException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    return transmitterDevices;
}
//Somewhere else 
//choose appropriate info somehow
MidiDevices<ArrayList> transmitterDevices = getTransmitterDevices();
    for(MidiDevice tmp : transmitterDevices) {
        if(tmp.getDeviceInfo().equals(info)) {
            try {
                midiController = tmp;
                Transmitter transmitter = midiController.getTransmitter();
                // something that implements receiver
                midiReceiver = new MidiReceiver(); 
                transmitter.setReceiver(midiReceiver);
                midiController.open();
                System.out.println("controller set ok");
            } catch (MidiUnavailableException e) {
                // TODO Auto-generated catch block
                    e.printStackTrace();
            }
       }
}