diff --git a/pom.xml b/pom.xml index 2d630d7..c8fb408 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ com.github.QuarkTheAwesome purejavahidapi - 3591b7e + f877704 org.hid4java diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java b/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java index af5d1e5..e1dfb6f 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/Controller.java @@ -170,7 +170,7 @@ public abstract class Controller implements Runnable { @Override public String toString() { - return getType() + " " + getIdentifier(); + return getType() + " " + getIdentifier().trim(); } @Override diff --git a/src/net/ash/HIDToVPADNetworkClient/controller/HidController.java b/src/net/ash/HIDToVPADNetworkClient/controller/HidController.java index c753d18..36912fb 100644 --- a/src/net/ash/HIDToVPADNetworkClient/controller/HidController.java +++ b/src/net/ash/HIDToVPADNetworkClient/controller/HidController.java @@ -119,6 +119,7 @@ public class HidController extends Controller { } } - return "USB HID on " + getIdentifier(); + String name = getHidDevice().getProductString(); + return ((name != null) ? name : "USB HID") + " on " + getIdentifier(); } } \ No newline at end of file diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java index 570d2b5..e3f654e 100644 --- a/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiInputControls.java @@ -30,7 +30,6 @@ import java.awt.event.ActionListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; -import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; @@ -60,19 +59,6 @@ public final class GuiInputControls extends JPanel { final JButton connectButton = new JButton(CONNECT); connectButton.setAlignmentX(Component.CENTER_ALIGNMENT); - final JCheckBox cbautoScanForController = new JCheckBox(); - cbautoScanForController.setSelected(Settings.SCAN_AUTOMATICALLY_FOR_CONTROLLERS); - - cbautoScanForController.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - boolean selected = ((JCheckBox) e.getSource()).isSelected(); - Settings.SCAN_AUTOMATICALLY_FOR_CONTROLLERS = selected; - cbautoScanForController.setSelected(selected); - } - }); - final JButton scanButton = new JButton("Scan for Controllers"); scanButton.setAlignmentX(Component.CENTER_ALIGNMENT); scanButton.addActionListener(new ActionListener() { @@ -86,11 +72,19 @@ public final class GuiInputControls extends JPanel { } }); - JPanel scanWrap = new JPanel(); - scanWrap.setLayout(new BoxLayout(scanWrap, BoxLayout.X_AXIS)); - JLabel label = new JLabel("Auto Scan for Controllers: "); - scanWrap.add(label); - scanWrap.add(cbautoScanForController); + final JButton optionsButton = new JButton("Options"); + optionsButton.setAlignmentX(Component.CENTER_ALIGNMENT); + optionsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GuiOptionsWindow.showWindow(GuiMain.getInstance()); + } + }); + } + }); ipTextBox = new JTextField(); ipTextBox.setColumns(15); @@ -100,23 +94,6 @@ public final class GuiInputControls extends JPanel { ipTextBoxWrap.add(ipTextBox); ipTextBoxWrap.setMaximumSize(new Dimension(1000, 20)); - final JCheckBox cbautoActivateController = new JCheckBox(); - cbautoActivateController.setSelected(Settings.AUTO_ACTIVATE_CONTROLLER); - cbautoActivateController.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - boolean selected = ((JCheckBox) e.getSource()).isSelected(); - Settings.AUTO_ACTIVATE_CONTROLLER = selected; - cbautoActivateController.setSelected(selected); - } - }); - - JPanel autoActivateWrap = new JPanel(); - autoActivateWrap.setLayout(new BoxLayout(autoActivateWrap, BoxLayout.X_AXIS)); - autoActivateWrap.add(new JLabel("Auto Activate Controller: ")); - autoActivateWrap.add(cbautoActivateController); - add(Box.createVerticalGlue()); add(ipTextBoxWrap); @@ -126,9 +103,7 @@ public final class GuiInputControls extends JPanel { add(Box.createRigidArea(new Dimension(1, 4))); add(scanButton); add(Box.createRigidArea(new Dimension(1, 4))); - add(scanWrap); - add(Box.createRigidArea(new Dimension(1, 4))); - add(autoActivateWrap); + add(optionsButton); add(Box.createVerticalGlue()); add(Box.createVerticalGlue()); diff --git a/src/net/ash/HIDToVPADNetworkClient/gui/GuiOptionsWindow.java b/src/net/ash/HIDToVPADNetworkClient/gui/GuiOptionsWindow.java new file mode 100644 index 0000000..a3efaf6 --- /dev/null +++ b/src/net/ash/HIDToVPADNetworkClient/gui/GuiOptionsWindow.java @@ -0,0 +1,267 @@ +/******************************************************************************* + * Copyright (c) 2017 Ash (QuarkTheAwesome) & Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *******************************************************************************/ +package net.ash.HIDToVPADNetworkClient.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.LayoutManager; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.border.EtchedBorder; + +import lombok.extern.java.Log; +import net.ash.HIDToVPADNetworkClient.util.Settings; +import net.ash.HIDToVPADNetworkClient.util.StatusReport; + +@Log +public class GuiOptionsWindow extends JPanel { + private static final long serialVersionUID = 1L; + private static final GuiOptionsWindow instance = new GuiOptionsWindow(); + + private final List tabs = new ArrayList(); + + public static void showWindow() { + showWindow(null); + } + + public static void showWindow(Component parent) { + instance.setOpaque(true); + for (Tab t : instance.tabs) { + t.updateTab(); + } + + JFrame window = new JFrame("Options"); + window.setContentPane(instance); + window.pack(); + window.setLocationRelativeTo(parent); + window.setVisible(true); + } + + private GuiOptionsWindow() { + super(new GridLayout(1, 1)); + + log.info("Hello from the Options window!"); + + setPreferredSize(new Dimension(600, 200)); + + JTabbedPane tabPane = new JTabbedPane(); + tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + + Tab controllerTab = new ControllerTab(); + tabs.add(controllerTab); + tabPane.addTab("Controllers", controllerTab); + + Tab infoTab = new InfoTab(); + tabs.add(infoTab); + tabPane.addTab("Info", infoTab); + + add(tabPane); + } + + private class ControllerTab extends Tab { + private static final long serialVersionUID = 1L; + + private final ControllerFilteringList cFilterList; + private final JCheckBox cBoxScanForControllers; + private final JCheckBox cBoxAutoActivateControllers; + + private ControllerTab() { + super(new GridLayout(1, 2)); + + cFilterList = new ControllerFilteringList(); + + for (Settings.ControllerFiltering.Type type : Settings.ControllerFiltering.Type.values()) { + if (!type.isSupportedOnPlatform()) continue; + ControllerFilteringListItem item = new ControllerFilteringListItem(type); + cFilterList.add(item); + } + + add(cFilterList); + + JPanel rightSideControls = new JPanel(); + rightSideControls.setLayout(new BoxLayout(rightSideControls, BoxLayout.PAGE_AXIS)); + rightSideControls.add(Box.createVerticalGlue()); + + cBoxScanForControllers = new JCheckBox("Automatically scan for controllers"); + cBoxScanForControllers.setAlignmentX(Component.CENTER_ALIGNMENT); + cBoxScanForControllers.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Settings.SCAN_AUTOMATICALLY_FOR_CONTROLLERS = cBoxScanForControllers.isSelected(); + } + }); + rightSideControls.add(cBoxScanForControllers); + + rightSideControls.add(Box.createVerticalStrut(2)); + + cBoxAutoActivateControllers = new JCheckBox("Automatically activate controllers"); + cBoxAutoActivateControllers.setAlignmentX(Component.CENTER_ALIGNMENT); + cBoxAutoActivateControllers.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Settings.AUTO_ACTIVATE_CONTROLLER = cBoxAutoActivateControllers.isSelected(); + } + }); + rightSideControls.add(cBoxAutoActivateControllers); + + rightSideControls.add(Box.createVerticalGlue()); + add(rightSideControls); + } + + @Override + public void updateTab() { + for (ControllerFilteringListItem c : cFilterList.items) { + c.updateItem(); + } + cBoxScanForControllers.setSelected(Settings.SCAN_AUTOMATICALLY_FOR_CONTROLLERS); + cBoxAutoActivateControllers.setSelected(Settings.AUTO_ACTIVATE_CONTROLLER); + } + + private class ControllerFilteringList extends JPanel { + private static final long serialVersionUID = 1L; + + private List items = new ArrayList(); + private JPanel innerPanel; + + private ControllerFilteringList() { + super(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0)); + + innerPanel = new JPanel(); + innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.PAGE_AXIS)); + + JScrollPane innerPanelWrap = new JScrollPane(innerPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + innerPanelWrap.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)); + add(innerPanelWrap, BorderLayout.CENTER); + + JLabel controllerFilterText = new JLabel("Controllers to show:"); + controllerFilterText.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + add(controllerFilterText, BorderLayout.PAGE_START); + } + + public Component add(ControllerFilteringListItem c) { + items.add(c); + return innerPanel.add(c); + } + } + + private class ControllerFilteringListItem extends JPanel { + private static final long serialVersionUID = 1L; + + private final JCheckBox cBox; + private final Settings.ControllerFiltering.Type type; + + private ControllerFilteringListItem(Settings.ControllerFiltering.Type typeIn) { + super(new GridLayout(1, 1)); + this.type = typeIn; + + cBox = new JCheckBox(type.getName()); + cBox.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + cBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Settings.ControllerFiltering.setFilterState(type, cBox.isSelected()); + } + }); + add(cBox); + } + + public void updateItem() { + cBox.setSelected(Settings.ControllerFiltering.getFilterState(type)); + } + + //I can't believe I didn't figure this out for GuiControllerList + @Override + public Dimension getMaximumSize() { + return new Dimension(Integer.MAX_VALUE, getPreferredSize().height); + } + } + } + + private class InfoTab extends Tab { + private static final long serialVersionUID = 1L; + + private final JTextArea infoText; + private final JScrollPane infoTextWrap; + + private InfoTab() { + super(); + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); + + infoText = new JTextArea(); + infoText.setEditable(false); + infoTextWrap = new JScrollPane(infoText, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + infoTextWrap.setAlignmentX(Component.CENTER_ALIGNMENT); + add(infoTextWrap); + + add(Box.createVerticalStrut(10)); + + JButton copyButton = new JButton("Copy"); + copyButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + StringSelection data = new StringSelection(infoText.getText()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(data, data); + } + }); + copyButton.setAlignmentX(Component.CENTER_ALIGNMENT); + add(copyButton); + } + + @Override + public void updateTab() { + infoText.setCaretPosition(0); + infoText.setText(StatusReport.generateStatusReport()); + infoText.setCaretPosition(0); + } + } + + private abstract class Tab extends JPanel { + private static final long serialVersionUID = 1L; + public abstract void updateTab(); + public Tab(LayoutManager l) { + super(l); + } + public Tab() { + super(); + } + } +} diff --git a/src/net/ash/HIDToVPADNetworkClient/hid/HidDevice.java b/src/net/ash/HIDToVPADNetworkClient/hid/HidDevice.java index 9d6fb38..2e33db2 100644 --- a/src/net/ash/HIDToVPADNetworkClient/hid/HidDevice.java +++ b/src/net/ash/HIDToVPADNetworkClient/hid/HidDevice.java @@ -57,11 +57,18 @@ public interface HidDevice { byte[] getLatestData(); /** - * Retuns the Usage of this HID-Device + * Retuns the Usage Page of this HID-Device * - * @return usage + * @return usage page */ - short getUsage(); + short getUsagePage(); + + /** + * Retuns the Usage ID of this HID-Device + * + * @return usage id + */ + short getUsageID(); /** * Returns the path of this HidDevice @@ -69,4 +76,11 @@ public interface HidDevice { * @return path */ String getPath(); + + /** + * Returns the name of the HID device + * + * @return product string (name) + */ + String getProductString(); } diff --git a/src/net/ash/HIDToVPADNetworkClient/hid/HidManager.java b/src/net/ash/HIDToVPADNetworkClient/hid/HidManager.java index 5ee6d49..f4bf2bb 100644 --- a/src/net/ash/HIDToVPADNetworkClient/hid/HidManager.java +++ b/src/net/ash/HIDToVPADNetworkClient/hid/HidManager.java @@ -37,28 +37,55 @@ public class HidManager { public static HidDevice getDeviceByPath(String path) throws IOException { return backend.getDeviceByPath(path); } - + public static List getAttachedControllers() { List connectedGamepads = new ArrayList(); for (HidDevice info : backend.enumerateDevices()) { if (isGamepad(info)) { - - // Skip Xbox controller under windows. We should use XInput instead. - if (isXboxController(info) && Settings.isWindows()) { - continue; + if (Settings.ControllerFiltering.getFilterState(Settings.ControllerFiltering.Type.HIDGAMEPAD)) { + // Skip Xbox controller under windows. We should use XInput instead. + if (isXboxController(info) && Settings.isWindows()) { + continue; + } + connectedGamepads.add(info); } + } else if (isKeyboard(info)) { + if (Settings.ControllerFiltering.getFilterState(Settings.ControllerFiltering.Type.HIDKEYBOARD)) { + connectedGamepads.add(info); + } + } else if (isMouse(info)) { + if (Settings.ControllerFiltering.getFilterState(Settings.ControllerFiltering.Type.HIDMOUSE)) { + connectedGamepads.add(info); + } + } else if (Settings.ControllerFiltering.getFilterState(Settings.ControllerFiltering.Type.HIDOTHER)) { connectedGamepads.add(info); } } return connectedGamepads; } + + public static List getAllAttachedControllers() { + return backend.enumerateDevices(); + } public static boolean isGamepad(HidDevice info) { if (info == null) return false; - short usage = info.getUsage(); + short usage = info.getUsageID(); return (usage == 0x05 || usage == 0x04 || isNintendoController(info) || isPlaystationController(info)); } + + public static boolean isKeyboard(HidDevice info) { + if (info == null) return false; + short usage = info.getUsageID(); + return (usage == 0x06); + } + + public static boolean isMouse(HidDevice info) { + if (info == null) return false; + short usage = info.getUsageID(); + return (usage == 0x02); + } private static boolean isPlaystationController(HidDevice info) { if (info == null) return false; @@ -75,13 +102,17 @@ public class HidManager { return (info.getVendorId() == (short) 0x045e) && ((info.getProductId() == (short) 0x02ff) || (info.getProductId() == (short) 0x02a1)); } + public static String getBackendType() { + return backend.getClass().getSimpleName(); + } + static { if (Settings.isMacOSX()) { backend = new Hid4JavaHidManagerBackend(); } else if (Settings.isWindows()) { backend = new PureJavaHidManagerBackend(); } else if (Settings.isLinux()) { - backend = new Hid4JavaHidManagerBackend(); + backend = new PureJavaHidManagerBackend(); } else { backend = null; } diff --git a/src/net/ash/HIDToVPADNetworkClient/hid/hid4java/Hid4JavaHidDevice.java b/src/net/ash/HIDToVPADNetworkClient/hid/hid4java/Hid4JavaHidDevice.java index ad6104f..362b3da 100644 --- a/src/net/ash/HIDToVPADNetworkClient/hid/hid4java/Hid4JavaHidDevice.java +++ b/src/net/ash/HIDToVPADNetworkClient/hid/hid4java/Hid4JavaHidDevice.java @@ -66,13 +66,23 @@ class Hid4JavaHidDevice implements HidDevice { return myDevice.getPath(); } + @Override + public String getProductString() { + return myDevice.getProduct(); + } + @Override public String toString() { - return "Hid4JavaHidDevice [vid= " + getVendorId() + ", pid= " + getProductId() + ", data=" + Arrays.toString(data) + "]"; + return "Hid4JavaHidDevice [vid= " + getVendorId() + ", pid= " + getProductId() + ", usage= " + String.format("%04X:%04X", getUsagePage(), getUsageID()) + ", data=" + Arrays.toString(data) + "]"; } @Override - public short getUsage() { + public short getUsageID() { return (short) myDevice.getUsage(); } + + @Override + public short getUsagePage() { + return (short) myDevice.getUsagePage(); + } } diff --git a/src/net/ash/HIDToVPADNetworkClient/hid/purejavahid/PureJavaHidDevice.java b/src/net/ash/HIDToVPADNetworkClient/hid/purejavahid/PureJavaHidDevice.java index d4b822d..fe3435a 100644 --- a/src/net/ash/HIDToVPADNetworkClient/hid/purejavahid/PureJavaHidDevice.java +++ b/src/net/ash/HIDToVPADNetworkClient/hid/purejavahid/PureJavaHidDevice.java @@ -81,18 +81,28 @@ class PureJavaHidDevice implements HidDevice, InputReportListener { } @Override - public short getUsage() { + public short getUsagePage() { return myDeviceInfo.getUsagePage(); } + + @Override + public short getUsageID() { + return myDeviceInfo.getUsageID(); + } @Override public String getPath() { return myDeviceInfo.getPath(); } + @Override + public String getProductString() { + return myDeviceInfo.getProductString(); + } + @Override public String toString() { - return "PureJavaHidDevice [vid= " + String.format("%04X", getVendorId()) + ", pid= " + String.format("%04X", getProductId()) + ", path= " + getPath() - + ", data=" + Arrays.toString(currentData) + "]"; + return "PureJavaHidDevice [vid= " + String.format("%04X", getVendorId()) + ", pid= " + String.format("%04X", getProductId()) + ", path= " + getPath().trim() + + ", usage= " + String.format("%04X:%04X", getUsagePage(), getUsageID()) + ", data=" + Arrays.toString(currentData) + "]"; } } diff --git a/src/net/ash/HIDToVPADNetworkClient/util/Settings.java b/src/net/ash/HIDToVPADNetworkClient/util/Settings.java index 74295fa..fe74dfd 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/Settings.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/Settings.java @@ -26,6 +26,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Arrays; import java.util.Properties; import lombok.Getter; @@ -117,6 +118,13 @@ public final class Settings { } } + String filterStates = prop.getProperty("filterStates"); + if (filterStates != null) { + ControllerFiltering.loadFilterStates(filterStates); + } else { + ControllerFiltering.setDefaultFilterStates(); + } + log.info("Loaded config successfully!"); } @@ -139,7 +147,8 @@ public final class Settings { prop.setProperty("autoActivatingController", Boolean.toString(Settings.AUTO_ACTIVATE_CONTROLLER)); prop.setProperty("sendDataOnlyOnChanges", Boolean.toString(Settings.SEND_DATA_ONLY_ON_CHANGE)); prop.setProperty("scanAutomaticallyForControllers", Boolean.toString(Settings.SCAN_AUTOMATICALLY_FOR_CONTROLLERS)); - + prop.setProperty("filterStates", ControllerFiltering.getFilterStates()); + try { FileOutputStream outStream = new FileOutputStream(configFile); prop.store(outStream, "HIDToVPADNetworkClient"); @@ -183,10 +192,65 @@ public final class Settings { } else if (os.contains("Mac OS X")) { return Platform.MAC_OS_X; } - return null; + return Platform.UNKNOWN; } public enum Platform { - LINUX, WINDOWS, MAC_OS_X, UNKNOWN + LINUX (0x1), WINDOWS (0x2), MAC_OS_X (0x4), UNKNOWN (0x8); + + private int mask; + private Platform(int mask) { + this.mask = mask; + } + } + + //TODO rename this to something less nonsensical + public static class ControllerFiltering { + public static enum Type { + HIDGAMEPAD (0, "HID Gamepads", Platform.LINUX.mask | Platform.WINDOWS.mask | Platform.MAC_OS_X.mask), + HIDKEYBOARD (1, "HID Keyboards", Platform.LINUX.mask | Platform.MAC_OS_X.mask), + HIDMOUSE (2, "HID Mice", Platform.LINUX.mask | Platform.MAC_OS_X.mask), + HIDOTHER (3, "Other HIDs", Platform.LINUX.mask | Platform.WINDOWS.mask | Platform.MAC_OS_X.mask); + + private int index; + @Getter private String name; + private int platforms; + private Type(int index, String name, int platforms) { + this.index = index; + this.name = name; + this.platforms = platforms; + } + public boolean isSupportedOnPlatform() { + return (platforms & getPlattform().mask) != 0; + } + } + + private static boolean[] filterStates = new boolean[Type.values().length]; + public static String getFilterStates() { + return Arrays.toString(filterStates); + } + public static void loadFilterStates(String newFilterStates) { + boolean[] newFilterStatesParsed = Utilities.stringToBoolArray(newFilterStates); + if (newFilterStatesParsed.length != filterStates.length) { + //TODO handle changes in filtering more gracefully + log.warning("Number of controller filters in config does not match reality, using defaults..."); + setDefaultFilterStates(); + } else { + filterStates = newFilterStatesParsed; + } + } + + public static void setFilterState(Type filter, boolean state) { + filterStates[filter.index] = state; + } + public static boolean getFilterState(Type filter) { + return filterStates[filter.index] || !filter.isSupportedOnPlatform(); + } + public static void setDefaultFilterStates() { + filterStates[Type.HIDGAMEPAD.index] = true; + filterStates[Type.HIDKEYBOARD.index] = false; + filterStates[Type.HIDMOUSE.index] = false; + filterStates[Type.HIDOTHER.index] = false; + } } } diff --git a/src/net/ash/HIDToVPADNetworkClient/util/StatusReport.java b/src/net/ash/HIDToVPADNetworkClient/util/StatusReport.java new file mode 100644 index 0000000..b6ab09f --- /dev/null +++ b/src/net/ash/HIDToVPADNetworkClient/util/StatusReport.java @@ -0,0 +1,39 @@ +package net.ash.HIDToVPADNetworkClient.util; + +import net.ash.HIDToVPADNetworkClient.controller.Controller; +import net.ash.HIDToVPADNetworkClient.hid.HidDevice; +import net.ash.HIDToVPADNetworkClient.hid.HidManager; +import net.ash.HIDToVPADNetworkClient.manager.ControllerManager; +import net.ash.HIDToVPADNetworkClient.network.NetworkManager; + +public class StatusReport { + public static String generateStatusReport() { + String report = "HID to VPAD Network Client\n\nRunning on "; + report += Settings.getPlattform(); + + report += "\nHID Backend: "; + report += HidManager.getBackendType(); + + report += "\nCurrently "; + report += (NetworkManager.getInstance().isConnected()) ? "Connected.\n" : "Disconnected.\n"; + report += (NetworkManager.getInstance().isReconnecting()) ? "" : "Not "; + report += "Reconnecting."; + + report += "\n\nCurrently attached controllers:"; + for (Controller c : ControllerManager.getAttachedControllers()) { + report += "\n"; + report += c.toString(); + } + + report += "\n\nFiltering settings:\n"; + report += Settings.ControllerFiltering.getFilterStates(); + + report += "\n\nAll HIDs:"; + for (HidDevice d : HidManager.getAllAttachedControllers()) { + report += "\n"; + report += d.toString(); + } + + return report; + } +} diff --git a/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java b/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java index af5f9de..52693ed 100644 --- a/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java +++ b/src/net/ash/HIDToVPADNetworkClient/util/Utilities.java @@ -76,4 +76,19 @@ public final class Utilities { public static short signedShortToByte(short value) { return signedShortToByte((int) value); } + + /** + * Arrays.toString(boolean[]) in reverse. + * https://stackoverflow.com/questions/456367/ + * @param string + * @return array + */ + public static boolean[] stringToBoolArray(String string) { + String[] strings = string.replace("[", "").replace("]", "").split(", "); + boolean result[] = new boolean[strings.length]; + for (int i = 0; i < result.length; i++) { + result[i] = Boolean.parseBoolean(strings[i]); + } + return result; + } }