diff --git a/limelight-pc/src/com/limelight/Limelight.java b/limelight-pc/src/com/limelight/Limelight.java index 1e2cb52..f7e2327 100644 --- a/limelight-pc/src/com/limelight/Limelight.java +++ b/limelight-pc/src/com/limelight/Limelight.java @@ -1,5 +1,8 @@ package com.limelight; +import java.lang.reflect.Constructor; +import java.util.LinkedList; + import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.UIManager; @@ -44,13 +47,44 @@ public class Limelight implements NvConnectionListener { new Thread(new Runnable() { @Override public void run() { - Controller[] ca = ControllerEnvironment.getDefaultEnvironment().getControllers(); - System.out.println("found " + ca.length + " controllers"); - for(int i =0; i < ca.length; i++){ - if (ca[i].getType() == Controller.Type.GAMEPAD) { - System.out.println("found a gamepad: " + ca[i].getName()); - GamepadHandler.addGamepad(ca[i], conn); + + /* + * This is really janky, but it is currently the only way to rescan for controllers. + * The DefaultControllerEnvironment class caches the results of scanning and if a controller is + * unplugged or plugged in, it will not detect it. Since DefaultControllerEnvironment is package-protected + * we have to use reflections in order to manually instantiate a new instance to ensure there is no caching. + * Supposedly Aaron is going to fix JInput and we will have the ability to rescan soon! + */ + try { + //#allthejank + Constructor construct = null; + + Class defEnv = ControllerEnvironment.getDefaultEnvironment().getClass(); + construct = defEnv.getDeclaredConstructor(); + construct.setAccessible(true); + + while(true) { + + ControllerEnvironment defaultEnv = null; + + defaultEnv = (ControllerEnvironment)construct.newInstance(); + + Controller[] ca = defaultEnv.getControllers(); + LinkedList gamepads = new LinkedList(); + for(int i = 0; i < ca.length; i++){ + if (ca[i].getType() == Controller.Type.GAMEPAD) { + gamepads.add(ca[i]); + } + } + GamepadHandler.addGamepads(gamepads, conn); + + + try { + Thread.sleep(1000); + } catch (InterruptedException e) {} } + } catch (Exception e) { + e.printStackTrace(); } } }).start(); diff --git a/limelight-pc/src/com/limelight/input/GamepadHandler.java b/limelight-pc/src/com/limelight/input/GamepadHandler.java index df952f3..598bc3a 100644 --- a/limelight-pc/src/com/limelight/input/GamepadHandler.java +++ b/limelight-pc/src/com/limelight/input/GamepadHandler.java @@ -1,7 +1,9 @@ package com.limelight.input; -import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import com.limelight.nvstream.NvConnection; import com.limelight.nvstream.input.ControllerPacket; @@ -14,9 +16,8 @@ import net.java.games.input.EventQueue; public class GamepadHandler { private NvConnection conn; - private Controller gamepad; - private static ArrayList gamepads; - private boolean run = true; + private static LinkedList gamepads = new LinkedList(); + private static GamepadHandler singleton; short inputMap = 0x0000; private byte leftTrigger = 0x00; @@ -26,181 +27,45 @@ public class GamepadHandler { private short leftStickX = 0x0000; private short leftStickY = 0x0000; - private GamepadHandler(Controller gamepad, NvConnection conn) { - this.gamepad = gamepad; + private GamepadHandler(NvConnection conn) { this.conn = conn; } - public static void addGamepad(Controller pad, NvConnection conn) { - if (gamepads == null) { - gamepads = new ArrayList(); + public static void addGamepads(List pads, NvConnection conn) { + if (singleton == null) { + singleton = new GamepadHandler(conn); + singleton.startUp(); } - if (!gamepads.contains(pad)) { - System.out.println("adding gamepad"); - GamepadHandler gh = new GamepadHandler(pad, conn); - gh.startUp(); - gamepads.add(gh); + + gamepads.clear(); + + for (Controller pad : pads) { + gamepads.add(pad); } } - - + private void startUp() { new Thread(new Runnable() { @Override public void run() { - while (run) { - if (!gamepad.poll()) { - run = false; - gamepads.remove(GamepadHandler.this); + while (true) { + for (Controller gamepad : gamepads) { + if (!gamepad.poll()) { + gamepads.remove(GamepadHandler.this); + break; + } + EventQueue queue = gamepad.getEventQueue(); + Event event = new Event(); + + while(queue.getNextEvent(event)) { + + //printInfo(gamepda, event); + + handleEvent(event); + + sendControllerPacket(); + } } - EventQueue queue = gamepad.getEventQueue(); - Event event = new Event(); - - while(queue.getNextEvent(event)) { - StringBuffer buffer = new StringBuffer(gamepad.getName()); - buffer.append(" at "); - buffer.append(event.getNanos()).append(", "); - Component comp = event.getComponent(); - buffer.append(comp.getName()).append(" changed to "); - float value = event.getValue(); - if(comp.isAnalog()) { - buffer.append(value); - } else { - if(value==1.0f) { - buffer.append("On"); - } else { - buffer.append("Off"); - } - } - System.out.println(buffer.toString()); - - if (comp.getName().equals("rx")) { - rightStickX = (short)Math.round(event.getValue() * 0x7FFF); - } - if (comp.getName().equals("ry")) { - rightStickY = (short)Math.round(-event.getValue() * 0x7FFF); - } - if (comp.getName().equals("x")) { - leftStickX = (short)Math.round(event.getValue() * 0x7FFF); - } - if (comp.getName().equals("y")) { - leftStickY = (short)Math.round(-event.getValue() * 0x7FFF); - } - if (comp.getName().equals("z")) { - leftTrigger = (byte)Math.round((event.getValue() + 1) / 2 * 0xFF); - } - if (comp.getName().equals("rz")) { - rightTrigger = (byte)Math.round((event.getValue() + 1) / 2 * 0xFF); - } - if (comp.getName().equals("13")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.LEFT_FLAG; - } else { - inputMap &= ~ControllerPacket.LEFT_FLAG; - } - } - if (comp.getName().equals("14")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.RIGHT_FLAG; - } else { - inputMap &= ~ControllerPacket.RIGHT_FLAG; - } - } - if (comp.getName().equals("11")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.UP_FLAG; - } else { - inputMap &= ~ControllerPacket.UP_FLAG; - } - } - if (comp.getName().equals("12")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.DOWN_FLAG; - } else { - inputMap &= ~ControllerPacket.DOWN_FLAG; - } - } - if (comp.getName().equals("0")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.A_FLAG; - } else { - inputMap &= ~ControllerPacket.A_FLAG; - } - } - if (comp.getName().equals("2")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.X_FLAG; - } else { - inputMap &= ~ControllerPacket.X_FLAG; - } - } - if (comp.getName().equals("3")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.Y_FLAG; - } else { - inputMap &= ~ControllerPacket.Y_FLAG; - } - } - if (comp.getName().equals("1")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.B_FLAG; - } else { - inputMap &= ~ControllerPacket.B_FLAG; - } - } - if (comp.getName().equals("4")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.LB_FLAG; - } else { - inputMap &= ~ControllerPacket.LB_FLAG; - } - } - if (comp.getName().equals("5")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.RB_FLAG; - } else { - inputMap &= ~ControllerPacket.RB_FLAG; - } - } - if (comp.getName().equals("9")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.BACK_FLAG; - } else { - inputMap &= ~ControllerPacket.BACK_FLAG; - } - } - if (comp.getName().equals("8")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.PLAY_FLAG; - } else { - inputMap &= ~ControllerPacket.PLAY_FLAG; - } - } - if (comp.getName().equals("10")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG; - } else { - inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG; - } - } - if (comp.getName().equals("6")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.LS_CLK_FLAG; - } else { - inputMap &= ~ControllerPacket.LS_CLK_FLAG; - } - } - if (comp.getName().equals("7")) { - if (event.getValue() == 1.0F) { - inputMap |= ControllerPacket.RS_CLK_FLAG; - } else { - inputMap &= ~ControllerPacket.RS_CLK_FLAG; - } - } - - sendControllerPacket(); - } - try { Thread.sleep(20); } catch (InterruptedException e) {} @@ -208,6 +73,102 @@ public class GamepadHandler { } }).start(); } + + private void printInfo(Controller gamepad, Event event) { + StringBuffer buffer = new StringBuffer(gamepad.getName()); + buffer.append(" at "); + buffer.append(event.getNanos()).append(", "); + Component comp = event.getComponent(); + buffer.append(comp.getName()).append(" changed to "); + float value = event.getValue(); + if(comp.isAnalog()) { + buffer.append(value); + } else { + if(value==1.0f) { + buffer.append("On"); + } else { + buffer.append("Off"); + } + } + System.out.println(buffer.toString()); + System.out.println(comp.getIdentifier().toString()); + } + + + private void handleEvent(Event event) { + Component comp = event.getComponent(); + float value = event.getValue(); + + if (comp.isAnalog()) { + handleAnalog(comp, value); + } else { + handleButtons(comp, value); + } + } + + private void toggle(short button, boolean press) { + if (press) { + inputMap |= button; + } else { + inputMap &= ~button; + } + } + + private void handleButtons(Component comp, float value) { + Component.Identifier id = comp.getIdentifier(); + boolean press = value > 0.5F; + + if (id == Component.Identifier.Button._13) { + toggle(ControllerPacket.LEFT_FLAG, press); + } else if (id == Component.Identifier.Button._14) { + toggle(ControllerPacket.RIGHT_FLAG, press); + } else if (id == Component.Identifier.Button._11) { + toggle(ControllerPacket.UP_FLAG, press); + } else if (id == Component.Identifier.Button._12) { + toggle(ControllerPacket.DOWN_FLAG, press); + } else if (id == Component.Identifier.Button._0) { + toggle(ControllerPacket.A_FLAG, press); + } else if (id == Component.Identifier.Button._2) { + toggle(ControllerPacket.X_FLAG, press); + } else if (id == Component.Identifier.Button._3) { + toggle(ControllerPacket.Y_FLAG, press); + } else if (id == Component.Identifier.Button._1) { + toggle(ControllerPacket.B_FLAG, press); + } else if (id == Component.Identifier.Button._9) { + toggle(ControllerPacket.BACK_FLAG, press); + } else if (id == Component.Identifier.Button._8) { + toggle(ControllerPacket.PLAY_FLAG, press); + } else if (id == Component.Identifier.Button._7) { + toggle(ControllerPacket.RS_CLK_FLAG, press); + } else if (id == Component.Identifier.Button._6) { + toggle(ControllerPacket.LS_CLK_FLAG, press); + } else if (id == Component.Identifier.Button._4) { + toggle(ControllerPacket.LB_FLAG, press); + } else if (id == Component.Identifier.Button._5) { + toggle(ControllerPacket.RB_FLAG, press); + } else if (id == Component.Identifier.Button._10) { + toggle(ControllerPacket.SPECIAL_BUTTON_FLAG, press); + } + } + + private void handleAnalog(Component comp, float value) { + Component.Identifier id = comp.getIdentifier(); + + if (id == Component.Identifier.Axis.RX) { + rightStickX = (short)Math.round(value * 0x7FFF); + } else if (id == Component.Identifier.Axis.RY) { + rightStickY = (short)Math.round(-value * 0x7FFF); + } else if (id == Component.Identifier.Axis.X) { + leftStickX = (short)Math.round(value * 0x7FFF); + } else if (id == Component.Identifier.Axis.Y) { + leftStickY = (short)Math.round(-value * 0x7FFF); + } else if (id == Component.Identifier.Axis.Z) { + leftTrigger = (byte)Math.round((value + 1 / 2) * 0xFF); + } else if (id == Component.Identifier.Axis.RZ) { + rightTrigger = (byte)Math.round((value + 2) / 2 * 0xFF); + } + + } private void sendControllerPacket() { conn.sendControllerInput(inputMap, leftTrigger, rightTrigger,