Browse Source

Added Android workaround to force BLE Midi devices on low-latency device path

tags/2021-05-28
hogliux 8 years ago
parent
commit
5b833d6648
5 changed files with 668 additions and 224 deletions
  1. +167
    -56
      examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java
  2. +167
    -56
      examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java
  3. +167
    -56
      extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java
  4. +166
    -56
      modules/juce_core/native/java/AndroidMidi.java
  5. +1
    -0
      modules/juce_core/native/java/JuceAppActivity.java

+ 167
- 56
examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java View File

@@ -54,6 +54,7 @@ import android.text.ClipboardManager;
import android.text.InputType; import android.text.InputType;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import java.lang.Runnable; import java.lang.Runnable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.*; import java.lang.reflect.*;
@@ -487,13 +488,34 @@ public class MidiTest extends Activity
//============================================================================== //==============================================================================
public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener
{ {
//==============================================================================
private class DummyBluetoothGattCallback extends BluetoothGattCallback
{
public DummyBluetoothGattCallback()
{
super();
}
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {}
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {}
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {}
}
//============================================================================== //==============================================================================
private class MidiDeviceOpenTask extends java.util.TimerTask private class MidiDeviceOpenTask extends java.util.TimerTask
{ {
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device)
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device, BluetoothGatt gattToUse)
{ {
owner = deviceManager; owner = deviceManager;
midiDevice = device; midiDevice = device;
btGatt = gattToUse;
} }
@Override @Override
@@ -504,6 +526,14 @@ public class MidiTest extends Activity
owner = null; owner = null;
boolean retval = super.cancel(); boolean retval = super.cancel();
if (btGatt != null)
{
btGatt.disconnect();
btGatt.close();
btGatt = null;
}
if (midiDevice != null) if (midiDevice != null)
{ {
try try
@@ -539,6 +569,8 @@ public class MidiTest extends Activity
return ""; return "";
} }
public BluetoothGatt getGatt() { return btGatt; }
public int getID() public int getID()
{ {
return midiDevice.getInfo().getId(); return midiDevice.getInfo().getId();
@@ -556,6 +588,7 @@ public class MidiTest extends Activity
private MidiDeviceManager owner; private MidiDeviceManager owner;
private MidiDevice midiDevice; private MidiDevice midiDevice;
private BluetoothGatt btGatt;
} }
//============================================================================== //==============================================================================
@@ -570,9 +603,9 @@ public class MidiTest extends Activity
} }
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>();
midiDevices = new ArrayList<Pair<MidiDevice,BluetoothGatt>>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
btDevicesPairing = new HashMap<String, BluetoothGatt>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -600,8 +633,18 @@ public class MidiTest extends Activity
openPorts = null; openPorts = null;
for (MidiDevice device : midiDevices)
device.close();
for (Pair<MidiDevice, BluetoothGatt> device : midiDevices)
{
if (device.second != null)
{
device.second.disconnect();
device.second.close();
}
device.first.close();
}
midiDevices.clear();
super.finalize(); super.finalize();
} }
@@ -647,30 +690,36 @@ public class MidiTest extends Activity
if (openPorts.containsKey (portInfo)) if (openPorts.containsKey (portInfo))
return null; return null;
MidiDevice device = getMidiDeviceForId (portInfo.deviceId);
if (device != null)
{
JuceMidiPort juceMidiPort = null;
Pair<MidiDevice,BluetoothGatt> devicePair = getMidiDevicePairForId (portInfo.deviceId);
if (isInput)
if (devicePair != null)
{
MidiDevice device = devicePair.first;
if (device != null)
{ {
MidiOutputPort outputPort = device.openOutputPort (portInfo.portIndex);
JuceMidiPort juceMidiPort = null;
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort (portInfo.portIndex);
if (isInput)
{
MidiOutputPort outputPort = device.openOutputPort(portInfo.portIndex);
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort(portInfo.portIndex);
if (juceMidiPort != null) {
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
return juceMidiPort;
if (juceMidiPort != null)
{
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
return juceMidiPort;
}
} }
} }
} }
@@ -699,7 +748,7 @@ public class MidiTest extends Activity
if (findMidiDeviceForBluetoothAddress (address) != null) if (findMidiDeviceForBluetoothAddress (address) != null)
return 1; return 1;
if (btDevicesPairing.contains (address))
if (btDevicesPairing.containsKey (address))
return 2; return 2;
if (findOpenTaskForBluetoothAddress (address) != null) if (findOpenTaskForBluetoothAddress (address) != null)
@@ -721,7 +770,11 @@ public class MidiTest extends Activity
if (getBluetoothDeviceStatus (btAddress) != 0) if (getBluetoothDeviceStatus (btAddress) != 0)
return false; return false;
btDevicesPairing.add (btDevice.getAddress());
BluetoothGatt gatt = btDevice.connectGatt (getApplicationContext(), true, new DummyBluetoothGattCallback());
if (gatt != null)
gatt.requestConnectionPriority (BluetoothGatt.CONNECTION_PRIORITY_HIGH);
btDevicesPairing.put (btDevice.getAddress(), gatt);
manager.openBluetoothDevice(btDevice, this, null); manager.openBluetoothDevice(btDevice, this, null);
} }
@@ -735,7 +788,17 @@ public class MidiTest extends Activity
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
btDevicesPairing.remove (address);
if (btDevicesPairing.containsKey (address))
{
BluetoothGatt gatt = btDevicesPairing.get (address);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
btDevicesPairing.remove (address);
}
MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address);
if (openTask != null) if (openTask != null)
@@ -745,9 +808,10 @@ public class MidiTest extends Activity
openTasks.remove (deviceID); openTasks.remove (deviceID);
} }
MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null)
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (address);
if (midiDevicePair != null)
{ {
MidiDevice midiDevice = midiDevicePair.first;
onDeviceRemoved (midiDevice.getInfo()); onDeviceRemoved (midiDevice.getInfo());
try { try {
@@ -761,11 +825,11 @@ public class MidiTest extends Activity
} }
} }
private MidiDevice findMidiDeviceForBluetoothAddress (String address)
private Pair<MidiDevice, BluetoothGatt> findMidiDeviceForBluetoothAddress (String address)
{ {
for (MidiDevice midiDevice : midiDevices)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
{ {
MidiDeviceInfo info = midiDevice.getInfo();
MidiDeviceInfo info = midiDevice.first.getInfo();
if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH)
{ {
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
@@ -825,24 +889,38 @@ public class MidiTest extends Activity
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
MidiDevice device = getMidiDeviceForId (info.getId());
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true) {
removedPort = false;
for (MidiPortPath key : openPorts.keySet()) {
if (key.deviceId == info.getId()) {
openPorts.get(key).get().close();
removedPort = true;
break;
Pair<MidiDevice, BluetoothGatt> devicePair = getMidiDevicePairForId (info.getId());
if (devicePair != null)
{
MidiDevice midiDevice = devicePair.first;
BluetoothGatt gatt = devicePair.second;
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true)
{
removedPort = false;
for (MidiPortPath key : openPorts.keySet())
{
if (key.deviceId == info.getId())
{
openPorts.get(key).get().close();
removedPort = true;
break;
}
} }
} }
}
if (device != null)
midiDevices.remove (device);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
midiDevices.remove (devicePair);
}
} }
} }
@@ -857,6 +935,7 @@ public class MidiTest extends Activity
{ {
MidiDeviceInfo info = theDevice.getInfo(); MidiDeviceInfo info = theDevice.getInfo();
int deviceID = info.getId(); int deviceID = info.getId();
BluetoothGatt gatt = null;
if (! openTasks.containsKey (deviceID)) if (! openTasks.containsKey (deviceID))
{ {
@@ -866,8 +945,9 @@ public class MidiTest extends Activity
if (btDevice != null) if (btDevice != null)
{ {
String btAddress = btDevice.getAddress(); String btAddress = btDevice.getAddress();
if (btDevicesPairing.contains (btAddress))
if (btDevicesPairing.containsKey (btAddress))
{ {
gatt = btDevicesPairing.get (btAddress);
btDevicesPairing.remove (btAddress); btDevicesPairing.remove (btAddress);
} }
else else
@@ -875,6 +955,18 @@ public class MidiTest extends Activity
// unpair was called in the mean time // unpair was called in the mean time
try try
{ {
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
theDevice.close(); theDevice.close();
} }
catch (IOException e) catch (IOException e)
@@ -885,7 +977,7 @@ public class MidiTest extends Activity
} }
} }
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice);
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice, gatt);
openTasks.put (deviceID, openTask); openTasks.put (deviceID, openTask);
new java.util.Timer().schedule (openTask, 3000); new java.util.Timer().schedule (openTask, 3000);
@@ -903,13 +995,32 @@ public class MidiTest extends Activity
{ {
if (! midiDevices.contains(theDevice)) if (! midiDevices.contains(theDevice))
{ {
BluetoothGatt gatt = openTasks.get (deviceID).getGatt();
openTasks.remove (deviceID); openTasks.remove (deviceID);
midiDevices.add (theDevice);
midiDevices.add (new Pair<MidiDevice,BluetoothGatt> (theDevice, gatt));
} }
} }
else else
{ {
// unpair was called in the mean time // unpair was called in the mean time
MidiDeviceInfo info = theDevice.getInfo();
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
if (btDevice != null)
{
String btAddress = btDevice.getAddress();
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
BluetoothGatt gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
}
try try
{ {
theDevice.close(); theDevice.close();
@@ -983,19 +1094,19 @@ public class MidiTest extends Activity
MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()]; MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()];
int idx = 0; int idx = 0;
for (MidiDevice midiDevice : midiDevices)
infos[idx++] = midiDevice.getInfo();
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
infos[idx++] = midiDevice.first.getInfo();
return infos; return infos;
} }
} }
private MidiDevice getMidiDeviceForId (int deviceId)
private Pair<MidiDevice, BluetoothGatt> getMidiDevicePairForId (int deviceId)
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
for (MidiDevice midiDevice : midiDevices)
if (midiDevice.getInfo().getId() == deviceId)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
if (midiDevice.first.getInfo().getId() == deviceId)
return midiDevice; return midiDevice;
} }
@@ -1003,9 +1114,9 @@ public class MidiTest extends Activity
} }
private MidiManager manager; private MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<String, BluetoothGatt> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks; private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices;
private ArrayList<Pair<MidiDevice, BluetoothGatt>> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;
} }


