Java 中的 Midi 设备更新列表
Posted
技术标签:
【中文标题】Java 中的 Midi 设备更新列表【英文标题】:Update list of Midi Devices in Java 【发布时间】:2016-12-13 14:32:38 【问题描述】:我在一个基于 MIDI 的 Java 项目上工作,并且努力刷新 Midi 设备列表。
据我所知MidiSystem.getMidiDeviceInfo();
应该给我一个Info[]
数组。然而,对我来说什么也没发生。插入或拔出新设备时,Array 中的 Objects 保持不变,长度也保持不变。
搜索 *** 将我带到 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
的处理方式。但这只是个人喜好。
只是一些即兴的想法,因为我无法在现实生活中测试它们——一种方法是设置一个客户端服务器系统,它是两个程序,其中一个可以终止;一个检查 - 如果需要,关闭 - 并将数据传输给另一个
【参考方案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();
【讨论】:
以上是关于Java 中的 Midi 设备更新列表的主要内容,如果未能解决你的问题,请参考以下文章
从 C# 控制台应用程序枚举 UWP MIDI API 设备?
使用带有 partitionByInstrument() 的 music21 读取 MIDI 文件以获取返回空列表的音符和和弦