Index: media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java |
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java b/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c17974d1fa84d28c88673b3fde686f2ca527fa6e |
--- /dev/null |
+++ b/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java |
@@ -0,0 +1,161 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.media.midi; |
+ |
+import android.content.Context; |
+import android.media.midi.MidiDevice; |
+import android.media.midi.MidiDeviceInfo; |
+import android.media.midi.MidiManager; |
+import android.os.Handler; |
+ |
+import org.chromium.base.ThreadUtils; |
+import org.chromium.base.annotations.CalledByNative; |
+import org.chromium.base.annotations.JNINamespace; |
+ |
+import java.util.ArrayList; |
+import java.util.HashSet; |
+import java.util.List; |
+import java.util.Set; |
+ |
+/** |
+ * A Java class implementing media::midi::MidiManagerAndroid functionality. |
+ */ |
+@JNINamespace("media::midi") |
+class MidiManagerAndroid { |
+ /** |
+ * Set true while this instance is being initialized. |
+ */ |
+ private boolean mIsInitializing = true; |
+ /** |
+ * The devices held by this manager. |
+ */ |
+ private final List<MidiDeviceAndroid> mDevices = new ArrayList<>(); |
+ /** |
+ * The device information instances which are being initialized. |
+ */ |
+ private final Set<MidiDeviceInfo> mPendingDevices = new HashSet<>(); |
+ /** |
+ * The underlying MidiManager. |
+ */ |
+ private final MidiManager mManager; |
+ /** |
+ * Callbacks will run on the message queue associated with this handler. |
+ */ |
+ private final Handler mHandler; |
+ /** |
+ * The associated media::midi::MidiDeviceAndroid instance. |
+ */ |
+ private final long mNativeManagerPointer; |
+ |
+ @CalledByNative |
+ /** |
+ * A creation function called by C++. |
+ * @param context |
+ * @param nativeManagerPointer The native pointer to a media::midi::MidiManagerAndroid object. |
+ */ |
+ static MidiManagerAndroid create(Context context, long nativeManagerPointer) { |
+ return new MidiManagerAndroid(context, nativeManagerPointer); |
+ } |
+ |
+ /** |
+ * @param context |
+ * @param nativeManagerPointer The native pointer to a media::midi::MidiManagerAndroid object. |
+ */ |
+ MidiManagerAndroid(Context context, long nativeManagerPointer) { |
+ assert ThreadUtils.runningOnUiThread(); |
+ |
+ mManager = (MidiManager) context.getSystemService(Context.MIDI_SERVICE); |
+ mHandler = new Handler(ThreadUtils.getUiThreadLooper()); |
+ mNativeManagerPointer = nativeManagerPointer; |
+ } |
+ |
+ /** |
+ * Initializes this object. |
+ * This function must be called right after creation. |
+ */ |
+ @CalledByNative |
+ void initialize() { |
+ mManager.registerDeviceCallback(new MidiManager.DeviceCallback() { |
+ @Override |
+ public void onDeviceAdded(MidiDeviceInfo device) { |
+ MidiManagerAndroid.this.onDeviceAdded(device); |
+ } |
+ |
+ @Override |
+ public void onDeviceRemoved(MidiDeviceInfo device) { |
+ MidiManagerAndroid.this.onDeviceRemoved(device); |
+ } |
+ }, mHandler); |
+ MidiDeviceInfo[] infos = mManager.getDevices(); |
+ |
+ for (final MidiDeviceInfo info : infos) { |
+ mPendingDevices.add(info); |
+ openDevice(info); |
+ } |
+ mHandler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ if (mPendingDevices.isEmpty() && mIsInitializing) { |
+ nativeOnInitialized( |
+ mNativeManagerPointer, mDevices.toArray(new MidiDeviceAndroid[0])); |
+ mIsInitializing = false; |
+ } |
+ } |
+ }); |
+ } |
+ |
+ private void openDevice(final MidiDeviceInfo info) { |
+ mManager.openDevice(info, new MidiManager.OnDeviceOpenedListener() { |
+ @Override |
+ public void onDeviceOpened(MidiDevice device) { |
+ MidiManagerAndroid.this.onDeviceOpened(device, info); |
+ } |
+ }, mHandler); |
+ } |
+ |
+ /** |
+ * Called when a midi device is attached. |
+ * @param info the attached device information. |
+ */ |
+ private void onDeviceAdded(final MidiDeviceInfo info) { |
+ if (mIsInitializing) { |
+ mPendingDevices.add(info); |
+ } |
+ openDevice(info); |
+ } |
+ |
+ /** |
+ * Called when a midi device is detached. |
+ * @param info the detached device information. |
+ */ |
+ private void onDeviceRemoved(MidiDeviceInfo info) { |
+ for (MidiDeviceAndroid device : mDevices) { |
+ if (device.isOpen() && device.getInfo().getId() == info.getId()) { |
+ device.close(); |
+ nativeOnDetached(mNativeManagerPointer, device); |
+ } |
+ } |
+ } |
+ |
+ private void onDeviceOpened(MidiDevice device, MidiDeviceInfo info) { |
+ mPendingDevices.remove(info); |
+ if (device != null) { |
+ MidiDeviceAndroid xdevice = new MidiDeviceAndroid(device); |
+ mDevices.add(xdevice); |
+ if (!mIsInitializing) { |
+ nativeOnAttached(mNativeManagerPointer, xdevice); |
+ } |
+ } |
+ if (mIsInitializing && mPendingDevices.isEmpty()) { |
+ nativeOnInitialized(mNativeManagerPointer, mDevices.toArray(new MidiDeviceAndroid[0])); |
+ mIsInitializing = false; |
+ } |
+ } |
+ |
+ static native void nativeOnInitialized( |
+ long nativeMidiManagerAndroid, MidiDeviceAndroid[] devices); |
+ static native void nativeOnAttached(long nativeMidiManagerAndroid, MidiDeviceAndroid device); |
+ static native void nativeOnDetached(long nativeMidiManagerAndroid, MidiDeviceAndroid device); |
+} |