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.common.midi; 18 19 import android.media.midi.MidiDevice; 20 import android.media.midi.MidiDevice.MidiConnection; 21 import android.media.midi.MidiDeviceInfo; 22 import android.media.midi.MidiInputPort; 23 import android.media.midi.MidiManager; 24 import android.os.Handler; 25 import android.util.Log; 26 27 import java.io.IOException; 28 29 /** 30 * Tool for connecting MIDI ports on two remote devices. 31 */ 32 public class MidiPortConnector { 33 private final MidiManager mMidiManager; 34 private MidiDevice mSourceDevice; 35 private MidiDevice mDestinationDevice; 36 private MidiConnection mConnection; 37 38 /** 39 * @param mMidiManager 40 */ 41 public MidiPortConnector(MidiManager midiManager) { 42 mMidiManager = midiManager; 43 } 44 45 public void close() throws IOException { 46 if (mConnection != null) { 47 Log.i(MidiConstants.TAG, 48 "MidiPortConnector closing connection " + mConnection); 49 mConnection.close(); 50 mConnection = null; 51 } 52 if (mSourceDevice != null) { 53 mSourceDevice.close(); 54 mSourceDevice = null; 55 } 56 if (mDestinationDevice != null) { 57 mDestinationDevice.close(); 58 mDestinationDevice = null; 59 } 60 } 61 62 private void safeClose() { 63 try { 64 close(); 65 } catch (IOException e) { 66 Log.e(MidiConstants.TAG, "could not close resources", e); 67 } 68 } 69 70 /** 71 * Listener class used for receiving the results of 72 * {@link #connectToDevicePort} 73 */ 74 public interface OnPortsConnectedListener { 75 /** 76 * Called to respond to a {@link #connectToDevicePort} request 77 * 78 * @param connection 79 * a {@link MidiConnection} that represents the connected 80 * ports, or null if connection failed 81 */ 82 abstract public void onPortsConnected(MidiConnection connection); 83 } 84 85 /** 86 * Open two devices and connect their ports. 87 * 88 * @param sourceDeviceInfo 89 * @param sourcePortIndex 90 * @param destinationDeviceInfo 91 * @param destinationPortIndex 92 */ 93 public void connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, 94 final int sourcePortIndex, 95 final MidiDeviceInfo destinationDeviceInfo, 96 final int destinationPortIndex) { 97 connectToDevicePort(sourceDeviceInfo, sourcePortIndex, 98 destinationDeviceInfo, destinationPortIndex, null, null); 99 } 100 101 /** 102 * Open two devices and connect their ports. 103 * 104 * @param sourceDeviceInfo 105 * @param sourcePortIndex 106 * @param destinationDeviceInfo 107 * @param destinationPortIndex 108 */ 109 public void connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, 110 final int sourcePortIndex, 111 final MidiDeviceInfo destinationDeviceInfo, 112 final int destinationPortIndex, 113 final OnPortsConnectedListener listener, final Handler handler) { 114 safeClose(); 115 mMidiManager.openDevice(destinationDeviceInfo, 116 new MidiManager.OnDeviceOpenedListener() { 117 @Override 118 public void onDeviceOpened(MidiDevice destinationDevice) { 119 if (destinationDevice == null) { 120 Log.e(MidiConstants.TAG, 121 "could not open " + destinationDeviceInfo); 122 if (listener != null) { 123 listener.onPortsConnected(null); 124 } 125 } else { 126 mDestinationDevice = destinationDevice; 127 Log.i(MidiConstants.TAG, 128 "connectToDevicePort opened " 129 + destinationDeviceInfo); 130 // Destination device was opened so go to next step. 131 MidiInputPort destinationInputPort = destinationDevice 132 .openInputPort(destinationPortIndex); 133 if (destinationInputPort != null) { 134 Log.i(MidiConstants.TAG, 135 "connectToDevicePort opened port on " 136 + destinationDeviceInfo); 137 connectToDevicePort(sourceDeviceInfo, 138 sourcePortIndex, 139 destinationInputPort, 140 listener, handler); 141 } else { 142 Log.e(MidiConstants.TAG, 143 "could not open port on " 144 + destinationDeviceInfo); 145 safeClose(); 146 if (listener != null) { 147 listener.onPortsConnected(null); 148 } 149 } 150 } 151 } 152 }, handler); 153 } 154 155 156 /** 157 * Open a source device and connect its output port to the 158 * destinationInputPort. 159 * 160 * @param sourceDeviceInfo 161 * @param sourcePortIndex 162 * @param destinationInputPort 163 */ 164 private void connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, 165 final int sourcePortIndex, 166 final MidiInputPort destinationInputPort, 167 final OnPortsConnectedListener listener, final Handler handler) { 168 mMidiManager.openDevice(sourceDeviceInfo, 169 new MidiManager.OnDeviceOpenedListener() { 170 @Override 171 public void onDeviceOpened(MidiDevice device) { 172 if (device == null) { 173 Log.e(MidiConstants.TAG, 174 "could not open " + sourceDeviceInfo); 175 safeClose(); 176 if (listener != null) { 177 listener.onPortsConnected(null); 178 } 179 } else { 180 Log.i(MidiConstants.TAG, 181 "connectToDevicePort opened " 182 + sourceDeviceInfo); 183 // Device was opened so connect the ports. 184 mSourceDevice = device; 185 mConnection = device.connectPorts( 186 destinationInputPort, sourcePortIndex); 187 if (mConnection == null) { 188 Log.e(MidiConstants.TAG, "could not connect to " 189 + sourceDeviceInfo); 190 safeClose(); 191 } 192 if (listener != null) { 193 listener.onPortsConnected(mConnection); 194 } 195 } 196 } 197 }, handler); 198 } 199 200 } 201