SkillAgentSearch skills...

CoreMidi4J

Core MIDI Service provider Interace (SPI) for Java 1.7 and above on OS X

Install / Use

/learn @DerekCook/CoreMidi4J
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CoreMidi4J

Core MIDI Service Provider Interface (SPI) for Java 1.7 and above on OS X, safe to load and interact with on any platform. (The SPI will simply not try to provide devices on platforms where they are not needed.)

Derek created CoreMidi4J as to our knowledge there is currently no Mac Java MIDI implementation under active development that properly supports sending System Exclusive messages, which still have not been fixed in the Java core distribution.

In collaboration with James, we added support for hot-swapping MIDI devices (the standard JAVA MIDI implementation will only recognize devices which were already connected when Java started), and proper support for inbound and outbound MIDI event timestamps, which can extend over network MIDI sessions thanks to CoreMIDI’s support for them.

Hopefully one day third-party SPIs like CoreMidi4J will not be required, but until then we are making this available.

For years we both used MMJ, but that appears to longer be under development and it does not work with later Java Runtimes. After looking around for a replacement, we decided it was necessary to create our own “lightweight” SPI, which Derek accomplished in 2015, and that we would make it publicly available for others to contribute to.

CoreMidi4J has been heavily used in some of our own projects for several years, and after resolving the last known outstanding issue we labeled it version 1.0. Over the next few years an occasional issue was discovered and fixed, or a new feature was thought up and added, leading to a new release. Feedback on any new problems or issues is always welcome.

Using with Java 24 and Above

If you plan to use CoreMIDI4J on Java 24 and above please be aware of JEP 472: Prepare to Restrict the Use of JNI which is described further in Quality Outreach Heads-up - JDK 24: Prepares Restricted Native Access.

This JEP requires the use of a command line option when launching your Java application to disable a warning that native methods are being called. At present this is currently a warning, but future Java versions will not permit access to native methods without this command line option.

As CoreMIDI4J needs to call CoreMIDI services via Java Native Interface (JNI) then native access will always be required by CoreMID4J.

Installation

The recommended approach for use as a library is to embed CoreMidi4J in your project and have its native code loaded automatically when on the OS X platform, so that end users do not need to worry about installing anything.

It is also still possible to download and install CoreMidi4J separately, to use it with applications that did not embed it (or if your own project does not use the Maven dependency-management ecosystem).

License

Using CoreMidi4J

:musical_keyboard: New to Jave MIDI? CoreMidi4J is designed to be transparently compatible with the standard Java MIDI API, so we don’t provide examples or explanations of how to use that. Oracle offers a tutorial and API documentation.

Once installed, if all you want to do is use the enhanced MIDI devices provided by CoreMidi4J, all you have to do is use the normal Java MIDI API, but choose CoreMidi4J’s device implementations instead of the ones provided by the native MIDI SPI. You will be able to identify them because their names will begin with CoreMidi4J -. These devices will:

  • properly support System Exclusive messages,
  • provide, translate, and respect CoreMidi timestamps on MIDI events, and
  • the list of devices available will correctly update even if you connect or detach devices after Java is already running.

If you are using an application written by someone else, and are not making any changes to it, then this is the best you can do; you will need to remember to choose the right version of each MIDI device that you want to use.

If you are writing your own program, or willing to change the source code of the program you are using, you can make things even easier by filtering out the broken MIDI devices, and only showing the ones that work:

Filtering Out Broken MIDI Devices

If your application runs on Macs as well as other platforms, you can ensure that your users only ever see MIDI devices whose implementations work properly, by using the getMidiDeviceInfo() method provided by uk.co.xfactorylibrarians.coremidi4j.CoreMidiDeviceProvider instead of the one in javax.sound.midi.MidiSystem. The CoreMidi4J version works on any platform. If you call it on anything but a Mac, it simply gives you the same result you would get from the standard method. On the Mac, it filters out any devices which have broken SysEx implementations, and returns the CoreMidi4J versions instead.

