diff --git a/src/com/limelight/gui/GamepadConfigFrame.java b/src/com/limelight/gui/GamepadConfigFrame.java
index a61e669..085eb0b 100644
--- a/src/com/limelight/gui/GamepadConfigFrame.java
+++ b/src/com/limelight/gui/GamepadConfigFrame.java
@@ -34,6 +34,7 @@ import com.limelight.input.gamepad.Gamepad;
import com.limelight.input.gamepad.GamepadHandler;
import com.limelight.input.gamepad.GamepadMapping;
import com.limelight.input.gamepad.GamepadMapping.Mapping;
+import com.limelight.input.gamepad.SourceComponent;
import com.limelight.settings.GamepadSettingsManager;
/**
@@ -244,10 +245,9 @@ public class GamepadConfigFrame extends JFrame {
@Override
public void run() {
- Component newComponent = waitForNewMapping(pad);
+ SourceComponent newComponent = waitForNewMapping(pad);
consumeEvents(pad);
-
if (newComponent != null) {
Mapping oldConfig = config.get(newComponent);
if (oldConfig != null) {
@@ -256,7 +256,7 @@ public class GamepadConfigFrame extends JFrame {
config.insertMapping(mappingToMap, newComponent);
- buttonPressed.setText(newComponent.getName());
+ buttonPressed.setText(newComponent.getComponent().getName());
configChanged = true;
} else {
@@ -275,8 +275,8 @@ public class GamepadConfigFrame extends JFrame {
/*
* Waits until the user chooses what to map to the clicked component
*/
- private Component waitForNewMapping(Gamepad pad) {
- Component newMapping = null;
+ private SourceComponent waitForNewMapping(Gamepad pad) {
+ SourceComponent newMapping = null;
while (newMapping == null) {
if (pad.poll()) {
@@ -287,8 +287,13 @@ public class GamepadConfigFrame extends JFrame {
if (!pad.poll()) {
break;
}
- if (Math.abs(event.getValue()) > .75F) {
- newMapping = event.getComponent();
+
+ if (event.getComponent().getIdentifier() == Component.Identifier.Axis.POV) {
+ newMapping = new SourceComponent(event.getComponent(), ""+event.getValue());
+ break;
+ }
+ else if (!event.getComponent().isAnalog() || Math.abs(event.getValue()) > .75F) {
+ newMapping = new SourceComponent(event.getComponent(), "");
break;
}
}
diff --git a/src/com/limelight/gui/StreamFrame.java b/src/com/limelight/gui/StreamFrame.java
index e904b04..3c6d178 100644
--- a/src/com/limelight/gui/StreamFrame.java
+++ b/src/com/limelight/gui/StreamFrame.java
@@ -10,6 +10,9 @@ import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
@@ -90,6 +93,8 @@ public class StreamFrame extends JFrame {
this.getContentPane().setBackground(Color.BLACK);
this.getRootPane().setBackground(Color.BLACK);
+ this.addWindowListener(createWindowListener());
+
if (fullscreen) {
makeFullScreen(streamConfig);
}
@@ -247,6 +252,19 @@ public class StreamFrame extends JFrame {
}
spinnerLabel.setText("Starting " + stage.getName() + "...");
}
+
+ /**
+ * Creates the listener for the window.
+ * It terminates the connection when the window is closed
+ */
+ private WindowListener createWindowListener() {
+ return new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ close();
+ }
+ };
+ }
/**
* Hides the spinner and the label
diff --git a/src/com/limelight/input/gamepad/Gamepad.java b/src/com/limelight/input/gamepad/Gamepad.java
index 60f0ead..58dc732 100644
--- a/src/com/limelight/input/gamepad/Gamepad.java
+++ b/src/com/limelight/input/gamepad/Gamepad.java
@@ -5,6 +5,7 @@ import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.ControllerPacket;
import net.java.games.input.Component;
+import net.java.games.input.Component.Identifier;
import net.java.games.input.Controller;
import net.java.games.input.Event;
import net.java.games.input.EventQueue;
@@ -97,8 +98,7 @@ public class Gamepad {
* Prints out the specified event information for the given gamepad
* used for debugging, normally unused.
*/
- @SuppressWarnings("unused")
- private void printInfo(Controller gamepad, Event event) {
+ public static void printInfo(Controller gamepad, Event event) {
Component comp = event.getComponent();
StringBuilder builder = new StringBuilder(gamepad.getName());
@@ -108,9 +108,40 @@ public class Gamepad {
builder.append(comp.getName()).append(" changed to ");
- float value = event.getValue();
+ float value = event.getValue();
if(comp.isAnalog()) {
builder.append(value);
+ } else if (comp.getIdentifier() == Identifier.Axis.POV) {
+ if (value == Component.POV.DOWN) {
+ builder.append("Down");
+ }
+ else if (value == Component.POV.UP) {
+ builder.append("Up");
+ }
+ else if (value == Component.POV.LEFT) {
+ builder.append("Left");
+ }
+ else if (value == Component.POV.RIGHT) {
+ builder.append("Right");
+ }
+ else if (value == Component.POV.CENTER) {
+ builder.append("Center");
+ }
+ else if (value == Component.POV.DOWN_LEFT) {
+ builder.append("Down-left");
+ }
+ else if (value == Component.POV.DOWN_RIGHT) {
+ builder.append("Down-right");
+ }
+ else if (value == Component.POV.UP_LEFT) {
+ builder.append("Up-left");
+ }
+ else if (value == Component.POV.UP_RIGHT) {
+ builder.append("Up-right");
+ }
+ else {
+ builder.append("Unknown");
+ }
} else {
if(value==1.0f) {
builder.append("On");
@@ -140,6 +171,9 @@ public class Gamepad {
if (mapping != null) {
if (mapping.contComp.isAnalog()) {
handleAnalog(mapping.contComp, sanitizeValue(mapping, value));
+ } else if (comp.getIdentifier() == Component.Identifier.Axis.POV) {
+ // The values are directional constants so they cannot be sanitized
+ handlePOV(value);
} else {
handleButtons(mapping.contComp, sanitizeValue(mapping, value));
}
@@ -171,6 +205,47 @@ public class Gamepad {
}
}
+ /*
+ * Handles POV component input
+ */
+ private void handlePOV(float value) {
+ if (value == Component.POV.UP ||
+ value == Component.POV.UP_LEFT ||
+ value == Component.POV.UP_RIGHT) {
+ toggle(ControllerPacket.UP_FLAG, true);
+ }
+ else {
+ toggle(ControllerPacket.UP_FLAG, false);
+ }
+
+ if (value == Component.POV.DOWN ||
+ value == Component.POV.DOWN_LEFT ||
+ value == Component.POV.DOWN_RIGHT) {
+ toggle(ControllerPacket.DOWN_FLAG, true);
+ }
+ else {
+ toggle(ControllerPacket.DOWN_FLAG, false);
+ }
+
+ if (value == Component.POV.LEFT ||
+ value == Component.POV.DOWN_LEFT ||
+ value == Component.POV.UP_LEFT) {
+ toggle(ControllerPacket.LEFT_FLAG, true);
+ }
+ else {
+ toggle(ControllerPacket.LEFT_FLAG, false);
+ }
+
+ if (value == Component.POV.RIGHT ||
+ value == Component.POV.UP_RIGHT ||
+ value == Component.POV.DOWN_RIGHT) {
+ toggle(ControllerPacket.RIGHT_FLAG, true);
+ }
+ else {
+ toggle(ControllerPacket.RIGHT_FLAG, false);
+ }
+ }
+
/*
* Handles analog component input
*/
diff --git a/src/com/limelight/input/gamepad/GamepadMapping.java b/src/com/limelight/input/gamepad/GamepadMapping.java
index 1ece52e..1525b2a 100644
--- a/src/com/limelight/input/gamepad/GamepadMapping.java
+++ b/src/com/limelight/input/gamepad/GamepadMapping.java
@@ -28,8 +28,12 @@ public class GamepadMapping implements Serializable {
* @param toMap a Mapping that will be mapped to the specified gamepad component
* @param comp the gamepad component to map to.
*/
- public void insertMapping(Mapping toMap, Component comp) {
- mapping.put(comp.getIdentifier().getName(), toMap);
+ public void insertMapping(Mapping toMap, SourceComponent comp) {
+ // This is the base mapping for components with multiple "buttons"
+ mapping.put(comp.getComponentId(), toMap);
+
+ // This is the more-specific mapping for the specific buttons
+ mapping.put(comp.getFullUniqueId(), toMap);
}
/**
@@ -41,12 +45,31 @@ public class GamepadMapping implements Serializable {
return mapping.get(comp.getIdentifier().getName());
}
+ /**
+ * Gets the mapping for the specified source component
+ * @param comp the source component to get a mapping for
+ * @return a mapping for the requested component
+ */
+ public Mapping get(SourceComponent comp) {
+ return mapping.get(comp.getFullUniqueId());
+ }
+
/**
* Removes the mapping to the specified component
* @param comp the component to no longer be mapped.
*/
- public void remove(Component comp) {
- mapping.remove(comp.getIdentifier().getName());
+ public void remove(SourceComponent comp) {
+ // Remove the most specific mapping
+ mapping.remove(comp.getFullUniqueId());
+
+ for (Entry entry : mapping.entrySet()) {
+ if (entry.getKey().startsWith(comp.getComponentId())) {
+ return;
+ }
+ }
+
+ // Remove the common mapping if no more specific mappings remain
+ mapping.remove(comp.getComponentId());
}
/**
diff --git a/src/com/limelight/input/gamepad/SourceComponent.java b/src/com/limelight/input/gamepad/SourceComponent.java
new file mode 100644
index 0000000..0474eca
--- /dev/null
+++ b/src/com/limelight/input/gamepad/SourceComponent.java
@@ -0,0 +1,29 @@
+package com.limelight.input.gamepad;
+
+import net.java.games.input.Component;
+
+public class SourceComponent {
+ private Component component;
+ private String id;
+
+ public SourceComponent(Component component, String id) {
+ this.component = component;
+ this.id = id;
+ }
+
+ public Component getComponent() {
+ return component;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getFullUniqueId() {
+ return getComponentId() + " " + getId();
+ }
+
+ public String getComponentId() {
+ return component.getIdentifier().getName();
+ }
+}