diff --git a/src/com/sheepit/client/Client.java b/src/com/sheepit/client/Client.java index 9f69047..66736d3 100644 --- a/src/com/sheepit/client/Client.java +++ b/src/com/sheepit/client/Client.java @@ -69,6 +69,7 @@ import lombok.Data; private BlockingQueue jobsToValidate; private boolean isValidatingJob; private long startTime; + private boolean sessionStarted; private boolean disableErrorSending; private boolean running; @@ -99,6 +100,8 @@ import lombok.Data; this.uploadQueueSize = 0; this.uploadQueueVolume = 0; this.noJobRetryIter = 0; + + this.sessionStarted = false; } public String toString() { diff --git a/src/com/sheepit/client/Configuration.java b/src/com/sheepit/client/Configuration.java index e89c25d..ce17fb0 100644 --- a/src/com/sheepit/client/Configuration.java +++ b/src/com/sheepit/client/Configuration.java @@ -34,8 +34,10 @@ import java.util.List; import com.sheepit.client.hardware.cpu.CPU; import com.sheepit.client.hardware.gpu.GPUDevice; import com.sheepit.client.os.OS; +import lombok.AllArgsConstructor; import lombok.Data; +@AllArgsConstructor @Data public class Configuration { public enum ComputeType { @@ -67,6 +69,7 @@ import lombok.Data; private String extras; private boolean autoSignIn; private boolean useSysTray; + private boolean headless; private String UIType; private String hostname; private String theme; @@ -99,10 +102,18 @@ import lombok.Data; this.extras = ""; this.autoSignIn = false; this.useSysTray = false; + this.headless = java.awt.GraphicsEnvironment.isHeadless(); this.UIType = null; this.theme = null; } + public Configuration(Configuration config) { + this(config.configFilePath, config.workingDirectory, config.sharedDownloadsDirectory, config.storageDirectory, config.userHasSpecifiedACacheDir, + config.static_exeDirName, config.login, config.password, config.proxy, config.maxUploadingJob, config.nbCores, config.maxMemory, config.maxRenderTime, + config.priority, config.computeMethod, config.GPUDevice, config.renderbucketSize, config.detectGPUs, config.printLog, config.requestTime, config.shutdownTime, + config.shutdownMode, config.extras, config.autoSignIn, config.useSysTray, config.headless, config.UIType, config.hostname, config.theme); + } + public String toString() { return String.format("Configuration (workingDirectory '%s')", this.workingDirectory.getAbsolutePath()); } diff --git a/src/com/sheepit/client/Server.java b/src/com/sheepit/client/Server.java index ac9acc9..cd28438 100644 --- a/src/com/sheepit/client/Server.java +++ b/src/com/sheepit/client/Server.java @@ -205,7 +205,7 @@ public class Server extends Thread { .add("hostname", user_config.getHostname()) .add("ui", client.getGui().getClass().getSimpleName()) .add("extras", user_config.getExtras()) - .add("headless", java.awt.GraphicsEnvironment.isHeadless() ? "1" : "0") + .add("headless", java.awt.GraphicsEnvironment.isHeadless() ? "1" : (user_config.isHeadless() ? "1" : "0")) .build(); this.log.debug("Server::getConfiguration url " + remoteURL.build().toString()); @@ -252,6 +252,7 @@ public class Server extends Thread { return Error.Type.UNKNOWN; } + client.setSessionStarted(true); this.client.getGui().successfulAuthenticationEvent(publickey); return Error.Type.OK; diff --git a/src/com/sheepit/client/SettingsLoader.java b/src/com/sheepit/client/SettingsLoader.java index 4ac7f97..1ab0f52 100644 --- a/src/com/sheepit/client/SettingsLoader.java +++ b/src/com/sheepit/client/SettingsLoader.java @@ -38,14 +38,15 @@ import com.sheepit.client.hardware.gpu.GPUDevice; import com.sheepit.client.standalone.GuiSwing; import com.sheepit.client.standalone.GuiText; import com.sheepit.client.standalone.GuiTextOneLine; -import lombok.Setter; +import lombok.Data; +@Data public class SettingsLoader { private String path; private String login; - @Setter private String password; + private String password; private String proxy; private String hostname; @@ -58,6 +59,7 @@ public class SettingsLoader { private String cacheDir; private String autoSignIn; private String useSysTray; + private String headless; private String ui; private String theme; private int priority; @@ -72,7 +74,7 @@ public class SettingsLoader { } public SettingsLoader(String path_, String login_, String password_, String proxy_, String hostname_, ComputeType computeMethod_, GPUDevice gpu_, - int renderbucketSize_, int cores_, long maxRam_, int maxRenderTime_, String cacheDir_, boolean autoSignIn_, boolean useSysTray_, String ui_, + int renderbucketSize_, int cores_, long maxRam_, int maxRenderTime_, String cacheDir_, boolean autoSignIn_, boolean useSysTray_, boolean isHeadless, String ui_, String theme_, int priority_) { if (path_ == null) { path = getDefaultFilePath(); @@ -87,6 +89,7 @@ public class SettingsLoader { cacheDir = cacheDir_; autoSignIn = String.valueOf(autoSignIn_); useSysTray = String.valueOf(useSysTray_); + headless = String.valueOf(isHeadless); ui = ui_; priority = priority_; theme = theme_; @@ -184,6 +187,10 @@ public class SettingsLoader { prop.setProperty("use-systray", useSysTray); } + if (headless != null) { + prop.setProperty("headless", headless); + } + if (ui != null) { prop.setProperty("ui", ui); } @@ -295,6 +302,10 @@ public class SettingsLoader { this.useSysTray = prop.getProperty("use-systray"); } + if (prop.containsKey("headless")) { + this.headless = prop.getProperty("headless"); + } + if (prop.containsKey("ui")) { this.ui = prop.getProperty("ui"); } @@ -360,6 +371,10 @@ public class SettingsLoader { config.setHostname(hostname); } + if (!config.isHeadless() && headless != null) { + config.setHeadless(Boolean.parseBoolean(headless)); + } + if (config.getPriority() == 19) { // 19 is default value config.setUsePriority(priority); } @@ -471,6 +486,7 @@ public class SettingsLoader { this.cacheDir = null; this.autoSignIn = null; this.useSysTray = String.valueOf(defaultConfigValues.isUseSysTray()); + this.headless = String.valueOf(defaultConfigValues.isHeadless()); this.ui = null; this.priority = defaultConfigValues.getPriority(); // must be the same default as Configuration this.ram = null; @@ -483,7 +499,7 @@ public class SettingsLoader { @Override public String toString() { return String.format( - "SettingsLoader [path=%s, login=%s, password=%s, computeMethod=%s, gpu=%s, renderbucket-size=%s, cacheDir=%s, theme=%s, priority=%d, autosign=%s, usetray=%s]", - path, login, password, computeMethod, gpu, renderbucketSize, cacheDir, theme, priority, autoSignIn, useSysTray); + "SettingsLoader [path=%s, login=%s, password=%s, computeMethod=%s, gpu=%s, renderbucket-size=%s, cacheDir=%s, theme=%s, priority=%d, autosign=%s, usetray=%s, headless=%s]", + path, login, password, computeMethod, gpu, renderbucketSize, cacheDir, theme, priority, autoSignIn, useSysTray, headless); } } diff --git a/src/com/sheepit/client/standalone/GuiSwing.java b/src/com/sheepit/client/standalone/GuiSwing.java index 08f16c5..5c3c65a 100644 --- a/src/com/sheepit/client/standalone/GuiSwing.java +++ b/src/com/sheepit/client/standalone/GuiSwing.java @@ -291,7 +291,7 @@ public class GuiSwing extends JFrame implements Gui { @Override public void successfulAuthenticationEvent(String publickey) { if (settingsLoader != null) { - if (publickey != null) { + if (publickey != null && activitySettings.getLaunchConfig().getLogin().equals(settingsLoader.getLogin())) { settingsLoader.setPassword(publickey); } settingsLoader.saveFile(); diff --git a/src/com/sheepit/client/standalone/Worker.java b/src/com/sheepit/client/standalone/Worker.java index 539d235..26cf8d4 100644 --- a/src/com/sheepit/client/standalone/Worker.java +++ b/src/com/sheepit/client/standalone/Worker.java @@ -110,6 +110,8 @@ public class Worker { @Option(name = "-hostname", usage = "Set a custom hostname name (name change will be lost when client is closed)", required = false) private String hostname = null; + @Option(name = "--headless", usage = "Mark your client manually as headless to block Eevee projects", required = false) private boolean headless = java.awt.GraphicsEnvironment.isHeadless(); + public static void main(String[] args) { if (OS.getOS() == null) { System.err.println(Error.humanString(Error.Type.OS_NOT_SUPPORTED)); @@ -182,6 +184,8 @@ public class Worker { // for further checks. config.setUseSysTray(!useSysTray); + config.setHeadless(headless); + if (gpu_device != null) { if (gpu_device.startsWith(Nvidia.TYPE) == false && gpu_device.startsWith(OpenCL.TYPE) == false) { System.err.println("ERROR: The entered GPU_ID is invalid. The GPU_ID should look like '" + Nvidia.TYPE + "_#' or '" + OpenCL.TYPE @@ -427,7 +431,8 @@ public class Worker { config.setConfigFilePath(config_file); } - new SettingsLoader(config_file).merge(config); + SettingsLoader settingsLoader = new SettingsLoader(config_file); + settingsLoader.merge(config); Log.getInstance(config).debug("client version " + config.getJarVersion()); // Hostname change will overwrite the existing one (default or read from configuration file) but changes will be lost when the client closes @@ -470,6 +475,7 @@ public class Worker { System.exit(3); } gui = new GuiSwing(config.isUseSysTray(), title); + ((GuiSwing) gui).setSettingsLoader(settingsLoader); break; } Client cli = new Client(gui, config, server); diff --git a/src/com/sheepit/client/standalone/swing/activity/Settings.java b/src/com/sheepit/client/standalone/swing/activity/Settings.java index 0ca7c67..8adcbe1 100644 --- a/src/com/sheepit/client/standalone/swing/activity/Settings.java +++ b/src/com/sheepit/client/standalone/swing/activity/Settings.java @@ -75,6 +75,8 @@ import com.sheepit.client.os.OS; import com.sheepit.client.standalone.GuiSwing; import com.sheepit.client.standalone.swing.SwingTooltips; import com.sheepit.client.standalone.swing.components.CollapsibleJPanel; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; public class Settings implements Activity { private static final String DUMMY_CACHE_DIR = "Auto detected"; @@ -89,6 +91,7 @@ public class Settings implements Activity { private JCheckBox useCPU; private List useGPUs; private JCheckBox useSysTray; + private JCheckBox headlessCheckbox; private JLabel renderbucketSizeLabel; private JSlider renderbucketSize; private JSlider cpuCores; @@ -108,18 +111,25 @@ public class Settings implements Activity { private boolean haveAutoStarted; private boolean useSysTrayPrevState; + private boolean isHeadlessPrevState; + private boolean sessionStarted; //indicates whether the settings activity gets shown on launch or mid-session. + // it should only be false when the settings activity gets shown right after launch + + @Getter private Configuration launchConfig; //the config we launched with, combined out of launch arguments and config file settings public Settings(GuiSwing parent_) { parent = parent_; cacheDir = null; useGPUs = new LinkedList(); haveAutoStarted = false; + sessionStarted = false; } @Override public void show() { Configuration config = parent.getConfiguration(); new SettingsLoader(config.getConfigFilePath()).merge(config); useSysTrayPrevState = config.isUseSysTray(); + isHeadlessPrevState = config.isHeadless(); applyTheme(config.getTheme()); // apply the proper theme (light/dark) @@ -494,7 +504,7 @@ public class Settings implements Activity { parent.getContentPanel().add(compute_devices_panel, constraints); // other - CollapsibleJPanel advanced_panel = new CollapsibleJPanel(new GridLayout(4, 2), this); + CollapsibleJPanel advanced_panel = new CollapsibleJPanel(new GridLayout(5, 2), this); advanced_panel.setBorder(BorderFactory.createTitledBorder("Advanced options")); JLabel useSysTrayLabel = new JLabel("Minimize to SysTray"); @@ -505,6 +515,12 @@ public class Settings implements Activity { advanced_panel.add(useSysTrayLabel); advanced_panel.add(useSysTray); + JLabel headlessLabel = new JLabel("Block Eevee projects"); + headlessCheckbox = new JCheckBox(); + headlessCheckbox.setSelected(config.isHeadless()); + advanced_panel.add(headlessLabel); + advanced_panel.add(headlessCheckbox); + JLabel proxyLabel = new JLabel("Proxy:"); proxyLabel.setToolTipText("http://login:password@host:port\n" + SwingTooltips.PROXY.getText()); proxy = new JTextField(); @@ -584,6 +600,11 @@ public class Settings implements Activity { haveAutoStarted = true; new SaveAction().actionPerformed(null); } + + //check so the launch config does not get overwritten if the user goes back to the settings activity mid-session + if(!sessionStarted) { + launchConfig = new Configuration(config); + } } public void resizeWindow() {} @@ -737,6 +758,10 @@ public class Settings implements Activity { return; } + if(config.isAutoSignIn() && launchConfig == null) { + launchConfig = new Configuration(config); + } + if (themeOptionsGroup.getSelection().getActionCommand() != null) config.setTheme(themeOptionsGroup.getSelection().getActionCommand()); @@ -756,17 +781,8 @@ public class Settings implements Activity { selected_gpu = box.getGPUDevice(); } } - - ComputeType method = ComputeType.CPU; - if (useCPU.isSelected() && selected_gpu == null) { - method = ComputeType.CPU; - } - else if (useCPU.isSelected() == false && selected_gpu != null) { - method = ComputeType.GPU; - } - else if (useCPU.isSelected() && selected_gpu != null) { - method = ComputeType.CPU_GPU; - } + + ComputeType method = getComputeType(selected_gpu); config.setComputeMethod(method); if (selected_gpu != null) { @@ -776,7 +792,9 @@ public class Settings implements Activity { int renderbucket_size = -1; if (renderbucketSize != null) { renderbucket_size = (int) Math.pow(2, (renderbucketSize.getValue() + 5)); + System.out.println(config.getRenderbucketSize() + " calced: " + renderbucket_size); } + config.setRenderbucketSize(renderbucket_size); int cpu_cores = -1; if (cpuCores != null) { @@ -814,6 +832,8 @@ public class Settings implements Activity { config.setUsePriority(19 - priority.getValue()); } + config.setHeadless(headlessCheckbox.isSelected()); + String proxyText = null; if (proxy != null) { try { @@ -826,35 +846,164 @@ public class Settings implements Activity { System.exit(2); } } + config.setProxy(proxyText); parent.setCredentials(login.getText(), new String(password.getPassword())); - String cachePath = null; - if (config.isUserHasSpecifiedACacheDir() && config.getCacheDirForSettings() != null) { - cachePath = config.getCacheDirForSettings().getAbsolutePath(); - } - String hostnameText = hostname.getText(); if (hostnameText == null || hostnameText.isEmpty()) { hostnameText = parent.getConfiguration().getHostname(); } + config.setHostname(hostnameText); + config.setAutoSignIn(autoSignIn.isSelected()); + config.setUseSysTray(useSysTray.isSelected()); +// config.setUIType(GuiSwing.type); + + if (saveFile.isSelected()) { - parent.setSettingsLoader( - new SettingsLoader(config.getConfigFilePath(), login.getText(), new String(password.getPassword()), proxyText, hostnameText, method, - selected_gpu, renderbucket_size, cpu_cores, max_ram, max_rendertime, cachePath, autoSignIn.isSelected(), useSysTray.isSelected(), - GuiSwing.type, themeOptionsGroup.getSelection().getActionCommand(), config.getPriority())); + //save config file values to seperate config for later comparison (only necessary for GuiSwing as the other uis dont save any configs) + Configuration configFileConfiguration = new Configuration(null, "", ""); + configFileConfiguration.setConfigFilePath(config.getConfigFilePath()); + parent.getSettingsLoader().merge(configFileConfiguration); + + mergeChanges(launchConfig, config, configFileConfiguration); +// parent.setSettingsLoader( +// new SettingsLoader(config.getConfigFilePath(), login.getText(), new String(password.getPassword()), proxyText, hostnameText, method, +// selected_gpu, renderbucket_size, cpu_cores, max_ram, max_rendertime, cachePath, autoSignIn.isSelected(), useSysTray.isSelected(), +// headlessCheckbox.isSelected(), GuiSwing.type, themeOptionsGroup.getSelection().getActionCommand(), config.getPriority())); // wait for successful authentication (to store the public key) // or do we already have one? if (parent.getClient().getServer().getServerConfig() != null && parent.getClient().getServer().getServerConfig().getPublickey() != null) { parent.getSettingsLoader().saveFile(); - } - - if (useSysTrayPrevState != useSysTray.isSelected()) { - JOptionPane.showMessageDialog(null, "You must restart the SheepIt app for the SysTray change to take effect"); + sessionStarted = true; } } + + boolean sysTrayChanged = useSysTray.isSelected() != useSysTrayPrevState; + boolean headlessChanged = headlessCheckbox.isSelected() != isHeadlessPrevState; + boolean restartRequired = sysTrayChanged || headlessChanged; + if (restartRequired) { + String warning = "The following changes require a restart to take effect: %s"; + List changes = new LinkedList<>(); + + if (sysTrayChanged) { + changes.add("Minimize to SysTray"); + } + + if (headlessChanged && sessionStarted) { //only show this when the setting gets changed in the middle of a session, not on launch + changes.add("Block Eevee Projects"); + } + + if (changes.size() > 0) { + warning = String.format(warning, String.join(", ", changes)); + JOptionPane.showMessageDialog(null, warning); + } + } + } + + @NotNull private ComputeType getComputeType(GPUDevice selected_gpu) { + ComputeType method = ComputeType.CPU; + if (useCPU.isSelected() && selected_gpu == null) { + method = ComputeType.CPU; + } + else if (useCPU.isSelected() == false && selected_gpu != null) { + method = ComputeType.GPU; + } + else if (useCPU.isSelected() && selected_gpu != null) { + method = ComputeType.CPU_GPU; + } + return method; + } + + private void mergeChanges(Configuration launchConfig, Configuration workingConfig, Configuration configFileConfiguration) { + + /* if the config value we are checking is different from the config file (e.g. because it got passed as a launch argument) we leave the settingsLoader as is + as to not overwrite it with the launch argument. However, if it was changed after launch we do save it + */ + if (saveSetting(launchConfig.getLogin(), configFileConfiguration.getLogin(), workingConfig.getLogin())) { + parent.getSettingsLoader().setLogin(workingConfig.getLogin()); + } + + if (saveSetting(launchConfig.getPassword(), configFileConfiguration.getPassword(), workingConfig.getPassword())) { + parent.getSettingsLoader().setPassword(workingConfig.getPassword()); + } + + if (saveSetting(launchConfig.getHostname(), configFileConfiguration.getHostname(), workingConfig.getHostname())) { + parent.getSettingsLoader().setHostname(workingConfig.getHostname()); + } + + if (saveSetting(launchConfig.getProxy(), configFileConfiguration.getProxy(), workingConfig.getProxy())) { + parent.getSettingsLoader().setProxy(workingConfig.getProxy()); + } + + if (saveSetting(launchConfig.getNbCores(), configFileConfiguration.getNbCores(), workingConfig.getNbCores())) { + parent.getSettingsLoader().setCores(String.valueOf(workingConfig.getNbCores())); + } + + if (saveSetting(launchConfig.getMaxMemory(), configFileConfiguration.getMaxMemory(), workingConfig.getMaxMemory())) { + parent.getSettingsLoader().setRam(String.valueOf(workingConfig.getMaxMemory())); + } + + if (saveSetting(launchConfig.getMaxRenderTime(), configFileConfiguration.getMaxRenderTime(), workingConfig.getMaxRenderTime())) { + parent.getSettingsLoader().setRenderTime(String.valueOf(workingConfig.getMaxRenderTime())); + } + + if (saveSetting(launchConfig.getGPUDevice(), configFileConfiguration.getGPUDevice(), workingConfig.getGPUDevice())) { + parent.getSettingsLoader().setGpu(workingConfig.getGPUDevice().getId()); //TODO presumably works + } + + if (saveSetting(launchConfig.getRenderbucketSize(), configFileConfiguration.getRenderbucketSize(), workingConfig.getRenderbucketSize())) { + parent.getSettingsLoader().setRenderbucketSize(String.valueOf(workingConfig.getRenderbucketSize())); + } + + if (saveSetting(getCachePath(launchConfig), getCachePath(configFileConfiguration), getCachePath(workingConfig))) { + parent.getSettingsLoader().setCacheDir(getCachePath(workingConfig)); + } + + //not changeable through launch arguments + if (saveSetting(launchConfig.isAutoSignIn(), configFileConfiguration.isAutoSignIn(), workingConfig.isAutoSignIn())) { + parent.getSettingsLoader().setAutoSignIn(String.valueOf(workingConfig.isAutoSignIn())); + } + + if (saveSetting(launchConfig.isUseSysTray(), configFileConfiguration.isUseSysTray(), workingConfig.isUseSysTray())) { + parent.getSettingsLoader().setUseSysTray(String.valueOf(workingConfig.isUseSysTray())); + } + + if (saveSetting(launchConfig.isHeadless(), configFileConfiguration.isHeadless(), workingConfig.isHeadless())) { + parent.getSettingsLoader().setHeadless(String.valueOf(workingConfig.isHeadless())); + } + + //not needed as the user has no way of modifying that setting after launch +// if (saveSetting(launchConfig.getUIType(), configFileConfiguration.getUIType(), workingConfig.getUIType())) { +// parent.getSettingsLoader().setUi(workingConfig.getUIType()); +// } + + if (saveSetting(launchConfig.getTheme(), configFileConfiguration.getTheme(), workingConfig.getTheme())) { + parent.getSettingsLoader().setTheme(workingConfig.getTheme()); + } + + if (saveSetting(launchConfig.getPriority(), configFileConfiguration.getPriority(), workingConfig.getPriority())) { + parent.getSettingsLoader().setPriority(workingConfig.getPriority()); + } + + + } + + private boolean saveSetting(T launchValue, T configFileValue, T workingValue) { + if (workingValue == null) { + return false; + } + return !workingValue.equals(configFileValue) && !workingValue.equals(launchValue); + } + + private String getCachePath(Configuration config) { + String cachePath = null; + if (config.isUserHasSpecifiedACacheDir() && config.getCacheDirForSettings() != null) { + cachePath = config.getCacheDirForSettings().getAbsolutePath(); + } + return cachePath; } }