// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.midi;
import android.media.midi.MidiDevice;
import android.media.midi.MidiOutputPort;
import android.media.midi.MidiReceiver;
import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
import java.io.IOException;
// Note "InputPort" is named in the Web MIDI manner. It corresponds to MidiOutputPort class in the
// Android API.
/** A MidiInputPortAndroid provides data to the associated midi::MidiInputPortAndroid object. */
@JNINamespace("midi")
class MidiInputPortAndroid {
/** The underlying port. */
private MidiOutputPort mPort;
/** A pointer to a midi::MidiInputPortAndroid object. */
private long mNativeReceiverPointer;
/** The device this port belongs to. */
private final MidiDevice mDevice;
/** The index of the port in the associated device. */
private final int mIndex;
/**
* constructor
* @param device the device this port belongs to.
* @param index the index of the port in the associated device.
*/
MidiInputPortAndroid(MidiDevice device, int index) {
mDevice = device;
mIndex = index;
}
/**
* Registers this object to the underlying port so as to the C++ function will be called with
* the given C++ object when data arrives.
* @param nativeReceiverPointer a pointer to a midi::MidiInputPortAndroid object.
* @return true if this operation succeeds or the port is already open.
*/
@CalledByNative
boolean open(long nativeReceiverPointer) {
if (mPort != null) {
return true;
}
mPort = mDevice.openOutputPort(mIndex);
if (mPort == null) {
return false;
}
mNativeReceiverPointer = nativeReceiverPointer;
mPort.connect(
new MidiReceiver() {
@Override
public void onSend(byte[] bs, int offset, int count, long timestamp) {
synchronized (MidiInputPortAndroid.this) {
if (mPort == null) {
return;
}
MidiInputPortAndroidJni.get()
.onData(mNativeReceiverPointer, bs, offset, count, timestamp);
}
}
});
return true;
}
/** Closes the port. */
@CalledByNative
synchronized void close() {
if (mPort == null) {
return;
}
try {
mPort.close();
} catch (IOException e) {
// We can do nothing here. Just ignore the error.
}
mNativeReceiverPointer = 0;
mPort = null;
}
@NativeMethods
interface Natives {
void onData(
long nativeMidiInputPortAndroid, byte[] bs, int offset, int count, long timestamp);
}
}