167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood/*
267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Copyright (C) 2014 The Android Open Source Project
367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood *
467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * you may not use this file except in compliance with the License.
667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * You may obtain a copy of the License at
767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood *
867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood *
1067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Unless required by applicable law or agreed to in writing, software
1167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * See the License for the specific language governing permissions and
1467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * limitations under the License.
1567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood */
1667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood
17b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwoodpackage android.media.midi;
1867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood
1967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport java.io.IOException;
2067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood
2167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood/**
22b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood * Interface for sending and receiving data to and from a MIDI device.
2367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood */
243b7664589be22ddad34b72e11ced937d48660ebbMike Lockwoodabstract public class MidiReceiver {
257eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood
267eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    private final int mMaxMessageSize;
277eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood
2878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood    /**
297eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Default MidiReceiver constructor. Maximum message size is set to
307eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * {@link java.lang.Integer#MAX_VALUE}
317eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     */
327eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    public MidiReceiver() {
337eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood        mMaxMessageSize = Integer.MAX_VALUE;
347eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    }
357eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood
367eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    /**
377eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * MidiReceiver constructor.
387eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * @param maxMessageSize the maximum size of a message this receiver can receive
397eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     */
407eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    public MidiReceiver(int maxMessageSize) {
417eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood        mMaxMessageSize = maxMessageSize;
427eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    }
437eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood
447eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    /**
457eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Called whenever the receiver is passed new MIDI data.
467eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Subclasses override this method to receive MIDI data.
4781b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * May fail if count exceeds {@link #getMaxMessageSize}.
4878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     *
4978beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     * NOTE: the msg array parameter is only valid within the context of this call.
5078beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     * The msg bytes should be copied by the receiver rather than retaining a reference
5178beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     * to this parameter.
52cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     * Also, modifying the contents of the msg array parameter may result in other receivers
537eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * in the same application receiving incorrect values in their {link #onSend} method.
5478beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     *
55a7e348eb4d2ef1632f2ebe3a742743607ccfd82bMike Lockwood     * @param msg a byte array containing the MIDI data
5681b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param offset the offset of the first byte of the data in the array to be processed
5781b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param count the number of bytes of MIDI data in the array to be processed
5878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     * @param timestamp the timestamp of the message (based on {@link java.lang.System#nanoTime}
5978beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     * @throws IOException
6078beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood     */
617eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    abstract public void onSend(byte[] msg, int offset, int count, long timestamp)
623b7664589be22ddad34b72e11ced937d48660ebbMike Lockwood            throws IOException;
630c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood
640c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood    /**
657eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Instructs the receiver to discard all pending MIDI data.
66b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * @throws IOException
67b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
68b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public void flush() throws IOException {
697eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood        onFlush();
707eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    }
717eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood
727eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    /**
737eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Called when the receiver is instructed to discard all pending MIDI data.
747eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Subclasses should override this method if they maintain a list or queue of MIDI data
757eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * to be processed in the future.
767eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * @throws IOException
777eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     */
787eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    public void onFlush() throws IOException {
79b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    }
80b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
81b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
820c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     * Returns the maximum size of a message this receiver can receive.
830c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     * @return maximum message size
840c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     */
857eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    public final int getMaxMessageSize() {
867eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood        return mMaxMessageSize;
870c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood    }
880c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood
890c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood    /**
90a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten     * Called to send MIDI data to the receiver without a timestamp.
91a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten     * Data will be processed by receiver in the order sent.
927eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Data will get split into multiple calls to {@link #onSend} if count exceeds
935db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * {@link #getMaxMessageSize}.  Blocks until all the data is sent or an exception occurs.
945db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * In the latter case, the amount of data sent prior to the exception is not provided to caller.
955db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * The communication should be considered corrupt.  The sender should reestablish
965db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * communication, reset all controllers and send all notes off.
9781b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     *
9881b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param msg a byte array containing the MIDI data
9981b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param offset the offset of the first byte of the data in the array to be sent
10081b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param count the number of bytes of MIDI data in the array to be sent
1015db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * @throws IOException if the data could not be sent in entirety
10281b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     */
10381b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood    public void send(byte[] msg, int offset, int count) throws IOException {
104a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten        // TODO add public static final TIMESTAMP_NONE = 0L
105a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten        send(msg, offset, count, 0L);
10681b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood    }
10781b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood
10881b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood    /**
109a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten     * Called to send MIDI data to the receiver with a specified timestamp.
110a32d5c8472bd5aad855165edf6d7253e35e42393Glenn Kasten     * Data will be processed by receiver in order first by timestamp, then in the order sent.
1117eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood     * Data will get split into multiple calls to {@link #onSend} if count exceeds
1125db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * {@link #getMaxMessageSize}.  Blocks until all the data is sent or an exception occurs.
1135db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * In the latter case, the amount of data sent prior to the exception is not provided to caller.
1145db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * The communication should be considered corrupt.  The sender should reestablish
1155db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * communication, reset all controllers and send all notes off.
1160c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     *
1170c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     * @param msg a byte array containing the MIDI data
11881b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param offset the offset of the first byte of the data in the array to be sent
11981b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood     * @param count the number of bytes of MIDI data in the array to be sent
1205db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * @param timestamp the timestamp of the message, based on {@link java.lang.System#nanoTime}
1215db6637f8c6c8b3365f0476f1264bf19dfbc7207Glenn Kasten     * @throws IOException if the data could not be sent in entirety
1220c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood     */
1237eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood    public void send(byte[] msg, int offset, int count, long timestamp)
12481b9f7d325a552c54e793b51f571ae3d65b26e94Mike Lockwood            throws IOException {
1250c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood        int messageSize = getMaxMessageSize();
1260c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood        while (count > 0) {
1270c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood            int length = (count > messageSize ? messageSize : count);
1287eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood            onSend(msg, offset, length, timestamp);
1290c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood            offset += length;
1300c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood            count -= length;
1310c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood        }
1320c7342f0153076c88ba8e6a1647999c248787906Mike Lockwood    }
13367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood}
134