167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood/* 267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Copyright (C) 2014 The Android Open Source Project 367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * 467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * you may not use this file except in compliance with the License. 667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * You may obtain a copy of the License at 767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * 867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * 1067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * See the License for the specific language governing permissions and 1467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * limitations under the License. 1567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood */ 1667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 17b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwoodpackage android.media.midi; 1867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 19f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwoodimport android.bluetooth.BluetoothDevice; 2067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport android.os.Binder; 2167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport android.os.IBinder; 2267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport android.os.Bundle; 23b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwoodimport android.os.Handler; 2467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport android.os.RemoteException; 2567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwoodimport android.util.Log; 2667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 27a95faf78bf810e0b4eb3cb211c414bfbbd1a8061Phil Burkimport java.util.concurrent.ConcurrentHashMap; 2867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 2967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood/** 3067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * This class is the public application interface to the MIDI service. 3167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * 3267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * <p>You can obtain an instance of this class by calling 3367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. 3467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * 3567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * {@samplecode 3667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);} 3767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood */ 38be215dd57282888b05b234c39bba44cc0a864b8aMike Lockwoodpublic final class MidiManager { 3967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood private static final String TAG = "MidiManager"; 4067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 41f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood /** 42f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * Intent for starting BluetoothMidiService 43f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * @hide 44f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood */ 45f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood public static final String BLUETOOTH_MIDI_SERVICE_INTENT = 46f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood "android.media.midi.BluetoothMidiService"; 47f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 48f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood /** 49f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * BluetoothMidiService package name 50e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood * @hide 51f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood */ 52e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public static final String BLUETOOTH_MIDI_SERVICE_PACKAGE = "com.android.bluetoothmidiservice"; 53f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 54f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood /** 55f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * BluetoothMidiService class name 56e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood * @hide 57f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood */ 58e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public static final String BLUETOOTH_MIDI_SERVICE_CLASS = 59f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood "com.android.bluetoothmidiservice.BluetoothMidiService"; 60f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 6167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood private final IMidiManager mService; 6267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood private final IBinder mToken = new Binder(); 6367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 64a95faf78bf810e0b4eb3cb211c414bfbbd1a8061Phil Burk private ConcurrentHashMap<DeviceCallback,DeviceListener> mDeviceListeners = 65a95faf78bf810e0b4eb3cb211c414bfbbd1a8061Phil Burk new ConcurrentHashMap<DeviceCallback,DeviceListener>(); 6667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 6767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood // Binder stub for receiving device notifications from MidiService 6811fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood private class DeviceListener extends IMidiDeviceListener.Stub { 69b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood private final DeviceCallback mCallback; 70b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood private final Handler mHandler; 7167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 72b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood public DeviceListener(DeviceCallback callback, Handler handler) { 7367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood mCallback = callback; 74b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mHandler = handler; 7567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 7667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 775ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood @Override 7867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood public void onDeviceAdded(MidiDeviceInfo device) { 79b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood if (mHandler != null) { 80b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood final MidiDeviceInfo deviceF = device; 81b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mHandler.post(new Runnable() { 82b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood @Override public void run() { 83b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mCallback.onDeviceAdded(deviceF); 84b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } 85b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood }); 86b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } else { 87b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mCallback.onDeviceAdded(device); 88b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } 8967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 9067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 915ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood @Override 9267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood public void onDeviceRemoved(MidiDeviceInfo device) { 93b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood if (mHandler != null) { 94b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood final MidiDeviceInfo deviceF = device; 95b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mHandler.post(new Runnable() { 96b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood @Override public void run() { 97b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mCallback.onDeviceRemoved(deviceF); 98b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } 99b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood }); 100b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } else { 101b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood mCallback.onDeviceRemoved(device); 102b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood } 10367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 1045ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood 1055ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood @Override 1065ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood public void onDeviceStatusChanged(MidiDeviceStatus status) { 1075ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood if (mHandler != null) { 1085ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood final MidiDeviceStatus statusF = status; 1095ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood mHandler.post(new Runnable() { 1105ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood @Override public void run() { 1115ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood mCallback.onDeviceStatusChanged(statusF); 1125ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 1135ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood }); 1145ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } else { 1155ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood mCallback.onDeviceStatusChanged(status); 1165ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 1175ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 11867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 11967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 12078beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 12190b9a6a4ab30fc162aee71b4dc484b3839534369Mike Lockwood * Callback class used for clients to receive MIDI device added and removed notifications 12278beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 1235ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood public static class DeviceCallback { 12478beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 12578beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Called to notify when a new MIDI device has been added 12678beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 12778beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * @param device a {@link MidiDeviceInfo} for the newly added device 12878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 1295ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood public void onDeviceAdded(MidiDeviceInfo device) { 1305ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 13178beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood 13278beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 13378beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Called to notify when a MIDI device has been removed 13478beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 13578beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * @param device a {@link MidiDeviceInfo} for the removed device 13678beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 1375ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood public void onDeviceRemoved(MidiDeviceInfo device) { 1385ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 1395ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood 1405ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood /** 1415ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood * Called to notify when the status of a MIDI device has changed 1425ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood * 1439db9326ad47279709a0f7989addaf4b45221b6b9Mike Lockwood * @param status a {@link MidiDeviceStatus} for the changed device 1445ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood */ 1455ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood public void onDeviceStatusChanged(MidiDeviceStatus status) { 1465ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood } 14711fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood } 14811fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood 14911fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood /** 1507eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * Listener class used for receiving the results of {@link #openDevice} and 1517eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * {@link #openBluetoothDevice} 15211fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood */ 1537eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood public interface OnDeviceOpenedListener { 15411fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood /** 15511fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood * Called to respond to a {@link #openDevice} request 15611fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood * 15711fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood * @param device a {@link MidiDevice} for opened device, or null if opening failed 15811fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood */ 1597eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood abstract public void onDeviceOpened(MidiDevice device); 160f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 161f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 162f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood /** 16367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood * @hide 16467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood */ 165e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public MidiManager(IMidiManager service) { 16667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood mService = service; 16767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 16867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 16978beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 17078beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Registers a callback to receive notifications when MIDI devices are added and removed. 17178beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 172b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * The {@link DeviceCallback#onDeviceStatusChanged} method will be called immediately 173b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * for any devices that have open ports. This allows applications to know which input 174b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * ports are already in use and, therefore, unavailable. 175b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * 176b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * Applications should call {@link #getDevices} before registering the callback 177b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * to get a list of devices already added. 178b2355940e3e697deeecd1b6511cd5094f9dc553aPhil Burk * 17978beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * @param callback a {@link DeviceCallback} for MIDI device notifications 180b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood * @param handler The {@link android.os.Handler Handler} that will be used for delivering the 181b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood * device notifications. If handler is null, then the thread used for the 182b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood * callback is unspecified. 18378beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 184b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood public void registerDeviceCallback(DeviceCallback callback, Handler handler) { 185b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood DeviceListener deviceListener = new DeviceListener(callback, handler); 18667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood try { 18767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood mService.registerListener(mToken, deviceListener); 18867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } catch (RemoteException e) { 189c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 19067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 19167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood mDeviceListeners.put(callback, deviceListener); 19267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 19367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 19478beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 19578beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Unregisters a {@link DeviceCallback}. 19678beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 19778beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * @param callback a {@link DeviceCallback} to unregister 19878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 19967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood public void unregisterDeviceCallback(DeviceCallback callback) { 20067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood DeviceListener deviceListener = mDeviceListeners.remove(callback); 20167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood if (deviceListener != null) { 20267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood try { 20367f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood mService.unregisterListener(mToken, deviceListener); 20467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } catch (RemoteException e) { 205c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 20667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 20767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 20867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 20967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 21078beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 21178beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Gets the list of all connected MIDI devices. 21278beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 21378beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * @return an array of all MIDI devices 21478beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 2157eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood public MidiDeviceInfo[] getDevices() { 21667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood try { 2177eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood return mService.getDevices(); 21867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } catch (RemoteException e) { 219c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 22067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 22167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 22267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 2237eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood private void sendOpenDeviceResponse(final MidiDevice device, 2247eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood final OnDeviceOpenedListener listener, Handler handler) { 22511fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood if (handler != null) { 22611fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood handler.post(new Runnable() { 22711fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood @Override public void run() { 2287eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood listener.onDeviceOpened(device); 22911fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood } 23011fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood }); 23111fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood } else { 2327eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood listener.onDeviceOpened(device); 233f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 234f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 235f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 23678beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood /** 23778beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * Opens a MIDI device for reading and writing. 23878beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood * 239b673770f7172d4fca9bc05de1f36bc53e93eb247Mike Lockwood * @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open 240e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood * @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called 2417eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * to receive the result 24211fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood * @param handler the {@link android.os.Handler Handler} that will be used for delivering 24311fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood * the result. If handler is null, then the thread used for the 2447eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * listener is unspecified. 24578beecffc3ea477b55b65d530e4868dd44b5e71bMike Lockwood */ 2467eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood public void openDevice(MidiDeviceInfo deviceInfo, OnDeviceOpenedListener listener, 24711fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood Handler handler) { 248e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood final MidiDeviceInfo deviceInfoF = deviceInfo; 249e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood final OnDeviceOpenedListener listenerF = listener; 250e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood final Handler handlerF = handler; 25111fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood 252e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood IMidiDeviceOpenCallback callback = new IMidiDeviceOpenCallback.Stub() { 253e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood @Override 254e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public void onDeviceOpened(IMidiDeviceServer server, IBinder deviceToken) { 255e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood MidiDevice device; 256e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood if (server != null) { 257e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood device = new MidiDevice(deviceInfoF, server, mService, mToken, deviceToken); 258e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood } else { 259e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood device = null; 26011fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood } 261e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood sendOpenDeviceResponse(device, listenerF, handlerF); 26267f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 263e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood }; 264e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood 265e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood try { 266e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood mService.openDevice(mToken, deviceInfo, callback); 26767f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } catch (RemoteException e) { 268c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 26967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 27067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 27167f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood 272f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood /** 273f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * Opens a Bluetooth MIDI device for reading and writing. 274f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * 275f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * @param bluetoothDevice a {@link android.bluetooth.BluetoothDevice} to open as a MIDI device 2767eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called to receive the 277f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * result 278f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * @param handler the {@link android.os.Handler Handler} that will be used for delivering 279f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood * the result. If handler is null, then the thread used for the 2807eb441cb4abcd3230a4d243469c5044f49e707c8Mike Lockwood * listener is unspecified. 281f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood */ 282e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public void openBluetoothDevice(BluetoothDevice bluetoothDevice, 283e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood OnDeviceOpenedListener listener, Handler handler) { 284e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood final OnDeviceOpenedListener listenerF = listener; 285e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood final Handler handlerF = handler; 286e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood 287e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood IMidiDeviceOpenCallback callback = new IMidiDeviceOpenCallback.Stub() { 288e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood @Override 289e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood public void onDeviceOpened(IMidiDeviceServer server, IBinder deviceToken) { 290e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood MidiDevice device = null; 291e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood if (server != null) { 292f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood try { 293f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood // fetch MidiDeviceInfo from the server 294f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood MidiDeviceInfo deviceInfo = server.getDeviceInfo(); 295e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood device = new MidiDevice(deviceInfo, server, mService, mToken, deviceToken); 296f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } catch (RemoteException e) { 297e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood Log.e(TAG, "remote exception in getDeviceInfo()"); 298f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 299f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 300e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood sendOpenDeviceResponse(device, listenerF, handlerF); 301e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood } 302e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood }; 303f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 304e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood try { 305e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood mService.openBluetoothDevice(mToken, bluetoothDevice, callback); 306e0a6ca64fac5bd4f10139321604031816e90adb4Mike Lockwood } catch (RemoteException e) { 307c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 308f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 309f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood } 310f0a41d1c591193fbe02c9ddbaf24c79af4da9972Mike Lockwood 31110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood /** @hide */ 31211fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers, 313f2cd8024028f602a5e4c27f3d9222e872e4e84f2Mike Lockwood int numOutputPorts, String[] inputPortNames, String[] outputPortNames, 314f2cd8024028f602a5e4c27f3d9222e872e4e84f2Mike Lockwood Bundle properties, int type, MidiDeviceServer.Callback callback) { 31567f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood try { 31611fd96d6ff25bc1d710448eab545fe09da55a5f5Mike Lockwood MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers, 3175ff9e2a1719f78cddc7a23d6572ab15ab595dafdMike Lockwood numOutputPorts, callback); 31810024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(), 319f2cd8024028f602a5e4c27f3d9222e872e4e84f2Mike Lockwood inputPortReceivers.length, numOutputPorts, inputPortNames, outputPortNames, 320f2cd8024028f602a5e4c27f3d9222e872e4e84f2Mike Lockwood properties, type); 32110024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood if (deviceInfo == null) { 32210024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood Log.e(TAG, "registerVirtualDevice failed"); 32310024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood return null; 32467f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 32510024b3dc12a8552c1547b67810c77b865045cc8Mike Lockwood return server; 32667f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } catch (RemoteException e) { 327c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey throw e.rethrowFromSystemServer(); 32867f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 32967f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood } 33067f8e8bd8927f24147d7a1edd6ec3db1a54233b2Mike Lockwood} 331