So to give your users the best experience possible, simply embed CoreMidi4J, and use its implementation of getMidiDeviceInfo() wherever you would otherwise have used the standard one, and your users will always only see working MIDI devices.

Watching for MIDI Device Changes

If you would like to be able to automatically update your user interface when the user connects, disconnects, or powers on/off a MIDI device, you can call addNotificationListener(listener) (also provided by the CoreMidiDeviceProvider class). This will call register a listener method to be called whenever such changes to the MIDI environment occur.

NOTE: If you use addNotificationListener on a non-macOS system, it needs to periodically scan the MIDI environment on a background thread. We have learned that the version of getMidiDeviceInfo in javax.sound.MidiSystem is not thread-safe, and if more than one thread uses it simultaneously, it will return invalid devices which throw exceptions when they are used. Because of that, you should only use the version of getMidiDeviceInfo provided by CoreMidiDeviceProvider, which uses synchronization to avoid this problem. Even if you are not using addNotificationListener, our version of the method is safer if you are using multiple threads for your own purposes.

For more details, you can consult the CoreMidi4J API documentation or even the source code, or simply keep reading.

Here is an example of what running the Example class (listed below) on a Mac, with CoreMidi4J in the classpath, produces. Notice that other than the sequencer and synthesizer, the only MIDI devices returned are the inputs and outputs offered by CoreMidi4J:

java -cp coremidi4j-1.1.jar:. Example
Working MIDI Devices:
  CoreMIDI4J - Bus 1
  CoreMIDI4J - Network
  CoreMIDI4J - Live Port
  CoreMIDI4J - User Port
  CoreMIDI4J - Traktor Virtual Output
  CoreMIDI4J - Bus 1
  CoreMIDI4J - Network
  CoreMIDI4J - Live Port
  CoreMIDI4J - User Port
  Gervill
  Real Time Sequencer
CoreMIDI4J native library is running.
Watching for MIDI environment changes for thirty seconds.
The MIDI environment has changed.
The MIDI environment has changed.

During the thirty seconds the code was running, a MIDI device was plugged in and later unplugged, demonstrating the fact that CoreMidi4J can adapt to changes in the MIDI environment, and notify the host application about them.

Sample Code

This class shows an example of how to ask CoreMidi4J for a list of only properly-working MIDI devices (filtering out the broken ones provided by the standard Mac OS X MIDI implementation). It also shows how to check whether the native library is available (which will only be true when you are running on a Mac), and how to ask to be notified whenever there is a change in the MIDI environment (in other words, a new device has become available, or an existing device has been removed, which works on any platform starting with CoreMidi4J version 1.4):

import uk.co.xfactorylibrarians.coremidi4j.CoreMidiDeviceProvider;
import uk.co.xfactorylibrarians.coremidi4j.CoreMidiNotification;
import uk.co.xfactorylibrarians.coremidi4j.CoreMidiException;
import javax.sound.midi.MidiDevice;

public class Example {

    public static boolean isCoreMidiLoaded() throws CoreMidiException {
        return CoreMidiDeviceProvider.isLibraryLoaded();
    }

    public static void watchForMidiChanges() throws CoreMidiException {
        CoreMidiDeviceProvider.addNotificationListener(new CoreMidiNotification() {
                public void midiSystemUpdated() {
                    System.out.println("The MIDI environment has changed.");
                }
            });
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Working MIDI Devices:");
        for (javax.sound.midi.MidiDevice.Info device : CoreMidiDeviceProvider.getMidiDeviceInfo()) {
            System.out.println("  " + device);
        }

        if (Example.isCoreMidiLoaded()) {
            System.out.println("CoreMIDI4J native library is running.");
        } else {
            System.out.println("CoreMIDI4J native library is not available.");
        }

        watchFo
View on GitHub
GitHub Stars59
CategoryDevelopment
Updated5mo ago
Forks15

Languages

Java

Security Score

92/100

Audited on Oct 28, 2025

No findings