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      */
MidiPortConnector(MidiManager midiManager)41     public MidiPortConnector(MidiManager midiManager) {
42         mMidiManager = midiManager;
43     }
44 
close()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 
safeClose()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          */
onPortsConnected(MidiConnection connection)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      */
connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, final int sourcePortIndex, final MidiDeviceInfo destinationDeviceInfo, final int destinationPortIndex)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      */
connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, final int sourcePortIndex, final MidiDeviceInfo destinationDeviceInfo, final int destinationPortIndex, final OnPortsConnectedListener listener, final Handler handler)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      */
connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, final int sourcePortIndex, final MidiInputPort destinationInputPort, final OnPortsConnectedListener listener, final Handler handler)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