ParcelFileDescriptor openInputPort(IBinder token, int portNumber);
ParcelFileDescriptor openOutputPort(IBinder token, int portNumber);
void closePort(IBinder token);
+
+ // connects the input port pfd to the specified output port
+ void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
}
import dalvik.system.CloseGuard;
+import libcore.io.IoUtils;
+
import java.io.Closeable;
import java.io.IOException;
private Context mContext;
private ServiceConnection mServiceConnection;
+
private final CloseGuard mGuard = CloseGuard.get();
+ public class MidiConnection implements Closeable {
+ private final IBinder mToken;
+ private final MidiInputPort mInputPort;
+
+ MidiConnection(IBinder token, MidiInputPort inputPort) {
+ mToken = token;
+ mInputPort = inputPort;
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ mDeviceServer.closePort(mToken);
+ IoUtils.closeQuietly(mInputPort);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in MidiConnection.close");
+ }
+ }
+ }
+
/* package */ MidiDevice(MidiDeviceInfo deviceInfo, IMidiDeviceServer server) {
this(deviceInfo, server, null, null);
}
}
}
+ /**
+ * Connects the supplied {@link MidiInputPort} to the output port of this device
+ * with the specified port number. Once the connection is made, the MidiInput port instance
+ * can no longer receive data via its {@link MidiReciever.receive} method.
+ * This method returns a {@link #MidiConnection} object, which can be used to close the connection
+ * @param inputPort the inputPort to connect
+ * @param outputPortNumber the port number of the output port to connect inputPort to.
+ * @return {@link #MidiConnection} object if the connection is successful, or null in case of failure
+ */
+ public MidiConnection connectPorts(MidiInputPort inputPort, int outputPortNumber) {
+ if (outputPortNumber < 0 || outputPortNumber >= mDeviceInfo.getOutputPortCount()) {
+ throw new IllegalArgumentException("outputPortNumber out of range");
+ }
+
+ ParcelFileDescriptor pfd = inputPort.claimFileDescriptor();
+ if (pfd == null) {
+ return null;
+ }
+ try {
+ IBinder token = new Binder();
+ mDeviceServer.connectPorts(token, pfd, outputPortNumber);
+ // close our copy of the file descriptor
+ IoUtils.closeQuietly(pfd);
+ return new MidiConnection(token, inputPort);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in connectPorts");
+ return null;
+ }
+ }
+
@Override
public void close() throws IOException {
synchronized (mGuard) {
}
}
}
+
+ @Override
+ public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
+ int outputPortNumber) {
+ MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
+ mOutputPortDispatchers[outputPortNumber].getSender().connect(inputPort);
+ mInputPorts.add(inputPort);
+ OutputPortClient client = new OutputPortClient(token, inputPort);
+ synchronized (mPortClients) {
+ mPortClients.put(token, client);
+ }
+ }
};
/* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
private IMidiDeviceServer mDeviceServer;
private final IBinder mToken;
private final int mPortNumber;
- private final FileOutputStream mOutputStream;
+ private ParcelFileDescriptor mParcelFileDescriptor;
+ private FileOutputStream mOutputStream;
private final CloseGuard mGuard = CloseGuard.get();
private boolean mIsClosed;
ParcelFileDescriptor pfd, int portNumber) {
mDeviceServer = server;
mToken = token;
+ mParcelFileDescriptor = pfd;
mPortNumber = portNumber;
- mOutputStream = new ParcelFileDescriptor.AutoCloseOutputStream(pfd);
+ mOutputStream = new FileOutputStream(pfd.getFileDescriptor());
mGuard.open("close");
}
}
synchronized (mBuffer) {
+ if (mOutputStream == null) {
+ throw new IOException("MidiInputPort is closed");
+ }
int length = MidiPortImpl.packMessage(msg, offset, count, timestamp, mBuffer);
mOutputStream.write(mBuffer, 0, length);
}
}
+ // used by MidiDevice.connectInputPort() to connect our socket directly to another device
+ /* package */ ParcelFileDescriptor claimFileDescriptor() {
+ synchronized (mBuffer) {
+ ParcelFileDescriptor pfd = mParcelFileDescriptor;
+ if (pfd != null) {
+ IoUtils.closeQuietly(mOutputStream);
+ mParcelFileDescriptor = null;
+ mOutputStream = null;
+ }
+ return pfd;
+ }
+ }
+
@Override
public int getMaxMessageSize() {
return MidiPortImpl.MAX_PACKET_DATA_SIZE;
synchronized (mGuard) {
if (mIsClosed) return;
mGuard.close();
- mOutputStream.close();
+ synchronized (mBuffer) {
+ if (mParcelFileDescriptor != null) {
+ mParcelFileDescriptor.close();
+ mParcelFileDescriptor = null;
+ }
+ if (mOutputStream != null) {
+ mOutputStream.close();
+ mOutputStream = null;
+ }
+ }
if (mDeviceServer != null) {
try {
mDeviceServer.closePort(mToken);