Some Code-Refactoring

This commit is contained in:
Maschell 2017-03-31 15:31:41 +02:00
parent ebe03a23c6
commit 4c814a2aaf
19 changed files with 122 additions and 137 deletions

View File

@ -51,7 +51,9 @@ public class Main {
});
MessageBoxManager.addMessageBoxListener(GuiMain.getInstance());
}
private Main() {
}
public static void fatal() {

View File

@ -43,10 +43,10 @@ public abstract class Controller implements Runnable {
boolean shutdown = false;
boolean shutdownDone = false;
private Object dataLock = new Object();
private Object shutdownLock = new Object();
private final Object dataLock = new Object();
private final Object shutdownLock = new Object();
private Object rumbleLock = new Object();
private final Object rumbleLock = new Object();
private boolean rumble = false;
private boolean hasConfig = true; // Let's be optimistic
@ -65,7 +65,7 @@ public abstract class Controller implements Runnable {
Utilities.sleep(Settings.DETECT_CONTROLLER_INTERVAL);
while (isActive()) {
byte[] newData = pollLatestData();
if (newData != null) {
if (newData != null && newData.length != 0) {
setLatestData(newData);
}
doSleepAfterPollingData();

View File

@ -31,10 +31,6 @@ import lombok.Setter;
import net.ash.HIDToVPADNetworkClient.exeption.ControllerInitializationFailedException;
public class LinuxDevInputController extends Controller implements Runnable {
public LinuxDevInputController(String identifier) throws ControllerInitializationFailedException {
super(ControllerType.LINUX, identifier);
}
public static final int NUM_SUPPORTED_AXIS = 10; // possibly off-by-one
public static final int CONTROLLER_DATA_SIZE = (Long.SIZE / Byte.SIZE) + ((Byte.SIZE / Byte.SIZE) * NUM_SUPPORTED_AXIS);
@ -47,6 +43,13 @@ public class LinuxDevInputController extends Controller implements Runnable {
@Getter @Setter private short VID;
@Getter @Setter private short PID;
private long buttonState = 0;
private byte[] axisState = new byte[NUM_SUPPORTED_AXIS];
public LinuxDevInputController(String identifier) throws ControllerInitializationFailedException {
super(ControllerType.LINUX, identifier);
}
@Override
public boolean initController(String identifier) {
try {
@ -65,9 +68,6 @@ public class LinuxDevInputController extends Controller implements Runnable {
return true;
}
private long buttonState = 0;
private byte[] axisState = new byte[NUM_SUPPORTED_AXIS];
@Override
public byte[] pollLatestData() {
DataInputStream inputStream = getController();
@ -151,5 +151,4 @@ public class LinuxDevInputController extends Controller implements Runnable {
public String getInfoText() {
return "Linux controller on " + getIdentifier();
}
}

View File

@ -34,6 +34,13 @@ import purejavahidapi.HidDevice;
import purejavahidapi.InputReportListener;
public class PureJavaHidController extends Controller implements InputReportListener {
private Object dataLock = new Object();
protected byte[] currentData = new byte[1];
protected int PACKET_LENGTH = 64;
@Getter @Setter(AccessLevel.PRIVATE) private HidDevice hidDevice;
public static Controller getInstance(String deviceIdentifier) throws IOException, ControllerInitializationFailedException {
HidDevice device = PureJavaHidApiManager.getDeviceByPath(deviceIdentifier);
// We use a special version to optimize the data for the switch pro controller
@ -52,13 +59,6 @@ public class PureJavaHidController extends Controller implements InputReportList
super(ControllerType.PureJAVAHid, identifier);
}
private Object dataLock = new Object();
protected byte[] currentData = new byte[1];
protected int PACKET_LENGTH = 64;
@Getter @Setter(AccessLevel.PRIVATE) private HidDevice hidDevice;
@Override
public boolean initController(String identifier) {
HidDevice device;

View File

@ -85,8 +85,8 @@ public class XInputController extends Controller {
if (buttons.lThumb) buttonState |= (1 << 12);
if (buttons.rThumb) buttonState |= (1 << 13);
if (buttons.unknown) buttonState |= (1 << 14);
if (XInputDevice.isGuideButtonSupported()) {
if (buttons.guide) buttonState |= (1 << 15);
if (XInputDevice.isGuideButtonSupported() && buttons.guide) {
buttonState |= (1 << 15);
}
XInputAxes axes = components.getAxes();
@ -107,7 +107,7 @@ public class XInputController extends Controller {
return (data.array());
}
return null;
return new byte[0];
}
@Override

View File

@ -37,25 +37,31 @@ public class GuiCloseListener implements WindowListener {
@Override
public void windowActivated(WindowEvent arg0) {
// not used
}
@Override
public void windowClosed(WindowEvent arg0) {
// not used
}
@Override
public void windowDeactivated(WindowEvent arg0) {
// not used
}
@Override
public void windowDeiconified(WindowEvent arg0) {
// not used
}
@Override
public void windowIconified(WindowEvent arg0) {
// not used
}
@Override
public void windowOpened(WindowEvent arg0) {
// not used
}
}

View File

@ -41,7 +41,8 @@ import net.ash.HIDToVPADNetworkClient.manager.ControllerManager;
public class GuiControllerList extends JPanel {
private static final long serialVersionUID = 1L;
private JPanel innerScrollPanel;
private final JPanel innerScrollPanel;
private final Object innerScrollPanelLock = new Object();;
public GuiControllerList() {
super(new BorderLayout());
@ -59,51 +60,48 @@ public class GuiControllerList extends JPanel {
new Timer(delay, taskPerformer).start();
}
public synchronized void updateControllerList() {
// System.out.println("[GuiControllerList] Updating controller
// list..."); //XXX debug text
public void updateControllerList() {
boolean repaintNeeded = false;
List<Controller> attachedControllers = ControllerManager.getAttachedControllers();
List<GuiControllerListItem> newComponents = new ArrayList<GuiControllerListItem>();
Map<Controller, GuiControllerListItem> components = new HashMap<Controller, GuiControllerListItem>();
for (Component component : innerScrollPanel.getComponents()) {
if (component instanceof GuiControllerListItem) {
GuiControllerListItem comp = (GuiControllerListItem) component;
Controller cont = comp.getController();
if (attachedControllers.contains(cont)) {
components.put(cont, comp);
} else {// Controller removed
repaintNeeded = true;
synchronized (innerScrollPanelLock) {
Map<Controller, GuiControllerListItem> components = new HashMap<Controller, GuiControllerListItem>();
for (Component component : innerScrollPanel.getComponents()) {
if (component instanceof GuiControllerListItem) {
GuiControllerListItem comp = (GuiControllerListItem) component;
Controller cont = comp.getController();
if (attachedControllers.contains(cont)) {
components.put(cont, comp);
} else {// Controller removed
repaintNeeded = true;
}
}
}
}
// Build new list of components.
for (Controller controller : attachedControllers) {
GuiControllerListItem i = null;
if (components.containsKey(controller)) {
newComponents.add(components.get(controller));
} else { // New controller was added
repaintNeeded = true;
i = new GuiControllerListItem(controller);
newComponents.add(i);
}
}
if (repaintNeeded) {
innerScrollPanel.removeAll();
for (GuiControllerListItem component : newComponents) {
innerScrollPanel.add(component);
// Build new list of components.
for (Controller controller : attachedControllers) {
GuiControllerListItem i = null;
if (components.containsKey(controller)) {
newComponents.add(components.get(controller));
} else { // New controller was added
repaintNeeded = true;
i = new GuiControllerListItem(controller);
newComponents.add(i);
}
}
innerScrollPanel.revalidate();
revalidate();
innerScrollPanel.repaint();
repaint();
if (repaintNeeded) {
innerScrollPanel.removeAll();
for (GuiControllerListItem component : newComponents) {
innerScrollPanel.add(component);
}
innerScrollPanel.revalidate();
revalidate();
innerScrollPanel.repaint();
repaint();
}
}
}
}

View File

@ -40,7 +40,7 @@ public class GuiControllerListItem extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
@Getter private final Controller controller;
private JCheckBox checkbox;
private final JCheckBox checkbox;
private boolean hasConfigCache = true;
@ -78,7 +78,7 @@ public class GuiControllerListItem extends JPanel implements ActionListener {
}
private void checkIfDisplayNoConfigMessage() {
if (hasConfigCache == false) {
if (!hasConfigCache) {
MessageBoxManager.addMessageBox("No configuration for this controller found on the console.", MessageBox.MESSAGE_ERROR);
}
}

View File

@ -37,50 +37,40 @@ import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import lombok.Getter;
import net.ash.HIDToVPADNetworkClient.network.NetworkManager;
import net.ash.HIDToVPADNetworkClient.util.Settings;
public class GuiInputControls extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private static GuiInputControls instance = null;
@Getter private static GuiInputControls instance = new GuiInputControls();
private static final String CONNECT = "Connect";
private static final String DISCONNECT = "Disconnect";
private static final String RECONNECTING = "Reconnecting";
private final JTextField ipTextBox;
private JButton connectButton;
private JTextField ipTextBox;
private JPanel ipTextBoxWrap;
private JLabel statusLabel;
private JPanel autoActivateWrap;
private JCheckBox cbautoActivateController;
public GuiInputControls() throws Exception {
private GuiInputControls() {
super();
if (instance != null) {
throw new Exception("GuiInputControls already has an instance!");
}
instance = this;
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
setPreferredSize(new Dimension(220, 150));
connectButton = new JButton(CONNECT);
JButton connectButton = new JButton(CONNECT);
connectButton.setAlignmentX(Component.CENTER_ALIGNMENT);
ipTextBox = new JTextField();
ipTextBox.setColumns(15);
ipTextBox.setText(Settings.getIpAddr());
ipTextBoxWrap = new JPanel(new FlowLayout());
JPanel ipTextBoxWrap = new JPanel(new FlowLayout());
ipTextBoxWrap.add(new JLabel("IP: "));
ipTextBoxWrap.add(ipTextBox);
ipTextBoxWrap.setMaximumSize(new Dimension(1000, 20));
statusLabel = new JLabel("Ready.");
JLabel statusLabel = new JLabel("Ready.");
statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
cbautoActivateController = new JCheckBox();
JCheckBox cbautoActivateController = new JCheckBox();
cbautoActivateController.setSelected(Settings.AUTO_ACTIVATE_CONTROLLER);
cbautoActivateController.addActionListener(new ActionListener() {
@ -92,7 +82,7 @@ public class GuiInputControls extends JPanel implements ActionListener {
}
});
autoActivateWrap = new JPanel(new FlowLayout());
JPanel autoActivateWrap = new JPanel(new FlowLayout());
autoActivateWrap.add(new JLabel("Auto Activate Controller: "));
autoActivateWrap.add(cbautoActivateController);
autoActivateWrap.setMaximumSize(new Dimension(1000, 20));
@ -130,10 +120,6 @@ public class GuiInputControls extends JPanel implements ActionListener {
new Timer(delay, taskPerformer).start();
}
public static GuiInputControls instance() {
return instance;
}
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {

View File

@ -30,7 +30,6 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.Main;
import net.ash.HIDToVPADNetworkClient.util.MessageBox;
import net.ash.HIDToVPADNetworkClient.util.MessageBoxListener;
@ -55,22 +54,13 @@ public class GuiMain extends JPanel implements MessageBoxListener {
return instance;
}
private GuiControllerList leftControllerList;
private GuiInputControls rightSideControls;
public GuiMain() {
super(new BorderLayout());
leftControllerList = new GuiControllerList();
GuiControllerList leftControllerList = new GuiControllerList();
leftControllerList.setPreferredSize(new Dimension(300, 100));
add(leftControllerList, BorderLayout.CENTER);
try {
rightSideControls = new GuiInputControls();
} catch (Exception e) {
e.printStackTrace();
Main.fatal();
}
GuiInputControls rightSideControls = GuiInputControls.getInstance();
add(rightSideControls, BorderLayout.LINE_END);
}

View File

@ -35,8 +35,9 @@ import net.ash.HIDToVPADNetworkClient.util.Settings;
import net.ash.HIDToVPADNetworkClient.util.Utilities;
@Log
public class ActiveControllerManager implements Runnable {
public final class ActiveControllerManager implements Runnable {
private static ActiveControllerManager instance = new ActiveControllerManager();
private final Map<Controller, NetworkHIDDevice> activeControllers = new HashMap<Controller, NetworkHIDDevice>();
private ActiveControllerManager() {
}
@ -46,7 +47,7 @@ public class ActiveControllerManager implements Runnable {
}
@Override
public void run() { // TODO: Add mechanism to stop these threads?
public void run() { // TODO: Add mechanism to stop these threads? And add a mechanism start only once?
new Thread(new Runnable() {
@Override
public void run() {
@ -69,8 +70,6 @@ public class ActiveControllerManager implements Runnable {
}).start();
}
private Map<Controller, NetworkHIDDevice> activeControllers = new HashMap<Controller, NetworkHIDDevice>();
public void updateControllerStates() {
List<Controller> currentControllers = ControllerManager.getActiveControllers();

View File

@ -51,9 +51,13 @@ import net.ash.HIDToVPADNetworkClient.util.Settings;
import purejavahidapi.HidDeviceInfo;
@Log
public class ControllerManager {
public final class ControllerManager {
private static Map<String, Controller> attachedControllers = new HashMap<String, Controller>();
private ControllerManager() {
// Utility Class
}
/**
* Detects all attached controller.
*/

View File

@ -42,12 +42,13 @@ public class NetworkHIDDevice {
@Getter @Setter private boolean needFirstData = false;
@Getter private int hidHandle = HandleFoundry.next();
@Getter(AccessLevel.PRIVATE) private List<DeviceCommand> commands = new ArrayList<DeviceCommand>();
private byte[] lastdata = null;
@Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE) private ReadCommand latestRead;
@Getter private final int hidHandle = HandleFoundry.next();
private Object readCommandLock = new Object();
@Getter(AccessLevel.PRIVATE) private List<DeviceCommand> commands = new ArrayList<DeviceCommand>();
@Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE) private ReadCommand latestRead;
public NetworkHIDDevice(short vid, short pid) {
this.vid = vid;
@ -70,8 +71,6 @@ public class NetworkHIDDevice {
addCommand(new DetachCommand(getHidHandle(), this));
}
private byte[] lastdata = null;
public void sendRead(byte[] data) {
if (!Settings.SEND_DATA_ONLY_ON_CHANGE || !Arrays.equals(lastdata, data) && Settings.SEND_DATA_ONLY_ON_CHANGE || isNeedFirstData()) {
synchronized (readCommandLock) {

View File

@ -37,27 +37,25 @@ import net.ash.HIDToVPADNetworkClient.util.Settings;
import net.ash.HIDToVPADNetworkClient.util.Utilities;
@Log
public class NetworkManager implements Runnable {
public final class NetworkManager implements Runnable {
private final TCPClient tcpClient = new TCPClient();
private UDPClient udpClient = null;
private static NetworkManager instance = null;
@Getter private static NetworkManager instance = new NetworkManager();
private List<DeviceCommand> ownCommands = new ArrayList<DeviceCommand>();
private final List<DeviceCommand> ownCommands = new ArrayList<DeviceCommand>();
@Getter private final List<NetworkHIDDevice> devices = new ArrayList<NetworkHIDDevice>();
/*
* We want to remove them at the end of a cycle. To make sure the detach was send before removing.
*/
@Getter private final List<NetworkHIDDevice> toRemove = new ArrayList<NetworkHIDDevice>();
private NetworkManager() {
// Singleton
}
public static NetworkManager getInstance() {
if (instance == null) {
instance = new NetworkManager();
}
return instance;
}
@Getter private List<NetworkHIDDevice> devices = new ArrayList<NetworkHIDDevice>();
public void addHIDDevice(NetworkHIDDevice device) {
if (!getDevices().contains(device)) {
synchronized (devices) {
@ -66,11 +64,6 @@ public class NetworkManager implements Runnable {
}
}
/*
* We want to remove them at the end of a cycle. To make sure the detach was send before removing.
*/
@Getter private List<NetworkHIDDevice> toRemove = new ArrayList<NetworkHIDDevice>();
@Synchronized("toRemove")
public void removeHIDDevice(NetworkHIDDevice device) {
device.sendDetach();

View File

@ -31,6 +31,7 @@ import java.nio.ByteBuffer;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.Synchronized;
import lombok.extern.java.Log;
import net.ash.HIDToVPADNetworkClient.manager.ActiveControllerManager;
import net.ash.HIDToVPADNetworkClient.network.Protocol.HandshakeReturnCode;
@ -38,6 +39,7 @@ import net.ash.HIDToVPADNetworkClient.util.Settings;
@Log
class TCPClient {
private final Object lock = new Object();
private Socket sock;
private DataInputStream in;
private DataOutputStream out;
@ -49,7 +51,8 @@ class TCPClient {
protected TCPClient() {
}
protected synchronized void connect(String ip) throws Exception {
@Synchronized("lock")
protected void connect(String ip) throws Exception {
sock = new Socket();
sock.connect(new InetSocketAddress(ip, Protocol.TCP_PORT), 2000);
in = new DataInputStream(sock.getInputStream());
@ -68,7 +71,8 @@ class TCPClient {
}
}
protected synchronized boolean abort() {
@Synchronized("lock")
protected boolean abort() {
try {
shouldRetry = Settings.MAXIMUM_TRIES_FOR_RECONNECTING;
sock.close();
@ -79,7 +83,8 @@ class TCPClient {
return true;
}
protected synchronized void send(byte[] rawCommand) throws IOException {
@Synchronized("lock")
protected void send(byte[] rawCommand) throws IOException {
try {
out.write(rawCommand);
out.flush();
@ -87,7 +92,7 @@ class TCPClient {
try {
if (shouldRetry++ < Settings.MAXIMUM_TRIES_FOR_RECONNECTING) {
log.info("Trying again to connect! Attempt number " + shouldRetry);
connect(ip); // TODO: this is for reconnecting when the WiiU switches the application. But this breaks disconnecting, woops.
connect(ip);
} else {
abort();
}
@ -98,15 +103,17 @@ class TCPClient {
}
}
protected synchronized void send(int value) throws IOException {
protected void send(int value) throws IOException {
send(ByteBuffer.allocate(4).putInt(value).array());
}
protected synchronized byte recvByte() throws IOException {
@Synchronized("lock")
protected byte recvByte() throws IOException {
return in.readByte();
}
protected synchronized short recvShort() throws IOException {
@Synchronized("lock")
protected short recvShort() throws IOException {
try {
return in.readShort();
} catch (IOException e) {
@ -115,7 +122,8 @@ class TCPClient {
}
}
protected synchronized boolean isConnected() {
@Synchronized("lock")
protected boolean isConnected() {
return (sock != null && sock.isConnected() && !sock.isClosed());
}

View File

@ -27,7 +27,7 @@ package net.ash.HIDToVPADNetworkClient.util;
import java.util.Random;
public class HandleFoundry {
public final class HandleFoundry {
// We start with a random value, so we have at each startup a different clientID!
private static int h = new Random().nextInt(Short.MAX_VALUE);
@ -35,6 +35,7 @@ public class HandleFoundry {
}
public static int next() {
if (h >= Short.MAX_VALUE) h = 0;
return h++;
}
}

View File

@ -28,7 +28,7 @@ import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class MessageBoxManager implements Runnable {
public final class MessageBoxManager implements Runnable {
private static final Queue<MessageBox> messageBoxQueue = new ConcurrentLinkedQueue<MessageBox>();
private static List<MessageBoxListener> newList = Collections.synchronizedList(new ArrayList<MessageBoxListener>());
private static Object listenerListLock = new Object();

View File

@ -90,14 +90,14 @@ public class Settings {
String sendDataOnlyOnChanges = prop.getProperty("sendDataOnlyOnChanges");
if (autoActivatingControllerString != null) { // We don't combine the if statements to keep the default value.
if (autoActivatingControllerString.equals("true")) {
if ("true".equals(autoActivatingControllerString)) {
Settings.AUTO_ACTIVATE_CONTROLLER = true;
} else {
Settings.AUTO_ACTIVATE_CONTROLLER = false;
}
}
if (sendDataOnlyOnChanges != null) { // We don't combine the if statements to keep the default value.
if (sendDataOnlyOnChanges.equals("true")) {
if ("true".equals(sendDataOnlyOnChanges)) {
Settings.SEND_DATA_ONLY_ON_CHANGE = true;
} else {
Settings.SEND_DATA_ONLY_ON_CHANGE = false;

View File

@ -21,7 +21,7 @@
*******************************************************************************/
package net.ash.HIDToVPADNetworkClient.util;
public class Utilities {
public final class Utilities {
private Utilities() {
}