Merge "MidiManager: Address API Council feedback:" into mnc-dev

This commit is contained in:
Mike Lockwood
2015-05-12 22:02:43 +00:00
committed by Android (Google) Code Review
19 changed files with 211 additions and 183 deletions

View File

@@ -17259,7 +17259,7 @@ package android.media.midi {
method public int getId();
method public int getInputPortCount();
method public int getOutputPortCount();
method public android.media.midi.MidiDeviceInfo.PortInfo[] getPortList();
method public android.media.midi.MidiDeviceInfo.PortInfo[] getPorts();
method public android.os.Bundle getProperties();
method public int getType();
method public boolean isPrivate();
@@ -17307,22 +17307,17 @@ package android.media.midi {
public final class MidiInputPort extends android.media.midi.MidiReceiver implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public final int getPortNumber();
method public void onReceive(byte[], int, int, long) throws java.io.IOException;
method public void onSend(byte[], int, int, long) throws java.io.IOException;
}
public final class MidiManager {
method public android.media.midi.MidiDeviceInfo[] getDeviceList();
method public void openBluetoothDevice(android.bluetooth.BluetoothDevice, android.media.midi.MidiManager.BluetoothOpenCallback, android.os.Handler);
method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.DeviceOpenCallback, android.os.Handler);
method public android.media.midi.MidiDeviceInfo[] getDevices();
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 unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
}
public static abstract class MidiManager.BluetoothOpenCallback {
ctor public MidiManager.BluetoothOpenCallback();
method public abstract void onDeviceOpened(android.bluetooth.BluetoothDevice, android.media.midi.MidiDevice);
}
public static class MidiManager.DeviceCallback {
ctor public MidiManager.DeviceCallback();
method public void onDeviceAdded(android.media.midi.MidiDeviceInfo);
@@ -17330,31 +17325,34 @@ package android.media.midi {
method public void onDeviceStatusChanged(android.media.midi.MidiDeviceStatus);
}
public static abstract class MidiManager.DeviceOpenCallback {
ctor public MidiManager.DeviceOpenCallback();
method public abstract void onDeviceOpened(android.media.midi.MidiDeviceInfo, android.media.midi.MidiDevice);
public static abstract interface MidiManager.OnDeviceOpenedListener {
method public abstract void onDeviceOpened(android.media.midi.MidiDevice);
}
public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public void connect(android.media.midi.MidiReceiver);
method public void disconnect(android.media.midi.MidiReceiver);
method public final int getPortNumber();
method public void onConnect(android.media.midi.MidiReceiver);
method public void onDisconnect(android.media.midi.MidiReceiver);
}
public abstract class MidiReceiver {
ctor public MidiReceiver();
ctor public MidiReceiver(int);
method public void flush() throws java.io.IOException;
method public int getMaxMessageSize();
method public abstract void onReceive(byte[], int, int, long) throws java.io.IOException;
method public final int getMaxMessageSize();
method public void onFlush() throws java.io.IOException;
method public abstract void onSend(byte[], int, int, long) throws java.io.IOException;
method public void send(byte[], int, int) throws java.io.IOException;
method public void sendWithTimestamp(byte[], int, int, long) throws java.io.IOException;
method public void send(byte[], int, int, long) throws java.io.IOException;
}
public abstract class MidiSender {
ctor public MidiSender();
method public abstract void connect(android.media.midi.MidiReceiver);
method public abstract void disconnect(android.media.midi.MidiReceiver);
method public void connect(android.media.midi.MidiReceiver);
method public void disconnect(android.media.midi.MidiReceiver);
method public abstract void onConnect(android.media.midi.MidiReceiver);
method public abstract void onDisconnect(android.media.midi.MidiReceiver);
}
}

View File

