Browse Source

Added pause after opening MIDI BLE device on Android to improve MIDI BLE reliability

tags/2021-05-28
hogliux 8 years ago
parent
commit
8aea84e20c
10 changed files with 855 additions and 50 deletions
  1. +2
    -2
      examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java
  2. +205
    -8
      examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java
  3. +2
    -2
      examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java
  4. +2
    -2
      examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java
  5. +2
    -2
      examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java
  6. +205
    -8
      examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java
  7. +205
    -8
      extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java
  8. +25
    -8
      modules/juce_audio_utils/native/juce_android_BluetoothMidiDevicePairingDialogue.cpp
  9. +205
    -8
      modules/juce_core/native/java/AndroidMidi.java
  10. +2
    -2
      modules/juce_core/native/java/AndroidMidiFallback.java

+ 2
- 2
examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java View File

@@ -179,9 +179,9 @@ public class JuceDemo extends Activity
return address; return address;
} }
public boolean isBluetoothDevicePaired (String address)
public int getBluetoothDeviceStatus (String address)
{ {
return false;
return 0;
} }
public void startStopScan (boolean shouldStart) public void startStopScan (boolean shouldStart)


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

@@ -194,9 +194,9 @@ public class MidiTest extends Activity
return btDevice.getName(); 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) public void startStopScan (boolean shouldStart)
@@ -487,7 +487,78 @@ 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 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() public MidiDeviceManager()
{ {
manager = (MidiManager) getSystemService (MIDI_SERVICE); manager = (MidiManager) getSystemService (MIDI_SERVICE);
@@ -500,6 +571,8 @@ public class MidiTest extends Activity
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>(); midiDevices = new ArrayList<MidiDevice>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -512,6 +585,16 @@ public class MidiTest extends Activity
{ {
manager.unregisterDeviceCallback (this); manager.unregisterDeviceCallback (this);
synchronized (MidiDeviceManager.class)
{
btDevicesPairing.clear();
for (Integer deviceID : openTasks.keySet())
openTasks.get (deviceID).cancel();
openTasks = null;
}
for (MidiPortPath key : openPorts.keySet()) for (MidiPortPath key : openPorts.keySet())
openPorts.get (key).get().close(); openPorts.get (key).get().close();
@@ -606,21 +689,62 @@ public class MidiTest extends Activity
return openMidiPortWithJuceIndex (index, 0, false); 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) 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; return true;
} }
public void unpairBluetoothDevice (String address) public void unpairBluetoothDevice (String address)
{ {
if (address.isEmpty())
return;
synchronized (MidiDeviceManager.class) 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); MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null) if (midiDevice != null)
{ {
@@ -653,6 +777,18 @@ public class MidiTest extends Activity
return null; 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) public void removePort (MidiPortPath path)
{ {
openPorts.remove (path); openPorts.remove (path);
@@ -719,9 +855,68 @@ public class MidiTest extends Activity
{ {
synchronized (MidiDeviceManager.class) 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 MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices; private ArrayList<MidiDevice> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;


+ 2
- 2
examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java View File

@@ -179,9 +179,9 @@ public class JUCENetworkGraphicsDemo extends Activity
return address; return address;
} }
public boolean isBluetoothDevicePaired (String address)
public int getBluetoothDeviceStatus (String address)
{ {
return false;
return 0;
} }
public void startStopScan (boolean shouldStart) public void startStopScan (boolean shouldStart)


+ 2
- 2
examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java View File

@@ -179,9 +179,9 @@ public class OSCReceiver extends Activity
return address; return address;
} }
public boolean isBluetoothDevicePaired (String address)
public int getBluetoothDeviceStatus (String address)
{ {
return false;
return 0;
} }
public void startStopScan (boolean shouldStart) public void startStopScan (boolean shouldStart)


+ 2
- 2
examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java View File

@@ -179,9 +179,9 @@ public class OSCSender extends Activity
return address; return address;
} }
public boolean isBluetoothDevicePaired (String address)
public int getBluetoothDeviceStatus (String address)
{ {
return false;
return 0;
} }
public void startStopScan (boolean shouldStart) public void startStopScan (boolean shouldStart)


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

