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.mobileer.miditools;
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 midiManager
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      * Then notify listener of the result.
104      *
105      * @param sourceDeviceInfo
106      * @param sourcePortIndex
107      * @param destinationDeviceInfo
108      * @param destinationPortIndex
109      * @param listener
110      * @param handler
111      */
connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, final int sourcePortIndex, final MidiDeviceInfo destinationDeviceInfo, final int destinationPortIndex, final OnPortsConnectedListener listener, final Handler handler)112     public void connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo,
113             final int sourcePortIndex,
114             final MidiDeviceInfo destinationDeviceInfo,
115             final int destinationPortIndex,
116             final OnPortsConnectedListener listener, final Handler handler) {
117         safeClose();
118         mMidiManager.openDevice(destinationDeviceInfo,
119                 new MidiManager.OnDeviceOpenedListener() {
120                     @Override
121                     public void onDeviceOpened(MidiDevice destinationDevice) {
122                         if (destinationDevice == null) {
123                             Log.e(MidiConstants.TAG,
124                                     "could not open " + destinationDeviceInfo);
125                             if (listener != null) {
126                                 listener.onPortsConnected(null);
127                             }
128                         } else {
129                             mDestinationDevice = destinationDevice;
130                             Log.i(MidiConstants.TAG,
131                                     "connectToDevicePort opened "
132                                             + destinationDeviceInfo);
133                             // Destination device was opened so go to next step.
134                             MidiInputPort destinationInputPort = destinationDevice
135                                     .openInputPort(destinationPortIndex);
136                             if (destinationInputPort != null) {
137                                 Log.i(MidiConstants.TAG,
138                                         "connectToDevicePort opened port on "
139                                                 + destinationDeviceInfo);
140                                 connectToDevicePort(sourceDeviceInfo,
141                                         sourcePortIndex,
142                                         destinationInputPort,
143                                         listener, handler);
144                             } else {
145                                 Log.e(MidiConstants.TAG,
146                                         "could not open port on "
147                                                 + destinationDeviceInfo);
148                                 safeClose();
149                                 if (listener != null) {
150                                     listener.onPortsConnected(null);
151                                 }
152                             }
153                         }
154                     }
155                 }, handler);
156     }
157 
158 
159     /**
160      * Open a source device and connect its output port to the
161      * destinationInputPort.
162      *
163      * @param sourceDeviceInfo
164      * @param sourcePortIndex
165      * @param destinationInputPort
166      */
connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo, final int sourcePortIndex, final MidiInputPort destinationInputPort, final OnPortsConnectedListener listener, final Handler handler)167     private void connectToDevicePort(final MidiDeviceInfo sourceDeviceInfo,
168             final int sourcePortIndex,
169             final MidiInputPort destinationInputPort,
170             final OnPortsConnectedListener listener, final Handler handler) {
171         mMidiManager.openDevice(sourceDeviceInfo,
172                 new MidiManager.OnDeviceOpenedListener() {
173                     @Override
174                     public void onDeviceOpened(MidiDevice device) {
175                         if (device == null) {
176                             Log.e(MidiConstants.TAG,
177                                     "could not open " + sourceDeviceInfo);
178                             safeClose();
179                             if (listener != null) {
180                                 listener.onPortsConnected(null);
181                             }
182                         } else {
183                             Log.i(MidiConstants.TAG,
184                                     "connectToDevicePort opened "
185                                             + sourceDeviceInfo);
186                             // Device was opened so connect the ports.
187                             mSourceDevice = device;
188                             mConnection = device.connectPorts(
189                                     destinationInputPort, sourcePortIndex);
190                             if (mConnection == null) {
191                                 Log.e(MidiConstants.TAG, "could not connect to "
192                                         + sourceDeviceInfo);
193                                 safeClose();
194                             }
195                             if (listener != null) {
196                                 listener.onPortsConnected(mConnection);
197                             }
198                         }
199                     }
200                 }, handler);
201     }
202 
203 }
204