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