From 4c7be5fd6454d21433d005017e6f1a874e08c242 Mon Sep 17 00:00:00 2001 From: Diego Waxemberg Date: Mon, 9 Dec 2013 14:43:34 -0500 Subject: [PATCH] added support for gamepads (known to work with xbox 360) --- limelight-pc/.classpath | 5 + limelight-pc/src/com/limelight/Limelight.java | 29 ++- .../src/com/limelight/gui/StreamFrame.java | 2 +- .../com/limelight/input/GamepadHandler.java | 216 ++++++++++++++++++ 4 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 limelight-pc/src/com/limelight/input/GamepadHandler.java diff --git a/limelight-pc/.classpath b/limelight-pc/.classpath index 5c9f161..71941f8 100644 --- a/limelight-pc/.classpath +++ b/limelight-pc/.classpath @@ -5,5 +5,10 @@ + + + + + diff --git a/limelight-pc/src/com/limelight/Limelight.java b/limelight-pc/src/com/limelight/Limelight.java index 22a9923..1598c13 100644 --- a/limelight-pc/src/com/limelight/Limelight.java +++ b/limelight-pc/src/com/limelight/Limelight.java @@ -3,9 +3,14 @@ package com.limelight; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.UIManager; + +import net.java.games.input.Controller; +import net.java.games.input.ControllerEnvironment; + import com.limelight.binding.PlatformBinding; import com.limelight.gui.MainFrame; import com.limelight.gui.StreamFrame; +import com.limelight.input.GamepadHandler; import com.limelight.nvstream.NvConnection; import com.limelight.nvstream.NvConnectionListener; import com.limelight.nvstream.av.video.VideoDecoderRenderer; @@ -18,7 +23,7 @@ public class Limelight implements NvConnectionListener { private NvConnection conn; private boolean connectionFailed; private static JFrame limeFrame; - + public Limelight(String host) { this.host = host; } @@ -31,6 +36,24 @@ public class Limelight implements NvConnectionListener { PlatformBinding.getAudioRenderer(), PlatformBinding.getVideoDecoderRenderer()); streamFrame.build(conn); + + startControllerListener(); + } + + private void startControllerListener() { + 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); + } + } + } + }).start(); } private static void createFrame() { @@ -38,7 +61,7 @@ public class Limelight implements NvConnectionListener { main.build(); limeFrame = main.getLimeFrame(); } - + public static void createInstance(String host) { Limelight limelight = new Limelight(host); limelight.startUp(); @@ -102,7 +125,7 @@ public class Limelight implements NvConnectionListener { public void displayMessage(String message) { JOptionPane.showMessageDialog(limeFrame, message, "Limelight", JOptionPane.INFORMATION_MESSAGE); } - + public void displayError(String title, String message) { JOptionPane.showMessageDialog(limeFrame, message, title, JOptionPane.ERROR_MESSAGE); } diff --git a/limelight-pc/src/com/limelight/gui/StreamFrame.java b/limelight-pc/src/com/limelight/gui/StreamFrame.java index 02d5048..ff134c3 100644 --- a/limelight-pc/src/com/limelight/gui/StreamFrame.java +++ b/limelight-pc/src/com/limelight/gui/StreamFrame.java @@ -48,7 +48,7 @@ public class StreamFrame extends JFrame { //This might break if the screen res is too small...not sure though this.setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2); - makeFullScreen(); + //makeFullScreen(); hideCursor(); this.setVisible(true); diff --git a/limelight-pc/src/com/limelight/input/GamepadHandler.java b/limelight-pc/src/com/limelight/input/GamepadHandler.java new file mode 100644 index 0000000..df952f3 --- /dev/null +++ b/limelight-pc/src/com/limelight/input/GamepadHandler.java @@ -0,0 +1,216 @@ +package com.limelight.input; + + +import java.util.ArrayList; + +import com.limelight.nvstream.NvConnection; +import com.limelight.nvstream.input.ControllerPacket; + +import net.java.games.input.Component; +import net.java.games.input.Controller; +import net.java.games.input.Event; +import net.java.games.input.EventQueue; + +public class GamepadHandler { + private NvConnection conn; + + private Controller gamepad; + private static ArrayList gamepads; + private boolean run = true; + + short inputMap = 0x0000; + private byte leftTrigger = 0x00; + private byte rightTrigger = 0x00; + private short rightStickX = 0x0000; + private short rightStickY = 0x0000; + private short leftStickX = 0x0000; + private short leftStickY = 0x0000; + + private GamepadHandler(Controller gamepad, NvConnection conn) { + this.gamepad = gamepad; + this.conn = conn; + } + + public static void addGamepad(Controller pad, NvConnection conn) { + if (gamepads == null) { + gamepads = new ArrayList(); + } + if (!gamepads.contains(pad)) { + System.out.println("adding gamepad"); + GamepadHandler gh = new GamepadHandler(pad, conn); + gh.startUp(); + gamepads.add(gh); + } + } + + + private void startUp() { + new Thread(new Runnable() { + @Override + public void run() { + while (run) { + if (!gamepad.poll()) { + run = false; + gamepads.remove(GamepadHandler.this); + } + 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) {} + } + } + }).start(); + } + + private void sendControllerPacket() { + conn.sendControllerInput(inputMap, leftTrigger, rightTrigger, + leftStickX, leftStickY, rightStickX, rightStickY); + } +}