Add multiple controller support

This commit is contained in:
Cameron Gutman 2015-02-01 04:37:35 -05:00
parent 9988330613
commit 51343a171d
5 changed files with 130 additions and 27 deletions

View File

@ -348,6 +348,20 @@ public class NvConnection {
inputStream.sendMouseButtonUp(mouseButton); inputStream.sendMouseButtonUp(mouseButton);
} }
public void sendControllerInput(final short controllerNumber,
final short buttonFlags,
final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY,
final short rightStickX, final short rightStickY)
{
if (inputStream == null)
return;
inputStream.sendControllerInput(controllerNumber, buttonFlags, leftTrigger,
rightTrigger, leftStickX, leftStickY,
rightStickX, rightStickY);
}
public void sendControllerInput(final short buttonFlags, public void sendControllerInput(final short buttonFlags,
final byte leftTrigger, final byte rightTrigger, final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY, final short leftStickX, final short leftStickY,

View File

@ -11,8 +11,9 @@ public class ControllerBatchingBlock {
private short leftStickY; private short leftStickY;
private short rightStickX; private short rightStickX;
private short rightStickY; private short rightStickY;
private short controllerNumber;
public ControllerBatchingBlock(ControllerPacket initialPacket) { public ControllerBatchingBlock(MultiControllerPacket initialPacket) {
this.buttonFlags = initialPacket.buttonFlags; this.buttonFlags = initialPacket.buttonFlags;
this.leftTrigger = initialPacket.leftTrigger; this.leftTrigger = initialPacket.leftTrigger;
this.rightTrigger = initialPacket.rightTrigger; this.rightTrigger = initialPacket.rightTrigger;
@ -54,8 +55,9 @@ public class ControllerBatchingBlock {
// We have several restrictions that will cause batching to break up the controller packets. // We have several restrictions that will cause batching to break up the controller packets.
// 1) Button flags must be the same for all packets in the batch // 1) Button flags must be the same for all packets in the batch
// 2) The movement direction of all axes must remain the same or be neutral // 2) The movement direction of all axes must remain the same or be neutral
public boolean submitNewPacket(ControllerPacket packet) { public boolean submitNewPacket(MultiControllerPacket packet) {
if (buttonFlags != packet.buttonFlags || if (buttonFlags != packet.buttonFlags ||
controllerNumber != packet.controllerNumber ||
!checkDirs(leftTrigger, packet.leftTrigger, 0) || !checkDirs(leftTrigger, packet.leftTrigger, 0) ||
!checkDirs(rightTrigger, packet.rightTrigger, 1) || !checkDirs(rightTrigger, packet.rightTrigger, 1) ||
!checkDirs(leftStickX, packet.leftStickX, 2) || !checkDirs(leftStickX, packet.leftStickX, 2) ||
@ -66,6 +68,7 @@ public class ControllerBatchingBlock {
return false; return false;
} }
this.controllerNumber = packet.controllerNumber;
this.leftTrigger = packet.leftTrigger; this.leftTrigger = packet.leftTrigger;
this.rightTrigger = packet.rightTrigger; this.rightTrigger = packet.rightTrigger;
this.leftStickX = packet.leftStickX; this.leftStickX = packet.leftStickX;
@ -75,7 +78,8 @@ public class ControllerBatchingBlock {
return true; return true;
} }
public void reinitializePacket(ControllerPacket packet) { public void reinitializePacket(MultiControllerPacket packet) {
packet.controllerNumber = controllerNumber;
packet.buttonFlags = buttonFlags; packet.buttonFlags = buttonFlags;
packet.leftTrigger = leftTrigger; packet.leftTrigger = leftTrigger;
packet.rightTrigger = rightTrigger; packet.rightTrigger = rightTrigger;

View File

@ -3,7 +3,7 @@ package com.limelight.nvstream.input;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
public class ControllerPacket extends InputPacket { public class ControllerPacket extends MultiControllerPacket {
public static final byte[] HEADER = public static final byte[] HEADER =
{ {
0x0A, 0x0A,
@ -46,26 +46,12 @@ public class ControllerPacket extends InputPacket {
public static final short PACKET_LENGTH = PAYLOAD_LENGTH + public static final short PACKET_LENGTH = PAYLOAD_LENGTH +
InputPacket.HEADER_LENGTH; InputPacket.HEADER_LENGTH;
// Set this flag if you want ControllerPacket to handle scaling for you
// You MUST properly handle deadzones to use this flag
//
// Note: This flag does nothing right now. It causes some controllers
// to behave badly.
public static boolean enableAxisScaling = false;
short buttonFlags;
byte leftTrigger;
byte rightTrigger;
short leftStickX;
short leftStickY;
short rightStickX;
short rightStickY;
public ControllerPacket(short buttonFlags, byte leftTrigger, byte rightTrigger, public ControllerPacket(short buttonFlags, byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY, short leftStickX, short leftStickY,
short rightStickX, short rightStickY) short rightStickX, short rightStickY)
{ {
super(PACKET_TYPE); super((short) 0, buttonFlags, leftTrigger, rightTrigger, leftStickX,
leftStickY, rightStickX, rightStickY);
this.buttonFlags = buttonFlags; this.buttonFlags = buttonFlags;
this.leftTrigger = leftTrigger; this.leftTrigger = leftTrigger;

View File

@ -129,8 +129,8 @@ public class ControllerStream {
} while (totalDeltaX != 0 && totalDeltaY != 0); } while (totalDeltaX != 0 && totalDeltaY != 0);
} }
// Try to batch axis changes on controller packets too // Try to batch axis changes on controller packets too
else if (!inputQueue.isEmpty() && packet instanceof ControllerPacket) { else if (!inputQueue.isEmpty() && packet instanceof MultiControllerPacket) {
ControllerPacket initialControllerPacket = (ControllerPacket) packet; MultiControllerPacket initialControllerPacket = (MultiControllerPacket) packet;
ControllerBatchingBlock batchingBlock = null; ControllerBatchingBlock batchingBlock = null;
synchronized (inputQueue) { synchronized (inputQueue) {
@ -138,13 +138,13 @@ public class ControllerStream {
while (i.hasNext()) { while (i.hasNext()) {
InputPacket queuedPacket = i.next(); InputPacket queuedPacket = i.next();
if (queuedPacket instanceof ControllerPacket) { if (queuedPacket instanceof MultiControllerPacket) {
// Only initialize the batching block if we got here // Only initialize the batching block if we got here
if (batchingBlock == null) { if (batchingBlock == null) {
batchingBlock = new ControllerBatchingBlock(initialControllerPacket); batchingBlock = new ControllerBatchingBlock(initialControllerPacket);
} }
if (batchingBlock.submitNewPacket((ControllerPacket) queuedPacket)) if (batchingBlock.submitNewPacket((MultiControllerPacket) queuedPacket))
{ {
// Batching was successful, so remove this packet // Batching was successful, so remove this packet
i.remove(); i.remove();
@ -263,9 +263,35 @@ public class ControllerStream {
public void sendControllerInput(short buttonFlags, byte leftTrigger, byte rightTrigger, public void sendControllerInput(short buttonFlags, byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY) short leftStickX, short leftStickY, short rightStickX, short rightStickY)
{ {
queuePacket(new ControllerPacket(buttonFlags, leftTrigger, if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) {
rightTrigger, leftStickX, leftStickY, // Use legacy controller packets for generation 3
rightStickX, rightStickY)); queuePacket(new ControllerPacket(buttonFlags, leftTrigger,
rightTrigger, leftStickX, leftStickY,
rightStickX, rightStickY));
}
else {
// Use multi-controller packets for generation 4 and above
queuePacket(new MultiControllerPacket((short) 0, buttonFlags, leftTrigger,
rightTrigger, leftStickX, leftStickY,
rightStickX, rightStickY));
}
}
public void sendControllerInput(short controllerNumber, short buttonFlags, byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
{
if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) {
// Use legacy controller packets for generation 3
queuePacket(new ControllerPacket(buttonFlags, leftTrigger,
rightTrigger, leftStickX, leftStickY,
rightStickX, rightStickY));
}
else {
// Use multi-controller packets for generation 4 and above
queuePacket(new MultiControllerPacket(controllerNumber, buttonFlags, leftTrigger,
rightTrigger, leftStickX, leftStickY,
rightStickX, rightStickY));
}
} }
public void sendMouseButtonDown(byte mouseButton) public void sendMouseButtonDown(byte mouseButton)

View File

@ -0,0 +1,73 @@
package com.limelight.nvstream.input;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class MultiControllerPacket extends InputPacket {
public static final byte[] TAIL =
{
(byte)0x9C,
0x00,
0x00,
0x00,
0x55,
0x00
};
public static final int PACKET_TYPE = 0x1e;
public static final short PAYLOAD_LENGTH = 30;
public static final short PACKET_LENGTH = PAYLOAD_LENGTH +
InputPacket.HEADER_LENGTH;
short controllerNumber;
short buttonFlags;
byte leftTrigger;
byte rightTrigger;
short leftStickX;
short leftStickY;
short rightStickX;
short rightStickY;
public MultiControllerPacket(short controllerNumber, short buttonFlags, byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY)
{
super(PACKET_TYPE);
this.controllerNumber = controllerNumber;
this.buttonFlags = buttonFlags;
this.leftTrigger = leftTrigger;
this.rightTrigger = rightTrigger;
this.leftStickX = leftStickX;
this.leftStickY = leftStickY;
this.rightStickX = rightStickX;
this.rightStickY = rightStickY;
}
@Override
public void toWirePayload(ByteBuffer bb) {
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(0xd);
bb.putShort((short) 0x1a);
bb.putShort(controllerNumber);
bb.putShort((short) 0x07);
bb.putShort((short) 0x14);
bb.putShort(buttonFlags);
bb.put(leftTrigger);
bb.put(rightTrigger);
bb.putShort(leftStickX);
bb.putShort(leftStickY);
bb.putShort(rightStickX);
bb.putShort(rightStickY);
bb.put(TAIL);
}
@Override
public int getPacketLength() {
return PACKET_LENGTH;
}
}