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 设备更新列表的主要内容,如果未能解决你的问题,请参考以下文章

Java 从 MIDI 序列中获取乐器列表

从 C# 控制台应用程序枚举 UWP MIDI API 设备?

MIDI,如何获取小节和音符

使用带有 partitionByInstrument() 的 music21 读取 MIDI 文件以获取返回空列表的音符和和弦

遍历列表并减去前面的元素会产生不需要的结果

如何使用 Java 在 Midi 文件中列出乐器名称?