+ 167
- 56
examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java View File

@@ -54,6 +54,7 @@ import android.text.ClipboardManager;
import android.text.InputType; import android.text.InputType;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import java.lang.Runnable; import java.lang.Runnable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.*; import java.lang.reflect.*;
@@ -487,13 +488,34 @@ public class JuceDemoPlugin extends Activity
//============================================================================== //==============================================================================
public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener
{ {
//==============================================================================
private class DummyBluetoothGattCallback extends BluetoothGattCallback
{
public DummyBluetoothGattCallback()
{
super();
}
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {}
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {}
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {}
}
//============================================================================== //==============================================================================
private class MidiDeviceOpenTask extends java.util.TimerTask private class MidiDeviceOpenTask extends java.util.TimerTask
{ {
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device)
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device, BluetoothGatt gattToUse)
{ {
owner = deviceManager; owner = deviceManager;
midiDevice = device; midiDevice = device;
btGatt = gattToUse;
} }
@Override @Override
@@ -504,6 +526,14 @@ public class JuceDemoPlugin extends Activity
owner = null; owner = null;
boolean retval = super.cancel(); boolean retval = super.cancel();
if (btGatt != null)
{
btGatt.disconnect();
btGatt.close();
btGatt = null;
}
if (midiDevice != null) if (midiDevice != null)
{ {
try try
@@ -539,6 +569,8 @@ public class JuceDemoPlugin extends Activity
return ""; return "";
} }
public BluetoothGatt getGatt() { return btGatt; }
public int getID() public int getID()
{ {
return midiDevice.getInfo().getId(); return midiDevice.getInfo().getId();
@@ -556,6 +588,7 @@ public class JuceDemoPlugin extends Activity
private MidiDeviceManager owner; private MidiDeviceManager owner;
private MidiDevice midiDevice; private MidiDevice midiDevice;
private BluetoothGatt btGatt;
} }
//============================================================================== //==============================================================================
@@ -570,9 +603,9 @@ public class JuceDemoPlugin extends Activity
} }
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>();
midiDevices = new ArrayList<Pair<MidiDevice,BluetoothGatt>>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
btDevicesPairing = new HashMap<String, BluetoothGatt>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -600,8 +633,18 @@ public class JuceDemoPlugin extends Activity
openPorts = null; openPorts = null;
for (MidiDevice device : midiDevices)
device.close();
for (Pair<MidiDevice, BluetoothGatt> device : midiDevices)
{
if (device.second != null)
{
device.second.disconnect();
device.second.close();
}
device.first.close();
}
midiDevices.clear();
super.finalize(); super.finalize();
} }
@@ -647,30 +690,36 @@ public class JuceDemoPlugin extends Activity
if (openPorts.containsKey (portInfo)) if (openPorts.containsKey (portInfo))
return null; return null;
MidiDevice device = getMidiDeviceForId (portInfo.deviceId);
if (device != null)
{
JuceMidiPort juceMidiPort = null;
Pair<MidiDevice,BluetoothGatt> devicePair = getMidiDevicePairForId (portInfo.deviceId);
if (isInput)
if (devicePair != null)
{
MidiDevice device = devicePair.first;
if (device != null)
{ {
MidiOutputPort outputPort = device.openOutputPort (portInfo.portIndex);
JuceMidiPort juceMidiPort = null;
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort (portInfo.portIndex);
if (isInput)
{
MidiOutputPort outputPort = device.openOutputPort(portInfo.portIndex);
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort(portInfo.portIndex);
if (juceMidiPort != null) {
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
return juceMidiPort;
if (juceMidiPort != null)
{
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
return juceMidiPort;
}
} }
} }
} }
@@ -699,7 +748,7 @@ public class JuceDemoPlugin extends Activity
if (findMidiDeviceForBluetoothAddress (address) != null) if (findMidiDeviceForBluetoothAddress (address) != null)
return 1; return 1;
if (btDevicesPairing.contains (address))
if (btDevicesPairing.containsKey (address))
return 2; return 2;
if (findOpenTaskForBluetoothAddress (address) != null) if (findOpenTaskForBluetoothAddress (address) != null)
@@ -721,7 +770,11 @@ public class JuceDemoPlugin extends Activity
if (getBluetoothDeviceStatus (btAddress) != 0) if (getBluetoothDeviceStatus (btAddress) != 0)
return false; return false;
btDevicesPairing.add (btDevice.getAddress());
BluetoothGatt gatt = btDevice.connectGatt (getApplicationContext(), true, new DummyBluetoothGattCallback());
if (gatt != null)
gatt.requestConnectionPriority (BluetoothGatt.CONNECTION_PRIORITY_HIGH);
btDevicesPairing.put (btDevice.getAddress(), gatt);
manager.openBluetoothDevice(btDevice, this, null); manager.openBluetoothDevice(btDevice, this, null);
} }
@@ -735,7 +788,17 @@ public class JuceDemoPlugin extends Activity
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
btDevicesPairing.remove (address);
if (btDevicesPairing.containsKey (address))
{
BluetoothGatt gatt = btDevicesPairing.get (address);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
btDevicesPairing.remove (address);
}
MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address);
if (openTask != null) if (openTask != null)
@@ -745,9 +808,10 @@ public class JuceDemoPlugin extends Activity
openTasks.remove (deviceID); openTasks.remove (deviceID);
} }
MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null)
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (address);
if (midiDevicePair != null)
{ {
MidiDevice midiDevice = midiDevicePair.first;
onDeviceRemoved (midiDevice.getInfo()); onDeviceRemoved (midiDevice.getInfo());
try { try {
@@ -761,11 +825,11 @@ public class JuceDemoPlugin extends Activity
} }
} }
private MidiDevice findMidiDeviceForBluetoothAddress (String address)
private Pair<MidiDevice, BluetoothGatt> findMidiDeviceForBluetoothAddress (String address)
{ {
for (MidiDevice midiDevice : midiDevices)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
{ {
MidiDeviceInfo info = midiDevice.getInfo();
MidiDeviceInfo info = midiDevice.first.getInfo();
if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH)
{ {
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
@@ -825,24 +889,38 @@ public class JuceDemoPlugin extends Activity
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
MidiDevice device = getMidiDeviceForId (info.getId());
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true) {
removedPort = false;
for (MidiPortPath key : openPorts.keySet()) {
if (key.deviceId == info.getId()) {
openPorts.get(key).get().close();
removedPort = true;
break;
Pair<MidiDevice, BluetoothGatt> devicePair = getMidiDevicePairForId (info.getId());
if (devicePair != null)
{
MidiDevice midiDevice = devicePair.first;
BluetoothGatt gatt = devicePair.second;
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true)
{
removedPort = false;
for (MidiPortPath key : openPorts.keySet())
{
if (key.deviceId == info.getId())
{
openPorts.get(key).get().close();
removedPort = true;
break;
}
} }
} }
}
if (device != null)
midiDevices.remove (device);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
midiDevices.remove (devicePair);
}
} }
} }
@@ -857,6 +935,7 @@ public class JuceDemoPlugin extends Activity
{ {
MidiDeviceInfo info = theDevice.getInfo(); MidiDeviceInfo info = theDevice.getInfo();
int deviceID = info.getId(); int deviceID = info.getId();
BluetoothGatt gatt = null;
if (! openTasks.containsKey (deviceID)) if (! openTasks.containsKey (deviceID))
{ {
@@ -866,8 +945,9 @@ public class JuceDemoPlugin extends Activity
if (btDevice != null) if (btDevice != null)
{ {
String btAddress = btDevice.getAddress(); String btAddress = btDevice.getAddress();
if (btDevicesPairing.contains (btAddress))
if (btDevicesPairing.containsKey (btAddress))
{ {
gatt = btDevicesPairing.get (btAddress);
btDevicesPairing.remove (btAddress); btDevicesPairing.remove (btAddress);
} }
else else
@@ -875,6 +955,18 @@ public class JuceDemoPlugin extends Activity
// unpair was called in the mean time // unpair was called in the mean time
try try
{ {
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
theDevice.close(); theDevice.close();
} }
catch (IOException e) catch (IOException e)
@@ -885,7 +977,7 @@ public class JuceDemoPlugin extends Activity
} }
} }
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice);
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice, gatt);
openTasks.put (deviceID, openTask); openTasks.put (deviceID, openTask);
new java.util.Timer().schedule (openTask, 3000); new java.util.Timer().schedule (openTask, 3000);
@@ -903,13 +995,32 @@ public class JuceDemoPlugin extends Activity
{ {
if (! midiDevices.contains(theDevice)) if (! midiDevices.contains(theDevice))
{ {
BluetoothGatt gatt = openTasks.get (deviceID).getGatt();
openTasks.remove (deviceID); openTasks.remove (deviceID);
midiDevices.add (theDevice);
midiDevices.add (new Pair<MidiDevice,BluetoothGatt> (theDevice, gatt));
} }
} }
else else
{ {
// unpair was called in the mean time // unpair was called in the mean time
MidiDeviceInfo info = theDevice.getInfo();
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
if (btDevice != null)
{
String btAddress = btDevice.getAddress();
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
BluetoothGatt gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
}
try try
{ {
theDevice.close(); theDevice.close();
@@ -983,19 +1094,19 @@ public class JuceDemoPlugin extends Activity
MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()]; MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()];
int idx = 0; int idx = 0;
for (MidiDevice midiDevice : midiDevices)
infos[idx++] = midiDevice.getInfo();
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
infos[idx++] = midiDevice.first.getInfo();
return infos; return infos;
} }
} }
private MidiDevice getMidiDeviceForId (int deviceId)
private Pair<MidiDevice, BluetoothGatt> getMidiDevicePairForId (int deviceId)
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
for (MidiDevice midiDevice : midiDevices)
if (midiDevice.getInfo().getId() == deviceId)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
if (midiDevice.first.getInfo().getId() == deviceId)
return midiDevice; return midiDevice;
} }
@@ -1003,9 +1114,9 @@ public class JuceDemoPlugin extends Activity
} }
private MidiManager manager; private MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<String, BluetoothGatt> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks; private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices;
private ArrayList<Pair<MidiDevice, BluetoothGatt>> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;
} }