@@ -194,9 +194,9 @@ public class JuceDemoPlugin extends Activity
return btDevice.getName(); 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) public void startStopScan (boolean shouldStart)
@@ -487,7 +487,78 @@ 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 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() public MidiDeviceManager()
{ {
manager = (MidiManager) getSystemService (MIDI_SERVICE); manager = (MidiManager) getSystemService (MIDI_SERVICE);
@@ -500,6 +571,8 @@ public class JuceDemoPlugin extends Activity
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>(); midiDevices = new ArrayList<MidiDevice>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -512,6 +585,16 @@ public class JuceDemoPlugin extends Activity
{ {
manager.unregisterDeviceCallback (this); manager.unregisterDeviceCallback (this);
synchronized (MidiDeviceManager.class)
{
btDevicesPairing.clear();
for (Integer deviceID : openTasks.keySet())
openTasks.get (deviceID).cancel();
openTasks = null;
}
for (MidiPortPath key : openPorts.keySet()) for (MidiPortPath key : openPorts.keySet())
openPorts.get (key).get().close(); openPorts.get (key).get().close();
@@ -606,21 +689,62 @@ public class JuceDemoPlugin extends Activity
return openMidiPortWithJuceIndex (index, 0, false); 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) 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; return true;
} }
public void unpairBluetoothDevice (String address) public void unpairBluetoothDevice (String address)
{ {
if (address.isEmpty())
return;
synchronized (MidiDeviceManager.class) 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); MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null) if (midiDevice != null)
{ {
@@ -653,6 +777,18 @@ public class JuceDemoPlugin extends Activity
return null; 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) public void removePort (MidiPortPath path)
{ {
openPorts.remove (path); openPorts.remove (path);
@@ -719,9 +855,68 @@ public class JuceDemoPlugin extends Activity
{ {
synchronized (MidiDeviceManager.class) 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 MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices; private ArrayList<MidiDevice> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;


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

@@ -194,9 +194,9 @@ public class AudioPerformanceTest extends Activity
return btDevice.getName(); 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) public void startStopScan (boolean shouldStart)
@@ -487,7 +487,78 @@ 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 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() public MidiDeviceManager()
{ {
manager = (MidiManager) getSystemService (MIDI_SERVICE); manager = (MidiManager) getSystemService (MIDI_SERVICE);
@@ -500,6 +571,8 @@ public class AudioPerformanceTest extends Activity
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>(); midiDevices = new ArrayList<MidiDevice>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -512,6 +585,16 @@ public class AudioPerformanceTest extends Activity
{ {
manager.unregisterDeviceCallback (this); manager.unregisterDeviceCallback (this);
synchronized (MidiDeviceManager.class)
{
btDevicesPairing.clear();
for (Integer deviceID : openTasks.keySet())
openTasks.get (deviceID).cancel();
openTasks = null;
}
for (MidiPortPath key : openPorts.keySet()) for (MidiPortPath key : openPorts.keySet())
openPorts.get (key).get().close(); openPorts.get (key).get().close();
@@ -606,21 +689,62 @@ public class AudioPerformanceTest extends Activity
return openMidiPortWithJuceIndex (index, 0, false); 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) 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; return true;
} }
public void unpairBluetoothDevice (String address) public void unpairBluetoothDevice (String address)
{ {
if (address.isEmpty())
return;
synchronized (MidiDeviceManager.class) 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); MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null) if (midiDevice != null)
{ {
@@ -653,6 +777,18 @@ public class AudioPerformanceTest extends Activity
return null; 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) public void removePort (MidiPortPath path)
{ {
openPorts.remove (path); openPorts.remove (path);
@@ -719,9 +855,68 @@ public class AudioPerformanceTest extends Activity
{ {
synchronized (MidiDeviceManager.class) 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 MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices; private ArrayList<MidiDevice> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;


+ 25
- 8
modules/juce_audio_utils/native/juce_android_BluetoothMidiDevicePairingDialogue.cpp View File

@@ -28,7 +28,7 @@
METHOD (pairBluetoothMidiDevice, "pairBluetoothMidiDevice", "(Ljava/lang/String;)Z") \ METHOD (pairBluetoothMidiDevice, "pairBluetoothMidiDevice", "(Ljava/lang/String;)Z") \
METHOD (unpairBluetoothMidiDevice, "unpairBluetoothMidiDevice", "(Ljava/lang/String;)V") \ METHOD (unpairBluetoothMidiDevice, "unpairBluetoothMidiDevice", "(Ljava/lang/String;)V") \
METHOD (getHumanReadableStringForBluetoothAddress, "getHumanReadableStringForBluetoothAddress", "(Ljava/lang/String;)Ljava/lang/String;") \ 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") METHOD (startStopScan, "startStopScan", "(Z)V")
DECLARE_JNI_CLASS (AndroidBluetoothManager, JUCE_ANDROID_ACTIVITY_CLASSPATH "$BluetoothManager"); 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(); JNIEnv* env = getEnv();
LocalRef<jobject> btManager (android.activity.callObjectMethod (JuceAppActivity.getAndroidBluetoothManager)); LocalRef<jobject> btManager (android.activity.callObjectMethod (JuceAppActivity.getAndroidBluetoothManager));
if (btManager.get() == nullptr) 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) address != bluetoothAddresses.end(); ++address)
{ {
String name = AndroidBluetoothMidiInterface::getHumanReadableStringForBluetoothAddress (*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)); newDevices.add (AndroidBluetoothMidiDevice (name, *address, status));
} }


+ 205
- 8
modules/juce_core/native/java/AndroidMidi.java View File

@@ -16,9 +16,9 @@
return btDevice.getName(); 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) public void startStopScan (boolean shouldStart)
@@ -309,7 +309,78 @@
//============================================================================== //==============================================================================
public class MidiDeviceManager extends MidiManager.DeviceCallback implements MidiManager.OnDeviceOpenedListener 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() public MidiDeviceManager()
{ {
manager = (MidiManager) getSystemService (MIDI_SERVICE); manager = (MidiManager) getSystemService (MIDI_SERVICE);
@@ -322,6 +393,8 @@
openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> (); openPorts = new HashMap<MidiPortPath, WeakReference<JuceMidiPort>> ();
midiDevices = new ArrayList<MidiDevice>(); midiDevices = new ArrayList<MidiDevice>();
openTasks = new HashMap<Integer, MidiDeviceOpenTask>();
btDevicesPairing = new HashSet<String>();
MidiDeviceInfo[] foundDevices = manager.getDevices(); MidiDeviceInfo[] foundDevices = manager.getDevices();
for (MidiDeviceInfo info : foundDevices) for (MidiDeviceInfo info : foundDevices)
@@ -334,6 +407,16 @@
{ {
manager.unregisterDeviceCallback (this); manager.unregisterDeviceCallback (this);
synchronized (MidiDeviceManager.class)
{
btDevicesPairing.clear();
for (Integer deviceID : openTasks.keySet())
openTasks.get (deviceID).cancel();
openTasks = null;
}
for (MidiPortPath key : openPorts.keySet()) for (MidiPortPath key : openPorts.keySet())
openPorts.get (key).get().close(); openPorts.get (key).get().close();
@@ -428,21 +511,62 @@
return openMidiPortWithJuceIndex (index, 0, false); 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) 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; return true;
} }
public void unpairBluetoothDevice (String address) public void unpairBluetoothDevice (String address)
{ {
if (address.isEmpty())
return;
synchronized (MidiDeviceManager.class) 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); MidiDevice midiDevice = findMidiDeviceForBluetoothAddress (address);
if (midiDevice != null) if (midiDevice != null)
{ {
@@ -475,6 +599,18 @@
return null; 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) public void removePort (MidiPortPath path)
{ {
openPorts.remove (path); openPorts.remove (path);
@@ -541,9 +677,68 @@
{ {
synchronized (MidiDeviceManager.class) 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 MidiManager manager;
private HashSet<String> btDevicesPairing;
private HashMap<Integer, MidiDeviceOpenTask> openTasks;
private ArrayList<MidiDevice> midiDevices; private ArrayList<MidiDevice> midiDevices;
private MidiDeviceInfo[] deviceInfos; private MidiDeviceInfo[] deviceInfos;
private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts; private HashMap<MidiPortPath, WeakReference<JuceMidiPort>> openPorts;


+ 2
- 2
modules/juce_core/native/java/AndroidMidiFallback.java View File

@@ -16,9 +16,9 @@
return address; return address;
} }
public boolean isBluetoothDevicePaired (String address)
public int getBluetoothDeviceStatus (String address)
{ {
return false;
return 0;
} }
public void startStopScan (boolean shouldStart) public void startStopScan (boolean shouldStart)


Loading…
Cancel
Save