更新Java中的Midi设备列表

时间:2016-12-13 14:32:38

标签: java macos midi macos-sierra

我在Java上使用基于MIDI的项目,并努力刷新Midi设备列表。

据我所知MidiSystem.getMidiDeviceInfo();应该给我一个Info[]数组。然而,对我来说没有任何事情当插入或拔出新设备时,阵列内的对象保持不变,这也是它的长度。

搜索Stackoverflow将我带到了this 6 year old question。其中一条评论表明,在OSX / macOS上可能会出现问题。我还没有在Windows或Linux上尝试过我的程序,但它应该适用于OSX / macOS。

另一条评论建议将缓存时间设置为短com.sun.media.sound.JDK13Services.setCachingPeriod(1);手动可以解决这个问题。但是不在OSX / macOS上。

对谷歌的进一步搜索让我找到openjdk bug report,声称这是苹果公司/ MacOS公司苹果方面的一些错误。

以下是我的Devices课程的缩短版本,用于验证,但我确信它应该是正确的。

private Info[] devices;

public Devices() {
    refreshDeviceList();
    printDeviceList();
}

// DeviceList Functions
public Info[] getDeviceList() {
    return devices;
}

public void printDeviceList() {
    for (int i = 0; i < devices.length; i++) {
        System.out.println("Description: \t" + devices[i].getDescription());
        System.out.println("Name: \t\t" + devices[i].getName());
        System.out.println("Vendor: \t" + devices[i].getVendor());
        System.out.println("Version: \t" + devices[i].getVersion());
        System.out.println();
    }
}

public void refreshDeviceList() {
    devices = MidiSystem.getMidiDeviceInfo();
}

// DeviceFunctions
public String getDeviceDescription(int i) {
    return devices[i].getDescription();
}

public String getDeviceName(int i) {
    return devices[i].getName();
}

public String getDeviceVendor(int i) {
    return devices[i].getVendor();
}

public String getDeviceVersion(int i) {
    return devices[i].getVersion();
}

请注意,在创建新refreshDevices()对象时首次调用Devices并打印可以获取可用设备列表。只是没有事后。在插入或拔出设备后重新启动程序会返回正确的新设备数。

有人可以为此提供解决方案吗?

3 个答案:

答案 0 :(得分:1)

现在有一个库CoreMidi4J,可以正确支持macOS上的热插拔(以及其他一些功能)。我不是作者,但它似乎可以很好地满足我的需求。

https://github.com/DerekCook/CoreMidi4J

答案 1 :(得分:0)

一种方法是按如下方式设置系统:

shell script:

start program with input 1 // that means it's the receiver

while(true) {
  start program with input 2 // that means it's the sender
  wait for an amount of time
}

end shell script

inside the program is the following:

    if code==1:
      while(true) {
      do whatever you have to do
      at specified point in time:
          read file "myfile"
          assemble the info
      }
      if code==2:
        read the device info
        write the info to "myfile"
        exit

答案 2 :(得分:0)

我找到了一个使用 JavaFX 线程的解决方案。出于某种原因,这至少适用于 MacOSX。在普通线程上它不起作用。

import fx.FX_Platform;
import javafx.embed.swing.JFXPanel;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;


public class miditest {
  
  
  static public void main( String[] args ) {
    // **** Just to init FX platform
    new JFXPanel();    
    new Thread( () -> {
      for( int ix=0; ix<1000; ix++ ) {
        try {
          Thread.sleep(2000);
        } catch( InterruptedException e ) {          
        }
        FX_Platform.runLater( () -> {
          MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
          System.out.println("FOUND: " + infos.length);
          for( MidiDevice.Info midiinfo : infos ) {
            System.out.println(midiinfo);
          }
        });
      }
    }).start();
    

  }
  
}