@@ -18562,7 +18562,7 @@ package android.media.midi {
method public int getId();
method public int getInputPortCount();
method public int getOutputPortCount();
method public android.media.midi.MidiDeviceInfo.PortInfo[] getPortList();
method public android.media.midi.MidiDeviceInfo.PortInfo[] getPorts();
method public android.os.Bundle getProperties();
method public int getType();
method public boolean isPrivate();
@@ -18610,22 +18610,17 @@ package android.media.midi {
public final class MidiInputPort extends android.media.midi.MidiReceiver implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public final int getPortNumber();
method public void onReceive(byte[], int, int, long) throws java.io.IOException;
method public void onSend(byte[], int, int, long) throws java.io.IOException;
}
public final class MidiManager {
method public android.media.midi.MidiDeviceInfo[] getDeviceList();
method public void openBluetoothDevice(android.bluetooth.BluetoothDevice, android.media.midi.MidiManager.BluetoothOpenCallback, android.os.Handler);
method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.DeviceOpenCallback, android.os.Handler);
method public android.media.midi.MidiDeviceInfo[] getDevices();
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 unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
}
public static abstract class MidiManager.BluetoothOpenCallback {
ctor public MidiManager.BluetoothOpenCallback();
method public abstract void onDeviceOpened(android.bluetooth.BluetoothDevice, android.media.midi.MidiDevice);
}
public static class MidiManager.DeviceCallback {
ctor public MidiManager.DeviceCallback();
method public void onDeviceAdded(android.media.midi.MidiDeviceInfo);
@@ -18633,31 +18628,34 @@ package android.media.midi {
method public void onDeviceStatusChanged(android.media.midi.MidiDeviceStatus);
}
public static abstract class MidiManager.DeviceOpenCallback {
ctor public MidiManager.DeviceOpenCallback();
method public abstract void onDeviceOpened(android.media.midi.MidiDeviceInfo, android.media.midi.MidiDevice);
public static abstract interface MidiManager.OnDeviceOpenedListener {
method public abstract void onDeviceOpened(android.media.midi.MidiDevice);
}
public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public void connect(android.media.midi.MidiReceiver);
method public void disconnect(android.media.midi.MidiReceiver);
method public final int getPortNumber();
method public void onConnect(android.media.midi.MidiReceiver);
method public void onDisconnect(android.media.midi.MidiReceiver);
}
public abstract class MidiReceiver {
ctor public MidiReceiver();
ctor public MidiReceiver(int);
method public void flush() throws java.io.IOException;
method public int getMaxMessageSize();
method public abstract void onReceive(byte[], int, int, long) throws java.io.IOException;
method public final int getMaxMessageSize();
method public void onFlush() throws java.io.IOException;
method public abstract void onSend(byte[], int, int, long) throws java.io.IOException;
method public void send(byte[], int, int) throws java.io.IOException;
method public void sendWithTimestamp(byte[], int, int, long) throws java.io.IOException;
method public void send(byte[], int, int, long) throws java.io.IOException;
}
public abstract class MidiSender {
ctor public MidiSender();
method public abstract void connect(android.media.midi.MidiReceiver);
method public abstract void disconnect(android.media.midi.MidiReceiver);
method public void connect(android.media.midi.MidiReceiver);
method public void disconnect(android.media.midi.MidiReceiver);
method public abstract void onConnect(android.media.midi.MidiReceiver);
method public abstract void onDisconnect(android.media.midi.MidiReceiver);
}
}

View File

