1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker  *
4*90c8c64dSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker  *
8*90c8c64dSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker  *
10*90c8c64dSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker  * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker  */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.midiscope;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker import android.media.midi.MidiDeviceInfo;
20*90c8c64dSAndroid Build Coastguard Worker import android.media.midi.MidiDeviceInfo.PortInfo;
21*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle;
22*90c8c64dSAndroid Build Coastguard Worker 
23*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.midi.MidiConstants;
24*90c8c64dSAndroid Build Coastguard Worker 
25*90c8c64dSAndroid Build Coastguard Worker /**
26*90c8c64dSAndroid Build Coastguard Worker  * Format a MIDI message for printing.
27*90c8c64dSAndroid Build Coastguard Worker  */
28*90c8c64dSAndroid Build Coastguard Worker public class MidiPrinter {
29*90c8c64dSAndroid Build Coastguard Worker 
30*90c8c64dSAndroid Build Coastguard Worker     public static final String[] CHANNEL_COMMAND_NAMES = { "NoteOff", "NoteOn",
31*90c8c64dSAndroid Build Coastguard Worker             "PolyTouch", "Control", "Program", "Pressure", "Bend" };
32*90c8c64dSAndroid Build Coastguard Worker     public static final String[] SYSTEM_COMMAND_NAMES = { "SysEx", // F0
33*90c8c64dSAndroid Build Coastguard Worker             "TimeCode",    // F1
34*90c8c64dSAndroid Build Coastguard Worker             "SongPos",     // F2
35*90c8c64dSAndroid Build Coastguard Worker             "SongSel",     // F3
36*90c8c64dSAndroid Build Coastguard Worker             "F4",          // F4
37*90c8c64dSAndroid Build Coastguard Worker             "F5",          // F5
38*90c8c64dSAndroid Build Coastguard Worker             "TuneReq",     // F6
39*90c8c64dSAndroid Build Coastguard Worker             "EndSysex",    // F7
40*90c8c64dSAndroid Build Coastguard Worker             "TimingClock", // F8
41*90c8c64dSAndroid Build Coastguard Worker             "F9",          // F9
42*90c8c64dSAndroid Build Coastguard Worker             "Start",       // FA
43*90c8c64dSAndroid Build Coastguard Worker             "Continue",    // FB
44*90c8c64dSAndroid Build Coastguard Worker             "Stop",        // FC
45*90c8c64dSAndroid Build Coastguard Worker             "FD",          // FD
46*90c8c64dSAndroid Build Coastguard Worker             "ActiveSensing", // FE
47*90c8c64dSAndroid Build Coastguard Worker             "Reset"        // FF
48*90c8c64dSAndroid Build Coastguard Worker     };
49*90c8c64dSAndroid Build Coastguard Worker 
getName(int status)50*90c8c64dSAndroid Build Coastguard Worker     public static String getName(int status) {
51*90c8c64dSAndroid Build Coastguard Worker         if (status >= 0xF0) {
52*90c8c64dSAndroid Build Coastguard Worker             int index = status & 0x0F;
53*90c8c64dSAndroid Build Coastguard Worker             return SYSTEM_COMMAND_NAMES[index];
54*90c8c64dSAndroid Build Coastguard Worker         } else if (status >= 0x80) {
55*90c8c64dSAndroid Build Coastguard Worker             int index = (status >> 4) & 0x07;
56*90c8c64dSAndroid Build Coastguard Worker             return CHANNEL_COMMAND_NAMES[index];
57*90c8c64dSAndroid Build Coastguard Worker         } else {
58*90c8c64dSAndroid Build Coastguard Worker             return "data";
59*90c8c64dSAndroid Build Coastguard Worker         }
60*90c8c64dSAndroid Build Coastguard Worker     }
61*90c8c64dSAndroid Build Coastguard Worker 
formatBytes(byte[] data, int offset, int count)62*90c8c64dSAndroid Build Coastguard Worker     public static String formatBytes(byte[] data, int offset, int count) {
63*90c8c64dSAndroid Build Coastguard Worker         StringBuilder sb = new StringBuilder();
64*90c8c64dSAndroid Build Coastguard Worker         for (int i = 0; i < count; i++) {
65*90c8c64dSAndroid Build Coastguard Worker             sb.append(String.format(" %02X", data[offset + i]));
66*90c8c64dSAndroid Build Coastguard Worker         }
67*90c8c64dSAndroid Build Coastguard Worker         return sb.toString();
68*90c8c64dSAndroid Build Coastguard Worker     }
69*90c8c64dSAndroid Build Coastguard Worker 
formatMessage(byte[] data, int offset, int count)70*90c8c64dSAndroid Build Coastguard Worker     public static String formatMessage(byte[] data, int offset, int count) {
71*90c8c64dSAndroid Build Coastguard Worker         StringBuilder sb = new StringBuilder();
72*90c8c64dSAndroid Build Coastguard Worker         byte statusByte = data[offset++];
73*90c8c64dSAndroid Build Coastguard Worker         int status = statusByte & 0xFF;
74*90c8c64dSAndroid Build Coastguard Worker         sb.append(getName(status)).append("(");
75*90c8c64dSAndroid Build Coastguard Worker         int numData = MidiConstants.getBytesPerMessage(statusByte) - 1;
76*90c8c64dSAndroid Build Coastguard Worker         if ((status >= 0x80) && (status < 0xF0)) { // channel message
77*90c8c64dSAndroid Build Coastguard Worker             int channel = status & 0x0F;
78*90c8c64dSAndroid Build Coastguard Worker             // Add 1 for humans who think channels are numbered 1-16.
79*90c8c64dSAndroid Build Coastguard Worker             sb.append((channel + 1)).append(", ");
80*90c8c64dSAndroid Build Coastguard Worker         }
81*90c8c64dSAndroid Build Coastguard Worker         for (int i = 0; i < numData; i++) {
82*90c8c64dSAndroid Build Coastguard Worker             if (i > 0) {
83*90c8c64dSAndroid Build Coastguard Worker                 sb.append(", ");
84*90c8c64dSAndroid Build Coastguard Worker             }
85*90c8c64dSAndroid Build Coastguard Worker             sb.append(data[offset++]);
86*90c8c64dSAndroid Build Coastguard Worker         }
87*90c8c64dSAndroid Build Coastguard Worker         sb.append(")");
88*90c8c64dSAndroid Build Coastguard Worker         return sb.toString();
89*90c8c64dSAndroid Build Coastguard Worker     }
90*90c8c64dSAndroid Build Coastguard Worker 
formatDeviceInfo(MidiDeviceInfo info)91*90c8c64dSAndroid Build Coastguard Worker     public static String formatDeviceInfo(MidiDeviceInfo info) {
92*90c8c64dSAndroid Build Coastguard Worker         StringBuilder sb = new StringBuilder();
93*90c8c64dSAndroid Build Coastguard Worker         if (info != null) {
94*90c8c64dSAndroid Build Coastguard Worker             Bundle properties = info.getProperties();
95*90c8c64dSAndroid Build Coastguard Worker             for (String key : properties.keySet()) {
96*90c8c64dSAndroid Build Coastguard Worker                 Object value = properties.get(key);
97*90c8c64dSAndroid Build Coastguard Worker                 sb.append(key).append(" = ").append(value).append('\n');
98*90c8c64dSAndroid Build Coastguard Worker             }
99*90c8c64dSAndroid Build Coastguard Worker             for (PortInfo port : info.getPorts()) {
100*90c8c64dSAndroid Build Coastguard Worker                 sb.append((port.getType() == PortInfo.TYPE_INPUT) ? "input"
101*90c8c64dSAndroid Build Coastguard Worker                         : "output");
102*90c8c64dSAndroid Build Coastguard Worker                 sb.append("[").append(port.getPortNumber()).append("] = \"").append(port.getName()
103*90c8c64dSAndroid Build Coastguard Worker                         + "\"\n");
104*90c8c64dSAndroid Build Coastguard Worker             }
105*90c8c64dSAndroid Build Coastguard Worker         }
106*90c8c64dSAndroid Build Coastguard Worker         return sb.toString();
107*90c8c64dSAndroid Build Coastguard Worker     }
108*90c8c64dSAndroid Build Coastguard Worker }
109