OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.media.midi; | |
6 | |
7 import android.annotation.TargetApi; | |
8 import android.content.Context; | |
9 import android.media.midi.MidiDevice; | |
10 import android.media.midi.MidiDeviceInfo; | |
11 import android.media.midi.MidiManager; | |
12 import android.os.Build; | |
13 import android.os.Handler; | |
14 | |
15 import org.chromium.base.ThreadUtils; | |
16 import org.chromium.base.annotations.CalledByNative; | |
17 import org.chromium.base.annotations.JNINamespace; | |
18 | |
19 import java.util.ArrayList; | |
20 import java.util.HashSet; | |
21 import java.util.List; | |
22 import java.util.Set; | |
23 | |
24 /** | |
25 * A Java class implementing media::midi::MidiManagerAndroid functionality. | |
26 */ | |
27 @JNINamespace("media::midi") | |
28 @TargetApi(Build.VERSION_CODES.M) | |
29 class MidiManagerAndroid { | |
30 /** | |
31 * Set true when this instance is successfully initialized. | |
32 */ | |
33 private boolean mIsInitialized = false; | |
34 /** | |
35 * The devices held by this manager. | |
36 */ | |
37 private final List<MidiDeviceAndroid> mDevices = new ArrayList<>(); | |
38 /** | |
39 * The device information instances which are being initialized. | |
40 */ | |
41 private final Set<MidiDeviceInfo> mPendingDevices = new HashSet<>(); | |
42 /** | |
43 * The underlying MidiManager. | |
44 */ | |
45 private final MidiManager mManager; | |
46 /** | |
47 * Callbacks will run on the message queue associated with this handler. | |
48 */ | |
49 private final Handler mHandler; | |
50 /** | |
51 * The associated media::midi::MidiDeviceAndroid instance. | |
52 */ | |
53 private final long mNativeManagerPointer; | |
54 | |
55 /** | |
56 * A creation function called by C++. | |
57 * @param context | |
58 * @param nativeManagerPointer The native pointer to a media::midi::MidiMana
gerAndroid object. | |
59 */ | |
60 @CalledByNative | |
61 static MidiManagerAndroid create(Context context, long nativeManagerPointer)
{ | |
62 return new MidiManagerAndroid(context, nativeManagerPointer); | |
63 } | |
64 | |
65 /** | |
66 * @param context | |
67 * @param nativeManagerPointer The native pointer to a media::midi::MidiMana
gerAndroid object. | |
68 */ | |
69 private MidiManagerAndroid(Context context, long nativeManagerPointer) { | |
70 assert ThreadUtils.runningOnUiThread(); | |
71 | |
72 mManager = (MidiManager) context.getSystemService(Context.MIDI_SERVICE); | |
73 mHandler = new Handler(ThreadUtils.getUiThreadLooper()); | |
74 mNativeManagerPointer = nativeManagerPointer; | |
75 } | |
76 | |
77 /** | |
78 * Initializes this object. | |
79 * This function must be called right after creation. | |
80 */ | |
81 @CalledByNative | |
82 void initialize() { | |
83 if (mManager == null) { | |
84 mHandler.post(new Runnable() { | |
85 @Override | |
86 public void run() { | |
87 nativeOnInitializationFailed(mNativeManagerPointer); | |
88 } | |
89 }); | |
90 return; | |
91 } | |
92 mManager.registerDeviceCallback(new MidiManager.DeviceCallback() { | |
93 @Override | |
94 public void onDeviceAdded(MidiDeviceInfo device) { | |
95 MidiManagerAndroid.this.onDeviceAdded(device); | |
96 } | |
97 | |
98 @Override | |
99 public void onDeviceRemoved(MidiDeviceInfo device) { | |
100 MidiManagerAndroid.this.onDeviceRemoved(device); | |
101 } | |
102 }, mHandler); | |
103 MidiDeviceInfo[] infos = mManager.getDevices(); | |
104 | |
105 for (final MidiDeviceInfo info : infos) { | |
106 mPendingDevices.add(info); | |
107 openDevice(info); | |
108 } | |
109 mHandler.post(new Runnable() { | |
110 @Override | |
111 public void run() { | |
112 if (mPendingDevices.isEmpty() && !mIsInitialized) { | |
113 nativeOnInitialized( | |
114 mNativeManagerPointer, mDevices.toArray(new MidiDevi
ceAndroid[0])); | |
115 mIsInitialized = true; | |
116 } | |
117 } | |
118 }); | |
119 } | |
120 | |
121 private void openDevice(final MidiDeviceInfo info) { | |
122 mManager.openDevice(info, new MidiManager.OnDeviceOpenedListener() { | |
123 @Override | |
124 public void onDeviceOpened(MidiDevice device) { | |
125 MidiManagerAndroid.this.onDeviceOpened(device, info); | |
126 } | |
127 }, mHandler); | |
128 } | |
129 | |
130 /** | |
131 * Called when a midi device is attached. | |
132 * @param info the attached device information. | |
133 */ | |
134 private void onDeviceAdded(final MidiDeviceInfo info) { | |
135 if (!mIsInitialized) { | |
136 mPendingDevices.add(info); | |
137 } | |
138 openDevice(info); | |
139 } | |
140 | |
141 /** | |
142 * Called when a midi device is detached. | |
143 * @param info the detached device information. | |
144 */ | |
145 private void onDeviceRemoved(MidiDeviceInfo info) { | |
146 for (MidiDeviceAndroid device : mDevices) { | |
147 if (device.isOpen() && device.getInfo().getId() == info.getId()) { | |
148 device.close(); | |
149 nativeOnDetached(mNativeManagerPointer, device); | |
150 } | |
151 } | |
152 } | |
153 | |
154 private void onDeviceOpened(MidiDevice device, MidiDeviceInfo info) { | |
155 mPendingDevices.remove(info); | |
156 if (device != null) { | |
157 MidiDeviceAndroid xdevice = new MidiDeviceAndroid(device); | |
158 mDevices.add(xdevice); | |
159 if (mIsInitialized) { | |
160 nativeOnAttached(mNativeManagerPointer, xdevice); | |
161 } | |
162 } | |
163 if (!mIsInitialized && mPendingDevices.isEmpty()) { | |
164 nativeOnInitialized(mNativeManagerPointer, mDevices.toArray(new Midi
DeviceAndroid[0])); | |
165 mIsInitialized = true; | |
166 } | |
167 } | |
168 | |
169 static native void nativeOnInitialized( | |
170 long nativeMidiManagerAndroid, MidiDeviceAndroid[] devices); | |
171 static native void nativeOnInitializationFailed(long nativeMidiManagerAndroi
d); | |
172 static native void nativeOnAttached(long nativeMidiManagerAndroid, MidiDevic
eAndroid device); | |
173 static native void nativeOnDetached(long nativeMidiManagerAndroid, MidiDevic
eAndroid device); | |
174 } | |
OLD | NEW |