@@ -27,7 +27,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* This class subclasses {@link android.media.midi.MidiReceiver} and dispatches any data it receives
* to its receiver list. Any receivers that throw an exception upon receiving data will
* be automatically removed from the receiver list, but no IOException will be returned
* from the dispatcher's {@link android.media.midi.MidiReceiver#onReceive} in that case.
* from the dispatcher's {@link android.media.midi.MidiReceiver#onSend} in that case.
*/
public final class MidiDispatcher extends MidiReceiver {
@@ -35,21 +35,13 @@ public final class MidiDispatcher extends MidiReceiver {
= new CopyOnWriteArrayList<MidiReceiver>();
private final MidiSender mSender = new MidiSender() {
/**
* Called to connect a {@link android.media.midi.MidiReceiver} to the sender
*
* @param receiver the receiver to connect
*/
public void connect(MidiReceiver receiver) {
@Override
public void onConnect(MidiReceiver receiver) {
mReceivers.add(receiver);
}
/**
* Called to disconnect a {@link android.media.midi.MidiReceiver} from the sender
*
* @param receiver the receiver to disconnect
*/
public void disconnect(MidiReceiver receiver) {
@Override
public void onDisconnect(MidiReceiver receiver) {
mReceivers.remove(receiver);
}
};
@@ -73,10 +65,10 @@ public final class MidiDispatcher extends MidiReceiver {
}
@Override
public void onReceive(byte[] msg, int offset, int count, long timestamp) throws IOException {
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
for (MidiReceiver receiver : mReceivers) {
try {
receiver.sendWithTimestamp(msg, offset, count, timestamp);
receiver.send(msg, offset, count, timestamp);
} catch (IOException e) {
// if the receiver fails we remove the receiver but do not propagate the exception
mReceivers.remove(receiver);
@@ -85,7 +77,7 @@ public final class MidiDispatcher extends MidiReceiver {
}
@Override
public void flush() throws IOException {
public void onFlush() throws IOException {
for (MidiReceiver receiver : mReceivers) {
receiver.flush();
}

View File

@@ -36,7 +36,7 @@ public class MidiEventScheduler extends EventScheduler {
* time.
*/
@Override
public void onReceive(byte[] msg, int offset, int count, long timestamp)
public void onSend(byte[] msg, int offset, int count, long timestamp)
throws IOException {
MidiEvent event = createScheduledEvent(msg, offset, count, timestamp);
if (event != null) {
@@ -45,7 +45,7 @@ public class MidiEventScheduler extends EventScheduler {
}
@Override
public void flush() {
public void onFlush() {
MidiEventScheduler.this.flush();
}
}

View File

@@ -54,10 +54,10 @@ public class MidiFramer extends MidiReceiver {
}
/*
* @see android.midi.MidiReceiver#onReceive(byte[], int, int, long)
* @see android.midi.MidiReceiver#onSend(byte[], int, int, long)
*/
@Override
public void onReceive(byte[] data, int offset, int count, long timestamp)
public void onSend(byte[] data, int offset, int count, long timestamp)
throws IOException {
// Log.i(TAG, formatMidiData(data, offset, count));
int sysExStartOffset = (mInSysEx ? offset : -1);
@@ -77,7 +77,7 @@ public class MidiFramer extends MidiReceiver {
} else if (b == 0xF7 /* SysEx End */) {
// Log.i(TAG, "SysEx End");
if (mInSysEx) {
mReceiver.sendWithTimestamp(data, sysExStartOffset,
mReceiver.send(data, sysExStartOffset,
offset - sysExStartOffset + 1, timestamp);
mInSysEx = false;
sysExStartOffset = -1;
@@ -91,11 +91,11 @@ public class MidiFramer extends MidiReceiver {
} else { // real-time?
// Single byte message interleaved with other data.
if (mInSysEx) {
mReceiver.sendWithTimestamp(data, sysExStartOffset,
mReceiver.send(data, sysExStartOffset,
offset - sysExStartOffset, timestamp);
sysExStartOffset = offset + 1;
}
mReceiver.sendWithTimestamp(data, offset, 1, timestamp);
mReceiver.send(data, offset, 1, timestamp);
}
} else { // data byte
// Save SysEx data for SysEx End marker or end of buffer.
@@ -105,7 +105,7 @@ public class MidiFramer extends MidiReceiver {
if (mRunningStatus != 0) {
mBuffer[0] = (byte) mRunningStatus;
}
mReceiver.sendWithTimestamp(mBuffer, 0, mCount, timestamp);
mReceiver.send(mBuffer, 0, mCount, timestamp);
mNeeded = MidiConstants.getBytesPerMessage(mBuffer[0]) - 1;
mCount = 1;
}
@@ -116,7 +116,7 @@ public class MidiFramer extends MidiReceiver {
// send any accumulatedSysEx data
if (sysExStartOffset >= 0 && sysExStartOffset < offset) {
mReceiver.sendWithTimestamp(data, sysExStartOffset,
mReceiver.send(data, sysExStartOffset,
offset - sysExStartOffset, timestamp);
}
}

View File

@@ -26,7 +26,7 @@ import android.os.IBinder;
/** @hide */
interface IMidiManager
{
MidiDeviceInfo[] getDeviceList();
MidiDeviceInfo[] getDevices();
// for device creation & removal notifications
void registerListener(IBinder token, in IMidiDeviceListener listener);

View File

@@ -136,11 +136,14 @@ public final class MidiDevice implements Closeable {
/**
* Connects the supplied {@link MidiInputPort} to the output port of this device
* with the specified port number. Once the connection is made, the MidiInput port instance
* can no longer receive data via its {@link MidiReceiver#onReceive} method.
* This method returns a {@link MidiDevice.MidiConnection} object, which can be used to close the connection
* can no longer receive data via its {@link MidiReceiver#onSend} method.
* This method returns a {@link MidiDevice.MidiConnection} object, which can be used
* to close the connection.
*
* @param inputPort the inputPort to connect
* @param outputPortNumber the port number of the output port to connect inputPort to.
* @return {@link MidiDevice.MidiConnection} object if the connection is successful, or null in case of failure
* @return {@link MidiDevice.MidiConnection} object if the connection is successful,
* or null in case of failure.
*/
public MidiConnection connectPorts(MidiInputPort inputPort, int outputPortNumber) {
if (outputPortNumber < 0 || outputPortNumber >= mDeviceInfo.getOutputPortCount()) {

View File

@@ -49,6 +49,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's user visible name property.
* The value for this property is of type {@link java.lang.String}.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
* For USB devices, this is a concatenation of the manufacturer and product names.
*/
@@ -56,6 +57,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's manufacturer name property.
* The value for this property is of type {@link java.lang.String}.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
* Matches the USB device manufacturer name string for USB MIDI devices.
*/
@@ -63,6 +65,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's product name property.
* The value for this property is of type {@link java.lang.String}.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
* Matches the USB device product name string for USB MIDI devices.
*/
@@ -70,6 +73,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's version property.
* The value for this property is of type {@link java.lang.String}.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
* Matches the USB device version number for USB MIDI devices.
*/
@@ -77,20 +81,23 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's serial number property.
* The value for this property is of type {@link java.lang.String}.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
* Matches the USB device serial number for USB MIDI devices.
*/
public static final String PROPERTY_SERIAL_NUMBER = "serial_number";
/**
* Bundle key for the device's {@link android.hardware.usb.UsbDevice}.
* Bundle key for the device's corresponding USB device.
* The value for this property is of type {@link android.hardware.usb.UsbDevice}.
* Only set for USB MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
*/
public static final String PROPERTY_USB_DEVICE = "usb_device";
/**
* Bundle key for the device's {@link android.bluetooth.BluetoothDevice}.
* Bundle key for the device's corresponding Bluetooth device.
* The value for this property is of type {@link android.bluetooth.BluetoothDevice}.
* Only set for Bluetooth MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
*/
@@ -98,6 +105,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's ALSA card number.
* The value for this property is an integer.
* Only set for USB MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
*
@@ -107,6 +115,7 @@ public final class MidiDeviceInfo implements Parcelable {
/**
* Bundle key for the device's ALSA device number.
* The value for this property is an integer.
* Only set for USB MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
*
@@ -115,7 +124,8 @@ public final class MidiDeviceInfo implements Parcelable {
public static final String PROPERTY_ALSA_DEVICE = "alsa_device";
/**
* {@link android.content.pm.ServiceInfo} for the service hosting the device implementation.
* ServiceInfo for the service hosting the device implementation.
* The value for this property is of type {@link android.content.pm.ServiceInfo}.
* Only set for Virtual MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
*
@@ -249,18 +259,18 @@ public final class MidiDeviceInfo implements Parcelable {
*
* @return array of {@link PortInfo}
*/
public PortInfo[] getPortList() {
PortInfo[] portInfoList = new PortInfo[mInputPortCount + mOutputPortCount];
public PortInfo[] getPorts() {
PortInfo[] ports = new PortInfo[mInputPortCount + mOutputPortCount];
int index = 0;
for (int i = 0; i < mInputPortCount; i++) {
portInfoList[index++] = new PortInfo(PortInfo.TYPE_INPUT, i, mInputPortNames[i]);
ports[index++] = new PortInfo(PortInfo.TYPE_INPUT, i, mInputPortNames[i]);
}
for (int i = 0; i < mOutputPortCount; i++) {
portInfoList[index++] = new PortInfo(PortInfo.TYPE_OUTPUT, i, mOutputPortNames[i]);
ports[index++] = new PortInfo(PortInfo.TYPE_OUTPUT, i, mOutputPortNames[i]);
}
return portInfoList;
return ports;
}
/**

View File

@@ -69,6 +69,7 @@ public final class MidiDeviceStatus implements Parcelable {
/**
* Returns true if an input port is open.
* An input port can only be opened by one client at a time.
*
* @param portNumber the input port's port number
* @return input port open status
@@ -78,7 +79,8 @@ public final class MidiDeviceStatus implements Parcelable {
}
/**
* Returns the open count for an output port.
* Returns the number of clients currently connected to the specified output port.
* Unlike input ports, an output port can be opened by multiple clients at the same time.
*
* @param portNumber the output port's port number
* @return output port open count

View File

@@ -49,6 +49,8 @@ public final class MidiInputPort extends MidiReceiver implements Closeable {
/* package */ MidiInputPort(IMidiDeviceServer server, IBinder token,
ParcelFileDescriptor pfd, int portNumber) {
super(MidiPortImpl.MAX_PACKET_DATA_SIZE);
mDeviceServer = server;
mToken = token;
mParcelFileDescriptor = pfd;
@@ -71,7 +73,7 @@ public final class MidiInputPort extends MidiReceiver implements Closeable {
}
@Override
public void onReceive(byte[] msg, int offset, int count, long timestamp) throws IOException {
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
if (offset < 0 || count < 0 || offset + count > msg.length) {
throw new IllegalArgumentException("offset or count out of range");
}
@@ -89,7 +91,7 @@ public final class MidiInputPort extends MidiReceiver implements Closeable {
}
@Override
public void flush() throws IOException {
public void onFlush() throws IOException {
synchronized (mBuffer) {
if (mOutputStream == null) {
throw new IOException("MidiInputPort is closed");
@@ -112,11 +114,6 @@ public final class MidiInputPort extends MidiReceiver implements Closeable {
}
}
@Override
public int getMaxMessageSize() {
return MidiPortImpl.MAX_PACKET_DATA_SIZE;
}
@Override
public void close() throws IOException {
synchronized (mGuard) {

View File

@@ -151,29 +151,16 @@ public final class MidiManager {
}
/**
* Callback class used for receiving the results of {@link #openDevice}
* Listener class used for receiving the results of {@link #openDevice} and
* {@link #openBluetoothDevice}
*/
abstract public static class DeviceOpenCallback {
public interface OnDeviceOpenedListener {
/**
* Called to respond to a {@link #openDevice} request
*
* @param deviceInfo the {@link MidiDeviceInfo} for the device to open
* @param device a {@link MidiDevice} for opened device, or null if opening failed
*/
abstract public void onDeviceOpened(MidiDeviceInfo deviceInfo, MidiDevice device);
}
/**
* Callback class used for receiving the results of {@link #openBluetoothDevice}
*/
abstract public static class BluetoothOpenCallback {
/**
* Called to respond to a {@link #openBluetoothDevice} request
*
* @param bluetoothDevice the {@link android.bluetooth.BluetoothDevice} to open
* @param device a {@link MidiDevice} for opened device, or null if opening failed
*/
abstract public void onDeviceOpened(BluetoothDevice bluetoothDevice, MidiDevice device);
abstract public void onDeviceOpened(MidiDevice device);
}
/**
@@ -224,38 +211,25 @@ public final class MidiManager {
*
* @return an array of all MIDI devices
*/
public MidiDeviceInfo[] getDeviceList() {
public MidiDeviceInfo[] getDevices() {
try {
return mService.getDeviceList();
return mService.getDevices();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getDeviceList");
Log.e(TAG, "RemoteException in getDevices");
return new MidiDeviceInfo[0];
}
}
private void sendOpenDeviceResponse(final MidiDeviceInfo deviceInfo, final MidiDevice device,
final DeviceOpenCallback callback, Handler handler) {
private void sendOpenDeviceResponse(final MidiDevice device,
final OnDeviceOpenedListener listener, Handler handler) {
if (handler != null) {
handler.post(new Runnable() {
@Override public void run() {
callback.onDeviceOpened(deviceInfo, device);
listener.onDeviceOpened(device);
}
});
} else {
callback.onDeviceOpened(deviceInfo, device);
}
}
private void sendBluetoothDeviceResponse(final BluetoothDevice bluetoothDevice,
final MidiDevice device, final BluetoothOpenCallback callback, Handler handler) {
if (handler != null) {
handler.post(new Runnable() {
@Override public void run() {
callback.onDeviceOpened(bluetoothDevice, device);
}
});
} else {
callback.onDeviceOpened(bluetoothDevice, device);
listener.onDeviceOpened(device);
}
}
@@ -263,12 +237,13 @@ public final class MidiManager {
* Opens a MIDI device for reading and writing.
*
* @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open
* @param callback a {@link MidiManager.DeviceOpenCallback} to be called to receive the result
* @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called
* to receive the result
* @param handler the {@link android.os.Handler Handler} that will be used for delivering
* the result. If handler is null, then the thread used for the
* callback is unspecified.
* listener is unspecified.
*/
public void openDevice(MidiDeviceInfo deviceInfo, DeviceOpenCallback callback,
public void openDevice(MidiDeviceInfo deviceInfo, OnDeviceOpenedListener listener,
Handler handler) {
MidiDevice device = null;
try {
@@ -283,7 +258,7 @@ public final class MidiManager {
intent.setComponent(new ComponentName(serviceInfo.packageName,
serviceInfo.name));
final MidiDeviceInfo deviceInfoF = deviceInfo;
final DeviceOpenCallback callbackF = callback;
final OnDeviceOpenedListener listenerF = listener;
final Handler handlerF = handler;
if (mContext.bindService(intent,
new ServiceConnection() {
@@ -291,8 +266,9 @@ public final class MidiManager {
public void onServiceConnected(ComponentName name, IBinder binder) {
IMidiDeviceServer server =
IMidiDeviceServer.Stub.asInterface(binder);
MidiDevice device = new MidiDevice(deviceInfoF, server, mContext, this);
sendOpenDeviceResponse(deviceInfoF, device, callbackF, handlerF);
MidiDevice device = new MidiDevice(deviceInfoF, server, mContext,
this);
sendOpenDeviceResponse(device, listenerF, handlerF);
}
@Override
@@ -314,21 +290,21 @@ public final class MidiManager {
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in openDevice");
}
sendOpenDeviceResponse(deviceInfo, device, callback, handler);
sendOpenDeviceResponse(device, listener, handler);
}
/**
* Opens a Bluetooth MIDI device for reading and writing.
*
* @param bluetoothDevice a {@link android.bluetooth.BluetoothDevice} to open as a MIDI device
* @param callback a {@link MidiManager.BluetoothOpenCallback} to be called to receive the
* @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called to receive the
* result
* @param handler the {@link android.os.Handler Handler} that will be used for delivering
* the result. If handler is null, then the thread used for the
* callback is unspecified.
* listener is unspecified.
*/
public void openBluetoothDevice(final BluetoothDevice bluetoothDevice,
final BluetoothOpenCallback callback, final Handler handler) {
final OnDeviceOpenedListener listener, final Handler handler) {
Intent intent = new Intent(BLUETOOTH_MIDI_SERVICE_INTENT);
intent.setComponent(new ComponentName(BLUETOOTH_MIDI_SERVICE_PACKAGE,
BLUETOOTH_MIDI_SERVICE_CLASS));
@@ -343,10 +319,10 @@ public final class MidiManager {
// fetch MidiDeviceInfo from the server
MidiDeviceInfo deviceInfo = server.getDeviceInfo();
MidiDevice device = new MidiDevice(deviceInfo, server, mContext, this);
sendBluetoothDeviceResponse(bluetoothDevice, device, callback, handler);
sendOpenDeviceResponse(device, listener, handler);
} catch (RemoteException e) {
Log.e(TAG, "remote exception in onServiceConnected");
sendBluetoothDeviceResponse(bluetoothDevice, null, callback, handler);
sendOpenDeviceResponse(null, listener, handler);
}
}
@@ -358,7 +334,7 @@ public final class MidiManager {
Context.BIND_AUTO_CREATE))
{
Log.e(TAG, "Unable to bind service: " + intent);
sendBluetoothDeviceResponse(bluetoothDevice, null, callback, handler);
sendOpenDeviceResponse(null, listener, handler);
}
}

View File

@@ -70,7 +70,7 @@ public final class MidiOutputPort extends MidiSender implements Closeable {
long timestamp = MidiPortImpl.getPacketTimestamp(buffer, count);
// dispatch to all our receivers
mDispatcher.sendWithTimestamp(buffer, offset, size, timestamp);
mDispatcher.send(buffer, offset, size, timestamp);
break;
}
case MidiPortImpl.PACKET_TYPE_FLUSH:
@@ -114,12 +114,12 @@ public final class MidiOutputPort extends MidiSender implements Closeable {
}
@Override
public void connect(MidiReceiver receiver) {
public void onConnect(MidiReceiver receiver) {
mDispatcher.getSender().connect(receiver);
}
@Override
public void disconnect(MidiReceiver receiver) {
public void onDisconnect(MidiReceiver receiver) {
mDispatcher.getSender().disconnect(receiver);
}

View File

@@ -22,19 +22,35 @@ import java.io.IOException;
* Interface for sending and receiving data to and from a MIDI device.
*/
abstract public class MidiReceiver {
private final int mMaxMessageSize;
/**
* Although public, this method should be considered a private implementation
* detail. Client code should call {@link #send} or {@link #sendWithTimestamp}
* instead.
*
* Called to pass MIDI data to the receiver.
* Default MidiReceiver constructor. Maximum message size is set to
* {@link java.lang.Integer#MAX_VALUE}
*/
public MidiReceiver() {
mMaxMessageSize = Integer.MAX_VALUE;
}
/**
* MidiReceiver constructor.
* @param maxMessageSize the maximum size of a message this receiver can receive
*/
public MidiReceiver(int maxMessageSize) {
mMaxMessageSize = maxMessageSize;
}
/**
* Called whenever the receiver is passed new MIDI data.
* Subclasses override this method to receive MIDI data.
* May fail if count exceeds {@link #getMaxMessageSize}.
*
* NOTE: the msg array parameter is only valid within the context of this call.
* The msg bytes should be copied by the receiver rather than retaining a reference
* to this parameter.
* Also, modifying the contents of the msg array parameter may result in other receivers
* in the same application receiving incorrect values in their {link #onReceive} method.
* in the same application receiving incorrect values in their {link #onSend} method.
*
* @param msg a byte array containing the MIDI data
* @param offset the offset of the first byte of the data in the array to be processed
@@ -42,28 +58,37 @@ abstract public class MidiReceiver {
* @param timestamp the timestamp of the message (based on {@link java.lang.System#nanoTime}
* @throws IOException
*/
abstract public void onReceive(byte[] msg, int offset, int count, long timestamp)
abstract public void onSend(byte[] msg, int offset, int count, long timestamp)
throws IOException;
/**
* Instructs the receiver to discard all pending events.
* Instructs the receiver to discard all pending MIDI data.
* @throws IOException
*/
public void flush() throws IOException {
onFlush();
}
/**
* Called when the receiver is instructed to discard all pending MIDI data.
* Subclasses should override this method if they maintain a list or queue of MIDI data
* to be processed in the future.
* @throws IOException
*/
public void onFlush() throws IOException {
}
/**
* Returns the maximum size of a message this receiver can receive.
* Defaults to {@link java.lang.Integer#MAX_VALUE} unless overridden.
* @return maximum message size
*/
public int getMaxMessageSize() {
return Integer.MAX_VALUE;
public final int getMaxMessageSize() {
return mMaxMessageSize;
}
/**
* Called to send MIDI data to the receiver
* Data will get split into multiple calls to {@link #onReceive} if count exceeds
* Data will get split into multiple calls to {@link #onSend} if count exceeds
* {@link #getMaxMessageSize}.
*
* @param msg a byte array containing the MIDI data
@@ -72,12 +97,12 @@ abstract public class MidiReceiver {
* @throws IOException
*/
public void send(byte[] msg, int offset, int count) throws IOException {
sendWithTimestamp(msg, offset, count, System.nanoTime());
send(msg, offset, count, System.nanoTime());
}
/**
* Called to send MIDI data to the receiver to be handled at a specified time in the future
* Data will get split into multiple calls to {@link #onReceive} if count exceeds
* Data will get split into multiple calls to {@link #onSend} if count exceeds
* {@link #getMaxMessageSize}.
*
* @param msg a byte array containing the MIDI data
@@ -86,12 +111,12 @@ abstract public class MidiReceiver {
* @param timestamp the timestamp of the message (based on {@link java.lang.System#nanoTime}
* @throws IOException
*/
public void sendWithTimestamp(byte[] msg, int offset, int count, long timestamp)
public void send(byte[] msg, int offset, int count, long timestamp)
throws IOException {
int messageSize = getMaxMessageSize();
while (count > 0) {
int length = (count > messageSize ? messageSize : count);
onReceive(msg, offset, length, timestamp);
onSend(msg, offset, length, timestamp);
offset += length;
count -= length;
}

View File

@@ -21,17 +21,42 @@ package android.media.midi;
* MidiReceivers to a MIDI device.
*/
abstract public class MidiSender {
/**
* Connects a {@link MidiReceiver} to the sender
*
* @param receiver the receiver to connect
*/
public void connect(MidiReceiver receiver) {
if (receiver == null) {
throw new NullPointerException("receiver null in MidiSender.connect");
}
onConnect(receiver);
}
/**
* Disconnects a {@link MidiReceiver} from the sender
*
* @param receiver the receiver to disconnect
*/
public void disconnect(MidiReceiver receiver) {
if (receiver == null) {
throw new NullPointerException("receiver null in MidiSender.disconnect");
}
onDisconnect(receiver);
}
/**
* Called to connect a {@link MidiReceiver} to the sender
*
* @param receiver the receiver to connect
*/
abstract public void connect(MidiReceiver receiver);
abstract public void onConnect(MidiReceiver receiver);
/**
* Called to disconnect a {@link MidiReceiver} from the sender
*
* @param receiver the receiver to disconnect
*/
abstract public void disconnect(MidiReceiver receiver);
abstract public void onDisconnect(MidiReceiver receiver);
}

View File

@@ -30,13 +30,13 @@ capabilities, etc.
messages.
<li> Support transmission of arbitrary length data for SysEx, etc.
<li> Timestamps to avoid jitter.
<li> Support direction connection or “patching” of devices for lower latency.
<li> Support direction connection or &ldquo;patching&rdquo; of devices for lower latency.
</ul>
<h2 id=transports_supported>Transports Supported</h2>
<p>The API is transport agnostic. But there are several transports currently
<p>The API is &ldquo;transport agnostic&rdquo;. But there are several transports currently
supported:</p>
<ul>
@@ -83,7 +83,7 @@ MidiManager m = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
information can be presented to a user, allowing them to choose a device.</p>
<pre class=prettyprint>
MidiDeviceInfo[] infos = m.getDeviceList();
MidiDeviceInfo[] infos = m.getDevices();
</pre>
@@ -116,9 +116,9 @@ int numOutputs = info.getOutputPortCount();
</pre>
<p>Note that “input” and “output” are from the standpoint of the device. So a
synthesizer will have an “input” port that receives messages. A keyboard will
have an “output” port that sends messages.</p>
<p>Note that &ldquo;input&rdquo; and &ldquo;output&rdquo; are from the standpoint of the device. So a
synthesizer will have an &ldquo;input&rdquo; port that receives messages. A keyboard will
have an &ldquo;output&rdquo; port that sends messages.</p>
<p>The MidiDeviceInfo has a bundle of properties.</p>
@@ -148,12 +148,11 @@ you need to provide a callback for completion. You can specify an optional
Handler if you want the callback to occur on a specific Thread.</p>
<pre class=prettyprint>
m.openDevice(info, new MidiManager.DeviceOpenCallback() {
m.openDevice(info, new MidiManager.OnDeviceOpenedListener() {
&#64;Override
public void onDeviceOpened(MidiDeviceInfo deviceInfo,
MidiDevice device) {
public void onDeviceOpened(MidiDevice device) {
if (device == null) {
Log.e(TAG, "could not open " + deviceInfo);
Log.e(TAG, "could not open device " + info);
} else {
...
}, new Handler(Looper.getMainLooper())
@@ -164,7 +163,7 @@ m.openDevice(info, new MidiManager.DeviceOpenCallback() {
<h2 id=open_a_midi_input_port>Open a MIDI Input Port</h2>
<p>If you want to send a message to a MIDI Device then you need to open an “input”
<p>If you want to send a message to a MIDI Device then you need to open an &ldquo;input&rdquo;
port with exclusive access.</p>
<pre class=prettyprint>
@@ -199,7 +198,7 @@ consistent with the other audio and input timers.</p>
<pre class=prettyprint>
long now = System.nanoTime();
long future = now + (2 * 1000000000);
inputPort.sendWithTimestamp(buffer, offset, numBytes, future);
inputPort.send(buffer, offset, numBytes, future);
</pre>
@@ -212,7 +211,7 @@ inputPort.flush(); // discard events
<p>If there were any MIDI NoteOff message left in the buffer then they will be
discarded and you may get stuck notes. So we recommend sending all notes off
discarded and you may get stuck notes. So we recommend sending &ldquo;all notes off&rdquo;
after doing a flush.</p>
<h2 id=receive_a_note>Receive a Note</h2>
@@ -223,7 +222,7 @@ connect your receiver to an output port of the device.</p>
<pre class=prettyprint>
class MyReceiver extends MidiReceiver {
public void onReceive(byte[] data, int offset,
public void onSend(byte[] data, int offset,
int count, long timestamp) throws IOException {
// parse MIDI or whatever
}
@@ -264,7 +263,7 @@ AndroidManifest.xml file.</p>
<p>The details of the resource in this example is stored in
res/xml/synth_device_info.xml.</p>
&ldquo;res/xml/synth_device_info.xml&rdquo;.</p>
<pre class=prettyprint>
&lt;devices>
@@ -279,7 +278,7 @@ AndroidManifest.xml file.</p>
<p>You then define your server by extending android.media.midi.MidiDeviceService.
Lets assume you have a MySynthEngine class that extends MidiReceiver.</p>
Let&lsquo;s assume you have a MySynthEngine class that extends MidiReceiver.</p>
<pre class=prettyprint>
import android.media.midi.MidiDeviceService;

View File

@@ -234,10 +234,10 @@ public final class BluetoothMidiDevice {
break;
}
try {
mPacketEncoder.sendWithTimestamp(event.data, 0, event.count,
mPacketEncoder.send(event.data, 0, event.count,
event.getTimestamp());
} catch (IOException e) {
Log.e(TAG, "mPacketAccumulator.sendWithTimestamp failed", e);
Log.e(TAG, "mPacketAccumulator.send failed", e);
}
mEventScheduler.addEventToPool(event);
}

View File

@@ -86,7 +86,7 @@ public class BluetoothPacketDecoder extends PacketDecoder {
if (dataCount > 0) {
// send previous message separately since it has a different timestamp
try {
receiver.sendWithTimestamp(mBuffer, 0, dataCount, nanoTimestamp);
receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
} catch (IOException e) {
// ???
}
@@ -106,7 +106,7 @@ public class BluetoothPacketDecoder extends PacketDecoder {
if (dataCount > 0) {
try {
receiver.sendWithTimestamp(mBuffer, 0, dataCount, nanoTimestamp);
receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
} catch (IOException e) {
// ???
}

View File

@@ -53,7 +53,7 @@ public class BluetoothPacketEncoder extends PacketEncoder {
// This receives normalized data from mMidiFramer and accumulates it into a packet buffer
private final MidiReceiver mFramedDataReceiver = new MidiReceiver() {
@Override
public void onReceive(byte[] msg, int offset, int count, long timestamp)
public void onSend(byte[] msg, int offset, int count, long timestamp)
throws IOException {
synchronized (mLock) {
@@ -130,7 +130,8 @@ public class BluetoothPacketEncoder extends PacketEncoder {
flushLocked(true);
appendHeader(milliTimestamp);
}
mAccumulationBuffer[mAccumulatedBytes++] = (byte)(0x80 | (milliTimestamp & 0x7F));
mAccumulationBuffer[mAccumulatedBytes++] =
(byte)(0x80 | (milliTimestamp & 0x7F));
mAccumulationBuffer[mAccumulatedBytes++] = MidiConstants.STATUS_END_SYSEX;
}
} else {
@@ -146,7 +147,8 @@ public class BluetoothPacketEncoder extends PacketEncoder {
// now copy data bytes
int dataLength = count - 1;
System.arraycopy(msg, offset + 1, mAccumulationBuffer, mAccumulatedBytes, dataLength);
System.arraycopy(msg, offset + 1, mAccumulationBuffer, mAccumulatedBytes,
dataLength);
mAccumulatedBytes += dataLength;
}
@@ -160,7 +162,8 @@ public class BluetoothPacketEncoder extends PacketEncoder {
// write header if we are starting a new packet
if (mAccumulatedBytes == 0) {
// header byte with timestamp bits 7 - 12
mAccumulationBuffer[mAccumulatedBytes++] = (byte)(0x80 | ((milliTimestamp >> 7) & 0x3F));
mAccumulationBuffer[mAccumulatedBytes++] =
(byte)(0x80 | ((milliTimestamp >> 7) & 0x3F));
mPacketTimestamp = milliTimestamp;
return true;
} else {
@@ -177,10 +180,10 @@ public class BluetoothPacketEncoder extends PacketEncoder {
}
@Override
public void onReceive(byte[] msg, int offset, int count, long timestamp)
public void onSend(byte[] msg, int offset, int count, long timestamp)
throws IOException {
// normalize the data by passing it through a MidiFramer first
mMidiFramer.sendWithTimestamp(msg, offset, count, timestamp);
mMidiFramer.send(msg, offset, count, timestamp);
}
@Override

View File

@@ -339,7 +339,7 @@ public class MidiService extends IMidiManager.Stub {
private static final MidiDeviceInfo[] EMPTY_DEVICE_INFO_ARRAY = new MidiDeviceInfo[0];
public MidiDeviceInfo[] getDeviceList() {
public MidiDeviceInfo[] getDevices() {
ArrayList<MidiDeviceInfo> deviceInfos = new ArrayList<MidiDeviceInfo>();
int uid = Binder.getCallingUid();