Передатчик MIDI OUT недоступен

Я ломал голову над этим весь день, читал все, что мог найти, следил за исходным кодом JDK, но мне не удалось узнать кровавые подробности о КАК или ГДЕ java ищет данные о миди-устройстве и определяет, что к чему.

Я пытаюсь захватить миди-сообщения через мой порт NI Audio 8 DJ MIDI IN, но java не «видит» порт MIDI IN, а только выход, который я успешно использовал для отправки миди. Я также получаю те же результаты с миди-устройством M-Audio USB UNO: MidiSystem.getMidiDeviceInfo() "видит" только выходной порт.

Я проверил работу порта MIDI IN с помощью:

amidi -p hw:2,0 -d

и посылает ему какие-то сигналы. Работает отлично.

getMaxTransmitters() возвращает ноль. MidiSystem.getMidiDeviceInfo() показывает только одну запись для обоих устройств: Audio8DJ [hw:2,0] или Interface [hw:2,0]

Приведенный ниже код отлично работает для приемника, и я думаю, что это только те биты, которые мне нужны, чтобы убедиться, что getTransmitter() захватывает порт, поскольку он просто работает для другого, и все работает нормально, вверх я получаю исключение MidiUnavailableException / Transmitter not available.

Я даже убрал ловушку 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, поэтому я задаюсь вопросом, как и где Java выясняет, что может предложить устройство, и почему он не видит входной порт, который видит alsa.

Я кодирую с помощью eclipse Версия: 3.8.1 IDE с JDK1.6, на ОС Linux Mint, .

Я буду рад предоставить все, о чем просят. Спасибо за чтение!


person Daniel Sevelt    schedule 05.01.2016    source источник
comment
Просто случайная мысль... вы пытались запустить его с помощью sudo? (т. е. sudo java your.class.name в командной строке.) Я встречал проблемы, когда для управления некоторыми устройствами нужно иметь права root, так что, возможно, стоит попробовать.   -  person Mike Harris    schedule 06.01.2016
comment
Я думал об этом, и я открыт для предложений, но я не решался попробовать по двум причинам, связанным с рефлекторной реакцией на то, что запуск сложных приложений от имени пользователя root опасен: 1) поскольку он может получить MIDI-данные. OUT без проблем, тогда я лучше узнаю, к каким файлам обращается java, и исправлю проблему там. 2) его не следует запускать с правами root, и если запуск с правами root решит эту проблему, я вернусь к той же проблеме выяснения того, какой файл имеет проблему с доступом.   -  person Daniel Sevelt    schedule 07.01.2016
comment
Еще раз спасибо за помощь, Майк, ты направил меня в правильном направлении. Пожалуйста, смотрите мой ответ ниже.   -  person Daniel Sevelt    schedule 02.02.2016


Ответы (2)


Решение для java, видящего передатчик, было в используемой версии JDK, хотя, к сожалению, в настоящее время у меня нет ответа на вопрос, почему сбой, только эта версия работала и подходит для моего потребности на данный момент. Если я найду этот ответ, я отредактирую этот ответ.

Из трех версий, между которыми я переключался для тестирования, jdk1.8.0_60, jdk1.7.0_80, jdk1.6.0_45, 1.7 не обнаружил ошибки и успешно получил передатчик с моего устройства. Я обнаружил это и то, что привилегии не были причиной моей конкретной проблемы, скомпилировав и запустив некоторый код, который я Найдено подходит для выполнения командной строки, которая пытается получить передатчик, распечатывает отправленные ему миди-данные и немного модифицирует их. ..

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, по-видимому, отвечает за выяснение того, что доступно для использования java из вашей MIDI-архитектуры.

Спасибо, Майк Харрис, за то, что направил меня на правильный путь тестирования командной строки, и jim829 на java-forums.org за пример кода для командной строки.

person Daniel Sevelt    schedule 02.02.2016
comment
JDK 1.7 больше не доступен в Ubuntu 16.04 и более поздних версиях... его можно установить вручную, но он небезопасен. Стоит ли сообщать об ошибке Java? - person nyanpasu64; 17.05.2019

У меня была эта проблема, которая была вызвана несколькими экземплярами информации об устройстве с тем же именем, которое было возвращено MidiSystem.getMidiDeviceInfo(). В основном, когда вы вызываете MidiSystem.getMidiDevice(Info), если вам не повезло, он вернет тот, у которого нет передатчика. Я не уверен, почему он это делает, но только у одного экземпляра есть передатчики (я думаю, что один может быть для входа и один для выхода, но не уверен). Сначала я получил только те устройства, у которых есть передатчики, а затем выбрал из них нужную информацию, и это сработало для меня. надеюсь, это поможет

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();
            }
       }
}
person A Witherby    schedule 11.08.2019