13

我正在开发一个使用 javax.sound.midi 库从 midi 硬件接收 midi 事件的 java 项目。在文档中,它说MidiSystem.getMidiDeviceInfo()返回所有连接的 MIDI 硬件的列表。它对我有用,但问题是,它只能工作一次。第一次实际扫描设备需要一点时间,但此后每次它都会立即返回相同的列表,即使已连接新设备也是如此。有没有办法强制它重新扫描?如果应用程序重新启动,它将重新扫描,但我不希望我的用户在连接新的 midi 设备时必须重新启动。

顺便说一句,我使用的是 Mac OS X ......有人指出,不同操作系统的行为可能不同。

4

5 回答 5

7

获取完整的MidiSystem.getMidiDeviceInfo()提供者列表,并从每个提供者中提取设备的信息。

MIDI 提供者列表通过静态方法从 JDK 底层类com.sun.media.sound.JDK13Services中恢复getProviders()

public static synchronized List getProviders(Class serviceClass) 获取一个列表,其中包含所请求服务的提供程序的已安装实例。提供者列表在 cachePeriod 给定的时间段内被缓存。在此期间,为相同类型的提供者返回相同的 List 实例。在此期间之后,将构造并返回一个新实例。返回的 List 是不可变的。

所以,这个类似乎将你的 Providers 列表保存在缓存中,一段时间后会重新加载。您可以使用 方法将此时间段设置为自定义值setCachingPeriod(int seconds)。据我所知,默认缓存时间设置为 60 秒。

例如,要每秒刷新一次缓存,您可以在代码中添加这一行:

com.sun.media.sound.JDK13Services.setCachingPeriod(1);

请注意,此解决方案使用 Sun 专有类,因此它不能 100% 可移植。

于 2010-09-29T10:04:46.727 回答
3

在我的工作 PC 或任何类型的 Mac 上缺少任何 MIDI 设备,我怀疑我能否正确测试它,但是......

MidiSystem 类似乎用于com.sun.media.sound.JDK13Services.getProviders(Class providerClass)查找系统上的设备列表。此类的API 文档指出,该列表是在 a 之外的连续调用中重新创建的cachingPeriod,可以通过调用方便地设置该列表setCachingPeriod(int seconds)

运气好的话,您可以在应用程序开始时调用一次并将其设置为 5 秒或其他时间,它会神奇地工作。但是,文档还声明“此方法仅用于测试。”,因此我不确定这种方法的效果如何。

希望这足以让你开始,同时我会继续四处寻找,看看我是否能找到一种更清洁的方法来做到这一点。

于 2010-09-29T10:04:03.053 回答
0

我回答这也是Java 中 Midi 设备的更新列表,但是对于在这里结束的人来说,现在有一个正确支持这个的库:https ://github.com/DerekCook/CoreMidi4J

该库充当 MIDI 子系统的设备提供程序,因此它基本上是一个插件,您现有的所有代码都可以工作。

我不是作者,但它很好地满足了我的需求,并且需要进行相当多的搜索才能找到,因此我将其发布在这里以供遇到问题的其他人使用。

于 2018-07-24T19:51:19.727 回答
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();
    

  }
  
}
于 2021-03-26T16:32:01.517 回答
-1

这听起来可能是操作系统特定的错误,但我可以想办法解决。

在 java 中,您可以向操作系统运行外部命令。(一个快速的谷歌,给了我这个例子http://www.javafaq.nu/java-example-code-186.html它看起来不错并且给了你这个想法)。

在检查新设备时,您可以发送一个外部命令来运行一个简单的 java 程序,该程序使用 MidiSystem.getMidiDeviceInfo() 快速查询 midi 设备并将结果输出到文本文件,或者您可以从 BufferedReader 对象中获取输出。

还要记住,用于查询 midi 设备的外部程序不必用 Java 编写,以防 Java 给您带来更多问题。或者,您可以只在操作系统中查询连接的设备并使用 grep 过滤结果。

希望这可以帮助。

于 2010-09-24T11:09:02.610 回答