【问题标题】:Update list of Midi Devices in JavaJava 中的 Midi 设备更新列表
【发布时间】:2016-12-13 14:32:38
【问题描述】:

我在一个基于 MIDI 的 Java 项目上工作,并且努力刷新 Midi 设备列表。

据我所知MidiSystem.getMidiDeviceInfo(); 应该给我一个Info[] 数组。然而,对我来说什么也没发生。插入或拔出新设备时,Array 中的 Objects 保持不变,长度也保持不变。

搜索 Stackoverflow 将我带到 this 6 year old question。其中一位 cmets 建议,在 OSX/macOS 上可能是问题所在。我还没有在 Windows 或 Linux 上尝试过我的程序,但无论如何它应该可以在 OSX/macOS 上运行。

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

在 Google 上的进一步搜索将我带到了 openjdk bug report,它声称这是 OSX/macOS 中 Apple 方面的一些错误。

下面是我的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();
}

请注意,在创建新的 Devices 对象时第一次调用 refreshDevices() 可以正常工作,并且打印会为我提供可用设备的列表。只是之后没有。但是,在插入或拔出设备后重新启动程序会返回正确的新设备数量。

谁能提供解决方案?

【问题讨论】:

  • 我无法回答您的直接问题,但代码 sn-p 确实看起来正确且功能正常。我个人建议在 printDeviceList() 方法中使用 devices 的设置器和增强的 for 循环,以迭代 Info[] devices,而不是 .length 的处理方式。但这只是个人喜好。
  • 只是一些即兴的想法,因为我无法在现实生活中测试它们——一种方法是设置一个客户端服务器系统,它是两个程序,其中一个可以终止;一个检查 - 如果需要,关闭 - 并将数据传输给另一个

标签: java macos midi macos-sierra


【解决方案1】:

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

https://github.com/DerekCook/CoreMidi4J

【讨论】:

  • 非常感谢!这似乎是一个可行的解决方案。我会投票,但不能因为我低于 15 业力阈值。我仍然感到失望的是,Apple 和 Java 支持都互相指责,让我在最长的时间里得到一个 meh-ish 的解决方案。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我找到了一个使用 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();
        
    
      }
      
    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-25
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多