mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Re-saved JuceDemo project due to changes in Android exporter.
This commit is contained in:
parent
5edc467755
commit
f1373fcfa6
6 changed files with 784 additions and 26 deletions
|
|
@ -3,11 +3,12 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="3.0.0"
|
||||
package="com.juce.jucedemo">
|
||||
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/>
|
||||
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="11"/>
|
||||
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="11"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
|
||||
<application android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" android:icon="@drawable/icon">
|
||||
<application android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar" android:icon="@drawable/icon"
|
||||
android:hardwareAccelerated="false">
|
||||
<activity android:name="JuceDemo" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="unspecified">
|
||||
<intent-filter>
|
||||
|
|
|
|||
|
|
@ -69,14 +69,14 @@ LOCAL_SRC_FILES := \
|
|||
../../../../../modules/juce_video/juce_video.cpp\
|
||||
|
||||
ifeq ($(NDK_DEBUG),1)
|
||||
LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=10" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=23" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_LDLIBS := -llog -lGLESv2 -landroid -lEGL
|
||||
LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=10" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -I "../../../../modules" -O0 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=23" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_LDLIBS := -llog -lGLESv2 -landroid -lEGL
|
||||
else
|
||||
LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=10" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=23" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_LDLIBS := -llog -lGLESv2 -landroid -lEGL
|
||||
LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=10" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_CFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -I "../../../../modules" -O3 -std=c++11 -std=gnu++11 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_API_VERSION=23" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemo_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemo/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" -D "JUCE_APP_VERSION=3.0.0" -D "JUCE_APP_VERSION_HEX=0x30000"
|
||||
LOCAL_LDLIBS := -llog -lGLESv2 -landroid -lEGL
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
APP_STL := gnustl_static
|
||||
APP_CPPFLAGS += -fsigned-char -fexceptions -frtti -Wno-psabi
|
||||
APP_PLATFORM := android-10
|
||||
APP_PLATFORM := android-23
|
||||
NDK_TOOLCHAIN_VERSION := 4.8
|
||||
|
||||
ifeq ($(NDK_DEBUG),1)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
# It is automatically generated - DO NOT EDIT IT or your changes will be lost!.
|
||||
|
||||
target=android-10
|
||||
target=android-23
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ import android.media.MediaScannerConnection;
|
|||
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
||||
|
||||
|
||||
import android.media.midi.*;
|
||||
import android.bluetooth.*;
|
||||
import android.bluetooth.le.*;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -125,85 +128,839 @@ public class JuceDemo extends Activity
|
|||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
public class BluetoothManager
|
||||
public class BluetoothManager extends ScanCallback
|
||||
{
|
||||
BluetoothManager()
|
||||
{
|
||||
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder();
|
||||
scanFilterBuilder.setServiceUuid (ParcelUuid.fromString (bluetoothLEMidiServiceUUID));
|
||||
|
||||
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
|
||||
scanSettingsBuilder.setCallbackType (ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
|
||||
.setScanMode (ScanSettings.SCAN_MODE_LOW_POWER)
|
||||
.setScanMode (ScanSettings.MATCH_MODE_STICKY);
|
||||
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
if (bluetoothAdapter == null)
|
||||
{
|
||||
Log.d ("JUCE", "BluetoothManager error: could not get default Bluetooth adapter");
|
||||
return;
|
||||
}
|
||||
|
||||
BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
|
||||
|
||||
if (bluetoothLeScanner == null)
|
||||
{
|
||||
Log.d ("JUCE", "BluetoothManager error: could not get Bluetooth LE scanner");
|
||||
return;
|
||||
}
|
||||
|
||||
bluetoothLeScanner.startScan (Arrays.asList (scanFilterBuilder.build()),
|
||||
scanSettingsBuilder.build(),
|
||||
this);
|
||||
}
|
||||
|
||||
public String[] getMidiBluetoothAddresses()
|
||||
{
|
||||
String[] bluetoothAddresses = new String[0];
|
||||
return bluetoothAddresses;
|
||||
return bluetoothMidiDevices.toArray (new String[bluetoothMidiDevices.size()]);
|
||||
}
|
||||
|
||||
public String getHumanReadableStringForBluetoothAddress (String address)
|
||||
{
|
||||
return address;
|
||||
BluetoothDevice btDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice (address);
|
||||
return btDevice.getName();
|
||||
}
|
||||
|
||||
public boolean isBluetoothDevicePaired (String address)
|
||||
{
|
||||
return false;
|
||||
return getAndroidMidiDeviceManager().isBluetoothDevicePaired (address);
|
||||
}
|
||||
|
||||
public boolean pairBluetoothMidiDevice(String address)
|
||||
{
|
||||
BluetoothDevice btDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice (address);
|
||||
|
||||
if (btDevice == null)
|
||||
{
|
||||
Log.d ("JUCE", "failed to create buletooth device from address");
|
||||
return false;
|
||||
}
|
||||
|
||||
MidiManager mm = (MidiManager) getSystemService (MIDI_SERVICE);
|
||||
|
||||
PhysicalMidiDevice midiDevice = PhysicalMidiDevice.fromBluetoothLeDevice (btDevice, mm);
|
||||
|
||||
if (midiDevice != null)
|
||||
{
|
||||
getAndroidMidiDeviceManager().addDeviceToList (midiDevice);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void unpairBluetoothMidiDevice (String address)
|
||||
{
|
||||
getAndroidMidiDeviceManager().unpairBluetoothDevice (address);
|
||||
}
|
||||
|
||||
public void onScanFailed (int errorCode)
|
||||
{
|
||||
}
|
||||
|
||||
public void onScanResult (int callbackType, ScanResult result)
|
||||
{
|
||||
if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES
|
||||
|| callbackType == ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
|
||||
{
|
||||
BluetoothDevice device = result.getDevice();
|
||||
|
||||
if (device != null)
|
||||
bluetoothMidiDevices.add (device.getAddress());
|
||||
}
|
||||
|
||||
if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST)
|
||||
{
|
||||
Log.d ("JUCE", "ScanSettings.CALLBACK_TYPE_MATCH_LOST");
|
||||
BluetoothDevice device = result.getDevice();
|
||||
|
||||
if (device != null)
|
||||
{
|
||||
bluetoothMidiDevices.remove (device.getAddress());
|
||||
unpairBluetoothMidiDevice (device.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onBatchScanResults (List<ScanResult> results)
|
||||
{
|
||||
for (ScanResult result : results)
|
||||
onScanResult (ScanSettings.CALLBACK_TYPE_ALL_MATCHES, result);
|
||||
}
|
||||
|
||||
private BluetoothLeScanner scanner;
|
||||
private static final String bluetoothLEMidiServiceUUID = "03B80E5A-EDE8-4B33-A751-6CE34EC4C700";
|
||||
|
||||
private HashSet<String> bluetoothMidiDevices = new HashSet<String>();
|
||||
}
|
||||
|
||||
public static class JuceMidiInputPort extends MidiReceiver implements JuceMidiPort
|
||||
{
|
||||
private native void handleReceive (long host, byte[] msg, int offset, int count, long timestamp);
|
||||
|
||||
public JuceMidiInputPort (PhysicalMidiDevice device, long host, MidiOutputPort midiPort)
|
||||
{
|
||||
parent = device;
|
||||
juceHost = host;
|
||||
port = midiPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputPort()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
port.connect (this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
port.disconnect (this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
stop();
|
||||
|
||||
try
|
||||
{
|
||||
port.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.d ("JUCE", "JuceMidiInputPort::close: IOException = " + e.toString());
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.removePort (port.getPortNumber(), true);
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void onSend (byte[] msg, int offset, int count, long timestamp)
|
||||
{
|
||||
if (count > 0)
|
||||
handleReceive (juceHost, msg, offset, count, timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MidiPortID getPortId()
|
||||
{
|
||||
return new MidiPortID (port.getPortNumber(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMidi (byte[] msg, int offset, int count)
|
||||
{
|
||||
}
|
||||
|
||||
private PhysicalMidiDevice parent = null;
|
||||
private long juceHost = 0;
|
||||
private MidiOutputPort port;
|
||||
}
|
||||
|
||||
public static class JuceMidiOutputPort implements JuceMidiPort
|
||||
{
|
||||
public JuceMidiOutputPort (PhysicalMidiDevice device, MidiInputPort midiPort)
|
||||
{
|
||||
parent = device;
|
||||
port = midiPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputPort()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMidi (byte[] msg, int offset, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
port.send(msg, offset, count);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.d ("JUCE", "JuceMidiOutputPort::sendMidi: IOException = " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
try
|
||||
{
|
||||
port.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.d ("JUCE", "JuceMidiOutputPort::close: IOException = " + e.toString());
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.removePort (port.getPortNumber(), false);
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MidiPortID getPortId()
|
||||
{
|
||||
return new MidiPortID (port.getPortNumber(), false);
|
||||
}
|
||||
|
||||
private PhysicalMidiDevice parent = null;
|
||||
private MidiInputPort port;
|
||||
}
|
||||
|
||||
public static class PhysicalMidiDevice
|
||||
{
|
||||
private static class MidiDeviceThread extends Thread
|
||||
{
|
||||
public Handler handler = null;
|
||||
public Object sync = null;
|
||||
|
||||
public MidiDeviceThread (Object syncrhonization)
|
||||
{
|
||||
sync = syncrhonization;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
Looper.prepare();
|
||||
|
||||
synchronized (sync)
|
||||
{
|
||||
handler = new Handler();
|
||||
sync.notifyAll();
|
||||
}
|
||||
|
||||
Looper.loop();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MidiDeviceOpenCallback implements MidiManager.OnDeviceOpenedListener
|
||||
{
|
||||
public Object sync = null;
|
||||
public boolean isWaiting = true;
|
||||
public android.media.midi.MidiDevice theDevice = null;
|
||||
|
||||
public MidiDeviceOpenCallback (Object waiter)
|
||||
{
|
||||
sync = waiter;
|
||||
}
|
||||
|
||||
public void onDeviceOpened (MidiDevice device)
|
||||
{
|
||||
synchronized (sync)
|
||||
{
|
||||
theDevice = device;
|
||||
isWaiting = false;
|
||||
sync.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static PhysicalMidiDevice fromBluetoothLeDevice (BluetoothDevice bluetoothDevice, MidiManager mm)
|
||||
{
|
||||
Object waitForCreation = new Object();
|
||||
MidiDeviceThread thread = new MidiDeviceThread (waitForCreation);
|
||||
thread.start();
|
||||
|
||||
synchronized (waitForCreation)
|
||||
{
|
||||
while (thread.handler == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
waitForCreation.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Log.d ("JUCE", "Wait was interrupted but we don't care");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object waitForDevice = new Object();
|
||||
|
||||
MidiDeviceOpenCallback openCallback = new MidiDeviceOpenCallback (waitForDevice);
|
||||
|
||||
synchronized (waitForDevice)
|
||||
{
|
||||
mm.openBluetoothDevice (bluetoothDevice, openCallback, thread.handler);
|
||||
|
||||
while (openCallback.isWaiting)
|
||||
{
|
||||
try
|
||||
{
|
||||
waitForDevice.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Log.d ("JUCE", "Wait was interrupted but we don't care");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openCallback.theDevice == null)
|
||||
{
|
||||
Log.d ("JUCE", "openBluetoothDevice failed");
|
||||
return null;
|
||||
}
|
||||
|
||||
PhysicalMidiDevice device = new PhysicalMidiDevice();
|
||||
|
||||
device.handle = openCallback.theDevice;
|
||||
device.info = device.handle.getInfo();
|
||||
device.bluetoothAddress = bluetoothDevice.getAddress();
|
||||
device.midiManager = mm;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
public void unpair()
|
||||
{
|
||||
if (! bluetoothAddress.equals ("") && handle != null)
|
||||
{
|
||||
JuceMidiPort ports[] = new JuceMidiPort[0];
|
||||
ports = juceOpenedPorts.values().toArray(ports);
|
||||
|
||||
for (int i = 0; i < ports.length; ++i)
|
||||
ports[i].close();
|
||||
|
||||
juceOpenedPorts.clear();
|
||||
|
||||
try
|
||||
{
|
||||
handle.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.d ("JUCE", "handle.close(): IOException = " + e.toString());
|
||||
}
|
||||
|
||||
handle = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static PhysicalMidiDevice fromMidiDeviceInfo (MidiDeviceInfo info, MidiManager mm)
|
||||
{
|
||||
PhysicalMidiDevice device = new PhysicalMidiDevice();
|
||||
device.info = info;
|
||||
device.midiManager = mm;
|
||||
return device;
|
||||
}
|
||||
|
||||
public PhysicalMidiDevice()
|
||||
{
|
||||
bluetoothAddress = "";
|
||||
juceOpenedPorts = new Hashtable<MidiPortID, JuceMidiPort>();
|
||||
handle = null;
|
||||
}
|
||||
|
||||
public MidiDeviceInfo.PortInfo[] getPorts()
|
||||
{
|
||||
return info.getPorts();
|
||||
}
|
||||
|
||||
public String getHumanReadableNameForPort (MidiDeviceInfo.PortInfo port, int portIndexToUseInName)
|
||||
{
|
||||
String portName = port.getName();
|
||||
|
||||
if (portName.equals (""))
|
||||
portName = ((port.getType() == MidiDeviceInfo.PortInfo.TYPE_OUTPUT) ? "Out " : "In ")
|
||||
+ Integer.toString (portIndexToUseInName);
|
||||
|
||||
return getHumanReadableDeviceName() + " " + portName;
|
||||
}
|
||||
|
||||
public String getHumanReadableNameForPort (int portType, int androidPortID, int portIndexToUseInName)
|
||||
{
|
||||
MidiDeviceInfo.PortInfo[] ports = info.getPorts();
|
||||
|
||||
for (MidiDeviceInfo.PortInfo port : ports)
|
||||
{
|
||||
if (port.getType() == portType)
|
||||
{
|
||||
if (port.getPortNumber() == androidPortID)
|
||||
return getHumanReadableNameForPort (port, portIndexToUseInName);
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public String getHumanReadableDeviceName()
|
||||
{
|
||||
Bundle bundle = info.getProperties();
|
||||
return bundle.getString (MidiDeviceInfo.PROPERTY_NAME , "Unknown device");
|
||||
}
|
||||
|
||||
public void checkIfDeviceCanBeClosed()
|
||||
{
|
||||
if (juceOpenedPorts.size() == 0)
|
||||
{
|
||||
// never close bluetooth LE devices, otherwise they unpair and we have
|
||||
// no idea how many ports they have.
|
||||
// Only remove bluetooth devices when we specifically unpair
|
||||
if (bluetoothAddress.equals (""))
|
||||
{
|
||||
try
|
||||
{
|
||||
handle.close();
|
||||
handle = null;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.d ("JUCE", "PhysicalMidiDevice::checkIfDeviceCanBeClosed: IOException = " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removePort (int portIdx, boolean isInput)
|
||||
{
|
||||
MidiPortID portID = new MidiPortID (portIdx, isInput);
|
||||
JuceMidiPort port = juceOpenedPorts.get (portID);
|
||||
|
||||
if (port != null)
|
||||
{
|
||||
juceOpenedPorts.remove (portID);
|
||||
checkIfDeviceCanBeClosed();
|
||||
return;
|
||||
}
|
||||
|
||||
// tried to remove a port that was never added
|
||||
assert false;
|
||||
}
|
||||
|
||||
public JuceMidiPort openPort (int portIdx, boolean isInput, long host)
|
||||
{
|
||||
open();
|
||||
|
||||
if (handle == null)
|
||||
{
|
||||
Log.d ("JUCE", "PhysicalMidiDevice::openPort: handle = null, device not open");
|
||||
return null;
|
||||
}
|
||||
|
||||
// make sure that the port is not already open
|
||||
if (findPortForIdx (portIdx, isInput) != null)
|
||||
{
|
||||
Log.d ("JUCE", "PhysicalMidiDevice::openInputPort: port already open, not opening again!");
|
||||
return null;
|
||||
}
|
||||
|
||||
JuceMidiPort retval = null;
|
||||
|
||||
if (isInput)
|
||||
{
|
||||
MidiOutputPort androidPort = handle.openOutputPort (portIdx);
|
||||
|
||||
if (androidPort == null)
|
||||
{
|
||||
Log.d ("JUCE", "PhysicalMidiDevice::openPort: MidiDevice::openOutputPort (portIdx = "
|
||||
+ Integer.toString (portIdx) + ") failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
retval = new JuceMidiInputPort (this, host, androidPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
MidiInputPort androidPort = handle.openInputPort (portIdx);
|
||||
|
||||
if (androidPort == null)
|
||||
{
|
||||
Log.d ("JUCE", "PhysicalMidiDevice::openPort: MidiDevice::openInputPort (portIdx = "
|
||||
+ Integer.toString (portIdx) + ") failed!");
|
||||
return null;
|
||||
}
|
||||
|
||||
retval = new JuceMidiOutputPort (this, androidPort);
|
||||
}
|
||||
|
||||
juceOpenedPorts.put (new MidiPortID (portIdx, isInput), retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
private JuceMidiPort findPortForIdx (int idx, boolean isInput)
|
||||
{
|
||||
return juceOpenedPorts.get (new MidiPortID (idx, isInput));
|
||||
}
|
||||
|
||||
// opens the device
|
||||
private synchronized void open()
|
||||
{
|
||||
if (handle != null)
|
||||
return;
|
||||
|
||||
Object waitForCreation = new Object();
|
||||
MidiDeviceThread thread = new MidiDeviceThread (waitForCreation);
|
||||
thread.start();
|
||||
|
||||
synchronized(waitForCreation)
|
||||
{
|
||||
while (thread.handler == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
waitForCreation.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Log.d ("JUCE", "wait was interrupted but we don't care");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object waitForDevice = new Object();
|
||||
|
||||
MidiDeviceOpenCallback openCallback = new MidiDeviceOpenCallback (waitForDevice);
|
||||
|
||||
synchronized (waitForDevice)
|
||||
{
|
||||
midiManager.openDevice (info, openCallback, thread.handler);
|
||||
|
||||
while (openCallback.isWaiting)
|
||||
{
|
||||
try
|
||||
{
|
||||
waitForDevice.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
Log.d ("JUCE", "wait was interrupted but we don't care");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle = openCallback.theDevice;
|
||||
}
|
||||
|
||||
private MidiDeviceInfo info;
|
||||
private Hashtable<MidiPortID, JuceMidiPort> juceOpenedPorts;
|
||||
public MidiDevice handle;
|
||||
public String bluetoothAddress;
|
||||
private MidiManager midiManager;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
public class MidiDeviceManager
|
||||
public class MidiDeviceManager extends MidiManager.DeviceCallback
|
||||
{
|
||||
public class MidiPortPath
|
||||
{
|
||||
public PhysicalMidiDevice midiDevice;
|
||||
public int androidMidiPortID;
|
||||
public int portIndexToUseInName;
|
||||
}
|
||||
|
||||
public class JuceDeviceList
|
||||
{
|
||||
public ArrayList<MidiPortPath> inPorts = new ArrayList<MidiPortPath>();
|
||||
public ArrayList<MidiPortPath> outPorts = new ArrayList<MidiPortPath>();
|
||||
}
|
||||
|
||||
// We need to keep a thread local copy of the devices
|
||||
// which we returned the last time
|
||||
// getJuceAndroidMidiIn/OutputDevices() was called
|
||||
private final ThreadLocal<JuceDeviceList> lastDevicesReturned =
|
||||
new ThreadLocal<JuceDeviceList>()
|
||||
{
|
||||
@Override protected JuceDeviceList initialValue()
|
||||
{
|
||||
return new JuceDeviceList();
|
||||
}
|
||||
};
|
||||
|
||||
public MidiDeviceManager()
|
||||
{
|
||||
physicalMidiDevices = new ArrayList<PhysicalMidiDevice>();
|
||||
manager = (MidiManager) getSystemService (MIDI_SERVICE);
|
||||
|
||||
if (manager == null)
|
||||
{
|
||||
Log.d ("JUCE", "MidiDeviceManager error: could not get MidiManager system service");
|
||||
return;
|
||||
}
|
||||
|
||||
manager.registerDeviceCallback (this, null);
|
||||
|
||||
MidiDeviceInfo[] foundDevices = manager.getDevices();
|
||||
|
||||
for (MidiDeviceInfo info : foundDevices)
|
||||
physicalMidiDevices.add (PhysicalMidiDevice.fromMidiDeviceInfo (info, manager));
|
||||
}
|
||||
|
||||
// specifically add a device to the list
|
||||
public void addDeviceToList (PhysicalMidiDevice device)
|
||||
{
|
||||
physicalMidiDevices.add (device);
|
||||
}
|
||||
|
||||
public void unpairBluetoothDevice (String address)
|
||||
{
|
||||
for (int i = 0; i < physicalMidiDevices.size(); ++i)
|
||||
{
|
||||
PhysicalMidiDevice device = physicalMidiDevices.get(i);
|
||||
|
||||
if (device.bluetoothAddress.equals (address))
|
||||
{
|
||||
physicalMidiDevices.remove (i);
|
||||
device.unpair();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBluetoothDevicePaired (String address)
|
||||
{
|
||||
for (int i = 0; i < physicalMidiDevices.size(); ++i)
|
||||
{
|
||||
PhysicalMidiDevice device = physicalMidiDevices.get(i);
|
||||
|
||||
if (device.bluetoothAddress.equals (address))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String[] getJuceAndroidMidiInputDevices()
|
||||
{
|
||||
return new String[0];
|
||||
return getJuceAndroidMidiDevices (MidiDeviceInfo.PortInfo.TYPE_INPUT);
|
||||
}
|
||||
|
||||
public String[] getJuceAndroidMidiOutputDevices()
|
||||
{
|
||||
return new String[0];
|
||||
return getJuceAndroidMidiDevices (MidiDeviceInfo.PortInfo.TYPE_OUTPUT);
|
||||
}
|
||||
|
||||
private String[] getJuceAndroidMidiDevices (int portType)
|
||||
{
|
||||
ArrayList<MidiPortPath> listOfReturnedDevices = new ArrayList<MidiPortPath>();
|
||||
List<String> deviceNames = new ArrayList<String>();
|
||||
|
||||
for (PhysicalMidiDevice physicalMidiDevice : physicalMidiDevices)
|
||||
{
|
||||
int portIdx = 0;
|
||||
MidiDeviceInfo.PortInfo[] ports = physicalMidiDevice.getPorts();
|
||||
|
||||
for (MidiDeviceInfo.PortInfo port : ports)
|
||||
{
|
||||
if (port.getType() == portType)
|
||||
{
|
||||
MidiPortPath path = new MidiPortPath();
|
||||
path.midiDevice = physicalMidiDevice;
|
||||
path.androidMidiPortID = port.getPortNumber();
|
||||
path.portIndexToUseInName = ++portIdx;
|
||||
listOfReturnedDevices.add (path);
|
||||
|
||||
deviceNames.add (physicalMidiDevice.getHumanReadableNameForPort (port,
|
||||
path.portIndexToUseInName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String[] deviceNamesArray = new String[deviceNames.size()];
|
||||
|
||||
if (portType == MidiDeviceInfo.PortInfo.TYPE_INPUT)
|
||||
{
|
||||
lastDevicesReturned.get().inPorts.clear();
|
||||
lastDevicesReturned.get().inPorts.addAll (listOfReturnedDevices);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastDevicesReturned.get().outPorts.clear();
|
||||
lastDevicesReturned.get().outPorts.addAll (listOfReturnedDevices);
|
||||
}
|
||||
|
||||
return deviceNames.toArray(deviceNamesArray);
|
||||
}
|
||||
|
||||
public JuceMidiPort openMidiInputPortWithJuceIndex (int index, long host)
|
||||
{
|
||||
return null;
|
||||
ArrayList<MidiPortPath> lastDevices = lastDevicesReturned.get().inPorts;
|
||||
|
||||
if (index >= lastDevices.size() || index < 0)
|
||||
return null;
|
||||
|
||||
MidiPortPath path = lastDevices.get (index);
|
||||
return path.midiDevice.openPort (path.androidMidiPortID, true, host);
|
||||
}
|
||||
|
||||
public JuceMidiPort openMidiOutputPortWithJuceIndex (int index)
|
||||
{
|
||||
return null;
|
||||
ArrayList<MidiPortPath> lastDevices = lastDevicesReturned.get().outPorts;
|
||||
|
||||
if (index >= lastDevices.size() || index < 0)
|
||||
return null;
|
||||
|
||||
MidiPortPath path = lastDevices.get (index);
|
||||
return path.midiDevice.openPort (path.androidMidiPortID, false, 0);
|
||||
}
|
||||
|
||||
public String getInputPortNameForJuceIndex (int index)
|
||||
{
|
||||
return "";
|
||||
ArrayList<MidiPortPath> lastDevices = lastDevicesReturned.get().inPorts;
|
||||
|
||||
if (index >= lastDevices.size() || index < 0)
|
||||
return "";
|
||||
|
||||
MidiPortPath path = lastDevices.get (index);
|
||||
|
||||
return path.midiDevice.getHumanReadableNameForPort (MidiDeviceInfo.PortInfo.TYPE_INPUT,
|
||||
path.androidMidiPortID,
|
||||
path.portIndexToUseInName);
|
||||
}
|
||||
|
||||
public String getOutputPortNameForJuceIndex (int index)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
ArrayList<MidiPortPath> lastDevices = lastDevicesReturned.get().outPorts;
|
||||
|
||||
if (index >= lastDevices.size() || index < 0)
|
||||
return "";
|
||||
|
||||
MidiPortPath path = lastDevices.get (index);
|
||||
|
||||
return path.midiDevice.getHumanReadableNameForPort (MidiDeviceInfo.PortInfo.TYPE_OUTPUT,
|
||||
path.androidMidiPortID,
|
||||
path.portIndexToUseInName);
|
||||
}
|
||||
|
||||
public void onDeviceAdded (MidiDeviceInfo info)
|
||||
{
|
||||
PhysicalMidiDevice device = PhysicalMidiDevice.fromMidiDeviceInfo (info, manager);
|
||||
|
||||
// Do not add bluetooth devices as they are already added by the native bluetooth dialog
|
||||
if (info.getType() != MidiDeviceInfo.TYPE_BLUETOOTH)
|
||||
physicalMidiDevices.add (device);
|
||||
}
|
||||
|
||||
public void onDeviceRemoved (MidiDeviceInfo info)
|
||||
{
|
||||
for (int i = 0; i < physicalMidiDevices.size(); ++i)
|
||||
{
|
||||
if (physicalMidiDevices.get(i).info.getId() == info.getId())
|
||||
{
|
||||
physicalMidiDevices.remove (i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Don't assert here as this may be called again after a bluetooth device is unpaired
|
||||
}
|
||||
|
||||
public void onDeviceStatusChanged (MidiDeviceStatus status)
|
||||
{
|
||||
}
|
||||
|
||||
private ArrayList<PhysicalMidiDevice> physicalMidiDevices;
|
||||
private MidiManager manager;
|
||||
}
|
||||
|
||||
public MidiDeviceManager getAndroidMidiDeviceManager()
|
||||
{
|
||||
return null;
|
||||
if (getSystemService (MIDI_SERVICE) == null)
|
||||
return null;
|
||||
|
||||
synchronized (JuceDemo.class)
|
||||
{
|
||||
if (midiDeviceManager == null)
|
||||
midiDeviceManager = new MidiDeviceManager();
|
||||
}
|
||||
|
||||
return midiDeviceManager;
|
||||
}
|
||||
|
||||
public BluetoothManager getAndroidBluetoothManager()
|
||||
{
|
||||
return null;
|
||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
if (adapter == null)
|
||||
return null;
|
||||
|
||||
if (adapter.getBluetoothLeScanner() == null)
|
||||
return null;
|
||||
|
||||
synchronized (JuceDemo.class)
|
||||
{
|
||||
if (bluetoothManager == null)
|
||||
bluetoothManager = new BluetoothManager();
|
||||
}
|
||||
|
||||
return bluetoothManager;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@
|
|||
</MODULEPATHS>
|
||||
</VS2015>
|
||||
<ANDROID targetFolder="Builds/Android" androidActivityClass="com.juce.jucedemo.JuceDemo"
|
||||
androidSDKPath="" androidNDKPath="" androidMinimumSDK="10" androidInternetNeeded="1"
|
||||
androidSDKPath="" androidNDKPath="" androidMinimumSDK="23" androidInternetNeeded="1"
|
||||
androidKeyStore="${user.home}/.android/debug.keystore" androidKeyStorePass="android"
|
||||
androidKeyAlias="androiddebugkey" androidKeyAliasPass="android"
|
||||
androidMicNeeded="1" bigIcon="xycKOk" androidCpp11="1" smallIcon="BvyE0d"
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
<MODULEPATH id="juce_box2d" path="../../modules"/>
|
||||
</MODULEPATHS>
|
||||
</ANDROID>
|
||||
<ANDROIDSTUDIO androidVersionCode="1" androidActivityClass="com.yourcompany.jucedemo.JuceDemo"
|
||||
<ANDROIDSTUDIO androidVersionCode="1" androidActivityClass="com.juce.jucedemo.JuceDemo"
|
||||
androidMinimumSDK="23" androidInternetNeeded="1" androidKeyStore="${user.home}/.android/debug.keystore"
|
||||
androidKeyStorePass="android" androidKeyAlias="androiddebugkey"
|
||||
androidKeyAliasPass="android" androidCpp11="1" targetFolder="Builds/AndroidStudio"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue