server
Clone or download
Modified Files
/*
/*
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
This program is free software: you can redistribute it and/or modify
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU General Public License for more details.
Written by : Debayan Sutradhar (rnayabed)
Written by : Debayan Sutradhar (rnayabed)
*/
*/
package com.stream_pi.server;
package com.stream_pi.server;
import com.stream_pi.server.controller.Controller;
import com.stream_pi.server.controller.Controller;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import javafx.application.Application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.Stage;
public class Main extends Application {
public class Main extends Application {
/**
/**
* First method to be called
* First method to be called
* This method first parses all the available command line arguments passed.
* This method first parses all the available command line arguments passed.
* Then a new instance of controller is created, and then initialised.
* Then a new instance of controller is created, and then initialised.
*/
*/
public void start(Stage stage) {
public void start(Stage stage) {
for(String eachArg : getParameters().getRaw())
for(String eachArg : getParameters().getRaw())
{
{
if(!eachArg.startsWith("-DStreamPi"))
if(!eachArg.startsWith("-DStreamPi"))
continue;
continue;
String[] r = eachArg.split("=");
String[] r = eachArg.split("=");
String arg = r[0];
String arg = r[0];
String val = r[1];
String val = r[1];
if(arg.equals("-DStreamPi.startupRunnerFileName"))
if(arg.equals("-DStreamPi.startupRunnerFileName"))
ServerInfo.getInstance().setRunnerFileName(val);
ServerInfo.getInstance().setRunnerFileName(val);
else if(arg.equals("-DStreamPi.startupMode"))
else if(arg.equals("-DStreamPi.startupMode"))
ServerInfo.getInstance().setStartMinimised(val.equals("min"));
ServerInfo.getInstance().setStartMinimised(val.equals("min"));
}
}
Controller d = new Controller();
Controller d = new Controller();
Scene s = new Scene(d);
Scene s = new Scene(d);
stage.setScene(s);
stage.setScene(s);
d.setHostServices(getHostServices());
d.setHostServices(getHostServices());
d.init();
d.init();
}
}
/**
/**
* This is a fallback. Called in some JVMs.
* This is a fallback. Called in some JVMs.
* This method just sends the command line arguments to JavaFX Application
* This method just sends the command line arguments to JavaFX Application
*/
*/
public static void main(String[] args)
public static void main(String[] args)
{
{
launch(args);
launch(args);
}
}
}
}
/*
/*
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
This program is free software: you can redistribute it and/or modify
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU General Public License for more details.
Written by : Debayan Sutradhar (rnayabed)
Written by : Debayan Sutradhar (rnayabed)
*/
*/
package com.stream_pi.server.action;
package com.stream_pi.server.action;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.actionproperty.ServerProperties;
import com.stream_pi.action_api.actionproperty.ServerProperties;
import com.stream_pi.action_api.actionproperty.property.Property;
import com.stream_pi.action_api.actionproperty.property.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.externalplugin.ExternalPlugin;
import com.stream_pi.action_api.externalplugin.ExternalPlugin;
import com.stream_pi.action_api.externalplugin.NormalAction;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.File;
import java.lang.module.*;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Path;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.ServiceLoader;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
import org.w3c.dom.Element;
public class ExternalPlugins
public class ExternalPlugins
{
{
private static ExternalPlugins instance = null;
private static ExternalPlugins instance = null;
private final Logger logger;
private final Logger logger;
private File configFile;
private File configFile;
private Document document;
private Document document;
private static String pluginsLocation = null;
private static String pluginsLocation = null;
/**
/**
* Singleton class instance getter. Creates new one, when asked for the first time
* Singleton class instance getter. Creates new one, when asked for the first time
*
*
* @return returns instance of NormalActionPlugins (one and only, always)
* @return returns instance of NormalActionPlugins (one and only, always)
*/
*/
public static synchronized ExternalPlugins getInstance()
public static synchronized ExternalPlugins getInstance()
{
{
if(instance == null)
if(instance == null)
{
{
instance = new ExternalPlugins();
instance = new ExternalPlugins();
}
}
return instance;
return instance;
}
}
/**
/**
* Sets the folder location where the plugin JARs and their dependencies are stored
* Sets the folder location where the plugin JARs and their dependencies are stored
*
*
* @param location Folder location
* @param location Folder location
*/
*/
public static void setPluginsLocation(String location)
public static void setPluginsLocation(String location)
{
{
pluginsLocation = location;
pluginsLocation = location;
}
}
/**
/**
* Private constructor
* Private constructor
*/
*/
private ExternalPlugins()
private ExternalPlugins()
{
{
logger = Logger.getLogger(ExternalPlugins.class.getName());
logger = Logger.getLogger(ExternalPlugins.class.getName());
externalPluginsHashmap = new HashMap<>();
externalPluginsHashmap = new HashMap<>();
}
}
/**
/**
* init Method
* init Method
*/
*/
public void init() throws SevereException, MinorException
public void init() throws SevereException, MinorException
{
{
registerPlugins();
registerPlugins();
initPlugins();
initPlugins();
}
}
/**
/**
* Used to fetch list of all external Plugins
* Used to fetch list of all external Plugins
*
*
* @return List of plugins
* @return List of plugins
*/
*/
public List<ExternalPlugin> getPlugins()
public List<ExternalPlugin> getPlugins()
{
{
return externalPlugins;
return externalPlugins;
}
}
/**
/**
* Returns a plugin by its module name
* Returns a plugin by its module name
*
*
* @param name Module Name
* @param name Module Name
* @return The plugin. If not found, then null is returned
* @return The plugin. If not found, then null is returned
*/
*/
public ExternalPlugin getPluginByModuleName(String name)
public ExternalPlugin getPluginByModuleName(String name)
{
{
logger.info("Plugin being requested : "+name);
logger.info("Plugin being requested : "+name);
Integer index = externalPluginsHashmap.getOrDefault(name, -1);
Integer index = externalPluginsHashmap.getOrDefault(name, -1);
if(index != -1)
if(index != -1)
{
{
return externalPlugins.get(index);
return externalPlugins.get(index);
}
}
return null;
return null;
}
}
private List<ExternalPlugin> externalPlugins = null;
private List<ExternalPlugin> externalPlugins = null;
HashMap<String, Integer> externalPluginsHashmap;
HashMap<String, Integer> externalPluginsHashmap;
/**
/**
* Used to register plugins from plugin location
* Used to register plugins from plugin location
*/
*/
public void registerPlugins() throws SevereException, MinorException
public void registerPlugins() throws SevereException, MinorException
{
{
logger.info("Registering external plugins from "+pluginsLocation+" ...");
logger.info("Registering external plugins from "+pluginsLocation+" ...");
try
try
{
{
configFile = new File(pluginsLocation+"/config.xml");
configFile = new File(pluginsLocation+"/config.xml");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
document = docBuilder.parse(configFile);
document = docBuilder.parse(configFile);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
}
}
ArrayList<ExternalPlugin> errorModules = new ArrayList<>();
ArrayList<ExternalPlugin> errorModules = new ArrayList<>();
ArrayList<String> errorModuleError = new ArrayList<>();
ArrayList<String> errorModuleError = new ArrayList<>();
ArrayList<Action> pluginsConfigs = new ArrayList<>();
ArrayList<Action> pluginsConfigs = new ArrayList<>();
NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
for(int i =0;i<actionsNode.getLength();i++)
for(int i=0; i<actionsNode.getLength(); i++)
{
{
Node eachActionNode = actionsNode.item(i);
Node eachActionNode = actionsNode.item(i);
if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
if(eachActionNode.getNodeType() != Node.ELEMENT_NODE ||
continue;
!eachActionNode.getNodeName().equals("action"))
if(!eachActionNode.getNodeName().equals("action"))
continue;
continue;
Element eachActionElement = (Element) eachActionNode;
Element eachActionElement = (Element) eachActionNode;
String name;
String name;
Version version;
Version version;
ActionType actionType;
ActionType actionType;
try
try
{
{
name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
actionType = ActionType.valueOf(XMLConfigHelper.getStringProperty(eachActionElement, "type"));
actionType = ActionType.valueOf(XMLConfigHelper.getStringProperty(eachActionElement, "type"));
version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
}
}
catch (Exception e)
catch (Exception e)
{
{
logger.log(Level.WARNING, "Skipping configuration because invalid ...");
logger.log(Level.WARNING, "Skipping configuration because invalid ...");
e.printStackTrace();
e.printStackTrace();
continue;
continue;
}
}
ServerProperties serverProperties = new ServerProperties();
ServerProperties serverProperties = new ServerProperties();
NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
{
{
Node eachPropertyNode = serverPropertiesNodeList.item(j);
Node eachPropertyNode = serverPropertiesNodeList.item(j);
if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
continue;
continue;
if(!eachPropertyNode.getNodeName().equals("property"))
if(!eachPropertyNode.getNodeName().equals("property"))
continue;
continue;
Element eachPropertyElement = (Element) eachPropertyNode;
Element eachPropertyElement = (Element) eachPropertyNode;
try
try
{
{
Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
serverProperties.addProperty(property);
serverProperties.addProperty(property);
}
}
catch (Exception e)
catch (Exception e)
{
{
logger.log(Level.WARNING, "Skipping property because invalid ...");
logger.log(Level.WARNING, "Skipping property because invalid ...");
e.printStackTrace();
e.printStackTrace();
}
}
}
}
Action action = new Action(actionType);
Action action = new Action(actionType);
action.setModuleName(name);
action.setModuleName(name);
action.setVersion(version);
action.setVersion(version);
action.getServerProperties().set(serverProperties);
action.getServerProperties().set(serverProperties);
pluginsConfigs.add(action);
pluginsConfigs.add(action);
}
}
logger.info("Size : "+pluginsConfigs.size());
logger.info("Size : "+pluginsConfigs.size());
Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
try
try
{
{
// Search for plugins in the plugins directory
// Search for plugins in the plugins directory
ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
// Find all names of all found plugin modules
// Find all names of all found plugin modules
List<String> p = pluginsFinder
List<String> p = pluginsFinder
.findAll()
.findAll()
.stream()
.stream()
.map(ModuleReference::descriptor)
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.map(ModuleDescriptor::name)
.collect(Collectors.toList());
.collect(Collectors.toList());
// Create configuration that will resolve plugin modules
// Create configuration that will resolve plugin modules
// (verify that the graph of modules is correct)
// (verify that the graph of modules is correct)
Configuration pluginsConfiguration = ModuleLayer
Configuration pluginsConfiguration = ModuleLayer
.boot()
.boot()
.configuration()
.configuration()
.resolve(pluginsFinder, ModuleFinder.of(), p);
.resolve(pluginsFinder, ModuleFinder.of(), p);
// Create a module layer for plugins
// Create a module layer for plugins
ModuleLayer layer = ModuleLayer
ModuleLayer layer = ModuleLayer
.boot()
.boot()
.defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
.defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
logger.info("Loading plugins from jar ...");
logger.info("Loading plugins from jar ...");
// Now you can use the new module layer to find service implementations in it
// Now you can use the new module layer to find service implementations in it
externalPlugins = ServiceLoader
externalPlugins = ServiceLoader
.load(layer, ExternalPlugin.class).stream()
.load(layer, ExternalPlugin.class).stream()
.map(ServiceLoader.Provider::get)
.map(ServiceLoader.Provider::get)
.collect(Collectors.toList());
.collect(Collectors.toList());
logger.info("...Done!");
logger.info("...Done!");
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
}
}
sortedPlugins = new HashMap<>();
sortedPlugins = new HashMap<>();
for (ExternalPlugin eachPlugin : externalPlugins)
for (ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.setPropertySaver(propertySaver);
eachPlugin.setPropertySaver(propertySaver);
eachPlugin.setServerConnection(serverConnection);
eachPlugin.setServerConnection(serverConnection);
eachPlugin.initProperties();
eachPlugin.initProperties();
logger.info("MODULE : "+eachPlugin.getModuleName());
logger.info("MODULE : "+eachPlugin.getModuleName());
Action foundAction = null;
Action foundAction = null;
for (Action action : pluginsConfigs) {
for (Action action : pluginsConfigs) {
if (action.getModuleName().equals(eachPlugin.getModuleName())
if (action.getModuleName().equals(eachPlugin.getModuleName())
&& action.getVersion().isEqual(eachPlugin.getVersion())) {
&& action.getVersion().isEqual(eachPlugin.getVersion())) {
foundAction = action;
foundAction = action;
List<Property> eachPluginStoredProperties = action.getServerProperties().get();
List<Property> eachPluginStoredProperties = action.getServerProperties().get();
List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
for (int i =0;i< eachPluginCodeProperties.size(); i++) {
for (int i =0;i< eachPluginCodeProperties.size(); i++) {
Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
Property foundProp = null;
Property foundProp = null;
for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
foundProp = eachPluginStoredProperty;
foundProp = eachPluginStoredProperty;
}
}
}
}
eachPluginCodeProperties.set(i, eachPluginCodeProperty);
eachPluginCodeProperties.set(i, eachPluginCodeProperty);
if (foundProp != null) {
if (foundProp != null) {
eachPluginStoredProperties.remove(foundProp);
eachPluginStoredProperties.remove(foundProp);
}
}
}
}
eachPlugin.getServerProperties().set(eachPluginCodeProperties);
eachPlugin.getServerProperties().set(eachPluginCodeProperties);
break;
break;
}
}
}
}
if (foundAction != null)
if (foundAction != null)
pluginsConfigs.remove(foundAction);
pluginsConfigs.remove(foundAction);
else
else
{
{
List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
for(Property property :eachPluginStoredProperties)
for(Property property :eachPluginStoredProperties)
{
{
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
property.setRawValue(property.getDefaultRawValue());
property.setRawValue(property.getDefaultRawValue());
}
}
}
}
if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
ArrayList<ExternalPlugin> actions = new ArrayList<>();
sortedPlugins.put(eachPlugin.getCategory(), new ArrayList<>());
sortedPlugins.put(eachPlugin.getCategory(), actions);
}
}
sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
errorModules.add(eachPlugin);
errorModules.add(eachPlugin);
errorModuleError.add(e.getMessage());
errorModuleError.add(e.getMessage());
}
}
}
}
try {
try {
saveServerSettings();
saveServerSettings();
} catch (MinorException e) {
} catch (MinorException e) {
e.printStackTrace();
e.printStackTrace();
}
}
logger.log(Level.INFO, "All plugins registered!");
logger.log(Level.INFO, "All plugins registered!");
if(errorModules.size() > 0)
if(errorModules.size() > 0)
{
{
StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
for(int i = 0; i<errorModules.size(); i++)
for(int i = 0; i<errorModules.size(); i++)
{
{
externalPlugins.remove(errorModules.get(i));
externalPlugins.remove(errorModules.get(i));
errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
.append(errorModuleError.get(i)).append(")");
.append(errorModuleError.get(i)).append(")");
}
}
throw new MinorException("Plugins", errors.toString());
throw new MinorException("Plugins", errors.toString());
}
}
for(int i=0; i<externalPlugins.size(); i++)
for(int i = 0;i<externalPlugins.size();i++)
{
{
externalPluginsHashmap.put(externalPlugins.get(i).getModuleName(), i);
externalPluginsHashmap.put(externalPlugins.get(i).getModuleName(), i);
}
}
}
}
/**
/**
* Used to init plugins
* Used to init plugins
*/
*/
public void initPlugins() throws MinorException
public void initPlugins() throws MinorException
{
{
StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
boolean isError = false;
boolean isError = false;
for(ExternalPlugin eachPlugin : externalPlugins)
for(ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.initAction();
eachPlugin.initAction();
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
isError = true;
isError = true;
errors.append("\n* ")
errors.append("\n* ")
.append(eachPlugin.getName())
.append(eachPlugin.getName())
.append(" - ")
.append(" - ")
.append(eachPlugin.getModuleName())
.append(eachPlugin.getModuleName())
.append("\n");
.append("\n");
if(e instanceof StreamPiException)
if(e instanceof StreamPiException)
errors.append(((MinorException) e).getShortMessage());
errors.append(((MinorException) e).getShortMessage());
errors.append("\n");
errors.append("\n");
}
}
}
}
if(isError)
if(isError)
{
{
throw new MinorException("Plugin init error", errors.toString());
throw new MinorException("Plugin init error", errors.toString());
}
}
}
}
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins;
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins;
/**
/**
* Gets list of sorted plugins
* Gets list of sorted plugins
*
*
* @return Hashmap with category key, and list of plugins of each category
* @return Hashmap with category key, and list of plugins of each category
*/
*/
public HashMap<String, ArrayList<ExternalPlugin>> getSortedPlugins()
public HashMap<String, ArrayList<ExternalPlugin>> getSortedPlugins()
{
{
return sortedPlugins;
return sortedPlugins;
}
}
/**
/**
* @return Gets actions element from the config.xml in plugins folder
* @return Gets actions element from the config.xml in plugins folder
*/
*/
private Element getActionsElement()
private Element getActionsElement()
{
{
return (Element) document.getElementsByTagName("actions").item(0);
return (Element) document.getElementsByTagName("actions").item(0);
}
}
/**
/**
* Saves ServerProperties of every plugin in config.xml in plugins folder
* Saves ServerProperties of every plugin in config.xml in plugins folder
*
*
* @throws MinorException Thrown when failed to save settings
* @throws MinorException Thrown when failed to save settings
*/
*/
public void saveServerSettings() throws MinorException
public void saveServerSettings() throws MinorException
{
{
XMLConfigHelper.removeChilds(getActionsElement());
XMLConfigHelper.removeChilds(getActionsElement());
for(ExternalPlugin externalPlugin : externalPlugins)
for(ExternalPlugin externalPlugin : externalPlugins)
{
{
Element actionElement = document.createElement("action");
Element actionElement = document.createElement("action");
getActionsElement().appendChild(actionElement);
getActionsElement().appendChild(actionElement);
Element moduleNameElement = document.createElement("module-name");
Element moduleNameElement = document.createElement("module-name");
moduleNameElement.setTextContent(externalPlugin.getModuleName());
moduleNameElement.setTextContent(externalPlugin.getModuleName());
actionElement.appendChild(moduleNameElement);
actionElement.appendChild(moduleNameElement);
Element versionElement = document.createElement("version");
Element versionElement = document.createElement("version");
versionElement.setTextContent(externalPlugin.getVersion().getText());
versionElement.setTextContent(externalPlugin.getVersion().getText());
actionElement.appendChild(versionElement);
actionElement.appendChild(versionElement);
Element actionTypeElement = document.createElement("type");
Element actionTypeElement = document.createElement("type");
actionTypeElement.setTextContent(externalPlugin.getActionType().toString());
actionTypeElement.setTextContent(externalPlugin.getActionType().toString());
actionElement.appendChild(actionTypeElement);
actionElement.appendChild(actionTypeElement);
Element propertiesElement = document.createElement("properties");
Element propertiesElement = document.createElement("properties");
actionElement.appendChild(propertiesElement);
actionElement.appendChild(propertiesElement);
for(String key : externalPlugin.getServerProperties().getNames())
for(String key : externalPlugin.getServerProperties().getNames())
{
{
for(Property eachProperty : externalPlugin.getServerProperties().getMultipleProperties(key))
for(Property eachProperty : externalPlugin.getServerProperties().getMultipleProperties(key))
{
{
Element propertyElement = document.createElement("property");
Element propertyElement = document.createElement("property");
propertiesElement.appendChild(propertyElement);
propertiesElement.appendChild(propertyElement);
Element nameElement = document.createElement("name");
Element nameElement = document.createElement("name");
nameElement.setTextContent(eachProperty.getName());
nameElement.setTextContent(eachProperty.getName());
propertyElement.appendChild(nameElement);
propertyElement.appendChild(nameElement);
Element valueElement = document.createElement("value");
Element valueElement = document.createElement("value");
valueElement.setTextContent(eachProperty.getRawValue());
valueElement.setTextContent(eachProperty.getRawValue());
propertyElement.appendChild(valueElement);
propertyElement.appendChild(valueElement);
}
}
}
}
}
}
save();
save();
}
}
private PropertySaver propertySaver = null;
private PropertySaver propertySaver = null;
/**
/**
* Set PropertySaver class
* Set PropertySaver class
* @param propertySaver instance of PropertySaver
* @param propertySaver instance of PropertySaver
*/
*/
public void setPropertySaver(PropertySaver propertySaver)
public void setPropertySaver(PropertySaver propertySaver)
{
{
this.propertySaver = propertySaver;
this.propertySaver = propertySaver;
}
}
private ServerConnection serverConnection = null;
private ServerConnection serverConnection = null;
/**
/**
* Set setServerConnection class
* Set setServerConnection class
* @param serverConnection instance of ServerConnection
* @param serverConnection instance of ServerConnection
*/
*/
public void setServerConnection(ServerConnection serverConnection)
public void setServerConnection(ServerConnection serverConnection)
{
{
this.serverConnection = serverConnection;
this.serverConnection = serverConnection;
}
}
/**
/**
* Get plugin from index from list
* Get plugin from index from list
*
*
* @param index of plugin
* @param index of plugin
* @return found plugin
* @return found plugin
*/
*/
public ExternalPlugin getActionFromIndex(int index)
public ExternalPlugin getActionFromIndex(int index)
{
{
return externalPlugins.get(index);
return externalPlugins.get(index);
}
}
/**
/**
* Calls onShutDown method in every plugin
* Calls onShutDown method in every plugin
*/
*/
public void shutDownActions()
public void shutDownActions()
{
{
if(externalPlugins != null)
if(externalPlugins != null)
{
{
for(ExternalPlugin eachPlugin : externalPlugins)
for(ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.onShutDown();
eachPlugin.onShutDown();
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
}
}
externalPlugins.clear();
externalPlugins.clear();
}
}
}
}
/**
/**
* Saves all Server Properties of each Plugin in config.xml in Plugins folder
* Saves all Server Properties of each Plugin in config.xml in Plugins folder
* @throws MinorException thrown when failed to save
* @throws MinorException thrown when failed to save
*/
*/
public void save() throws MinorException
public void save() throws MinorException
{
{
try
try
{
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(configFile);
Result output = new StreamResult(configFile);
Source input = new DOMSource(document);
Source input = new DOMSource(document);
transformer.transform(input, output);
transformer.transform(input, output);
}
}
catch (Exception e)
catch (Exception e)
{
{
throw new MinorException("Config", "unable to save server plugins settings");
throw new MinorException("Config", "unable to save server plugins settings");
}
}
}
}
}
}
package com.stream_pi.server.connection;
package com.stream_pi.server.connection;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.dashboard.ClientAndProfileSelectorPane;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import javafx.application.Platform;
import javafx.application.Platform;
import javafx.stage.Stage;
import java.io.IOException;
import java.io.IOException;
import java.net.*;
import java.net.*;
import java.util.Enumeration;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import java.util.logging.Logger;
public class MainServer extends Thread{
public class MainServer extends Thread {
private ServerListener serverListener;
private ServerListener serverListener;
private Logger logger = Logger.getLogger(MainServer.class.getName());
private Logger logger = Logger.getLogger(MainServer.class.getName());
private int port;
private int port;
private ServerSocket serverSocket = null;
private ServerSocket serverSocket = null;
//private Server server;
//private Server server;
private AtomicBoolean stop = new AtomicBoolean(false);
private AtomicBoolean stop = new AtomicBoolean(false);
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
public MainServer(ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
public MainServer(ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
{
{
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.serverListener = serverListener;
this.serverListener = serverListener;
}
}
public void setPort(int port) {
public void setPort(int port) {
this.port = port;
this.port = port;
}
}
@Override
@Override
public synchronized void start() {
public synchronized void start() {
stop.set(false);
stop.set(false);
super.start();
super.start();
}
}
public void stopListeningForConnections()
public void stopListeningForConnections()
{
{
/*if(server !=null)
/*if(server !=null)
{
{
if(!server.isShutdown())
if(!server.isShutdown())
server.shutdown();
server.shutdown();
}*/
}*/
try
try
{
{
logger.info("Stopping listening for connections ...");
logger.info("Stopping listening for connections ...");
if(serverSocket!=null)
if(serverSocket!=null)
if(!serverSocket.isClosed())
if(!serverSocket.isClosed())
{
{
stop.set(true);
stop.set(true);
serverSocket.close();
serverSocket.close();
}
}
} catch (IOException e) {
} catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
}
}
finally {
finally {
logger.info("... Done!");
logger.info("... Done!");
}
}
}
}
@Override
@Override
public void run() {
public void run() {
logger.warning("Starting main server on port "+port+" ...");
logger.warning("Starting main server on port "+port+" ...");
try {
try {
logger.info("Starting server on port "+port+" ...");
logger.info("Starting server on port "+port+" ...");
serverSocket = new ServerSocket(port);
serverSocket = new ServerSocket(port);
setupStageTitle(true);
setupStageTitle(true);
while(!stop.get())
while(!stop.get())
{
{
Socket s = serverSocket.accept();
Socket s = serverSocket.accept();
ClientConnections.getInstance().addConnection(new ClientConnection(s, serverListener, exceptionAndAlertHandler));
ClientConnections.getInstance().addConnection(new ClientConnection(s, serverListener, exceptionAndAlertHandler));
logger.info("New client connected ("+s.getRemoteSocketAddress()+") !");
logger.info("New client connected ("+s.getRemoteSocketAddress()+") !");
}
}
}
}
catch (SocketException e)
catch (SocketException e)
{
{
if(!e.getMessage().contains("Socket closed") && !e.getMessage().contains("Interrupted function call: accept failed"))
if(!e.getMessage().contains("Socket closed") && !e.getMessage().contains("Interrupted function call: accept failed"))
{
{
logger.info("Main Server stopped accepting calls ...");
logger.info("Main Server stopped accepting calls ...");
setupStageTitle(false);
setupStageTitle(false);
exceptionAndAlertHandler.handleMinorException(new MinorException("Sorry!","Server could not be started at "+port+".\n" +
exceptionAndAlertHandler.handleMinorException(new MinorException("Sorry!","Server could not be started at "+port+".\n" +
"This could be due to another process or another instance of Stream-Pi Server using the same port. \n\n" +
"This could be due to another process or another instance of Stream-Pi Server using the same port. \n\n" +
"If another Server Instance probably running, close it. If not, try changing the port in settings and restart Stream-Pi Server." +
"If another Server Instance probably running, close it. If not, try changing the port in settings and restart Stream-Pi Server." +
"If the problem still persists, consider contacting us. \n\nFull Message : "+e.getMessage()));
"If the problem still persists, consider contacting us. \n\nFull Message : "+e.getMessage()));
e.printStackTrace();
e.printStackTrace();
}
}
}
}
catch (IOException e)
catch (IOException e)
{
{
exceptionAndAlertHandler.handleSevereException(new SevereException("MainServer io Exception occurred!"));
exceptionAndAlertHandler.handleSevereException(new SevereException("MainServer io Exception occurred!"));
e.printStackTrace();
e.printStackTrace();
}
}
}
}
private void setupStageTitle(boolean isSuccess)
private void setupStageTitle(boolean isSuccess)
{
{
try
try
{
{
if(isSuccess)
if(isSuccess)
{
{
StringBuilder ips = new StringBuilder();
StringBuilder ips = new StringBuilder();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements())
while(e.hasMoreElements())
{
{
NetworkInterface n = e.nextElement();
NetworkInterface n = e.nextElement();
Enumeration<InetAddress> ee = n.getInetAddresses();
Enumeration<InetAddress> ee = n.getInetAddresses();
while (ee.hasMoreElements())
while (ee.hasMoreElements())
{
{
InetAddress i = ee.nextElement();
InetAddress i = ee.nextElement();
String hostAddress = i.getHostAddress();
String hostAddress = i.getHostAddress();
if(i instanceof Inet4Address)
if(i instanceof Inet4Address)
{
{
ips.append(hostAddress);
ips.append(hostAddress);
if(e.hasMoreElements())
if(e.hasMoreElements())
ips.append(" / ");
ips.append(" / ");
}
}
}
}
}
}
Platform.runLater(()-> serverListener.getStage().setTitle("Stream-Pi Server - IP(s): "+ips.toString()+" | Port: "+ port));
Platform.runLater(()-> serverListener.getStage().setTitle("Stream-Pi Server - IP(s): "+ips.toString()+" | Port: "+ port));
}
}
else
else
{
{
Platform.runLater(()-> serverListener.getStage().setTitle("Stream-Pi Server - Offline"));
Platform.runLater(()-> serverListener.getStage().setTitle("Stream-Pi Server - Offline"));
}
}
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleMinorException(new MinorException("Error",e.getMessage()));
exceptionAndAlertHandler.handleMinorException(new MinorException("Error",e.getMessage()));
}
}
}
}
}
}
package com.stream_pi.server.controller;
package com.stream_pi.server.controller;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.externalplugin.NormalAction;
import com.stream_pi.action_api.externalplugin.NormalAction;
import com.stream_pi.action_api.externalplugin.ToggleAction;
import com.stream_pi.action_api.externalplugin.ToggleAction;
import com.stream_pi.server.Main;
import com.stream_pi.server.Main;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.connection.ClientConnection;
import com.stream_pi.server.connection.ClientConnection;
import com.stream_pi.server.connection.ClientConnections;
import com.stream_pi.server.connection.ClientConnections;
import com.stream_pi.server.connection.MainServer;
import com.stream_pi.server.connection.MainServer;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.window.Base;
import com.stream_pi.server.window.Base;
import com.stream_pi.server.window.dashboard.ClientAndProfileSelectorPane;
import com.stream_pi.server.window.dashboard.DashboardBase;
import com.stream_pi.server.window.dashboard.DashboardBase;
import com.stream_pi.server.window.dashboard.DonatePopupContent;
import com.stream_pi.server.window.dashboard.DonatePopupContent;
import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
import com.stream_pi.server.window.firsttimeuse.FirstTimeUse;
import com.stream_pi.server.window.firsttimeuse.FirstTimeUse;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlertListener;
import com.stream_pi.util.alert.StreamPiAlertListener;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.concurrent.Task;
import javafx.scene.Node;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.stage.WindowEvent;
import java.awt.SystemTray;
import javafx.util.Duration;
import javafx.util.Duration;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.TrayIcon;
import java.awt.PopupMenu;
import java.awt.MenuItem;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketAddress;
import java.util.Enumeration;
import java.util.Random;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Level;
public class Controller extends Base implements PropertySaver, ServerConnection
public class Controller extends Base implements PropertySaver, ServerConnection
{
{
MainServer mainServer;
private ExecutorService executor = Executors.newCachedThreadPool();
private MainServer mainServer;
private Animation openSettingsAnimation;
private Animation closeSettingsAnimation;
public Controller(){
mainServer = null;
}
public void setupDashWindow() throws SevereException
public void setupDashWindow() throws SevereException
{
{
try
try
{
{
getStage().setOnCloseRequest(this::onCloseRequest);
getStage().setOnCloseRequest(this::onCloseRequest);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException(e.getMessage());
throw new SevereException(e.getMessage());
}
}
}
}
@Override
@Override
public void init()
public void init()
{
{
try {
try {
initBase();
initBase();
setupDashWindow();
setupDashWindow();
setupSettingsWindowsAnimations();
setupSettingsWindowsAnimations();
ExternalPlugins.getInstance().setPropertySaver(this);
ExternalPlugins.getInstance().setPropertySaver(this);
ExternalPlugins.getInstance().setServerConnection(this);
ExternalPlugins.getInstance().setServerConnection(this);
getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
openSettingsTimeLine.play();
openSettingsAnimation.play();
});
});
getSettingsPane().getCloseButton().setOnAction(event -> {
getSettingsPane().getCloseButton().setOnAction(event -> {
closeSettingsTimeLine.play();
closeSettingsAnimation.play();
});
});
getSettingsPane().getThemesSettings().setController(this);
getSettingsPane().getThemesSettings().setController(this);
mainServer = new MainServer(this, this);
mainServer = new MainServer(this, this);
if(getConfig().isFirstTimeUse())
if(getConfig().isFirstTimeUse())
{
{
Stage stage = new Stage();
Stage stage = new Stage();
Scene s = new Scene(new FirstTimeUse(this, this),
Scene s = new Scene(new FirstTimeUse(this, this),
getConfig().getStartupWindowWidth(), getConfig().getStartupWindowHeight());
getConfig().getStartupWindowWidth(), getConfig().getStartupWindowHeight());
stage.setResizable(false);
stage.setResizable(false);
stage.setScene(s);
stage.setScene(s);
stage.setTitle("Stream-Pi Server Setup");
stage.setTitle("Stream-Pi Server Setup");
stage.initModality(Modality.APPLICATION_MODAL);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setOnCloseRequest(event->Platform.exit());
stage.setOnCloseRequest(event->Platform.exit());
stage.show();
stage.show();
}
}
else
else
{
{
if(getConfig().isAllowDonatePopup())
if(getConfig().isAllowDonatePopup())
{
{
if(new Random().nextInt(5) == 3)
if(new Random().nextInt(5) == 3)
new DonatePopupContent(getHostServices(), this).show();
new DonatePopupContent(getHostServices(), this).show();
}
}
othInit();
othInit();
}
}
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
}
}
@Override
@Override
public void othInit()
public void othInit()
{
{
try
try
{
{
if(ServerInfo.getInstance().isStartMinimised() && SystemTray.isSupported())
if(ServerInfo.getInstance().isStartMinimised() && SystemTray.isSupported())
minimiseApp();
minimiseApp();
else
else
getStage().show();
getStage().show();
}
}
catch(MinorException e)
catch(MinorException e)
{
{
handleMinorException(e);
handleMinorException(e);
}
}
new Thread(new Task<Void>() {
executor.execute(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
try
try
{
{
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
//themes
//themes
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().getThemesSettings().loadThemes();
//clients
//clients
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getClientsSettings().loadData();
try
try
{
{
//Plugins
//Plugins
Platform.runLater(()->{
Platform.runLater(()->{
getDashboardPane().getPluginsPane().clearData();
getDashboardPane().getPluginsPane().clearData();
getDashboardPane().getPluginsPane().loadOtherActions();
getDashboardPane().getPluginsPane().loadOtherActions();
});
});
ExternalPlugins.setPluginsLocation(getConfig().getPluginsPath());
ExternalPlugins.setPluginsLocation(getConfig().getPluginsPath());
ExternalPlugins.getInstance().init();
ExternalPlugins.getInstance().init();
Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getPluginsSettings().loadPlugins();
}
}
catch (MinorException e)
catch (MinorException e)
{
{
getSettingsPane().getPluginsSettings().showPluginInitError();
getSettingsPane().getPluginsSettings().showPluginInitError();
handleMinorException(e);
handleMinorException(e);
}
}
//Server
//Server
mainServer.setPort(getConfig().getPort());
mainServer.setPort(getConfig().getPort());
mainServer.start();
mainServer.start();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
return null;
return null;
}
}
}).start();
});
}
}
@Override
@Override
public DashboardBase getDashboardBase() {
public DashboardBase getDashboardBase() {
return getDashboardPane();
return getDashboardPane();
}
}
private void setupSettingsWindowsAnimations()
private void setupSettingsWindowsAnimations()
{
{
Node settingsNode = getSettingsPane();
Node settingsNode = getSettingsPane();
Node dashboardNode = getDashboardPane();
Node dashboardNode = getDashboardPane();
openSettingsTimeLine = new Timeline();
openSettingsAnimation = createOpenSettingsAnimation(settingsNode, dashboardNode);
openSettingsTimeLine.setCycleCount(1);
closeSettingsAnimation = createCloseSettingsAnimation(settingsNode, dashboardNode);
openSettingsTimeLine.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.EASE_IN)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR))
);
openSettingsTimeLine.setOnFinished(event1 -> {
settingsNode.toFront();
});
closeSettingsTimeLine = new Timeline();
closeSettingsTimeLine.setCycleCount(1);
closeSettingsTimeLine.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR))
);
closeSettingsTimeLine.setOnFinished(event1 -> {
dashboardNode.toFront();
new Thread(new Task<Void>() {
@Override
protected Void call() {
try {
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().setDefaultTabToGeneral();
}
catch (SevereException e)
{
handleSevereException(e);
}
catch (MinorException e)
{
handleMinorException(e);
}
return null;
}
}).start();
});
}
private Timeline openSettingsTimeLine;
private Timeline closeSettingsTimeLine;
public Controller(){
mainServer = null;
}
}
public void onCloseRequest(WindowEvent event)
public void onCloseRequest(WindowEvent event)
{
{
try
try
{
{
if(Config.getInstance().getMinimiseToSystemTrayOnClose() &&
if(Config.getInstance().getMinimiseToSystemTrayOnClose() &&
SystemTray.isSupported())
SystemTray.isSupported())
{
{
minimiseApp();
minimiseApp();
event.consume();
event.consume();
return;
return;
}
}
getConfig().setStartupWindowSize(
getConfig().setStartupWindowSize(getWidth(), getHeight());
getWidth(),
getHeight()
);
getConfig().save();
getConfig().save();
onQuitApp();
onQuitApp();
ExternalPlugins.getInstance().shutDownActions();
ExternalPlugins.getInstance().shutDownActions();
Platform.exit();
Platform.exit();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
catch (MinorException e)
catch (MinorException e)
{
{
handleMinorException(e);
handleMinorException(e);
}
}
finally
finally
{
{
closeLogger();
closeLogger();
}
}
}
}
public void onQuitApp()
public void onQuitApp()
{
{
if(mainServer!=null)
if(mainServer!=null)
mainServer.stopListeningForConnections();
mainServer.stopListeningForConnections();
ClientConnections.getInstance().disconnectAll();
ClientConnections.getInstance().disconnectAll();
executor.shutdown();
getLogger().info("Shutting down ...");
getLogger().info("Shutting down ...");
}
}
public void minimiseApp() throws MinorException
public void minimiseApp() throws MinorException
{
{
try
try
{
{
SystemTray systemTray = SystemTray.getSystemTray();
SystemTray systemTray = SystemTray.getSystemTray();
if(getTrayIcon() == null)
if(getTrayIcon() == null)
initIconTray(systemTray);
initIconTray(systemTray);
systemTray.add(getTrayIcon());
systemTray.add(getTrayIcon());
getStage().hide();
getStage().hide();
getStage().setOnShown(windowEvent -> {
getStage().setOnShown(windowEvent -> {
systemTray.remove(getTrayIcon());
systemTray.remove(getTrayIcon());
});
});
}
}
catch(Exception e)
catch(Exception e)
{
{
throw new MinorException(e.getMessage());
throw new MinorException(e.getMessage());
}
}
}
}
public void initIconTray(SystemTray systemTray)
public void initIconTray(SystemTray systemTray)
{
{
Platform.setImplicitExit(false);
Platform.setImplicitExit(false);
PopupMenu popup = new PopupMenu();
PopupMenu popup = new PopupMenu();
MenuItem exitItem = new MenuItem("Exit");
MenuItem exitItem = new MenuItem("Exit");
exitItem.addActionListener(l->{
exitItem.addActionListener(l->{
systemTray.remove(getTrayIcon());
systemTray.remove(getTrayIcon());
onQuitApp();
onQuitApp();
Platform.exit();
Platform.exit();
});
});
popup.add(exitItem);
popup.add(exitItem);
TrayIcon trayIcon = new TrayIcon(
TrayIcon trayIcon = new TrayIcon(
Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
Toolkit.getDefaultToolkit().getImage(Main.class.getResource("app_icon.png")),
"Stream-Pi Server",
"Stream-Pi Server",
popup
popup
);
);
trayIcon.addActionListener(l-> Platform.runLater(()-> getStage().show()));
trayIcon.addActionListener(l-> Platform.runLater(()-> getStage().show()));
trayIcon.setImageAutoSize(true);
trayIcon.setImageAutoSize(true);
this.trayIcon = trayIcon;
this.trayIcon = trayIcon;
}
}
private TrayIcon trayIcon = null;
private TrayIcon trayIcon = null;
public TrayIcon getTrayIcon()
public TrayIcon getTrayIcon()
{
{
return trayIcon;
return trayIcon;
}
}
@Override
@Override
public void handleMinorException(MinorException e)
public void handleMinorException(MinorException e)
{
{
getLogger().log(Level.SEVERE, e.getMessage(), e);
getLogger().log(Level.SEVERE, e.getMessage(), e);
e.printStackTrace();
e.printStackTrace();
Platform.runLater(()-> new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show());
Platform.runLater(()-> new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.WARNING).show());
}
}
@Override
@Override
public void handleSevereException(SevereException e) {
public void handleSevereException(SevereException e) {
getLogger().log(Level.SEVERE, e.getMessage(), e);
getLogger().log(Level.SEVERE, e.getMessage(), e);
e.printStackTrace();
e.printStackTrace();
Platform.runLater(()->{
Platform.runLater(()->{
StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
StreamPiAlert alert = new StreamPiAlert(e.getTitle(), e.getShortMessage(), StreamPiAlertType.ERROR);
alert.setOnClicked(new StreamPiAlertListener()
alert.setOnClicked(new StreamPiAlertListener()
{
{
@Override
@Override
public void onClick(String txt)
public void onClick(String txt)
{
{
onQuitApp();
onQuitApp();
Platform.exit();
Platform.exit();
}
}
});
});
alert.show();
alert.show();
});
});
}
}
@Override
@Override
public synchronized boolean onNormalActionClicked(NormalAction action, String profileID) {
public synchronized boolean onNormalActionClicked(NormalAction action, String profileID) {
try{
try{
getLogger().info("action "+action.getID()+" clicked!");
getLogger().info("action "+action.getID()+" clicked!");
action.onActionClicked();
action.onActionClicked();
ActionBox actionBox = getDashboardBase().getActionGridPane().getActionBoxByIDAndProfileID(
ActionBox actionBox = getDashboardBase().getActionGridPane().getActionBoxByIDAndProfileID(
action.getID(),
action.getID(),
profileID
profileID
);
);
if(actionBox != null)
if(actionBox != null)
{
{
Platform.runLater(actionBox::init);
Platform.runLater(actionBox::init);
}
}
return true;
return true;
}
}
catch (Exception e)
catch (Exception e)
{
{
//check if its windows UAC related
//check if its windows UAC related
if(e.getMessage().contains("operation requires elevation"))
if(e.getMessage().contains("operation requires elevation"))
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
);
);
}
}
else
else
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
);
);
}
}
return false;
return false;
}
}
}
}
@Override
@Override
public boolean onToggleActionClicked(ToggleAction action, boolean toggle, String profileID)
public boolean onToggleActionClicked(ToggleAction action, boolean toggle, String profileID)
{
{
try{
try{
getLogger().info("action "+action.getID()+" clicked!");
getLogger().info("action "+action.getID()+" clicked!");
if(toggle)
if(toggle)
{
{
action.onToggleOn();
action.onToggleOn();
}
}
else
else
{
{
action.onToggleOff();
action.onToggleOff();
}
}
// ActionBox actionBox = getDashboardBase().getActionGridPane().getActionBoxByIDAndProfileID(
// ActionBox actionBox = getDashboardBase().getActionGridPane().getActionBoxByIDAndProfileID(
// action.getID(),
// action.getID(),
// profileID
// profileID
// );
// );
//
//
// if(actionBox != null)
// if(actionBox != null)
// {
// {
// Platform.runLater(()->actionBox.init(toggle));
// Platform.runLater(()->actionBox.init(toggle));
// }
// }
return true;
return true;
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
//check if its windows UAC related
//check if its windows UAC related
if(e.getMessage().contains("operation requires elevation"))
if(e.getMessage().contains("operation requires elevation"))
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
"This action requires higher UAC privileges. Re-launch Stream-Pi Server with 'Administrator Privileges' in order to run this command.")
);
);
}
}
else
else
{
{
handleMinorException(new MinorException(
handleMinorException(new MinorException(
"Action Execution Failed!",
"Action Execution Failed!",
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Error running action at ["+action.getLocation().getRow()+","+action.getLocation().getCol()+"] ("+action.getDisplayText()+")\n"+
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
"Check stacktrace/log to know what exactly happened\n\nMessage : \n"+e.getMessage() )
);
);
}
}
return false;
return false;
}
}
}
}
@Override
@Override
public void clearTemp() {
public void clearTemp() {
Platform.runLater(() -> {
Platform.runLater(() -> {
getDashboardPane().getClientAndProfileSelectorPane().refresh();
getDashboardPane().getClientAndProfileSelectorPane().refresh();
getDashboardPane().getActionGridPane().clear();
getDashboardPane().getActionGridPane().clear();
getDashboardPane().getActionGridPane().setFreshRender(true);
getDashboardPane().getActionGridPane().setFreshRender(true);
getDashboardPane().getActionDetailsPane().clear();
getDashboardPane().getActionDetailsPane().clear();
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getClientsSettings().loadData();
});
});
}
}
@Override
@Override
public void saveServerProperties()
public void saveServerProperties()
{
{
try
try
{
{
ExternalPlugins.getInstance().saveServerSettings();
ExternalPlugins.getInstance().saveServerSettings();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getPluginsSettings().loadPlugins();
} catch (MinorException e) {
} catch (MinorException e) {
e.printStackTrace();
e.printStackTrace();
handleMinorException(e);
handleMinorException(e);
}
}
}
}
private void saveClientActionMain(String profileID, String actionID, SocketAddress socketAddress, boolean sendIcons)
private void saveClientActionMain(String profileID, String actionID, SocketAddress socketAddress, boolean sendIcons)
{
{
try {
try {
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
Action action = clientProfile.getActionByID(actionID);
Action action = clientProfile.getActionByID(actionID);
clientConnection.saveActionDetails(profileID, action);
clientConnection.saveActionDetails(profileID, action);
if(sendIcons && action.isHasIcon())
if(sendIcons && action.isHasIcon())
{
{
saveAllIcons(profileID, actionID, socketAddress, false);
saveAllIcons(profileID, actionID, socketAddress, false);
}
}
Platform.runLater(()->{
Platform.runLater(()->{
try {
try {
// if(getDashboardPane().getActionGridPane().getCurrentParent().equals(action.getParent()) &&
// if(getDashboardPane().getActionGridPane().getCurrentParent().equals(action.getParent()) &&
// getDashboardPane().getClientAndProfileSelectorPane().getCurrentSelectedClientProfile().getID().equals(profileID) &&
// getDashboardPane().getClientAndProfileSelectorPane().getCurrentSelectedClientProfile().getID().equals(profileID) &&
// getDashboardPane().getClientAndProfileSelectorPane().getCurrentSelectedClientConnection().getRemoteSocketAddress().equals(socketAddress))
// getDashboardPane().getClientAndProfileSelectorPane().getCurrentSelectedClientConnection().getRemoteSocketAddress().equals(socketAddress))
// {
// {
// getDashboardPane().getActionGridPane().renderAction(action);
// getDashboardPane().getActionGridPane().renderAction(action);
// }
// }
if(getDashboardBase().getActionDetailsPane().getAction() != null)
if(getDashboardBase().getActionDetailsPane().getAction() != null)
{
{
// This block is executed when no Action is selected.
// This block is executed when no Action is selected.
if(getDashboardPane().getActionDetailsPane().getAction().getID().equals(actionID))
if(getDashboardPane().getActionDetailsPane().getAction().getID().equals(actionID))
{
{
getDashboardPane().getActionDetailsPane().setAction(action);
getDashboardPane().getActionDetailsPane().setAction(action);
getDashboardPane().getActionDetailsPane().refresh();
getDashboardPane().getActionDetailsPane().refresh();
}
}
}
}
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
});
});
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
}
}
@Override
@Override
public void saveClientAction(String profileID, String actionID, SocketAddress socketAddress, boolean sendIcons, boolean runAsync)
public void saveClientAction(String profileID, String actionID, SocketAddress socketAddress, boolean sendIcons, boolean runAsync)
{
{
if(runAsync)
if(runAsync)
{
{
new Thread(new Task<Void>() {
executor.execute(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
saveClientActionMain(profileID, actionID, socketAddress, sendIcons);
saveClientActionMain(profileID, actionID, socketAddress, sendIcons);
return null;
return null;
}
}
}).start();
});
}
}
else
else
{
{
saveClientActionMain(profileID, actionID, socketAddress, sendIcons);
saveClientActionMain(profileID, actionID, socketAddress, sendIcons);
}
}
}
}
@Override
@Override
public void saveAllIcons(String profileID, String actionID, SocketAddress socketAddress)
public void saveAllIcons(String profileID, String actionID, SocketAddress socketAddress)
{
{
saveAllIcons(profileID, actionID, socketAddress, true);
saveAllIcons(profileID, actionID, socketAddress, true);
}
}
public void saveAllIcons(String profileID, String actionID, SocketAddress socketAddress, boolean async)
public void saveAllIcons(String profileID, String actionID, SocketAddress socketAddress, boolean async)
{
{
if(async)
if(async)
{
{
new Thread(new Task<Void>() {
executor.execute(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
saveAllIconsMain(profileID, actionID, socketAddress);
saveAllIconsMain(profileID, actionID, socketAddress);
return null;
return null;
}
}
}).start();
});
}
}
else
else
{
{
saveAllIconsMain(profileID, actionID, socketAddress);
saveAllIconsMain(profileID, actionID, socketAddress);
}
}
}
}
private void saveAllIconsMain(String profileID, String actionID, SocketAddress socketAddress)
private void saveAllIconsMain(String profileID, String actionID, SocketAddress socketAddress)
{
{
try {
try {
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
Action action = clientProfile.getActionByID(actionID);
Action action = clientProfile.getActionByID(actionID);
for(String eachState : action.getIcons().keySet())
for(String eachState : action.getIcons().keySet())
{
{
clientConnection.sendIcon(profileID, actionID, eachState,
clientConnection.sendIcon(profileID, actionID, eachState,
action.getIcon(eachState));
action.getIcon(eachState));
}
}
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
}
}
@Override
@Override
public void saveIcon(String state, String profileID, String actionID, SocketAddress socketAddress) {
public void saveIcon(String state, String profileID, String actionID, SocketAddress socketAddress) {
new Thread(new Task<Void>() {
executor.execute(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
try {
try {
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientConnection clientConnection = ClientConnections.getInstance().getClientConnectionBySocketAddress(socketAddress);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
ClientProfile clientProfile = clientConnection.getClient().getProfileByID(profileID);
Action action = clientProfile.getActionByID(actionID);
Action action = clientProfile.getActionByID(actionID);
clientConnection.sendIcon(profileID, actionID, state, action.getIcon(state));
clientConnection.sendIcon(profileID, actionID, state, action.getIcon(state));
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
return null;
return null;
}
}
}).start();
});
}
}
@Override
@Override
public com.stream_pi.util.platform.Platform getPlatform() {
public com.stream_pi.util.platform.Platform getPlatform() {
return ServerInfo.getInstance().getPlatform();
return ServerInfo.getInstance().getPlatform();
}
}
private Animation createOpenSettingsAnimation(Node settingsNode, Node dashboardNode) {
Timeline openSettingsTimeline = new Timeline();
openSettingsTimeline.setCycleCount(1);
openSettingsTimeline.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.EASE_IN),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.EASE_IN)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR))
);
openSettingsTimeline.setOnFinished(e -> settingsNode.toFront());
return openSettingsTimeline;
}
private Animation createCloseSettingsAnimation(Node settingsNode, Node dashboardNode) {
Timeline closeSettingsTimeline = new Timeline();
closeSettingsTimeline.setCycleCount(1);
closeSettingsTimeline.getKeyFrames().addAll(
new KeyFrame(Duration.millis(0.0D),
new KeyValue(settingsNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.0D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(settingsNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleXProperty(),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleYProperty(),
1.1D, Interpolator.LINEAR),
new KeyValue(settingsNode.scaleZProperty(),
1.1D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(0.0D),
new KeyValue(dashboardNode.opacityProperty(),
0.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
0.9D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
0.9D, Interpolator.LINEAR)),
new KeyFrame(Duration.millis(90.0D),
new KeyValue(dashboardNode.opacityProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleXProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleYProperty(),
1.0D, Interpolator.LINEAR),
new KeyValue(dashboardNode.scaleZProperty(),
1.0D, Interpolator.LINEAR))
);
closeSettingsTimeline.setOnFinished(event1 -> {
dashboardNode.toFront();
executor.execute(new Task<Void>() {
@Override
protected Void call() {
try {
getSettingsPane().getClientsSettings().loadData();
getSettingsPane().getGeneralSettings().loadDataFromConfig();
getSettingsPane().getPluginsSettings().loadPlugins();
getSettingsPane().getThemesSettings().setThemes(getThemes());
getSettingsPane().getThemesSettings().setCurrentThemeFullName(getCurrentTheme().getFullName());
getSettingsPane().getThemesSettings().loadThemes();
getSettingsPane().setDefaultTabToGeneral();
}
catch (SevereException e)
{
handleSevereException(e);
}
catch (MinorException e)
{
handleMinorException(e);
}
return null;
}
});
});
return closeSettingsTimeline;
}
}
}
package com.stream_pi.server.window;
package com.stream_pi.server.window;
import com.stream_pi.server.connection.ServerListener;
import com.stream_pi.server.connection.ServerListener;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.io.Config;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.Main;
import com.stream_pi.server.Main;
import com.stream_pi.server.window.dashboard.DashboardBase;
import com.stream_pi.server.window.dashboard.DashboardBase;
import com.stream_pi.server.window.settings.SettingsBase;
import com.stream_pi.server.window.settings.SettingsBase;
import com.stream_pi.theme_api.Theme;
import com.stream_pi.theme_api.Theme;
import com.stream_pi.theme_api.Themes;
import com.stream_pi.theme_api.Themes;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.iohelper.IOHelper;
import com.stream_pi.util.iohelper.IOHelper;
import com.stream_pi.util.loggerhelper.StreamPiLogFallbackHandler;
import com.stream_pi.util.loggerhelper.StreamPiLogFallbackHandler;
import com.stream_pi.util.loggerhelper.StreamPiLogFileHandler;
import com.stream_pi.util.loggerhelper.StreamPiLogFileHandler;
import com.stream_pi.util.platform.Platform;
import com.stream_pi.util.platform.Platform;
import javafx.application.HostServices;
import javafx.application.HostServices;
import javafx.scene.image.Image;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.stage.Stage;
import java.awt.*;
import java.awt.*;
import java.io.File;
import java.io.File;
import java.util.logging.Logger;
import java.util.logging.Logger;
public abstract class Base extends StackPane implements ExceptionAndAlertHandler, ServerListener {
public abstract class Base extends StackPane implements ExceptionAndAlertHandler, ServerListener {
private Config config;
private Config config;
private ServerInfo serverInfo;
private ServerInfo serverInfo;
private Stage stage;
private Stage stage;
private HostServices hostServices;
private HostServices hostServices;
private SettingsBase settingsBase;
private DashboardBase dashboardBase;
private StackPane alertStackPane;
private StreamPiLogFileHandler logFileHandler = null;
private StreamPiLogFallbackHandler logFallbackHandler = null;
private Logger logger = null;
public Logger getLogger(){
public Logger getLogger(){
return logger;
return logger;
}
}
private SettingsBase settingsBase;
private DashboardBase dashboardBase;
private StackPane alertStackPane;
public void setHostServices(HostServices hostServices)
public void setHostServices(HostServices hostServices)
{
{
this.hostServices = hostServices;
this.hostServices = hostServices;
}
}
public HostServices getHostServices()
public HostServices getHostServices()
{
{
return hostServices;
return hostServices;
}
}
private Logger logger = null;
private StreamPiLogFileHandler logFileHandler = null;
private StreamPiLogFallbackHandler logFallbackHandler = null;
@Override
@Override
public void initLogger()
public void initLogger()
{
{
try
try
{
{
if(logFileHandler != null)
if(logFileHandler != null)
return;
return;
closeLogger();
closeLogger();
logger = Logger.getLogger("");
logger = Logger.getLogger("");
if(new File(ServerInfo.getInstance().getPrePath()).getAbsoluteFile().getParentFile().canWrite())
if(new File(ServerInfo.getInstance().getPrePath()).getAbsoluteFile().getParentFile().canWrite())
{
{
String path = ServerInfo.getInstance().getPrePath()+"../stream-pi-server.log";
String path = ServerInfo.getInstance().getPrePath()+"../stream-pi-server.log";
if(ServerInfo.getInstance().getPlatform() == Platform.ANDROID)
if(ServerInfo.getInstance().getPlatform() == Platform.ANDROID)
path = ServerInfo.getInstance().getPrePath()+"stream-pi-server.log";
path = ServerInfo.getInstance().getPrePath()+"stream-pi-server.log";
logFileHandler = new StreamPiLogFileHandler(path);
logFileHandler = new StreamPiLogFileHandler(path);
logger.addHandler(logFileHandler);
logger.addHandler(logFileHandler);
}
}
else
else
{
{
logFallbackHandler = new StreamPiLogFallbackHandler();
logFallbackHandler = new StreamPiLogFallbackHandler();
logger.addHandler(logFallbackHandler);
logger.addHandler(logFallbackHandler);
}
}
}
}
catch(Exception e)
catch(Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
logFallbackHandler = new StreamPiLogFallbackHandler();
logFallbackHandler = new StreamPiLogFallbackHandler();
logger.addHandler(logFallbackHandler);
logger.addHandler(logFallbackHandler);
}
}
}
}
public void closeLogger()
public void closeLogger()
{
{
if(logFileHandler != null)
if(logFileHandler != null)
logFileHandler.close();
logFileHandler.close();
else if(logFallbackHandler != null)
else if(logFallbackHandler != null)
logFallbackHandler.close();
logFallbackHandler.close();
}
}
public void initBase() throws SevereException
public void initBase() throws SevereException
{
{
stage = (Stage) getScene().getWindow();
stage = (Stage) getScene().getWindow();
getStage().getIcons().add(new Image(Main.class.getResourceAsStream("app_icon.png")));
getStage().getIcons().add(new Image(Main.class.getResourceAsStream("app_icon.png")));
getStage().setMinWidth(500);
getStage().setMinWidth(500);
getStage().setMinHeight(500);
getStage().setMinHeight(500);
serverInfo = ServerInfo.getInstance();
serverInfo = ServerInfo.getInstance();
settingsBase = new SettingsBase(getHostServices(), this, this);
settingsBase = new SettingsBase(getHostServices(), this, this);
settingsBase.prefWidthProperty().bind(widthProperty());
settingsBase.prefWidthProperty().bind(widthProperty());
settingsBase.prefHeightProperty().bind(heightProperty());
settingsBase.prefHeightProperty().bind(heightProperty());
dashboardBase = new DashboardBase(this, getHostServices());
dashboardBase = new DashboardBase(this, getHostServices());
dashboardBase.prefWidthProperty().bind(widthProperty());
dashboardBase.prefWidthProperty().bind(widthProperty());
dashboardBase.prefHeightProperty().bind(heightProperty());
dashboardBase.prefHeightProperty().bind(heightProperty());
alertStackPane = new StackPane();
alertStackPane = new StackPane();
alertStackPane.setVisible(false);
alertStackPane.setVisible(false);
StreamPiAlert.setParent(alertStackPane);
StreamPiAlert.setParent(alertStackPane);
getChildren().clear();
getChildren().clear();
getChildren().addAll(alertStackPane);
getChildren().addAll(alertStackPane);
initLogger();
initLogger();
checkPrePathDirectory();
checkPrePathDirectory();
getChildren().addAll(settingsBase, dashboardBase);
getChildren().addAll(settingsBase, dashboardBase);
config = Config.getInstance();
config = Config.getInstance();
initThemes();
initThemes();
stage.setWidth(config.getStartupWindowWidth());
stage.setWidth(config.getStartupWindowWidth());
stage.setHeight(config.getStartupWindowHeight());
stage.setHeight(config.getStartupWindowHeight());
stage.centerOnScreen();
stage.centerOnScreen();
dashboardBase.toFront();
dashboardBase.toFront();
}
}
private void checkPrePathDirectory() throws SevereException
private void checkPrePathDirectory() throws SevereException
{
{
try
try
{
{
File filex = new File(ServerInfo.getInstance().getPrePath());
File filex = new File(ServerInfo.getInstance().getPrePath());
if(!filex.exists())
if(!filex.exists())
{
{
boolean result = filex.mkdirs();
boolean result = filex.mkdirs();
if(result)
if(result)
{
{
IOHelper.unzip(Main.class.getResourceAsStream("Default.zip"), ServerInfo.getInstance().getPrePath());
IOHelper.unzip(Main.class.getResourceAsStream("Default.zip"), ServerInfo.getInstance().getPrePath());
Config.getInstance().setThemesPath(ServerInfo.getInstance().getPrePath()+"Themes/");
Config.getInstance().setThemesPath(ServerInfo.getInstance().getPrePath()+"Themes/");
Config.getInstance().setPluginsPath(ServerInfo.getInstance().getPrePath()+"Plugins/");
Config.getInstance().setPluginsPath(ServerInfo.getInstance().getPrePath()+"Plugins/");
if(SystemTray.isSupported())
if(SystemTray.isSupported())
{
{
Config.getInstance().setMinimiseToSystemTrayOnClose(true);
Config.getInstance().setMinimiseToSystemTrayOnClose(true);
}
}
Config.getInstance().save();
Config.getInstance().save();
initLogger();
initLogger();
}
}
else
else
{
{
setPrefSize(300,300);
setPrefSize(300,300);
clearStylesheets();
clearStylesheets();
applyDefaultStylesheet();
applyDefaultStylesheet();
applyDefaultIconsStylesheet();
applyDefaultIconsStylesheet();
getStage().show();
getStage().show();
throw new SevereException("No storage permission. Give it!");
throw new SevereException("No storage permission. Give it!");
}
}
}
}
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException(e.getMessage());
throw new SevereException(e.getMessage());
}
}
}
}
public void initThemes() throws SevereException {
public void initThemes() throws SevereException {
clearStylesheets();
clearStylesheets();
registerThemes();
registerThemes();
applyDefaultStylesheet();
applyDefaultStylesheet();
applyDefaultTheme();
applyDefaultTheme();
applyDefaultIconsStylesheet();
applyDefaultIconsStylesheet();
}
}
@Override
@Override
public Stage getStage()
public Stage getStage()
{
{
return stage;
return stage;
}
}
public void applyDefaultStylesheet()
public void applyDefaultStylesheet()
{
{
logger.info("Applying default stylesheet ...");
logger.info("Applying default stylesheet ...");
Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
logger.info("... Done!");
logger.info("... Done!");
}
}
public void applyDefaultIconsStylesheet()
public void applyDefaultIconsStylesheet()
{
{
Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
Font.loadFont(Main.class.getResourceAsStream("Roboto.ttf"), 13);
getStylesheets().add(Main.class.getResource("default_icons.css").toExternalForm());
getStylesheets().add(Main.class.getResource("default_icons.css").toExternalForm());
}
}
public DashboardBase getDashboardPane()
public DashboardBase getDashboardPane()
{
{
return dashboardBase;
return dashboardBase;
}
}
public SettingsBase getSettingsPane()
public SettingsBase getSettingsPane()
{
{
return settingsBase;
return settingsBase;
}
}
public Config getConfig()
public Config getConfig()
{
{
return config;
return config;
}
}
public ServerInfo getServerInfo()
public ServerInfo getServerInfo()
{
{
return serverInfo;
return serverInfo;
}
}
private Theme currentTheme;
private Theme currentTheme;
public Theme getCurrentTheme()
public Theme getCurrentTheme()
{
{
return currentTheme;
return currentTheme;
}
}
public void applyTheme(Theme t)
public void applyTheme(Theme t)
{
{
logger.info("Applying theme '"+t.getFullName()+"' ...");
logger.info("Applying theme '"+t.getFullName()+"' ...");
if(t.getFonts() != null)
if(t.getFonts() != null)
{
{
for(String fontFile : t.getFonts())
for(String fontFile : t.getFonts())
{
{
Font.loadFont(fontFile.replace("%20",""), 13);
Font.loadFont(fontFile.replace("%20",""), 13);
}
}
}
}
currentTheme = t;
currentTheme = t;
getStylesheets().addAll(t.getStylesheets());
getStylesheets().addAll(t.getStylesheets());
logger.info("... Done!");
logger.info("... Theme applied successfully!");
}
}
public void clearStylesheets()
public void clearStylesheets()
{
{
getStylesheets().clear();
getStylesheets().clear();
}
}
Themes themes;
Themes themes;
public void registerThemes() throws SevereException
public void registerThemes() throws SevereException
{
{
logger.info("Loading themes ...");
logger.info("Loading themes ...");
themes = new Themes(getConfig().getThemesPath(), getConfig().getCurrentThemeFullName(), serverInfo.getMinThemeSupportVersion());
themes = new Themes(getConfig().getThemesPath(), getConfig().getCurrentThemeFullName(), serverInfo.getMinThemeSupportVersion());
if(themes.getErrors().size()>0)
if(!themes.getErrors().isEmpty())
{
{
StringBuilder themeErrors = new StringBuilder();
StringBuilder themeErrors = new StringBuilder();
for(MinorException eachException : themes.getErrors())
for(MinorException eachException : themes.getErrors())
{
{
themeErrors.append("\n * ").append(eachException.getShortMessage());
themeErrors.append("\n * ").append(eachException.getShortMessage());
}
}
if(themes.getIsBadThemeTheCurrentOne())
if(themes.getIsBadThemeTheCurrentOne())
{
{
themeErrors.append("\n\nReverted to default theme! (").append(getConfig().getDefaultCurrentThemeFullName()).append(")");
themeErrors.append("\n\nReverted to default theme! (").append(getConfig().getDefaultCurrentThemeFullName()).append(")");
getConfig().setCurrentThemeFullName(getConfig().getDefaultCurrentThemeFullName());
getConfig().setCurrentThemeFullName(getConfig().getDefaultCurrentThemeFullName());
getConfig().save();
getConfig().save();
}
}
handleMinorException(new MinorException("Theme Loading issues", themeErrors.toString()));
handleMinorException(new MinorException("Theme Loading issues", themeErrors.toString()));
}
}
logger.info("...Themes loaded successfully !");
logger.info("... Done!");
}
}
public Themes getThemes()
public Themes getThemes()
{
{
return themes;
return themes;
}
}
public void applyDefaultTheme()
public void applyDefaultTheme()
{
{
logger.info("Applying default theme ...");
logger.info("Applying default theme ...");
boolean foundTheme = false;
boolean foundTheme = false;
for(Theme t: themes.getThemeList())
for(Theme t: themes.getThemeList())
{
{
if(t.getFullName().equals(config.getCurrentThemeFullName()))
if(t.getFullName().equals(config.getCurrentThemeFullName()))
{
{
foundTheme = true;
foundTheme = true;
applyTheme(t);
applyTheme(t);
break;
break;
}
}
}
}
if(foundTheme)
if(!foundTheme)
logger.info("... Done!");
else
{
{
logger.info("Theme not found. reverting to light theme ...");
logger.info("Theme not found. reverting to light theme ...");
try {
try {
Config.getInstance().setCurrentThemeFullName("com.streampi.DefaultLight");
Config.getInstance().setCurrentThemeFullName("com.streampi.DefaultLight");
Config.getInstance().save();
Config.getInstance().save();
applyDefaultTheme();
applyDefaultTheme();
}
}
catch (SevereException e)
catch (SevereException e)
{
{
handleSevereException(e);
handleSevereException(e);
}
}
}
}
}
}
}
}
module com.stream_pi.server {
module com.stream_pi.server {
uses com.stream_pi.action_api.action.Action;
uses com.stream_pi.action_api.action.Action;
uses com.stream_pi.action_api.externalplugin.NormalAction;
uses com.stream_pi.action_api.externalplugin.NormalAction;
uses com.stream_pi.action_api.externalplugin.ExternalPlugin;
uses com.stream_pi.action_api.externalplugin.ExternalPlugin;
requires com.stream_pi.action_api;
requires com.stream_pi.action_api;
requires com.stream_pi.util;
requires com.stream_pi.util;
requires com.stream_pi.theme_api;
requires com.stream_pi.theme_api;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.javafx;
requires java.xml;
requires java.xml;
requires javafx.base;
requires javafx.base;
requires javafx.graphics;
requires javafx.graphics;
requires javafx.controls;
requires javafx.controls;
requires javafx.media;
requires javafx.media;
requires java.desktop;
requires java.desktop;
requires java.sql;
requires java.sql;
exports com.stream_pi.server;
exports com.stream_pi.server;
}
}