+ 167
- 56
extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java View File

@@ -54,6 +54,7 @@ import android.text.ClipboardManager;
import android.text.InputType; import android.text.InputType;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import java.lang.Runnable; import java.lang.Runnable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.*; import java.lang.reflect.*;
@@ -487,13 +488,34 @@ public class AudioPerformanceTest extends Activity
//============================================================================== //==============================================================================
public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener
{ {
//==============================================================================
private class DummyBluetoothGattCallback extends BluetoothGattCallback
{
public DummyBluetoothGattCallback()
{
super();
}
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {}
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {}
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {}
}
//============================================================================== //==============================================================================
private class MidiDeviceOpenTask extends java.util.TimerTask private class MidiDeviceOpenTask extends java.util.TimerTask
{ {
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device)
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device, BluetoothGatt gattToUse)
{ {
owner = deviceManager; owner = deviceManager;
midiDevice = device; midiDevice = device;
btGatt = gattToUse;
} }
@Override @Override
@@ -504,6 +526,14 @@ public class AudioPerformanceTest extends Activity
owner = null; owner = null;
boolean retval = super.cancel(); boolean retval = super.cancel();
if (btGatt != null)
{
btGatt.disconnect();
btGatt.close();
btGatt = null;
}
if (midiDevice != null) if (midiDevice != null)
{ {
try try
@@ -539,6 +569,8 @@ public class AudioPerformanceTest extends Activity
return ""; return "";
} }
public BluetoothGatt getGatt() { return btGatt; }
public int getID() public int getID()
{ {
return midiDevice.getInfo().getId(); return midiDevice.getInfo().getId();
@@ -556,6 +588,7 @@ public class AudioPerformanceTest extends Activity
private MidiDeviceManager owner; private MidiDeviceManager owner;
private MidiDevice midiDevice; private MidiDevice midiDevice;
private BluetoothGatt btGatt;
} }
//============================================================================== //==============================================================================
@@ -570,9 +603,9 @@ public class AudioPerformanceTest extends Activity
} }
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>();
midiDevices = new ArrayList<Pair<MidiDevice,BluetoothGatt>>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
btDevicesPairing = new HashMap<String, BluetoothGatt>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -600,8 +633,18 @@ public class AudioPerformanceTest extends Activity
openPorts = null; openPorts = null;
for (MidiDevice device : midiDevices)
device.close();
for (Pair<MidiDevice, BluetoothGatt> device : midiDevices)
{
if (device.second != null)
{
device.second.disconnect();
device.second.close();
}
device.first.close();
}
midiDevices.clear();
super.finalize(); super.finalize();
} }
@@ -647,30 +690,36 @@ public class AudioPerformanceTest extends Activity
if (openPorts.containsKey (portInfo)) if (openPorts.containsKey (portInfo))
return null; return null;
MidiDevice device = getMidiDeviceForId (portInfo.deviceId);
if (device != null)
{
JuceMidiPort juceMidiPort = null;
Pair<MidiDevice,BluetoothGatt> devicePair = getMidiDevicePairForId (portInfo.deviceId);
if (isInput)
if (devicePair != null)
{
MidiDevice device = devicePair.first;
if (device != null)
{ {
MidiOutputPort outputPort = device.openOutputPort (portInfo.portIndex);
JuceMidiPort juceMidiPort = null;
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort (portInfo.portIndex);
if (isInput)
{
MidiOutputPort outputPort = device.openOutputPort(portInfo.portIndex);
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort(portInfo.portIndex);
if (juceMidiPort != null) {
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
return juceMidiPort;
if (juceMidiPort != null)
{
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
return juceMidiPort;
}
} }
} }
} }
@@ -699,7 +748,7 @@ public class AudioPerformanceTest extends Activity
if (findMidiDeviceForBluetoothAddress (address) != null) if (findMidiDeviceForBluetoothAddress (address) != null)
return 1; return 1;
if (btDevicesPairing.contains (address))
if (btDevicesPairing.containsKey (address))
return 2; return 2;
if (findOpenTaskForBluetoothAddress (address) != null) if (findOpenTaskForBluetoothAddress (address) != null)
@@ -721,7 +770,11 @@ public class AudioPerformanceTest extends Activity
if (getBluetoothDeviceStatus (btAddress) != 0) if (getBluetoothDeviceStatus (btAddress) != 0)
return false; return false;
btDevicesPairing.add (btDevice.getAddress());
BluetoothGatt gatt = btDevice.connectGatt (getApplicationContext(), true, new DummyBluetoothGattCallback());
if (gatt != null)
gatt.requestConnectionPriority (BluetoothGatt.CONNECTION_PRIORITY_HIGH);
btDevicesPairing.put (btDevice.getAddress(), gatt);
manager.openBluetoothDevice(btDevice, this, null); manager.openBluetoothDevice(btDevice, this, null);
} }
@@ -735,7 +788,17 @@ public class AudioPerformanceTest extends Activity
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
btDevicesPairing.remove (address);
if (btDevicesPairing.containsKey (address))
{
BluetoothGatt gatt = btDevicesPairing.get (address);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
btDevicesPairing.remove (address);
}
MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address);
if (openTask != null) if (openTask != null)
@@ -745,9 +808,10 @@ public class AudioPerformanceTest extends Activity
openTasks.remove (deviceID); openTasks.remove (deviceID);
} }
MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null)
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (address);
if (midiDevicePair != null)
{ {
MidiDevice midiDevice = midiDevicePair.first;
onDeviceRemoved (midiDevice.getInfo()); onDeviceRemoved (midiDevice.getInfo());
try { try {
@@ -761,11 +825,11 @@ public class AudioPerformanceTest extends Activity
} }
} }
private MidiDevice findMidiDeviceForBluetoothAddress (String address)
private Pair<MidiDevice, BluetoothGatt> findMidiDeviceForBluetoothAddress (String address)
{ {
for (MidiDevice midiDevice : midiDevices)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
{ {
MidiDeviceInfo info = midiDevice.getInfo();
MidiDeviceInfo info = midiDevice.first.getInfo();
if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH)
{ {
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
@@ -825,24 +889,38 @@ public class AudioPerformanceTest extends Activity
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
MidiDevice device = getMidiDeviceForId (info.getId());
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true) {
removedPort = false;
for (MidiPortPath key : openPorts.keySet()) {
if (key.deviceId == info.getId()) {
openPorts.get(key).get().close();
removedPort = true;
break;
Pair<MidiDevice, BluetoothGatt> devicePair = getMidiDevicePairForId (info.getId());
if (devicePair != null)
{
MidiDevice midiDevice = devicePair.first;
BluetoothGatt gatt = devicePair.second;
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true)
{
removedPort = false;
for (MidiPortPath key : openPorts.keySet())
{
if (key.deviceId == info.getId())
{
openPorts.get(key).get().close();
removedPort = true;
break;
}
} }
} }
}
if (device != null)
midiDevices.remove (device);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
midiDevices.remove (devicePair);
}
} }
} }
@@ -857,6 +935,7 @@ public class AudioPerformanceTest extends Activity
{ {
MidiDeviceInfo info = theDevice.getInfo(); MidiDeviceInfo info = theDevice.getInfo();
int deviceID = info.getId(); int deviceID = info.getId();
BluetoothGatt gatt = null;
if (! openTasks.containsKey (deviceID)) if (! openTasks.containsKey (deviceID))
{ {
@@ -866,8 +945,9 @@ public class AudioPerformanceTest extends Activity
if (btDevice != null) if (btDevice != null)
{ {
String btAddress = btDevice.getAddress(); String btAddress = btDevice.getAddress();
if (btDevicesPairing.contains (btAddress))
if (btDevicesPairing.containsKey (btAddress))
{ {
gatt = btDevicesPairing.get (btAddress);
btDevicesPairing.remove (btAddress); btDevicesPairing.remove (btAddress);
} }
else else
@@ -875,6 +955,18 @@ public class AudioPerformanceTest extends Activity
// unpair was called in the mean time // unpair was called in the mean time
try try
{ {
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
theDevice.close(); theDevice.close();
} }
catch (IOException e) catch (IOException e)
@@ -885,7 +977,7 @@ public class AudioPerformanceTest extends Activity
} }
} }
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice);
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice, gatt);
openTasks.put (deviceID, openTask); openTasks.put (deviceID, openTask);
new java.util.Timer().schedule (openTask, 3000); new java.util.Timer().schedule (openTask, 3000);
@@ -903,13 +995,32 @@ public class AudioPerformanceTest extends Activity
{ {
if (! midiDevices.contains(theDevice)) if (! midiDevices.contains(theDevice))
{ {
BluetoothGatt gatt = openTasks.get (deviceID).getGatt();
openTasks.remove (deviceID); openTasks.remove (deviceID);
midiDevices.add (theDevice);
midiDevices.add (new Pair<MidiDevice,BluetoothGatt> (theDevice, gatt));
} }
} }
else else
{ {
// unpair was called in the mean time // unpair was called in the mean time
MidiDeviceInfo info = theDevice.getInfo();
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
if (btDevice != null)
{
String btAddress = btDevice.getAddress();
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
BluetoothGatt gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
}
try try
{ {
theDevice.close(); theDevice.close();
@@ -983,19 +1094,19 @@ public class AudioPerformanceTest extends Activity
MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()]; MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()];
int idx = 0; int idx = 0;
for (MidiDevice midiDevice : midiDevices)
infos[idx++] = midiDevice.getInfo();
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
infos[idx++] = midiDevice.first.getInfo();
return infos; return infos;
} }
} }
private MidiDevice getMidiDeviceForId (int deviceId)
private Pair<MidiDevice, BluetoothGatt> getMidiDevicePairForId (int deviceId)
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
for (MidiDevice midiDevice : midiDevices)
if (midiDevice.getInfo().getId() == deviceId)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
if (midiDevice.first.getInfo().getId() == deviceId)
return midiDevice; return midiDevice;
} }
@@ -1003,9 +1114,9 @@ public class AudioPerformanceTest extends Activity
} }
private MidiManager manager; private MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<String, BluetoothGatt> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks; private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices;
private ArrayList<Pair<MidiDevice, BluetoothGatt>> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;
} }


