| @@ -179,9 +179,9 @@ public class JuceDemo extends Activity | |||
| return address; | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return false; | |||
| return 0; | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -194,9 +194,9 @@ public class MidiTest extends Activity | |||
| return btDevice.getName(); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return getAndroidMidiDeviceManager().isBluetoothDevicePaired (address); | |||
| return getAndroidMidiDeviceManager().getBluetoothDeviceStatus (address); | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -487,7 +487,78 @@ public class MidiTest extends Activity | |||
| //============================================================================== | |||
| public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener | |||
| { | |||
| //============================================================================== | |||
| private class MidiDeviceOpenTask extends java.util.TimerTask | |||
| { | |||
| public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device) | |||
| { | |||
| owner = deviceManager; | |||
| midiDevice = device; | |||
| } | |||
| @Override | |||
| public boolean cancel() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| owner = null; | |||
| boolean retval = super.cancel(); | |||
| if (midiDevice != null) | |||
| { | |||
| try | |||
| { | |||
| midiDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| midiDevice = null; | |||
| } | |||
| return retval; | |||
| } | |||
| } | |||
| public String getBluetoothAddress() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (midiDevice != null) | |||
| { | |||
| MidiDeviceInfo info = midiDevice.getInfo(); | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| return btDevice.getAddress(); | |||
| } | |||
| } | |||
| } | |||
| return ""; | |||
| } | |||
| public int getID() | |||
| { | |||
| return midiDevice.getInfo().getId(); | |||
| } | |||
| @Override | |||
| public void run() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (owner != null && midiDevice != null) | |||
| owner.onDeviceOpenedDelayed (midiDevice); | |||
| } | |||
| } | |||
| private MidiDeviceManager owner; | |||
| private MidiDevice midiDevice; | |||
| } | |||
| //============================================================================== | |||
| public MidiDeviceManager() | |||
| { | |||
| manager = (MidiManager) getSystemService (MIDI_SERVICE); | |||
| @@ -500,6 +571,8 @@ public class MidiTest extends Activity | |||
| openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); | |||
| midiDevices = new ArrayList<MidiDevice>(); | |||
| openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); | |||
| btDevicesPairing = new HashSet<String>(); | |||
| MidiDeviceInfo[] foundDevices = manager.getDevices(); | |||
| for (MidiDeviceInfo info : foundDevices) | |||
| @@ -512,6 +585,16 @@ public class MidiTest extends Activity | |||
| { | |||
| manager.unregisterDeviceCallback (this); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.clear(); | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| openTasks.get (deviceID).cancel(); | |||
| openTasks = null; | |||
| } | |||
| for (MidiPortPath key : openPorts.keySet()) | |||
| openPorts.get (key).get().close(); | |||
| @@ -606,21 +689,62 @@ public class MidiTest extends Activity | |||
| return openMidiPortWithJuceIndex (index, 0, false); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| /* 0: unpaired, 1: paired, 2: pairing */ | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return (findMidiDeviceForBluetoothAddress (address) != null); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (! address.isEmpty()) | |||
| { | |||
| if (findMidiDeviceForBluetoothAddress (address) != null) | |||
| return 1; | |||
| if (btDevicesPairing.contains (address)) | |||
| return 2; | |||
| if (findOpenTaskForBluetoothAddress (address) != null) | |||
| return 2; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| public boolean pairBluetoothDevice (BluetoothDevice btDevice) | |||
| { | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btAddress.isEmpty()) | |||
| return false; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (getBluetoothDeviceStatus (btAddress) != 0) | |||
| return false; | |||
| btDevicesPairing.add (btDevice.getAddress()); | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| } | |||
| return true; | |||
| } | |||
| public void unpairBluetoothDevice (String address) | |||
| { | |||
| if (address.isEmpty()) | |||
| return; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.remove (address); | |||
| MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); | |||
| if (openTask != null) | |||
| { | |||
| int deviceID = openTask.getID(); | |||
| openTask.cancel(); | |||
| openTasks.remove (deviceID); | |||
| } | |||
| MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address); | |||
| if (midiDevice != null) | |||
| { | |||
| @@ -653,6 +777,18 @@ public class MidiTest extends Activity | |||
| return null; | |||
| } | |||
| private MidiDeviceOpenTask findOpenTaskForBluetoothAddress (String address) | |||
| { | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| { | |||
| MidiDeviceOpenTask openTask = openTasks.get (deviceID); | |||
| if (openTask.getBluetoothAddress().equals (address)) | |||
| return openTask; | |||
| } | |||
| return null; | |||
| } | |||
| public void removePort (MidiPortPath path) | |||
| { | |||
| openPorts.remove (path); | |||
| @@ -719,9 +855,68 @@ public class MidiTest extends Activity | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| // make sure it's not already there | |||
| if (! midiDevices.contains(theDevice)) | |||
| midiDevices.add (theDevice); | |||
| MidiDeviceInfo info = theDevice.getInfo(); | |||
| int deviceID = info.getId(); | |||
| if (! openTasks.containsKey (deviceID)) | |||
| { | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| { | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btDevicesPairing.contains (btAddress)) | |||
| { | |||
| btDevicesPairing.remove (btAddress); | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice); | |||
| openTasks.put (deviceID, openTask); | |||
| new java.util.Timer().schedule (openTask, 3000); | |||
| } | |||
| } | |||
| } | |||
| public void onDeviceOpenedDelayed (MidiDevice theDevice) | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| int deviceID = theDevice.getInfo().getId(); | |||
| if (openTasks.containsKey (deviceID)) | |||
| { | |||
| if (! midiDevices.contains(theDevice)) | |||
| { | |||
| openTasks.remove (deviceID); | |||
| midiDevices.add (theDevice); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| } | |||
| } | |||
| } | |||
| @@ -808,6 +1003,8 @@ public class MidiTest extends Activity | |||
| } | |||
| private MidiManager manager; | |||
| private HashSet<String> btDevicesPairing; | |||
| private HashMap<Integer, MidiDeviceOpenTask> openTasks; | |||
| private ArrayList<MidiDevice> midiDevices; | |||
| private MidiDeviceInfo[] deviceInfos; | |||
| private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; | |||
| @@ -179,9 +179,9 @@ public class JUCENetworkGraphicsDemo extends Activity | |||
| return address; | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return false; | |||
| return 0; | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -179,9 +179,9 @@ public class OSCReceiver extends Activity | |||
| return address; | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return false; | |||
| return 0; | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -179,9 +179,9 @@ public class OSCSender extends Activity | |||
| return address; | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return false; | |||
| return 0; | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -194,9 +194,9 @@ public class JuceDemoPlugin extends Activity | |||
| return btDevice.getName(); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return getAndroidMidiDeviceManager().isBluetoothDevicePaired (address); | |||
| return getAndroidMidiDeviceManager().getBluetoothDeviceStatus (address); | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -487,7 +487,78 @@ public class JuceDemoPlugin extends Activity | |||
| //============================================================================== | |||
| public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener | |||
| { | |||
| //============================================================================== | |||
| private class MidiDeviceOpenTask extends java.util.TimerTask | |||
| { | |||
| public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device) | |||
| { | |||
| owner = deviceManager; | |||
| midiDevice = device; | |||
| } | |||
| @Override | |||
| public boolean cancel() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| owner = null; | |||
| boolean retval = super.cancel(); | |||
| if (midiDevice != null) | |||
| { | |||
| try | |||
| { | |||
| midiDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| midiDevice = null; | |||
| } | |||
| return retval; | |||
| } | |||
| } | |||
| public String getBluetoothAddress() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (midiDevice != null) | |||
| { | |||
| MidiDeviceInfo info = midiDevice.getInfo(); | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| return btDevice.getAddress(); | |||
| } | |||
| } | |||
| } | |||
| return ""; | |||
| } | |||
| public int getID() | |||
| { | |||
| return midiDevice.getInfo().getId(); | |||
| } | |||
| @Override | |||
| public void run() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (owner != null && midiDevice != null) | |||
| owner.onDeviceOpenedDelayed (midiDevice); | |||
| } | |||
| } | |||
| private MidiDeviceManager owner; | |||
| private MidiDevice midiDevice; | |||
| } | |||
| //============================================================================== | |||
| public MidiDeviceManager() | |||
| { | |||
| manager = (MidiManager) getSystemService (MIDI_SERVICE); | |||
| @@ -500,6 +571,8 @@ public class JuceDemoPlugin extends Activity | |||
| openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); | |||
| midiDevices = new ArrayList<MidiDevice>(); | |||
| openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); | |||
| btDevicesPairing = new HashSet<String>(); | |||
| MidiDeviceInfo[] foundDevices = manager.getDevices(); | |||
| for (MidiDeviceInfo info : foundDevices) | |||
| @@ -512,6 +585,16 @@ public class JuceDemoPlugin extends Activity | |||
| { | |||
| manager.unregisterDeviceCallback (this); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.clear(); | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| openTasks.get (deviceID).cancel(); | |||
| openTasks = null; | |||
| } | |||
| for (MidiPortPath key : openPorts.keySet()) | |||
| openPorts.get (key).get().close(); | |||
| @@ -606,21 +689,62 @@ public class JuceDemoPlugin extends Activity | |||
| return openMidiPortWithJuceIndex (index, 0, false); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| /* 0: unpaired, 1: paired, 2: pairing */ | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return (findMidiDeviceForBluetoothAddress (address) != null); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (! address.isEmpty()) | |||
| { | |||
| if (findMidiDeviceForBluetoothAddress (address) != null) | |||
| return 1; | |||
| if (btDevicesPairing.contains (address)) | |||
| return 2; | |||
| if (findOpenTaskForBluetoothAddress (address) != null) | |||
| return 2; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| public boolean pairBluetoothDevice (BluetoothDevice btDevice) | |||
| { | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btAddress.isEmpty()) | |||
| return false; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (getBluetoothDeviceStatus (btAddress) != 0) | |||
| return false; | |||
| btDevicesPairing.add (btDevice.getAddress()); | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| } | |||
| return true; | |||
| } | |||
| public void unpairBluetoothDevice (String address) | |||
| { | |||
| if (address.isEmpty()) | |||
| return; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.remove (address); | |||
| MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); | |||
| if (openTask != null) | |||
| { | |||
| int deviceID = openTask.getID(); | |||
| openTask.cancel(); | |||
| openTasks.remove (deviceID); | |||
| } | |||
| MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address); | |||
| if (midiDevice != null) | |||
| { | |||
| @@ -653,6 +777,18 @@ public class JuceDemoPlugin extends Activity | |||
| return null; | |||
| } | |||
| private MidiDeviceOpenTask findOpenTaskForBluetoothAddress (String address) | |||
| { | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| { | |||
| MidiDeviceOpenTask openTask = openTasks.get (deviceID); | |||
| if (openTask.getBluetoothAddress().equals (address)) | |||
| return openTask; | |||
| } | |||
| return null; | |||
| } | |||
| public void removePort (MidiPortPath path) | |||
| { | |||
| openPorts.remove (path); | |||
| @@ -719,9 +855,68 @@ public class JuceDemoPlugin extends Activity | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| // make sure it's not already there | |||
| if (! midiDevices.contains(theDevice)) | |||
| midiDevices.add (theDevice); | |||
| MidiDeviceInfo info = theDevice.getInfo(); | |||
| int deviceID = info.getId(); | |||
| if (! openTasks.containsKey (deviceID)) | |||
| { | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| { | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btDevicesPairing.contains (btAddress)) | |||
| { | |||
| btDevicesPairing.remove (btAddress); | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice); | |||
| openTasks.put (deviceID, openTask); | |||
| new java.util.Timer().schedule (openTask, 3000); | |||
| } | |||
| } | |||
| } | |||
| public void onDeviceOpenedDelayed (MidiDevice theDevice) | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| int deviceID = theDevice.getInfo().getId(); | |||
| if (openTasks.containsKey (deviceID)) | |||
| { | |||
| if (! midiDevices.contains(theDevice)) | |||
| { | |||
| openTasks.remove (deviceID); | |||
| midiDevices.add (theDevice); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| } | |||
| } | |||
| } | |||
| @@ -808,6 +1003,8 @@ public class JuceDemoPlugin extends Activity | |||
| } | |||
| private MidiManager manager; | |||
| private HashSet<String> btDevicesPairing; | |||
| private HashMap<Integer, MidiDeviceOpenTask> openTasks; | |||
| private ArrayList<MidiDevice> midiDevices; | |||
| private MidiDeviceInfo[] deviceInfos; | |||
| private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; | |||
| @@ -194,9 +194,9 @@ public class AudioPerformanceTest extends Activity | |||
| return btDevice.getName(); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return getAndroidMidiDeviceManager().isBluetoothDevicePaired (address); | |||
| return getAndroidMidiDeviceManager().getBluetoothDeviceStatus (address); | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -487,7 +487,78 @@ public class AudioPerformanceTest extends Activity | |||
| //============================================================================== | |||
| public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener | |||
| { | |||
| //============================================================================== | |||
| private class MidiDeviceOpenTask extends java.util.TimerTask | |||
| { | |||
| public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device) | |||
| { | |||
| owner = deviceManager; | |||
| midiDevice = device; | |||
| } | |||
| @Override | |||
| public boolean cancel() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| owner = null; | |||
| boolean retval = super.cancel(); | |||
| if (midiDevice != null) | |||
| { | |||
| try | |||
| { | |||
| midiDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| midiDevice = null; | |||
| } | |||
| return retval; | |||
| } | |||
| } | |||
| public String getBluetoothAddress() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (midiDevice != null) | |||
| { | |||
| MidiDeviceInfo info = midiDevice.getInfo(); | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| return btDevice.getAddress(); | |||
| } | |||
| } | |||
| } | |||
| return ""; | |||
| } | |||
| public int getID() | |||
| { | |||
| return midiDevice.getInfo().getId(); | |||
| } | |||
| @Override | |||
| public void run() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (owner != null && midiDevice != null) | |||
| owner.onDeviceOpenedDelayed (midiDevice); | |||
| } | |||
| } | |||
| private MidiDeviceManager owner; | |||
| private MidiDevice midiDevice; | |||
| } | |||
| //============================================================================== | |||
| public MidiDeviceManager() | |||
| { | |||
| manager = (MidiManager) getSystemService (MIDI_SERVICE); | |||
| @@ -500,6 +571,8 @@ public class AudioPerformanceTest extends Activity | |||
| openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); | |||
| midiDevices = new ArrayList<MidiDevice>(); | |||
| openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); | |||
| btDevicesPairing = new HashSet<String>(); | |||
| MidiDeviceInfo[] foundDevices = manager.getDevices(); | |||
| for (MidiDeviceInfo info : foundDevices) | |||
| @@ -512,6 +585,16 @@ public class AudioPerformanceTest extends Activity | |||
| { | |||
| manager.unregisterDeviceCallback (this); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.clear(); | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| openTasks.get (deviceID).cancel(); | |||
| openTasks = null; | |||
| } | |||
| for (MidiPortPath key : openPorts.keySet()) | |||
| openPorts.get (key).get().close(); | |||
| @@ -606,21 +689,62 @@ public class AudioPerformanceTest extends Activity | |||
| return openMidiPortWithJuceIndex (index, 0, false); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| /* 0: unpaired, 1: paired, 2: pairing */ | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return (findMidiDeviceForBluetoothAddress (address) != null); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (! address.isEmpty()) | |||
| { | |||
| if (findMidiDeviceForBluetoothAddress (address) != null) | |||
| return 1; | |||
| if (btDevicesPairing.contains (address)) | |||
| return 2; | |||
| if (findOpenTaskForBluetoothAddress (address) != null) | |||
| return 2; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| public boolean pairBluetoothDevice (BluetoothDevice btDevice) | |||
| { | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btAddress.isEmpty()) | |||
| return false; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (getBluetoothDeviceStatus (btAddress) != 0) | |||
| return false; | |||
| btDevicesPairing.add (btDevice.getAddress()); | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| } | |||
| return true; | |||
| } | |||
| public void unpairBluetoothDevice (String address) | |||
| { | |||
| if (address.isEmpty()) | |||
| return; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.remove (address); | |||
| MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); | |||
| if (openTask != null) | |||
| { | |||
| int deviceID = openTask.getID(); | |||
| openTask.cancel(); | |||
| openTasks.remove (deviceID); | |||
| } | |||
| MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address); | |||
| if (midiDevice != null) | |||
| { | |||
| @@ -653,6 +777,18 @@ public class AudioPerformanceTest extends Activity | |||
| return null; | |||
| } | |||
| private MidiDeviceOpenTask findOpenTaskForBluetoothAddress (String address) | |||
| { | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| { | |||
| MidiDeviceOpenTask openTask = openTasks.get (deviceID); | |||
| if (openTask.getBluetoothAddress().equals (address)) | |||
| return openTask; | |||
| } | |||
| return null; | |||
| } | |||
| public void removePort (MidiPortPath path) | |||
| { | |||
| openPorts.remove (path); | |||
| @@ -719,9 +855,68 @@ public class AudioPerformanceTest extends Activity | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| // make sure it's not already there | |||
| if (! midiDevices.contains(theDevice)) | |||
| midiDevices.add (theDevice); | |||
| MidiDeviceInfo info = theDevice.getInfo(); | |||
| int deviceID = info.getId(); | |||
| if (! openTasks.containsKey (deviceID)) | |||
| { | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| { | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btDevicesPairing.contains (btAddress)) | |||
| { | |||
| btDevicesPairing.remove (btAddress); | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice); | |||
| openTasks.put (deviceID, openTask); | |||
| new java.util.Timer().schedule (openTask, 3000); | |||
| } | |||
| } | |||
| } | |||
| public void onDeviceOpenedDelayed (MidiDevice theDevice) | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| int deviceID = theDevice.getInfo().getId(); | |||
| if (openTasks.containsKey (deviceID)) | |||
| { | |||
| if (! midiDevices.contains(theDevice)) | |||
| { | |||
| openTasks.remove (deviceID); | |||
| midiDevices.add (theDevice); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| } | |||
| } | |||
| } | |||
| @@ -808,6 +1003,8 @@ public class AudioPerformanceTest extends Activity | |||
| } | |||
| private MidiManager manager; | |||
| private HashSet<String> btDevicesPairing; | |||
| private HashMap<Integer, MidiDeviceOpenTask> openTasks; | |||
| private ArrayList<MidiDevice> midiDevices; | |||
| private MidiDeviceInfo[] deviceInfos; | |||
| private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; | |||
| @@ -28,7 +28,7 @@ | |||
| METHOD (pairBluetoothMidiDevice, "pairBluetoothMidiDevice", "(Ljava/lang/String;)Z") \ | |||
| METHOD (unpairBluetoothMidiDevice, "unpairBluetoothMidiDevice", "(Ljava/lang/String;)V") \ | |||
| METHOD (getHumanReadableStringForBluetoothAddress, "getHumanReadableStringForBluetoothAddress", "(Ljava/lang/String;)Ljava/lang/String;") \ | |||
| METHOD (isBluetoothDevicePaired, "isBluetoothDevicePaired", "(Ljava/lang/String;)Z") \ | |||
| METHOD (getBluetoothDeviceStatus, "getBluetoothDeviceStatus", "(Ljava/lang/String;)I") \ | |||
| METHOD (startStopScan, "startStopScan", "(Z)V") | |||
| DECLARE_JNI_CLASS (AndroidBluetoothManager, JUCE_ANDROID_ACTIVITY_CLASSPATH "$BluetoothManager"); | |||
| @@ -121,17 +121,24 @@ struct AndroidBluetoothMidiInterface | |||
| } | |||
| //============================================================================== | |||
| static bool isBluetoothDevicePaired (const String& address) | |||
| enum PairStatus | |||
| { | |||
| unpaired = 0, | |||
| paired = 1, | |||
| pairing = 2 | |||
| }; | |||
| static PairStatus isBluetoothDevicePaired (const String& address) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| LocalRef<jobject> btManager (android.activity.callObjectMethod (JuceAppActivity.getAndroidBluetoothManager)); | |||
| if (btManager.get() == nullptr) | |||
| return false; | |||
| return unpaired; | |||
| return env->CallBooleanMethod (btManager.get(), AndroidBluetoothManager.isBluetoothDevicePaired, | |||
| javaString (address).get()); | |||
| return static_cast<PairStatus> (env->CallIntMethod (btManager.get(), AndroidBluetoothManager.getBluetoothDeviceStatus, | |||
| javaString (address).get())); | |||
| } | |||
| }; | |||
| @@ -350,9 +357,19 @@ private: | |||
| address != bluetoothAddresses.end(); ++address) | |||
| { | |||
| String name = AndroidBluetoothMidiInterface::getHumanReadableStringForBluetoothAddress (*address); | |||
| DeviceStatus status = AndroidBluetoothMidiInterface::isBluetoothDevicePaired (*address) | |||
| ? AndroidBluetoothMidiDevice::connected | |||
| : AndroidBluetoothMidiDevice::disconnected; | |||
| DeviceStatus status; | |||
| switch (AndroidBluetoothMidiInterface::isBluetoothDevicePaired (*address)) | |||
| { | |||
| case AndroidBluetoothMidiInterface::pairing: | |||
| status = AndroidBluetoothMidiDevice::connecting; | |||
| break; | |||
| case AndroidBluetoothMidiInterface::paired: | |||
| status = AndroidBluetoothMidiDevice::connected; | |||
| break; | |||
| default: | |||
| status = AndroidBluetoothMidiDevice::disconnected; | |||
| } | |||
| newDevices.add (AndroidBluetoothMidiDevice (name, *address, status)); | |||
| } | |||
| @@ -16,9 +16,9 @@ | |||
| return btDevice.getName(); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return getAndroidMidiDeviceManager().isBluetoothDevicePaired (address); | |||
| return getAndroidMidiDeviceManager().getBluetoothDeviceStatus (address); | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||
| @@ -309,7 +309,78 @@ | |||
| //============================================================================== | |||
| public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener | |||
| { | |||
| //============================================================================== | |||
| private class MidiDeviceOpenTask extends java.util.TimerTask | |||
| { | |||
| public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device) | |||
| { | |||
| owner = deviceManager; | |||
| midiDevice = device; | |||
| } | |||
| @Override | |||
| public boolean cancel() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| owner = null; | |||
| boolean retval = super.cancel(); | |||
| if (midiDevice != null) | |||
| { | |||
| try | |||
| { | |||
| midiDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| midiDevice = null; | |||
| } | |||
| return retval; | |||
| } | |||
| } | |||
| public String getBluetoothAddress() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (midiDevice != null) | |||
| { | |||
| MidiDeviceInfo info = midiDevice.getInfo(); | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| return btDevice.getAddress(); | |||
| } | |||
| } | |||
| } | |||
| return ""; | |||
| } | |||
| public int getID() | |||
| { | |||
| return midiDevice.getInfo().getId(); | |||
| } | |||
| @Override | |||
| public void run() | |||
| { | |||
| synchronized (MidiDeviceOpenTask.class) | |||
| { | |||
| if (owner != null && midiDevice != null) | |||
| owner.onDeviceOpenedDelayed (midiDevice); | |||
| } | |||
| } | |||
| private MidiDeviceManager owner; | |||
| private MidiDevice midiDevice; | |||
| } | |||
| //============================================================================== | |||
| public MidiDeviceManager() | |||
| { | |||
| manager = (MidiManager) getSystemService (MIDI_SERVICE); | |||
| @@ -322,6 +393,8 @@ | |||
| openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); | |||
| midiDevices = new ArrayList<MidiDevice>(); | |||
| openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); | |||
| btDevicesPairing = new HashSet<String>(); | |||
| MidiDeviceInfo[] foundDevices = manager.getDevices(); | |||
| for (MidiDeviceInfo info : foundDevices) | |||
| @@ -334,6 +407,16 @@ | |||
| { | |||
| manager.unregisterDeviceCallback (this); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.clear(); | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| openTasks.get (deviceID).cancel(); | |||
| openTasks = null; | |||
| } | |||
| for (MidiPortPath key : openPorts.keySet()) | |||
| openPorts.get (key).get().close(); | |||
| @@ -428,21 +511,62 @@ | |||
| return openMidiPortWithJuceIndex (index, 0, false); | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| /* 0: unpaired, 1: paired, 2: pairing */ | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return (findMidiDeviceForBluetoothAddress (address) != null); | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (! address.isEmpty()) | |||
| { | |||
| if (findMidiDeviceForBluetoothAddress (address) != null) | |||
| return 1; | |||
| if (btDevicesPairing.contains (address)) | |||
| return 2; | |||
| if (findOpenTaskForBluetoothAddress (address) != null) | |||
| return 2; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| public boolean pairBluetoothDevice (BluetoothDevice btDevice) | |||
| { | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btAddress.isEmpty()) | |||
| return false; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| if (getBluetoothDeviceStatus (btAddress) != 0) | |||
| return false; | |||
| btDevicesPairing.add (btDevice.getAddress()); | |||
| manager.openBluetoothDevice(btDevice, this, null); | |||
| } | |||
| return true; | |||
| } | |||
| public void unpairBluetoothDevice (String address) | |||
| { | |||
| if (address.isEmpty()) | |||
| return; | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| btDevicesPairing.remove (address); | |||
| MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); | |||
| if (openTask != null) | |||
| { | |||
| int deviceID = openTask.getID(); | |||
| openTask.cancel(); | |||
| openTasks.remove (deviceID); | |||
| } | |||
| MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address); | |||
| if (midiDevice != null) | |||
| { | |||
| @@ -475,6 +599,18 @@ | |||
| return null; | |||
| } | |||
| private MidiDeviceOpenTask findOpenTaskForBluetoothAddress (String address) | |||
| { | |||
| for (Integer deviceID : openTasks.keySet()) | |||
| { | |||
| MidiDeviceOpenTask openTask = openTasks.get (deviceID); | |||
| if (openTask.getBluetoothAddress().equals (address)) | |||
| return openTask; | |||
| } | |||
| return null; | |||
| } | |||
| public void removePort (MidiPortPath path) | |||
| { | |||
| openPorts.remove (path); | |||
| @@ -541,9 +677,68 @@ | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| // make sure it's not already there | |||
| if (! midiDevices.contains(theDevice)) | |||
| midiDevices.add (theDevice); | |||
| MidiDeviceInfo info = theDevice.getInfo(); | |||
| int deviceID = info.getId(); | |||
| if (! openTasks.containsKey (deviceID)) | |||
| { | |||
| if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) | |||
| { | |||
| BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); | |||
| if (btDevice != null) | |||
| { | |||
| String btAddress = btDevice.getAddress(); | |||
| if (btDevicesPairing.contains (btAddress)) | |||
| { | |||
| btDevicesPairing.remove (btAddress); | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice); | |||
| openTasks.put (deviceID, openTask); | |||
| new java.util.Timer().schedule (openTask, 3000); | |||
| } | |||
| } | |||
| } | |||
| public void onDeviceOpenedDelayed (MidiDevice theDevice) | |||
| { | |||
| synchronized (MidiDeviceManager.class) | |||
| { | |||
| int deviceID = theDevice.getInfo().getId(); | |||
| if (openTasks.containsKey (deviceID)) | |||
| { | |||
| if (! midiDevices.contains(theDevice)) | |||
| { | |||
| openTasks.remove (deviceID); | |||
| midiDevices.add (theDevice); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // unpair was called in the mean time | |||
| try | |||
| { | |||
| theDevice.close(); | |||
| } | |||
| catch (IOException e) | |||
| {} | |||
| } | |||
| } | |||
| } | |||
| @@ -630,6 +825,8 @@ | |||
| } | |||
| private MidiManager manager; | |||
| private HashSet<String> btDevicesPairing; | |||
| private HashMap<Integer, MidiDeviceOpenTask> openTasks; | |||
| private ArrayList<MidiDevice> midiDevices; | |||
| private MidiDeviceInfo[] deviceInfos; | |||
| private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; | |||
| @@ -16,9 +16,9 @@ | |||
| return address; | |||
| } | |||
| public boolean isBluetoothDevicePaired (String address) | |||
| public int getBluetoothDeviceStatus (String address) | |||
| { | |||
| return false; | |||
| return 0; | |||
| } | |||
| public void startStopScan (boolean shouldStart) | |||