1b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood/*
2b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * Copyright (C) 2014 The Android Open Source Project
3b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood *
4b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * you may not use this file except in compliance with the License.
6b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * You may obtain a copy of the License at
7b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood *
8b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood *
10b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * Unless required by applicable law or agreed to in writing, software
11b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * See the License for the specific language governing permissions and
14b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood * limitations under the License.
15b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood */
16b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood
17b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwoodpackage android.media.midi;
18b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood
19b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood/**
2020821ecbe81ba52b260ae232096bc2bfb3e92ad0Mike Lockwood * This class contains utilities for socket communication between a
2120821ecbe81ba52b260ae232096bc2bfb3e92ad0Mike Lockwood * MidiInputPort and MidiOutputPort
22b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood */
2320821ecbe81ba52b260ae232096bc2bfb3e92ad0Mike Lockwood/* package */ class MidiPortImpl {
2410024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    private static final String TAG = "MidiPort";
25b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood
2610024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
27b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Packet type for data packet
28b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
29b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static final int PACKET_TYPE_DATA = 1;
30b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
31b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
32b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Packet type for flush packet
33b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
34b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static final int PACKET_TYPE_FLUSH = 2;
35b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
36b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
37b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood     * Maximum size of a packet that can pass through our ParcelFileDescriptor.
3810024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
39b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood    public static final int MAX_PACKET_SIZE = 1024;
4010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
4110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
42cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     * size of message timestamp in bytes
4310024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
44cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood    private static final int TIMESTAMP_SIZE = 8;
45cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood
46cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood    /**
47b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Data packet overhead is timestamp size plus packet type byte
48b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
49b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    private static final int DATA_PACKET_OVERHEAD = TIMESTAMP_SIZE + 1;
50b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
51b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
52cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     * Maximum amount of MIDI data that can be included in a packet
53cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     */
54b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static final int MAX_PACKET_DATA_SIZE = MAX_PACKET_SIZE - DATA_PACKET_OVERHEAD;
5510024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
5610024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
57b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Utility function for packing MIDI data to be sent through our ParcelFileDescriptor
5810024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     *
5910024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * message byte array contains variable length MIDI message.
6010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * messageSize is size of variable length MIDI message
6110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * timestamp is message timestamp to pack
6210024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * dest is buffer to pack into
6310024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * returns size of packed message
6410024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
65b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static int packData(byte[] message, int offset, int size, long timestamp,
6610024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood            byte[] dest) {
67b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        if (size  > MAX_PACKET_DATA_SIZE) {
68b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood            size = MAX_PACKET_DATA_SIZE;
69cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        }
70b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        int length = 0;
71b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        // packet type goes first
72b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        dest[length++] = PACKET_TYPE_DATA;
73b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        // data goes next
74b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        System.arraycopy(message, offset, dest, length, size);
75b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        length += size;
76cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood
77cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        // followed by timestamp
78cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
79b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood            dest[length++] = (byte)timestamp;
8010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood            timestamp >>= 8;
8110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood        }
8210024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
83b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        return length;
84b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    }
85b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
86b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
87b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Utility function for packing a flush command to be sent through our ParcelFileDescriptor
88b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
89b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static int packFlush(byte[] dest) {
90b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        dest[0] = PACKET_TYPE_FLUSH;
91b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        return 1;
92b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    }
93b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood
94b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    /**
95b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Returns the packet type (PACKET_TYPE_DATA or PACKET_TYPE_FLUSH)
96b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     */
97b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static int getPacketType(byte[] buffer, int bufferLength) {
98b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        return buffer[0];
9910024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    }
10010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
10110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
102b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Utility function for unpacking MIDI data received from our ParcelFileDescriptor
103cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     * returns the offset of the MIDI message in packed buffer
10410024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
105b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static int getDataOffset(byte[] buffer, int bufferLength) {
106b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        // data follows packet type byte
107b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        return 1;
10810024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    }
10910024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
11010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
111b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Utility function for unpacking MIDI data received from our ParcelFileDescriptor
112cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood     * returns size of MIDI data in packed buffer
11310024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
114b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static int getDataSize(byte[] buffer, int bufferLength) {
115cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        // message length is total buffer length minus size of the timestamp
116b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood        return bufferLength - DATA_PACKET_OVERHEAD;
11710024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    }
11810024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
11910024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood    /**
120b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood     * Utility function for unpacking MIDI data received from our ParcelFileDescriptor
12110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     * unpacks timestamp from packed buffer
12210024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood     */
123b6f50d357bd3d4d296be6bb047f5ce93a79cbca1Mike Lockwood    public static long getPacketTimestamp(byte[] buffer, int bufferLength) {
124cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        // timestamp is at end of the packet
125cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        int offset = bufferLength;
12610024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood        long timestamp = 0;
12710024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood
128cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
129cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood            int b = (int)buffer[--offset] & 0xFF;
13010024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood            timestamp = (timestamp << 8) | b;
13110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood        }
13210024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood        return timestamp;
133cb096273734d96f4676014fa9030b57ea48b58d8Mike Lockwood    }
134b6b9a91c02b7a44cf56943e5358cee68fa4aece5Mike Lockwood}
135