Merge "MIDI Manager work in progress"

This commit is contained in:
Mike Lockwood
2014-12-08 18:46:35 +00:00
committed by Android (Google) Code Review
19 changed files with 1584 additions and 0 deletions

View File

@@ -80,6 +80,8 @@ import android.media.projection.MediaProjectionManager;
import android.media.session.MediaSessionManager;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.midi.IMidiManager;
import android.midi.MidiManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.EthernetManager;
@@ -777,6 +779,12 @@ class ContextImpl extends Context {
IBinder b = ServiceManager.getService(APPWIDGET_SERVICE);
return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b));
}});
registerService(MIDI_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(MIDI_SERVICE);
return new MidiManager(ctx, IMidiManager.Stub.asInterface(b));
}});
}
static ContextImpl getImpl(Context context) {

View File

@@ -2143,6 +2143,7 @@ public abstract class Context {
MEDIA_SESSION_SERVICE,
BATTERY_SERVICE,
JOB_SCHEDULER_SERVICE,
MIDI_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -2915,6 +2916,15 @@ public abstract class Context {
*/
public static final String MEDIA_PROJECTION_SERVICE = "media_projection";
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.midi.MidiManager} for accessing the MIDI service.
*
* @see #getSystemService
* @hide
*/
public static final String MIDI_SERVICE = "midi";
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.midi.MidiDeviceInfo;
/** @hide */
oneway interface IMidiListener
{
void onDeviceAdded(in MidiDeviceInfo device);
void onDeviceRemoved(in MidiDeviceInfo device);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.hardware.usb.UsbDevice;
import android.midi.IMidiListener;
import android.midi.MidiDevice;
import android.midi.MidiDeviceInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
/** @hide */
interface IMidiManager
{
MidiDeviceInfo[] getDeviceList();
// for device creation & removal notifications
void registerListener(IBinder token, in IMidiListener listener);
void unregisterListener(IBinder token, in IMidiListener listener);
// for communicating with MIDI devices
ParcelFileDescriptor openDevice(IBinder token, in MidiDeviceInfo device);
// for implementing virtual MIDI devices
MidiDevice registerVirtualDevice(IBinder token, in Bundle properties);
void unregisterVirtualDevice(IBinder token, in MidiDeviceInfo device);
// for use by UsbAudioManager
void alsaDeviceAdded(int card, int device, in UsbDevice usbDevice);
void alsaDeviceRemoved(in UsbDevice usbDevice);
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2014, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
parcelable MidiDevice;

View File

@@ -0,0 +1,292 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
/**
* This class is used for sending and receiving data to and from an midi device
* Instances of this class are created by {@link MidiManager#openDevice}.
* This class can also be used to provide the implementation for a virtual device.
*
* This class implements Parcelable so it can be returned from MidiService when creating
* virtual MIDI devices.
*
* @hide
*/
public final class MidiDevice implements Parcelable {
private static final String TAG = "MidiDevice";
private final MidiDeviceInfo mDeviceInfo;
private ParcelFileDescriptor mParcelFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
private final ArrayList<MidiReceiver> mReceivers = new ArrayList<MidiReceiver>();
/**
* Minimum size of packed message as sent through our ParcelFileDescriptor
* 8 bytes for timestamp and 1 to 3 bytes for message
* @hide
*/
public static final int MIN_PACKED_MESSAGE_SIZE = 9;
/**
* Maximum size of packed message as sent through our ParcelFileDescriptor
* 8 bytes for timestamp and 1 to 3 bytes for message
* @hide
*/
public static final int MAX_PACKED_MESSAGE_SIZE = 11;
// This thread reads MIDI events from a socket and distributes them to the list of
// MidiReceivers attached to this device.
private final Thread mThread = new Thread() {
@Override
public void run() {
byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE];
ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>();
try {
while (true) {
// read next event
int count = mInputStream.read(buffer);
if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) {
Log.e(TAG, "Number of bytes read out of range: " + count);
break;
}
int offset = getMessageOffset(buffer, count);
int size = getMessageSize(buffer, count);
long timestamp = getMessageTimeStamp(buffer, count);
synchronized (mReceivers) {
for (int i = 0; i < mReceivers.size(); i++) {
MidiReceiver receiver = mReceivers.get(i);
try {
mReceivers.get(i).onPost(buffer, offset, size, timestamp);
} catch (IOException e) {
Log.e(TAG, "post failed");
deadReceivers.add(receiver);
}
}
// remove any receivers that failed
if (deadReceivers.size() > 0) {
for (MidiReceiver receiver: deadReceivers) {
mReceivers.remove(receiver);
}
deadReceivers.clear();
}
// exit if we have no receivers left
if (mReceivers.size() == 0) {
break;
}
}
}
} catch (IOException e) {
Log.e(TAG, "read failed");
}
}
};
// This is the receiver that clients use for sending events to this device.
private final MidiReceiver mReceiver = new MidiReceiver() {
private final byte[] mBuffer = new byte[MAX_PACKED_MESSAGE_SIZE];
public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
synchronized (mBuffer) {
int length = packMessage(msg, offset, count, timestamp, mBuffer);
mOutputStream.write(mBuffer, 0, length);
}
}
};
// Our MidiSender object, to which clients can attach MidiReceivers.
private final MidiSender mSender = new MidiSender() {
public void connect(MidiReceiver receiver) {
synchronized (mReceivers) {
if (mReceivers.size() == 0) {
mThread.start();
}
mReceivers.add(receiver);
}
}
public void disconnect(MidiReceiver receiver) {
synchronized (mReceivers) {
mReceivers.remove(receiver);
if (mReceivers.size() == 0) {
// ???
}
}
}
};
/**
* MidiDevice should only be instantiated by MidiManager or MidiService
* @hide
*/
public MidiDevice(MidiDeviceInfo deviceInfo, ParcelFileDescriptor pfd) {
mDeviceInfo = deviceInfo;
mParcelFileDescriptor = pfd;
}
public boolean open() {
FileDescriptor fd = mParcelFileDescriptor.getFileDescriptor();
try {
mInputStream = new FileInputStream(fd);
} catch (Exception e) {
Log.e(TAG, "could not create mInputStream", e);
return false;
}
try {
mOutputStream = new FileOutputStream(fd);
} catch (Exception e) {
Log.e(TAG, "could not create mOutputStream", e);
return false;
}
return true;
}
void close() {
try {
if (mInputStream != null) {
mInputStream.close();
}
if (mOutputStream != null) {
mOutputStream.close();
}
mParcelFileDescriptor.close();
} catch (IOException e) {
}
}
// returns our MidiDeviceInfo object, which describes this device
public MidiDeviceInfo getInfo() {
return mDeviceInfo;
}
// returns our MidiReceiver, which clients can use for sending events to this device.
public MidiReceiver getReceiver() {
return mReceiver;
}
// Returns our MidiSender object, to which clients can attach MidiReceivers.
public MidiSender getSender() {
return mSender;
}
@Override
public String toString() {
return ("MidiDevice: " + mDeviceInfo.toString() + " fd: " + mParcelFileDescriptor);
}
public static final Parcelable.Creator<MidiDevice> CREATOR =
new Parcelable.Creator<MidiDevice>() {
public MidiDevice createFromParcel(Parcel in) {
MidiDeviceInfo deviceInfo = (MidiDeviceInfo)in.readParcelable(null);
ParcelFileDescriptor pfd = (ParcelFileDescriptor)in.readParcelable(null);
return new MidiDevice(deviceInfo, pfd);
}
public MidiDevice[] newArray(int size) {
return new MidiDevice[size];
}
};
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeParcelable(mDeviceInfo, flags);
parcel.writeParcelable(mParcelFileDescriptor, flags);
}
/**
* Utility function for packing a MIDI message to be sent through our ParcelFileDescriptor
*
* message byte array contains variable length MIDI message.
* messageSize is size of variable length MIDI message
* timestamp is message timestamp to pack
* dest is buffer to pack into
* returns size of packed message
*
* @hide
*/
public static int packMessage(byte[] message, int offset, int size, long timestamp,
byte[] dest) {
// pack variable length message first
System.arraycopy(message, offset, dest, 0, size);
int destOffset = size;
// timestamp takes 8 bytes
for (int i = 0; i < 8; i++) {
dest[destOffset++] = (byte)timestamp;
timestamp >>= 8;
}
return destOffset;
}
/**
* Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
* returns the offet of of MIDI message in packed buffer
*
* @hide
*/
public static int getMessageOffset(byte[] buffer, int bufferLength) {
// message is at start of buffer
return 0;
}
/**
* Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
* returns size of MIDI message in packed buffer
*
* @hide
*/
public static int getMessageSize(byte[] buffer, int bufferLength) {
// message length is total buffer length minus size of the timestamp
return bufferLength - 8;
}
/**
* Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
* unpacks timestamp from packed buffer
*
* @hide
*/
public static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
long timestamp = 0;
// timestamp follows variable length message data
int dataLength = getMessageSize(buffer, bufferLength);
for (int i = dataLength + 7; i >= dataLength; i--) {
// why can't Java deal with unsigned ints?
int b = buffer[i];
if (b < 0) b += 256;
timestamp = (timestamp << 8) | b;
}
return timestamp;
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2014, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
parcelable MidiDeviceInfo;

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
/**
* This class contains information to describe a MIDI device.
* For now we only have information that can be retrieved easily for USB devices,
* but we will probably expand this in the future.
*
* This class is just an immutable object to encapsulate the MIDI device description.
* Use the MidiDevice class to actually communicate with devices.
*
* @hide
*/
public class MidiDeviceInfo implements Parcelable {
private static final String TAG = "MidiDeviceInfo";
public static final int TYPE_USB = 1;
public static final int TYPE_VIRTUAL = 2;
private final int mType; // USB or virtual
private final int mId; // unique ID generated by MidiService
private final Bundle mProperties;
// used for USB devices only
private final int mAlsaCard;
private final int mAlsaDevice;
/**
* Bundle key for the device's manufacturer name property.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}.
* Matches the USB device manufacturer name string for USB MIDI devices.
*/
public static final String PROPERTY_MANUFACTURER = "manufacturer";
/**
* Bundle key for the device's model name property.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
* Matches the USB device product name string for USB MIDI devices.
*/
public static final String PROPERTY_MODEL = "model";
/**
* Bundle key for the device's serial number property.
* 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}.
* 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";
/**
* MidiDeviceInfo should only be instantiated by MidiService implementation
* @hide
*/
public MidiDeviceInfo(int type, int id, Bundle properties) {
mType = type;
mId = id;
mProperties = properties;
mAlsaCard = -1;
mAlsaDevice = -1;
}
/**
* MidiDeviceInfo should only be instantiated by MidiService implementation
* @hide
*/
public MidiDeviceInfo(int type, int id, Bundle properties,
int alsaCard, int alsaDevice) {
mType = type;
mId = id;
mProperties = properties;
mAlsaCard = alsaCard;
mAlsaDevice = alsaDevice;
}
/**
* Returns the type of the device.
*
* @return the device's type
*/
public int getType() {
return mType;
}
/**
* Returns the ID of the device.
* This ID is generated by the MIDI service and is not persistent across device unplugs.
*
* @return the device's ID
*/
public int getId() {
return mId;
}
/**
* Returns the {@link android.os.Bundle} containing the device's properties.
*
* @return the device's properties
*/
public Bundle getProperties() {
return mProperties;
}
/**
* @hide
*/
public int getAlsaCard() {
return mAlsaCard;
}
/**
* @hide
*/
public int getAlsaDevice() {
return mAlsaDevice;
}
@Override
public boolean equals(Object o) {
if (o instanceof MidiDeviceInfo) {
return (((MidiDeviceInfo)o).mId == mId);
} else {
return false;
}
}
@Override
public int hashCode() {
return mId;
}
@Override
public String toString() {
return ("MidiDeviceInfo[mType=" + mType +
",mId=" + mId +
",mProperties=" + mProperties +
",mAlsaCard=" + mAlsaCard +
",mAlsaDevice=" + mAlsaDevice);
}
public static final Parcelable.Creator<MidiDeviceInfo> CREATOR =
new Parcelable.Creator<MidiDeviceInfo>() {
public MidiDeviceInfo createFromParcel(Parcel in) {
int type = in.readInt();
int id = in.readInt();
Bundle properties = in.readBundle();
int card = in.readInt();
int device = in.readInt();
return new MidiDeviceInfo(type, id, properties, card, device);
}
public MidiDeviceInfo[] newArray(int size) {
return new MidiDeviceInfo[size];
}
};
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
parcel.writeInt(mId);
parcel.writeBundle(mProperties);
parcel.writeInt(mAlsaCard);
parcel.writeInt(mAlsaDevice);
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
import java.util.HashMap;
/**
* This class is the public application interface to the MIDI service.
*
* <p>You can obtain an instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
*
* {@samplecode
* MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
* @hide
*/
public class MidiManager {
private static final String TAG = "MidiManager";
private final Context mContext;
private final IMidiManager mService;
private final IBinder mToken = new Binder();
private HashMap<DeviceCallback,DeviceListener> mDeviceListeners =
new HashMap<DeviceCallback,DeviceListener>();
// Binder stub for receiving device notifications from MidiService
private class DeviceListener extends IMidiListener.Stub {
private DeviceCallback mCallback;
public DeviceListener(DeviceCallback callback) {
mCallback = callback;
}
public void onDeviceAdded(MidiDeviceInfo device) {
mCallback.onDeviceAdded(device);
}
public void onDeviceRemoved(MidiDeviceInfo device) {
mCallback.onDeviceRemoved(device);
}
}
// Callback interface clients to receive Device added and removed notifications
public interface DeviceCallback {
void onDeviceAdded(MidiDeviceInfo device);
void onDeviceRemoved(MidiDeviceInfo device);
}
/**
* @hide
*/
public MidiManager(Context context, IMidiManager service) {
mContext = context;
mService = service;
}
// Used by clients to register for Device added and removed notifications
public void registerDeviceCallback(DeviceCallback callback) {
DeviceListener deviceListener = new DeviceListener(callback);
try {
mService.registerListener(mToken, deviceListener);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in registerDeviceListener");
return;
}
mDeviceListeners.put(callback, deviceListener);
}
// Used by clients to unregister for device added and removed notifications
public void unregisterDeviceCallback(DeviceCallback callback) {
DeviceListener deviceListener = mDeviceListeners.remove(callback);
if (deviceListener != null) {
try {
mService.unregisterListener(mToken, deviceListener);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in unregisterDeviceListener");
}
}
}
public MidiDeviceInfo[] getDeviceList() {
try {
return mService.getDeviceList();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getDeviceList");
return new MidiDeviceInfo[0];
}
}
// Use this if you want to communicate with a MIDI device.
public MidiDevice openDevice(MidiDeviceInfo deviceInfo) {
try {
ParcelFileDescriptor pfd = mService.openDevice(mToken, deviceInfo);
if (pfd == null) {
Log.e(TAG, "could not open device " + deviceInfo);
return null;
}
MidiDevice device = new MidiDevice(deviceInfo, pfd);
if (device.open()) {
Log.d(TAG, "openDevice returning " + device);
return device;
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in openDevice");
}
return null;
}
// Use this if you want to register and implement a virtual device.
// The MidiDevice returned by this method is the proxy you use to implement the device.
public MidiDevice createVirtualDevice(Bundle properties) {
try {
MidiDevice device = mService.registerVirtualDevice(mToken, properties);
if (device != null && !device.open()) {
device = null;
}
return device;
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in createVirtualDevice");
return null;
}
}
public void closeVirtualDevice(MidiDevice device) {
try {
device.close();
mService.unregisterVirtualDevice(mToken, device.getInfo());
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in unregisterVirtualDevice");
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import java.io.IOException;
/**
* Interface for receiving events from a MIDI device.
*
* @hide
*/
public interface MidiReceiver {
// NOTE: the msg array is only valid within the context of this call.
// the byte array may get reused by the MIDI device for the next message.
public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
/**
* Interface provided by a device to allow attaching
* MidiReceivers to a MIDI device.
*
* @hide
*/
public interface MidiSender {
public void connect(MidiReceiver receiver);
public void disconnect(MidiReceiver receiver);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.midi;
import android.util.Log;
/**
* Class containing miscellaneous MIDI utilities.
*
* @hide
*/
public final class MidiUtils {
private static final String TAG = "MidiUtils";
/**
* Returns data size of a MIDI message based on the message's command byte
* @param b the message command byte
* @return the message's data length
*/
public static int getMessageDataSize(byte b) {
switch (b & 0xF0) {
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
return 2;
case 0xC0:
case 0xD0:
return 1;
case 0xF0:
switch (b & 0x0F) {
case 0x00:
Log.e(TAG, "System Exclusive not supported yet");
return -1;
case 0x01:
case 0x03:
return 1;
case 0x02:
return 2;
default:
return 0;
}
default:
Log.e(TAG, "unknown MIDI command " + b);
return -1;
}
}
}