This patch implements better USB MIDI handling, including listening for detach, and handling the case where it's connected while the activity is active.master
parent
5a20308469
commit
9746d9626e
@ -0,0 +1,93 @@ |
|||||||
|
// TODO copyright
|
||||||
|
|
||||||
|
// Class representing a USB MIDI keyboard
|
||||||
|
|
||||||
|
package com.levien.synthesizer.android.usb; |
||||||
|
|
||||||
|
import android.annotation.TargetApi; |
||||||
|
import android.hardware.usb.UsbConstants; |
||||||
|
import android.hardware.usb.UsbDeviceConnection; |
||||||
|
import android.hardware.usb.UsbEndpoint; |
||||||
|
import android.hardware.usb.UsbInterface; |
||||||
|
import android.os.Build; |
||||||
|
import android.util.Log; |
||||||
|
|
||||||
|
import com.levien.synthesizer.android.ui.PianoActivity2; |
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) |
||||||
|
public class UsbMidiDevice { |
||||||
|
private final PianoActivity2 mActivity; |
||||||
|
private final UsbDeviceConnection mDeviceConnection; |
||||||
|
private final UsbEndpoint mEndpoint; |
||||||
|
|
||||||
|
private final WaiterThread mWaiterThread = new WaiterThread(); |
||||||
|
|
||||||
|
public UsbMidiDevice(PianoActivity2 activity, UsbDeviceConnection connection, UsbInterface intf) { |
||||||
|
mActivity = activity; |
||||||
|
mDeviceConnection = connection; |
||||||
|
|
||||||
|
mEndpoint = getInputEndpoint(intf); |
||||||
|
} |
||||||
|
|
||||||
|
private UsbEndpoint getInputEndpoint(UsbInterface usbIf) { |
||||||
|
Log.d("synth", "interface:" + usbIf.toString()); |
||||||
|
int nEndpoints = usbIf.getEndpointCount(); |
||||||
|
for (int i = 0; i < nEndpoints; i++) { |
||||||
|
UsbEndpoint endpoint = usbIf.getEndpoint(i); |
||||||
|
if (endpoint.getDirection() == UsbConstants.USB_DIR_IN && |
||||||
|
endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { |
||||||
|
return endpoint; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void start() { |
||||||
|
Log.d("synth", "midi USB waiter thread starting"); |
||||||
|
mWaiterThread.start(); |
||||||
|
} |
||||||
|
|
||||||
|
public void stop() { |
||||||
|
synchronized (mWaiterThread) { |
||||||
|
mWaiterThread.mStop = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class WaiterThread extends Thread { |
||||||
|
public boolean mStop; |
||||||
|
|
||||||
|
public void run() { |
||||||
|
byte[] buf = new byte[mEndpoint.getMaxPacketSize()]; |
||||||
|
while (true) { |
||||||
|
synchronized (this) { |
||||||
|
if (mStop) { |
||||||
|
Log.d("synth", "midi USB waiter thread shutting down"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
final int TIMEOUT = 1000; |
||||||
|
int nBytes = mDeviceConnection.bulkTransfer(mEndpoint, buf, buf.length, TIMEOUT); |
||||||
|
if (nBytes < 0) { |
||||||
|
Log.e("synth", "bulkTransfer error " + nBytes); |
||||||
|
// break;
|
||||||
|
} |
||||||
|
for (int i = 0; i < nBytes; i += 4) { |
||||||
|
int codeIndexNumber = buf[i] & 0xf; |
||||||
|
int payloadBytes = 0; |
||||||
|
if (codeIndexNumber == 8 || codeIndexNumber == 9 || codeIndexNumber == 11 || |
||||||
|
codeIndexNumber == 14) { |
||||||
|
payloadBytes = 3; |
||||||
|
} else if (codeIndexNumber == 12) { |
||||||
|
payloadBytes = 2; |
||||||
|
} |
||||||
|
if (payloadBytes > 0) { |
||||||
|
byte[] newBuf = new byte[payloadBytes]; |
||||||
|
System.arraycopy(buf, i + 1, newBuf, 0, payloadBytes); |
||||||
|
Log.d("synth", "sending midi"); |
||||||
|
mActivity.sendMidiBytes(newBuf); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue