Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 008fcbd1 authored by Robert Wu's avatar Robert Wu Committed by Android (Google) Code Review
Browse files

Merge "Add MIDI 2.0 host mode support"

parents 24672908 a936a251
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -25710,6 +25710,7 @@ package android.media.midi {
  public final class MidiDeviceInfo implements android.os.Parcelable {
    method public int describeContents();
    method public int getDefaultProtocol();
    method public int getId();
    method public int getInputPortCount();
    method public int getOutputPortCount();
@@ -25726,6 +25727,14 @@ package android.media.midi {
    field public static final String PROPERTY_SERIAL_NUMBER = "serial_number";
    field public static final String PROPERTY_USB_DEVICE = "usb_device";
    field public static final String PROPERTY_VERSION = "version";
    field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3; // 0x3
    field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4; // 0x4
    field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1; // 0x1
    field public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2; // 0x2
    field public static final int PROTOCOL_UMP_MIDI_2_0 = 17; // 0x11
    field public static final int PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18; // 0x12
    field public static final int PROTOCOL_UMP_USE_MIDI_CI = 0; // 0x0
    field public static final int PROTOCOL_UNKNOWN = -1; // 0xffffffff
    field public static final int TYPE_BLUETOOTH = 3; // 0x3
    field public static final int TYPE_USB = 1; // 0x1
    field public static final int TYPE_VIRTUAL = 2; // 0x2
@@ -25767,10 +25776,14 @@ package android.media.midi {
  public final class MidiManager {
    method public android.media.midi.MidiDeviceInfo[] getDevices();
    method @NonNull public java.util.Collection<android.media.midi.MidiDeviceInfo> getDevicesForTransport(int);
    method public void openBluetoothDevice(android.bluetooth.BluetoothDevice, android.media.midi.MidiManager.OnDeviceOpenedListener, android.os.Handler);
    method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.OnDeviceOpenedListener, android.os.Handler);
    method public void registerDeviceCallback(android.media.midi.MidiManager.DeviceCallback, android.os.Handler);
    method public void registerDeviceCallbackForTransport(@NonNull android.media.midi.MidiManager.DeviceCallback, @Nullable android.os.Handler, int);
    method public void unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
    field public static final int TRANSPORT_MIDI_BYTE_STREAM = 1; // 0x1
    field public static final int TRANSPORT_UNIVERSAL_MIDI_PACKETS = 2; // 0x2
  }
  public static class MidiManager.DeviceCallback {
+3 −1
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ interface IMidiManager
{
    MidiDeviceInfo[] getDevices();

    MidiDeviceInfo[] getDevicesForTransport(int transport);

    // for device creation & removal notifications
    void registerListener(IBinder clientToken, in IMidiDeviceListener listener);
    void unregisterListener(IBinder clientToken, in IMidiDeviceListener listener);
@@ -43,7 +45,7 @@ interface IMidiManager
    // for registering built-in MIDI devices
    MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts,
            int numOutputPorts, in String[] inputPortNames, in String[] outputPortNames,
            in Bundle properties, int type);
            in Bundle properties, int type, int defaultProtocol);

    // for unregistering built-in MIDI devices
    void unregisterDeviceServer(in IMidiDeviceServer server);
+133 −7
Original line number Diff line number Diff line
@@ -16,11 +16,15 @@

package android.media.midi;

import android.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * This class contains information to describe a MIDI device.
 * For now we only have information that can be retrieved easily for USB devices,
@@ -53,6 +57,110 @@ public final class MidiDeviceInfo implements Parcelable {
     */
    public static final int TYPE_BLUETOOTH = 3;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use UMP to negotiate with the device with MIDI-CI.
     * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_USE_MIDI_CI = 0;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 1.0 through UMP with packet sizes up to 64 bits.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS = 1;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 1.0 through UMP with packet sizes up to 64 bits and jitter reduction timestamps.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS = 2;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 1.0 through UMP with packet sizes up to 128 bits.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS = 3;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 1.0 through UMP with packet sizes up to 128 bits and jitter reduction timestamps.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS = 4;

    /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 2.0 through UMP.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_2_0 = 17;

     /**
     * Constant representing a default protocol with Universal MIDI Packets (UMP).
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * All UMP data should be a multiple of 4 bytes.
     * Use MIDI 2.0 through UMP and jitter reduction timestamps.
     * Call {@link MidiManager#getDevicesForTransport} with parameter
     * {@link MidiManager#TRANSPORT_UNIVERSAL_MIDI_PACKETS} to get devices with this transport.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UMP_MIDI_2_0_AND_JRTS = 18;

    /**
     * Constant representing a device with an unknown default protocol.
     * If Universal MIDI Packets (UMP) are needed, use MIDI-CI through MIDI 1.0.
     * UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
     * MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
     * @see MidiDeviceInfo#getDefaultProtocol
     */
    public static final int PROTOCOL_UNKNOWN = -1;

    /**
     * @see MidiDeviceInfo#getDefaultProtocol
     * @hide
     */
    @IntDef(prefix = { "PROTOCOL_" }, value = {
            PROTOCOL_UMP_USE_MIDI_CI,
            PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS,
            PROTOCOL_UMP_MIDI_1_0_UP_TO_64_BITS_AND_JRTS,
            PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS,
            PROTOCOL_UMP_MIDI_1_0_UP_TO_128_BITS_AND_JRTS,
            PROTOCOL_UMP_MIDI_2_0,
            PROTOCOL_UMP_MIDI_2_0_AND_JRTS,
            PROTOCOL_UNKNOWN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DefaultProtocol {}

    /**
     * Bundle key for the device's user visible name property.
     * The value for this property is of type {@link java.lang.String}.
@@ -196,6 +304,7 @@ public final class MidiDeviceInfo implements Parcelable {
    private final String[] mOutputPortNames;
    private final Bundle mProperties;
    private final boolean mIsPrivate;
    private final int mDefaultProtocol;

    /**
     * MidiDeviceInfo should only be instantiated by MidiService implementation
@@ -203,7 +312,7 @@ public final class MidiDeviceInfo implements Parcelable {
     */
    public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts,
            String[] inputPortNames, String[] outputPortNames, Bundle properties,
            boolean isPrivate) {
            boolean isPrivate, int defaultProtocol) {
        // Check num ports for out-of-range values. Typical values will be
        // between zero and three. More than 16 would be very unlikely
        // because the port index field in the USB packet is only 4 bits.
@@ -234,6 +343,7 @@ public final class MidiDeviceInfo implements Parcelable {
        }
        mProperties = properties;
        mIsPrivate = isPrivate;
        mDefaultProtocol = defaultProtocol;
    }

    /**
@@ -312,6 +422,18 @@ public final class MidiDeviceInfo implements Parcelable {
        return mIsPrivate;
    }

    /**
     * Returns the default protocol. For most devices, this will be {@link #PROTOCOL_UNKNOWN}.
     * Returning {@link #PROTOCOL_UNKNOWN} is not an error; the device just doesn't support
     * Universal MIDI Packets by default.
     *
     * @return the device's default protocol.
     */
    @DefaultProtocol
    public int getDefaultProtocol() {
        return mDefaultProtocol;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof MidiDeviceInfo) {
@@ -331,11 +453,12 @@ public final class MidiDeviceInfo implements Parcelable {
        // This is a hack to force the mProperties Bundle to unparcel so we can
        // print all the names and values.
        mProperties.getString(PROPERTY_NAME);
        return ("MidiDeviceInfo[mType=" + mType +
                ",mInputPortCount=" + mInputPortCount +
                ",mOutputPortCount=" + mOutputPortCount +
                ",mProperties=" + mProperties +
                ",mIsPrivate=" + mIsPrivate);
        return ("MidiDeviceInfo[mType=" + mType
                + ",mInputPortCount=" + mInputPortCount
                + ",mOutputPortCount=" + mOutputPortCount
                + ",mProperties=" + mProperties
                + ",mIsPrivate=" + mIsPrivate
                + ",mDefaultProtocol=" + mDefaultProtocol);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<MidiDeviceInfo> CREATOR =
@@ -349,10 +472,12 @@ public final class MidiDeviceInfo implements Parcelable {
            String[] inputPortNames = in.createStringArray();
            String[] outputPortNames = in.createStringArray();
            boolean isPrivate = (in.readInt() == 1);
            int defaultProtocol = in.readInt();
            Bundle basicPropertiesIgnored = in.readBundle();
            Bundle properties = in.readBundle();
            return new MidiDeviceInfo(type, id, inputPortCount, outputPortCount,
                    inputPortNames, outputPortNames, properties, isPrivate);
                    inputPortNames, outputPortNames, properties, isPrivate,
                    defaultProtocol);
        }

        public MidiDeviceInfo[] newArray(int size) {
@@ -390,6 +515,7 @@ public final class MidiDeviceInfo implements Parcelable {
        parcel.writeStringArray(mInputPortNames);
        parcel.writeStringArray(mOutputPortNames);
        parcel.writeInt(mIsPrivate ? 1 : 0);
        parcel.writeInt(mDefaultProtocol);
        // "Basic" properties only contain properties of primitive types
        // and thus can be read back by native code. "Extra" properties is
        // a superset that contains all properties.
+143 −27
Original line number Diff line number Diff line
@@ -16,18 +16,25 @@

package android.media.midi;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.SystemService;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

/**
@@ -38,6 +45,39 @@ import java.util.concurrent.ConcurrentHashMap;
public final class MidiManager {
    private static final String TAG = "MidiManager";

    /**
     * Constant representing MIDI devices.
     * These devices do NOT support Universal MIDI Packets by default.
     * These support the original MIDI 1.0 byte stream.
     * When communicating to a USB device, a raw byte stream will be padded for USB.
     * Likewise, for a Bluetooth device, the raw bytes will be converted for Bluetooth.
     * For virtual devices, the byte stream will be passed directly.
     * If Universal MIDI Packets are needed, please use MIDI-CI.
     * @see MidiManager#getDevicesForTransport
     */
    public static final int TRANSPORT_MIDI_BYTE_STREAM = 1;

    /**
     * Constant representing Universal MIDI devices.
     * These devices do support Universal MIDI Packets (UMP) by default.
     * When sending data to these devices, please send UMP.
     * Packets should always be a multiple of 4 bytes.
     * UMP is defined in the USB MIDI 2.0 spec. Please read the standard for more info.
     * @see MidiManager#getDevicesForTransport
     */
    public static final int TRANSPORT_UNIVERSAL_MIDI_PACKETS = 2;

    /**
     * @see MidiManager#getDevicesForTransport
     * @hide
     */
    @IntDef(prefix = { "TRANSPORT_" }, value = {
            TRANSPORT_MIDI_BYTE_STREAM,
            TRANSPORT_UNIVERSAL_MIDI_PACKETS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Transport {}

    /**
     * Intent for starting BluetoothMidiService
     * @hide
@@ -68,14 +108,17 @@ public final class MidiManager {
    private class DeviceListener extends IMidiDeviceListener.Stub {
        private final DeviceCallback mCallback;
        private final Handler mHandler;
        private final int mTransport;

        public DeviceListener(DeviceCallback callback, Handler handler) {
        DeviceListener(DeviceCallback callback, Handler handler, int transport) {
            mCallback = callback;
            mHandler = handler;
            mTransport = transport;
        }

        @Override
        public void onDeviceAdded(MidiDeviceInfo device) {
            if (shouldInvokeCallback(device)) {
                if (mHandler != null) {
                    final MidiDeviceInfo deviceF = device;
                    mHandler.post(new Runnable() {
@@ -87,9 +130,11 @@ public final class MidiManager {
                    mCallback.onDeviceAdded(device);
                }
            }
        }

        @Override
        public void onDeviceRemoved(MidiDeviceInfo device) {
            if (shouldInvokeCallback(device)) {
                if (mHandler != null) {
                    final MidiDeviceInfo deviceF = device;
                    mHandler.post(new Runnable() {
@@ -101,6 +146,7 @@ public final class MidiManager {
                    mCallback.onDeviceRemoved(device);
                }
            }
        }

        @Override
        public void onDeviceStatusChanged(MidiDeviceStatus status) {
@@ -115,6 +161,25 @@ public final class MidiManager {
                mCallback.onDeviceStatusChanged(status);
            }
        }

        /**
         * Used to figure out whether callbacks should be invoked. Only invoke callbacks of
         * the correct type.
         *
         * @param MidiDeviceInfo the device to check
         * @return whether to invoke a callback
         */
        private boolean shouldInvokeCallback(MidiDeviceInfo device) {
            // UMP devices have protocols that are not PROTOCOL_UNKNOWN
            if (mTransport == TRANSPORT_UNIVERSAL_MIDI_PACKETS) {
                return (device.getDefaultProtocol() != MidiDeviceInfo.PROTOCOL_UNKNOWN);
            } else if (mTransport == TRANSPORT_MIDI_BYTE_STREAM) {
                return (device.getDefaultProtocol() == MidiDeviceInfo.PROTOCOL_UNKNOWN);
            } else {
                Log.e(TAG, "Invalid transport type: " + mTransport);
                return false;
            }
        }
    }

    /**
@@ -167,8 +232,10 @@ public final class MidiManager {
    }

    /**
     * Registers a callback to receive notifications when MIDI devices are added and removed.
     *
     * Registers a callback to receive notifications when MIDI 1.0 devices are added and removed.
     * These are devices that do not default to Universal MIDI Packets. To register for a callback
     * for those, call {@link #registerDeviceCallbackForTransport} instead.

     * The {@link  DeviceCallback#onDeviceStatusChanged} method will be called immediately
     * for any devices that have open ports. This allows applications to know which input
     * ports are already in use and, therefore, unavailable.
@@ -182,7 +249,30 @@ public final class MidiManager {
     *                callback is unspecified.
     */
    public void registerDeviceCallback(DeviceCallback callback, Handler handler) {
        DeviceListener deviceListener = new DeviceListener(callback, handler);
        registerDeviceCallbackForTransport(callback, handler, TRANSPORT_MIDI_BYTE_STREAM);
    }

    /**
     * Registers a callback to receive notifications when MIDI devices are added and removed
     * for a specific transport type.
     *
     * The {@link  DeviceCallback#onDeviceStatusChanged} method will be called immediately
     * for any devices that have open ports. This allows applications to know which input
     * ports are already in use and, therefore, unavailable.
     *
     * Applications should call {@link #getDevicesForTransport} before registering the callback
     * to get a list of devices already added.
     *
     * @param callback a {@link DeviceCallback} for MIDI device notifications
     * @param handler The {@link android.os.Handler Handler} that will be used for delivering the
     *                device notifications. If handler is null, then the thread used for the
     *                callback is unspecified.
     * @param transport The transport to be used. This is either TRANSPORT_MIDI_BYTE_STREAM or
     *            TRANSPORT_UNIVERSAL_MIDI_PACKETS.
     */
    public void registerDeviceCallbackForTransport(@NonNull DeviceCallback callback,
            @Nullable Handler handler, @Transport int transport) {
        DeviceListener deviceListener = new DeviceListener(callback, handler, transport);
        try {
            mService.registerListener(mToken, deviceListener);
        } catch (RemoteException e) {
@@ -208,9 +298,11 @@ public final class MidiManager {
    }

    /**
     * Gets the list of all connected MIDI devices.
     * Gets a list of connected MIDI devices. This returns all devices that do
     * not default to Universal MIDI Packets. To get those instead, please call
     * {@link #getDevicesForTransport} instead.
     *
     * @return an array of all MIDI devices
     * @return an array of MIDI devices
     */
    public MidiDeviceInfo[] getDevices() {
        try {
@@ -220,6 +312,29 @@ public final class MidiManager {
        }
    }

    /**
     * Gets a list of connected MIDI devices by transport. TRANSPORT_MIDI_BYTE_STREAM
     * is used for MIDI 1.0 and is the most common.
     * For devices with built in Universal MIDI Packet support, use
     * TRANSPORT_UNIVERSAL_MIDI_PACKETS instead.
     *
     * @param transport The transport to be used. This is either TRANSPORT_MIDI_BYTE_STREAM or
     *                  TRANSPORT_UNIVERSAL_MIDI_PACKETS.
     * @return a collection of MIDI devices
     */
    public @NonNull Collection<MidiDeviceInfo> getDevicesForTransport(@Transport int transport) {
        try {
            MidiDeviceInfo[] devices = mService.getDevicesForTransport(transport);
            Collection<MidiDeviceInfo> out = new ArrayList<MidiDeviceInfo>(devices.length);
            for (int i = 0; i < devices.length; i++) {
                out.add(devices[i]);
            }
            return out;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private void sendOpenDeviceResponse(final MidiDevice device,
            final OnDeviceOpenedListener listener, Handler handler) {
        if (handler != null) {
@@ -311,13 +426,14 @@ public final class MidiManager {
    /** @hide */
    public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
            int numOutputPorts, String[] inputPortNames, String[] outputPortNames,
            Bundle properties, int type, MidiDeviceServer.Callback callback) {
            Bundle properties, int type, int defaultProtocol,
            MidiDeviceServer.Callback callback) {
        try {
            MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers,
                    numOutputPorts, callback);
            MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(),
                    inputPortReceivers.length, numOutputPorts, inputPortNames, outputPortNames,
                    properties, type);
                    properties, type, defaultProtocol);
            if (deviceInfo == null) {
                Log.e(TAG, "registerVirtualDevice failed");
                return null;
+41 −0
Original line number Diff line number Diff line
@@ -405,5 +405,46 @@ apps using the
<a href="#get_list_of_already_plugged_in_entities">MIDI device discovery calls described above</a>.
</p>

<h1 id=using_midi_2_0_over_usb>Using MIDI 2.0 over USB</h1>

<p>An app can use MIDI 2.0 over USB starting in Android T. MIDI 2.0 packets are embedded in
Universal MIDI Packets, or UMP for short. A MIDI 2.0 USB device should create two interfaces,
one endpoint that accepts only MIDI 1.0 packets and one that accepts only UMP packets.
For more info about MIDI 2.0 and UMP, please read the MIDI 2.0 USB spec.</p>

<p>MidiManager.getDevices() would simply return the 1.0 interface. This interface should work
exactly the same as before. In order to use the new UMP interface, retrieve the device with the
following code snippet.</p>

<pre class=prettyprint>
Collection&#60;MidiDeviceInfo&#62; universalDeviceInfos = midiManager.getDevicesForTransport(
        MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS);
</pre>

<p>UMP Packets are always in multiple of 4 bytes. For each set of 4 bytes, they are sent in network
order. Compare the following NoteOn code snippet with the NoteOn code snippet above. </p>

<pre class=prettyprint>
byte[] buffer = new byte[32];
int numBytes = 0;
int channel = 3; // MIDI channels 1-16 are encoded as 0-15.
int group = 0;
buffer[numBytes++] = (byte)(0x20 + group); // MIDI 1.0 voice message
buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
buffer[numBytes++] = (byte)60; // pitch is middle C
buffer[numBytes++] = (byte)127; // max velocity
int offset = 0;
// post is non-blocking
inputPort.send(buffer, offset, numBytes);
</pre>

<p>MIDI 2.0 messages can be sent through UMP after negotiating with the device. This is called
MIDI-CI and is documented in the MIDI 2.0 spec. Some USB devices support pre-negotiated MIDI 2.0.
For a MidiDeviceInfo, you can query the defaultProtocol.</p>

<pre class=prettyprint>
int defaultProtocol = info.getDefaultProtocol();
</pre>

</body>
</html>
Loading