我正在开发一个java项目,它使用javax.sound.midi库从midi硬件接收midi事件。在文档中,它说MidiSystem.getMidiDeviceInfo()
返回所有连接的midi硬件的列表。它适用于我,但问题是,它只能工作一次。第一次实际扫描设备需要花费一些时间,但每次在此之后,即使已连接新设备,它也会立即返回相同的列表。有没有办法强迫它重新扫描?如果重新启动应用程序,它将重新扫描,但我不希望我的用户在连接新的midi设备时必须重新启动。
顺便说一下,我正在使用Mac OS X ......有人指出不同操作系统的行为可能会有所不同。
答案 0 :(得分:7)
MidiSystem.getMidiDeviceInfo()
获取完整的提供者列表,并从每个提供者中提取设备的信息。
通过静态方法getProviders()
public static synchronized List getProviders(Class serviceClass) 获得包含已安装的List 提供者的实例 要求的服务。清单 提供程序缓存期间 时间由cachingPeriod给出。中 这个时期,同一个List实例是 返回相同类型的 供应商。在此期间,一个新的 构造并返回实例。 返回的List是不可变的。
因此,似乎这个类在缓存中保存了提供者列表,在一段时间后将重新加载。您可以使用方法setCachingPeriod(int seconds)
将此期间设置为自定义值。只要我知道,默认缓存时间设置为60秒。
例如,要每秒刷新此缓存,您可以将此行添加到您的代码中:
com.sun.media.sound.JDK13Services.setCachingPeriod(1);
请注意,此解决方案使用Sun专属类,因此无法100%移植。
答案 1 :(得分:3)
在我的工作PC或任何类型的Mac上缺少任何MIDI设备,我怀疑我是否能够正确测试它,但是...
MidiSystem类似乎使用com.sun.media.sound.JDK13Services.getProviders(Class providerClass)
来查找系统上的设备列表。 API docs for this class表示在cachingPeriod
之外的连续调用中重新创建列表,可以通过调用setCachingPeriod(int seconds)
方便地设置。
运气好的话,你可以在应用程序开始时调用它一次,并将其设置为5秒或者其他东西,它会神奇地起作用。但是,文档还声明“此方法仅用于测试。”因此我不确定这种方法的效果如何。
希望这足以让你开始,在此期间我会继续探索,看看我是否能找到更清洁的方法来做到这一点。
答案 2 :(得分:0)
我也回答了Update list of Midi Devices in Java,但是对于那些热衷于此的人们来说,现在有一个可以正确支持此功能的图书馆:https://github.com/DerekCook/CoreMidi4J
该库充当MIDI子系统的设备提供者,因此它基本上是一个插件,您所有现有的代码都可以使用。
我不是作者,但是它可以很好地满足我的需求,并且经过大量的搜索才能找到,因此我将其发布在这里,供其他遇到此问题的人使用。
答案 3 :(得分: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();
}
}
答案 4 :(得分:-1)
听起来这可能是一个操作系统特定的bug,但我可以想到一个解决方法。
在java中,您可以对操作系统运行外部命令。 (一个快速的谷歌,给了我这个例子http://www.javafaq.nu/java-example-code-186.html它看起来很好,并给你的想法)。
在检查新设备时,您可以发送外部命令来运行一个简单的java程序,该程序使用MidiSystem.getMidiDeviceInfo()快速查询midi设备并将结果输出到文本文件,或者您可以从BufferedReader对象获取输出
还要记住,用于查询midi设备的外部程序不必用Java编写,因为Java会导致更多问题。或者,您可以只查询连接设备的操作系统,并使用grep过滤结果。
希望这有帮助。