+ 166
- 56
modules/juce_core/native/java/AndroidMidi.java View File

@@ -309,13 +309,34 @@
//============================================================================== //==============================================================================
public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener
{ {
//==============================================================================
private class DummyBluetoothGattCallback extends BluetoothGattCallback
{
public DummyBluetoothGattCallback()
{
super();
}
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {}
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {}
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {}
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {}
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {}
}
//============================================================================== //==============================================================================
private class MidiDeviceOpenTask extends java.util.TimerTask private class MidiDeviceOpenTask extends java.util.TimerTask
{ {
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device)
public MidiDeviceOpenTask (MidiDeviceManager deviceManager, MidiDevice device, BluetoothGatt gattToUse)
{ {
owner = deviceManager; owner = deviceManager;
midiDevice = device; midiDevice = device;
btGatt = gattToUse;
} }
@Override @Override
@@ -326,6 +347,14 @@
owner = null; owner = null;
boolean retval = super.cancel(); boolean retval = super.cancel();
if (btGatt != null)
{
btGatt.disconnect();
btGatt.close();
btGatt = null;
}
if (midiDevice != null) if (midiDevice != null)
{ {
try try
@@ -361,6 +390,8 @@
return ""; return "";
} }
public BluetoothGatt getGatt() { return btGatt; }
public int getID() public int getID()
{ {
return midiDevice.getInfo().getId(); return midiDevice.getInfo().getId();
@@ -378,6 +409,7 @@
private MidiDeviceManager owner; private MidiDeviceManager owner;
private MidiDevice midiDevice; private MidiDevice midiDevice;
private BluetoothGatt btGatt;
} }
//============================================================================== //==============================================================================
@@ -392,9 +424,9 @@
} }
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>();
midiDevices = new ArrayList<Pair<MidiDevice,BluetoothGatt>>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>(); openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
btDevicesPairing = new HashMap<String, BluetoothGatt>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -422,8 +454,18 @@
openPorts = null; openPorts = null;
for (MidiDevice device : midiDevices)
device.close();
for (Pair<MidiDevice, BluetoothGatt> device : midiDevices)
{
if (device.second != null)
{
device.second.disconnect();
device.second.close();
}
device.first.close();
}
midiDevices.clear();
super.finalize(); super.finalize();
} }
@@ -469,30 +511,36 @@
if (openPorts.containsKey (portInfo)) if (openPorts.containsKey (portInfo))
return null; return null;
MidiDevice device = getMidiDeviceForId (portInfo.deviceId);
if (device != null)
{
JuceMidiPort juceMidiPort = null;
Pair<MidiDevice,BluetoothGatt> devicePair = getMidiDevicePairForId (portInfo.deviceId);
if (isInput)
if (devicePair != null)
{
MidiDevice device = devicePair.first;
if (device != null)
{ {
MidiOutputPort outputPort = device.openOutputPort (portInfo.portIndex);
JuceMidiPort juceMidiPort = null;
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort (portInfo.portIndex);
if (isInput)
{
MidiOutputPort outputPort = device.openOutputPort(portInfo.portIndex);
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
if (outputPort != null)
juceMidiPort = new JuceMidiInputPort(this, outputPort, portInfo, host);
}
else
{
MidiInputPort inputPort = device.openInputPort(portInfo.portIndex);
if (juceMidiPort != null) {
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
if (inputPort != null)
juceMidiPort = new JuceMidiOutputPort(this, inputPort, portInfo);
}
return juceMidiPort;
if (juceMidiPort != null)
{
openPorts.put(portInfo, new WeakReference<JuceMidiPort>(juceMidiPort));
return juceMidiPort;
}
} }
} }
} }
@@ -521,7 +569,7 @@
if (findMidiDeviceForBluetoothAddress (address) != null) if (findMidiDeviceForBluetoothAddress (address) != null)
return 1; return 1;
if (btDevicesPairing.contains (address))
if (btDevicesPairing.containsKey (address))
return 2; return 2;
if (findOpenTaskForBluetoothAddress (address) != null) if (findOpenTaskForBluetoothAddress (address) != null)
@@ -543,7 +591,11 @@
if (getBluetoothDeviceStatus (btAddress) != 0) if (getBluetoothDeviceStatus (btAddress) != 0)
return false; return false;
btDevicesPairing.add (btDevice.getAddress());
BluetoothGatt gatt = btDevice.connectGatt (getApplicationContext(), true, new DummyBluetoothGattCallback());
if (gatt != null)
gatt.requestConnectionPriority (BluetoothGatt.CONNECTION_PRIORITY_HIGH);
btDevicesPairing.put (btDevice.getAddress(), gatt);
manager.openBluetoothDevice(btDevice, this, null); manager.openBluetoothDevice(btDevice, this, null);
} }
@@ -557,7 +609,17 @@
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
btDevicesPairing.remove (address);
if (btDevicesPairing.containsKey (address))
{
BluetoothGatt gatt = btDevicesPairing.get (address);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
btDevicesPairing.remove (address);
}
MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address); MidiDeviceOpenTask openTask = findOpenTaskForBluetoothAddress (address);
if (openTask != null) if (openTask != null)
@@ -567,9 +629,10 @@
openTasks.remove (deviceID); openTasks.remove (deviceID);
} }
MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null)
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (address);
if (midiDevicePair != null)
{ {
MidiDevice midiDevice = midiDevicePair.first;
onDeviceRemoved (midiDevice.getInfo()); onDeviceRemoved (midiDevice.getInfo());
try { try {
@@ -583,11 +646,11 @@
} }
} }
private MidiDevice findMidiDeviceForBluetoothAddress (String address)
private Pair<MidiDevice, BluetoothGatt> findMidiDeviceForBluetoothAddress (String address)
{ {
for (MidiDevice midiDevice : midiDevices)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
{ {
MidiDeviceInfo info = midiDevice.getInfo();
MidiDeviceInfo info = midiDevice.first.getInfo();
if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH) if (info.getType() == MidiDeviceInfo.TYPE_BLUETOOTH)
{ {
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE); BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
@@ -647,24 +710,38 @@
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
MidiDevice device = getMidiDeviceForId (info.getId());
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true) {
removedPort = false;
for (MidiPortPath key : openPorts.keySet()) {
if (key.deviceId == info.getId()) {
openPorts.get(key).get().close();
removedPort = true;
break;
Pair<MidiDevice, BluetoothGatt> devicePair = getMidiDevicePairForId (info.getId());
if (devicePair != null)
{
MidiDevice midiDevice = devicePair.first;
BluetoothGatt gatt = devicePair.second;
// close all ports that use this device
boolean removedPort = true;
while (removedPort == true)
{
removedPort = false;
for (MidiPortPath key : openPorts.keySet())
{
if (key.deviceId == info.getId())
{
openPorts.get(key).get().close();
removedPort = true;
break;
}
} }
} }
}
if (device != null)
midiDevices.remove (device);
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
midiDevices.remove (devicePair);
}
} }
} }
@@ -679,6 +756,7 @@
{ {
MidiDeviceInfo info = theDevice.getInfo(); MidiDeviceInfo info = theDevice.getInfo();
int deviceID = info.getId(); int deviceID = info.getId();
BluetoothGatt gatt = null;
if (! openTasks.containsKey (deviceID)) if (! openTasks.containsKey (deviceID))
{ {
@@ -688,8 +766,9 @@
if (btDevice != null) if (btDevice != null)
{ {
String btAddress = btDevice.getAddress(); String btAddress = btDevice.getAddress();
if (btDevicesPairing.contains (btAddress))
if (btDevicesPairing.containsKey (btAddress))
{ {
gatt = btDevicesPairing.get (btAddress);
btDevicesPairing.remove (btAddress); btDevicesPairing.remove (btAddress);
} }
else else
@@ -697,6 +776,18 @@
// unpair was called in the mean time // unpair was called in the mean time
try try
{ {
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
theDevice.close(); theDevice.close();
} }
catch (IOException e) catch (IOException e)
@@ -707,7 +798,7 @@
} }
} }
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice);
MidiDeviceOpenTask openTask = new MidiDeviceOpenTask (this, theDevice, gatt);
openTasks.put (deviceID, openTask); openTasks.put (deviceID, openTask);
new java.util.Timer().schedule (openTask, 3000); new java.util.Timer().schedule (openTask, 3000);
@@ -725,13 +816,32 @@
{ {
if (! midiDevices.contains(theDevice)) if (! midiDevices.contains(theDevice))
{ {
BluetoothGatt gatt = openTasks.get (deviceID).getGatt();
openTasks.remove (deviceID); openTasks.remove (deviceID);
midiDevices.add (theDevice);
midiDevices.add (new Pair<MidiDevice,BluetoothGatt> (theDevice, gatt));
} }
} }
else else
{ {
// unpair was called in the mean time // unpair was called in the mean time
MidiDeviceInfo info = theDevice.getInfo();
BluetoothDevice btDevice = (BluetoothDevice) info.getProperties().get (info.PROPERTY_BLUETOOTH_DEVICE);
if (btDevice != null)
{
String btAddress = btDevice.getAddress();
Pair<MidiDevice, BluetoothGatt> midiDevicePair = findMidiDeviceForBluetoothAddress (btDevice.getAddress());
if (midiDevicePair != null)
{
BluetoothGatt gatt = midiDevicePair.second;
if (gatt != null)
{
gatt.disconnect();
gatt.close();
}
}
}
try try
{ {
theDevice.close(); theDevice.close();
@@ -805,19 +915,19 @@
MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()]; MidiDeviceInfo[] infos = new MidiDeviceInfo[midiDevices.size()];
int idx = 0; int idx = 0;
for (MidiDevice midiDevice : midiDevices)
infos[idx++] = midiDevice.getInfo();
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
infos[idx++] = midiDevice.first.getInfo();
return infos; return infos;
} }
} }
private MidiDevice getMidiDeviceForId (int deviceId)
private Pair<MidiDevice, BluetoothGatt> getMidiDevicePairForId (int deviceId)
{ {
synchronized (MidiDeviceManager.class) synchronized (MidiDeviceManager.class)
{ {
for (MidiDevice midiDevice : midiDevices)
if (midiDevice.getInfo().getId() == deviceId)
for (Pair<MidiDevice,BluetoothGatt> midiDevice : midiDevices)
if (midiDevice.first.getInfo().getId() == deviceId)
return midiDevice; return midiDevice;
} }
@@ -825,9 +935,9 @@
} }
private MidiManager manager; private MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<String, BluetoothGatt> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks; private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices;
private ArrayList<Pair<MidiDevice, BluetoothGatt>> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;
} }


+ 1
- 0
modules/juce_core/native/java/JuceAppActivity.java View File

@@ -54,6 +54,7 @@ import android.text.ClipboardManager;
import android.text.InputType; import android.text.InputType;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import java.lang.Runnable; import java.lang.Runnable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.*; import java.lang.reflect.*;


Loading…
Cancel
Save