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

Commit 3b7549ee authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "MIDI Manager: Remove message packetization from MIDI transport"

parents 18985e08 cb096273
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ public class MidiInputPort extends MidiPort implements MidiReceiver {
    private final FileOutputStream mOutputStream;

    // buffer to use for sending messages out our output stream
    private final byte[] mBuffer = new byte[MAX_PACKED_MESSAGE_SIZE];
    private final byte[] mBuffer = new byte[MAX_PACKET_SIZE];

  /* package */ MidiInputPort(ParcelFileDescriptor pfd, int portNumber) {
        super(portNumber);
@@ -50,10 +50,19 @@ public class MidiInputPort extends MidiPort implements MidiReceiver {
     *                  {@link java.lang.System#nanoTime}
     */
    public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
        assert(offset >= 0 && count >= 0 && offset + count <= msg.length);

        synchronized (mBuffer) {
            int length = packMessage(msg, offset, count, timestamp, mBuffer);
            try {
                while (count > 0) {
                    int length = packMessage(msg, offset, count, timestamp, mBuffer);
                    mOutputStream.write(mBuffer, 0, length);
                    int sent = getMessageSize(mBuffer, length);
                    assert(sent >= 0 && sent <= length);

                    offset += sent;
                    count -= sent;
                }
            } catch (IOException e) {
                IoUtils.closeQuietly(mOutputStream);
                // report I/O failure
+1 −5
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ public class MidiOutputPort extends MidiPort implements MidiSender {
    private final Thread mThread = new Thread() {
        @Override
        public void run() {
            byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE];
            byte[] buffer = new byte[MAX_PACKET_SIZE];
            ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>();

            try {
@@ -54,9 +54,6 @@ public class MidiOutputPort extends MidiPort implements MidiSender {
                    int count = mInputStream.read(buffer);
                    if (count < 0) {
                        break;
                    } else if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) {
                        Log.e(TAG, "Number of bytes read out of range: " + count);
                        continue;
                    }

                    int offset = getMessageOffset(buffer, count);
@@ -96,7 +93,6 @@ public class MidiOutputPort extends MidiPort implements MidiSender {
        }
    };


  /* package */ MidiOutputPort(ParcelFileDescriptor pfd, int portNumber) {
        super(portNumber);
        mInputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+31 −25
Original line number Diff line number Diff line
@@ -32,16 +32,19 @@ abstract public class MidiPort implements Closeable {
    private final int mPortNumber;

    /**
     * Minimum size of packed message as sent through our ParcelFileDescriptor
     * 8 bytes for timestamp and 1 to 3 bytes for message
     * Maximum size of a packet that can pass through our ParcelFileDescriptor
     */
    protected static final int MIN_PACKED_MESSAGE_SIZE = 9;
    protected static final int MAX_PACKET_SIZE = 1024;

    /**
     * Maximum size of packed message as sent through our ParcelFileDescriptor
     * 8 bytes for timestamp and 1 to 3 bytes for message
     * size of message timestamp in bytes
     */
    protected static final int MAX_PACKED_MESSAGE_SIZE = 11;
    private static final int TIMESTAMP_SIZE = 8;

    /**
     * Maximum amount of MIDI data that can be included in a packet
     */
    public static final int MAX_PACKET_DATA_SIZE = MAX_PACKET_SIZE - TIMESTAMP_SIZE;


  /* package */ MidiPort(int portNumber) {
@@ -76,47 +79,50 @@ abstract public class MidiPort implements Closeable {
     */
    protected static int packMessage(byte[] message, int offset, int size, long timestamp,
            byte[] dest) {
        // pack variable length message first
        if (size + TIMESTAMP_SIZE > MAX_PACKET_SIZE) {
            size = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
        }
        // message data goes 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;

        // followed by timestamp
        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
            dest[size++] = (byte)timestamp;
            timestamp >>= 8;
        }

        return destOffset;
        return size;
    }

    /**
     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
     * returns the offet of of MIDI message in packed buffer
     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
     * returns the offset of the MIDI message in packed buffer
     */
    protected static int getMessageOffset(byte[] buffer, int bufferLength) {
        // message is at start of buffer
        // message is at the beginning
        return 0;
    }

    /**
     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
     * returns size of MIDI message in packed buffer
     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
     * returns size of MIDI data in packed buffer
     */
    protected static int getMessageSize(byte[] buffer, int bufferLength) {
        // message length is total buffer length minus size of the timestamp and port number
        return bufferLength - 8 /* sizeof(timestamp) */;
        // message length is total buffer length minus size of the timestamp
        return bufferLength - TIMESTAMP_SIZE;
    }

    /**
     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
     * unpacks timestamp from packed buffer
     */
    protected static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
        // timestamp is at end of the packet
        int offset = bufferLength;
        long timestamp = 0;

        // timestamp follows variable length message data
        int dataLength = getMessageSize(buffer, bufferLength);
        for (int i = dataLength + 7; i >= dataLength; i--) {
            int b = (int)buffer[i] & 0xFF;
        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
            int b = (int)buffer[--offset] & 0xFF;
            timestamp = (timestamp << 8) | b;
        }
        return timestamp;
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ public interface MidiReceiver {
     * 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 onPost() method.
     *
     * @param msg a byte array containing the MIDI message
     * @param offset the offset of the first byte of the message in the byte array
+0 −65
Original line number Diff line number Diff line
/*
 * 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";

    private 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;
        }
    }
}
Loading