diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 97219aa00..d378c320d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,11 +21,11 @@ jobs: echo $RELEASE_VERSION echo ${{ env.RELEASE_VERSION }} shell: bash - - name: Set up AdoptOpenJDK 20 + - name: Set up AdoptOpenJDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '20' + java-version: '21' architecture: x64 - name: Install submodules run: | @@ -50,7 +50,7 @@ jobs: mv target/FireflyLuciferin-${{steps.get-id.outputs.id}}-jar-with-dependencies.jar target/FireflyLuciferin-jar-with-dependencies.jar cd build_tools/wixtools; echo ${{github.run_number}} - jpackage -i ../../target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon ../../data/img/java_fast_screen_capture_logo.ico --win-menu --win-menu-group Luciferin --copyright "Davide Perini" --name "Firefly Luciferin" --vendor DPsoftware --win-dir-chooser --win-shortcut --win-per-user-install --win-upgrade-uuid 33c82dc4-e0e0-11ea-87d0-0242ac130003 --app-version "0.0.${{github.run_number}}" + jpackage -i ../../target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon ../../data/img/java_fast_screen_capture_logo.ico --win-menu --win-menu-group Luciferin --copyright "Davide Perini" --name "Firefly Luciferin" --vendor DPsoftware --win-dir-chooser --win-shortcut --win-per-user-install --win-upgrade-uuid 33c82dc4-e0e0-11ea-87d0-0242ac130003 --app-version "0.0.${{github.run_number}}" --win-shortcut --win-shortcut-prompt --java-options "-XX:+UseZGC -XX:+ZGenerational -XX:+UseStringDeduplication -Xms64m -Xmx1024m" shell: bash - name: Adding asset to the release env: @@ -79,11 +79,11 @@ jobs: run: | echo $RELEASE_VERSION echo ${{ env.RELEASE_VERSION }} - - name: Set up AdoptOpenJDK 20 + - name: Set up AdoptOpenJDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '20' + java-version: '21' architecture: x64 - id: get-id run: | @@ -101,7 +101,7 @@ jobs: ls -la target rm -rf target/fireflyluciferin-${{steps.get-id.outputs.id}}.jar; mv target/FireflyLuciferin-${{steps.get-id.outputs.id}}-jar-with-dependencies.jar target/FireflyLuciferin-jar-with-dependencies.jar - jpackage -i target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon data/img/luciferin_logo.png --linux-shortcut --copyright "Davide Perini" --name FireflyLuciferin --vendor DPsoftware --app-version "${{steps.get-id.outputs.id}}" + jpackage -i target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon data/img/luciferin_logo.png --linux-shortcut --copyright "Davide Perini" --name FireflyLuciferin --vendor DPsoftware --app-version "${{steps.get-id.outputs.id}}" --java-options "-XX:+UseZGC -XX:+ZGenerational -XX:+UseStringDeduplication -Xms64m -Xmx1024m" - name: Adding Linux asset to the release (Debian flavour) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d6c3565e6..cdd3675e9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,11 +34,11 @@ jobs: with: languages: ${{ matrix.language }} - - name: Set up AdoptOpenJDK 20 + - name: Set up AdoptOpenJDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '20' + java-version: '21' architecture: x64 - name: Autobuild diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ff670177..1ffe0d498 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,7 +79,7 @@ jobs: rm -rf target/fireflyluciferin-${{steps.get-id.outputs.id}}.jar; mv target/FireflyLuciferin-${{steps.get-id.outputs.id}}-jar-with-dependencies.jar target/FireflyLuciferin-jar-with-dependencies.jar cd build_tools/wixtools; - jpackage -i ../../target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon ../../data/img/java_fast_screen_capture_logo.ico --win-menu --win-menu-group Luciferin --copyright "Davide Perini" --name "Firefly Luciferin" --vendor DPsoftware --win-dir-chooser --win-shortcut --win-per-user-install --win-upgrade-uuid 33c82dc4-e0e0-11ea-87d0-0242ac130003 --app-version "${{steps.get-id.outputs.id}}" + jpackage -i ../../target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon ../../data/img/java_fast_screen_capture_logo.ico --win-menu --win-menu-group Luciferin --copyright "Davide Perini" --name "Firefly Luciferin" --vendor DPsoftware --win-dir-chooser --win-shortcut --win-per-user-install --win-upgrade-uuid 33c82dc4-e0e0-11ea-87d0-0242ac130003 --app-version "${{steps.get-id.outputs.id}}" --win-shortcut --win-shortcut-prompt --java-options "-XX:+UseZGC -Xms64m -Xmx1024m" shell: bash - name: Adding asset to the release env: @@ -103,11 +103,11 @@ jobs: run: | echo $RELEASE_VERSION echo ${{ env.RELEASE_VERSION }} - - name: Set up AdoptOpenJDK 20 + - name: Set up AdoptOpenJDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '20' + java-version: '21' architecture: x64 - id: get-id run: | @@ -126,7 +126,7 @@ jobs: ls -la target rm -rf target/fireflyluciferin-${{steps.get-id.outputs.id}}.jar; mv target/FireflyLuciferin-${{steps.get-id.outputs.id}}-jar-with-dependencies.jar target/FireflyLuciferin-jar-with-dependencies.jar - jpackage -i target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon data/img/luciferin_logo.png --linux-shortcut --copyright "Davide Perini" --name FireflyLuciferin --vendor DPsoftware --app-version "${{steps.get-id.outputs.id}}" + jpackage -i target --main-class org.dpsoftware.JavaFXStarter --main-jar FireflyLuciferin-jar-with-dependencies.jar --icon data/img/luciferin_logo.png --linux-shortcut --copyright "Davide Perini" --name FireflyLuciferin --vendor DPsoftware --app-version "${{steps.get-id.outputs.id}}" --java-options "-XX:+UseZGC -Xms64m -Xmx1024m" - name: Adding Linux asset to the release (Debian flavour) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -162,11 +162,11 @@ jobs: id=$(echo $RELEASE_VERSION | cut -dv -f2) echo "id=$id" >> $GITHUB_OUTPUT shell: bash - - name: Set up AdoptOpenJDK 20 + - name: Set up AdoptOpenJDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '20' + java-version: '21' architecture: x64 - name: Set up Maven Settings for deploy uses: s4u/maven-settings-action@v2.8.0 diff --git a/data/img/baud_rate.jpg b/data/img/baud_rate.jpg index b1a9dd499..7e8462b16 100644 Binary files a/data/img/baud_rate.jpg and b/data/img/baud_rate.jpg differ diff --git a/data/img/color_order.jpg b/data/img/color_order.jpg index 253a4cbba..588010079 100644 Binary files a/data/img/color_order.jpg and b/data/img/color_order.jpg differ diff --git a/data/img/dark_theme.png b/data/img/dark_theme.png index 236fc7076..cb415cbcc 100644 Binary files a/data/img/dark_theme.png and b/data/img/dark_theme.png differ diff --git a/data/img/default_theme.png b/data/img/default_theme.png index 14e1d11b5..91f7bb28e 100644 Binary files a/data/img/default_theme.png and b/data/img/default_theme.png differ diff --git a/data/img/device_tab.jpg b/data/img/device_tab.jpg index dda23f833..e16bf6bc1 100644 Binary files a/data/img/device_tab.jpg and b/data/img/device_tab.jpg differ diff --git a/data/img/enable_wifi.jpg b/data/img/enable_wifi.jpg index 52c0698ce..0177a9b58 100644 Binary files a/data/img/enable_wifi.jpg and b/data/img/enable_wifi.jpg differ diff --git a/data/img/gpio1.jpg b/data/img/gpio1.jpg index 8589e1b5d..569df2e85 100644 Binary files a/data/img/gpio1.jpg and b/data/img/gpio1.jpg differ diff --git a/data/img/groupleds.jpg b/data/img/groupleds.jpg index 255b9dec3..eb7aa4422 100644 Binary files a/data/img/groupleds.jpg and b/data/img/groupleds.jpg differ diff --git a/data/img/ha_integration_auto.jpg b/data/img/ha_integration_auto.jpg index 5035ed0e1..0b225a26f 100644 Binary files a/data/img/ha_integration_auto.jpg and b/data/img/ha_integration_auto.jpg differ diff --git a/data/img/mode_settings.jpg b/data/img/mode_settings.jpg index 603e7f738..cdcbbd1fb 100644 Binary files a/data/img/mode_settings.jpg and b/data/img/mode_settings.jpg differ diff --git a/data/img/multi_display/multimonitor_3.jpg b/data/img/multi_display/multimonitor_3.jpg index 7980859d9..73bd2799d 100644 Binary files a/data/img/multi_display/multimonitor_3.jpg and b/data/img/multi_display/multimonitor_3.jpg differ diff --git a/data/img/multi_display/multimonitor_6.jpg b/data/img/multi_display/multimonitor_6.jpg index 8e56e3bf6..09db2b2d3 100644 Binary files a/data/img/multi_display/multimonitor_6.jpg and b/data/img/multi_display/multimonitor_6.jpg differ diff --git a/data/img/power_saving.jpg b/data/img/power_saving.jpg index cccef4803..54867803d 100644 Binary files a/data/img/power_saving.jpg and b/data/img/power_saving.jpg differ diff --git a/data/img/profiles.jpg b/data/img/profiles.jpg index 3a07bf3c1..2c9953cd6 100644 Binary files a/data/img/profiles.jpg and b/data/img/profiles.jpg differ diff --git a/data/img/satellite_1.jpg b/data/img/satellite_1.jpg index 932b31b4e..14ac2e762 100644 Binary files a/data/img/satellite_1.jpg and b/data/img/satellite_1.jpg differ diff --git a/data/img/satellite_2.jpg b/data/img/satellite_2.jpg index d6141a7b7..50669e1e3 100644 Binary files a/data/img/satellite_2.jpg and b/data/img/satellite_2.jpg differ diff --git a/data/img/smoothing_frame_insertion.jpg b/data/img/smoothing_frame_insertion.jpg index a1675e5e7..4226fdad3 100644 Binary files a/data/img/smoothing_frame_insertion.jpg and b/data/img/smoothing_frame_insertion.jpg differ diff --git a/data/img/smoothing_framerate.jpg b/data/img/smoothing_framerate.jpg index 7d6d66e01..ffcdee679 100644 Binary files a/data/img/smoothing_framerate.jpg and b/data/img/smoothing_framerate.jpg differ diff --git a/data/img/static_ip.jpg b/data/img/static_ip.jpg index 36c32ac58..9bd580183 100644 Binary files a/data/img/static_ip.jpg and b/data/img/static_ip.jpg differ diff --git a/data/img/theme_selector.png b/data/img/theme_selector.png index 3b08fed49..705e05475 100644 Binary files a/data/img/theme_selector.png and b/data/img/theme_selector.png differ diff --git a/data/img/webinterfaceaccess.png b/data/img/webinterfaceaccess.png index 1e1d32fce..5e8a45741 100644 Binary files a/data/img/webinterfaceaccess.png and b/data/img/webinterfaceaccess.png differ diff --git a/docs/index.md b/docs/index.md index 86207c5a8..f1d53ab0f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,36 +19,29 @@ ### In this release: -- Hotfix release: Fixed a regression that doesn't permit to drive LEDs via USB when MQTT is enabled. **This issue - affects Firefly Luciferin only, there is no need to update the firmware.** +- ***Breaking changes***: requires `Glow Worm Luciferin` firmware (v5.12.9). +- **Introducing the Luciferin surround lighting with satellites.** +- **Added Wayland support for Linux.** Thanks @h7io for the contribution to this feature. +- **It's now possible to **disable Glow Worm device auto discovery** in Firefly Luciferin PC software.** This is useful + when PC and ESP lives in separate VLANs/Subnets. +- **Added the possibility to average the color of the screen on all the LEDs**. +- **Big performance improvements for Linux while running on X11.** +- **Added an optimization for Linux users that is specific for NVIDIA GPUs.** Thanks to @Phoshi for the support on this + feature. +- **Ram usage improvements.** +- **UI/UX improvements.** Revamped title bar, one left click on tray icon now open settings. Double left click on tray + icon starts/stops screen capture, right left click opens the menu as usual. (Windows only, Linux version has no tray + bar). +- Added an option during the installation process to create a desktop shortcut to Firefly Luciferin (Windows only). +- Added an option during the installation process to create a start menu shortcut to Firefly Luciferin (Windows only). +- Potential off-heap memory leak on Linux. Fixed. Thanks @jypma for fixing this issue. +- Firefly Luciferin caused a brief audio stutter on some systems during startup. Fixed. +- Fixed sporadic crashes on ESP32-S3 devices. +- Fixed an issue that prevented Glow Worm Luciferin firmware to be flashed using external tools like esptool. +- Upgrade to Java 21 and JavaFX 21. +- Arduino Bootstrapper update (v.1.15.3). ### In the previous release: -- ***Breaking changes***: requires `Glow Worm Luciferin` (v5.11.8) -- **Added support for ESP32-C3, ESP32-S2, ESP32-S3.** - Lolin ESP32-C3, Lolin ESP32-S2 and Lolin ESP32-S3 are now fully compatible with the existing Luciferin Official PCB. - TinyS2 and TinyS3 are now compatible with the existing Luciferin Module for the Luciferin Official PCB. - Closes [#46]. -- Added **support for DotStar LED strips.** Closes [#42]. -- Added the possibility to **configure GPIOs for Relay, Button and LDR**. -- Added the possibility to **switch profiles through MQTT**. Closes [#110]. -- Added **BRG, RBG, GBR color order** support. -- Improved power saving mode. Closes [#107]. -- Improved existing light effects. -- Improved aspect ratio auto detection, very dark scenes do not trigger an aspect ratio switch as there is no way to - know which is the correct one. -- IMAX 1.85:1 format now triggers the letterbox aspect ratio. -- There is now a single Web Installer for both stable and beta firmware. -- Reduced firmware footprint. -- Removed the hard limit on the maximum number of LEDs. You can now use as many LEDs as you want as long as your - microcontroller has enough memory. -- Increased the priority of the capturing threads. This fixed a flickering issue that occurs while using the smoothing - effect (frame generation) on Hybrid CPUs. Does not affect CPU load. -- UDP broadcast collision fix. Corrects weird behaviours when using two instances of Firefly Luciferin on two or more - computers on the same network with UDP stream. -- Configuring the Web Interface no longer requires an Internet connection. Closes [#52]. -- Fixed a bottleneck that reduced performance when driving many LEDs via USB. ESP32 was able to drive 500LEDs at 5FPS, - now it can drive the same amount of LEDs at 30FPS. -- Fixed an issue that prevented a profile from changing the current framerate without pausing and restarting the - capture. -- Arduino Bootstrapper update (v.1.15.2). \ No newline at end of file +- Hotfix release: Fixed a regression that doesn't permit to drive LEDs via USB when MQTT is enabled. **This issue + affects Firefly Luciferin only, there is no need to update the firmware.**. \ No newline at end of file diff --git a/pom.xml b/pom.xml index e20bec58d..1ad50ec50 100644 --- a/pom.xml +++ b/pom.xml @@ -22,26 +22,27 @@ 2.12.5 UTF-8 UTF-8 - 20.0.2 + 21.0.1 0.0.8 - 20 - 20 + 21 + 21 3.11.0 3.6.0 3.2.4 5.2.1 - 2.15.2 - 2.15.2 - 2.15.2 - 2.15.2 - 1.18.28 + 2.16.0 + 2.16.0 + 2.16.0 + 2.16.0 + 1.18.30 1.5.5.Final 5.13.0 1.4.0 1.2.5 - 1.4.8 + 1.4.11 2.0.9 2.0 + 4.3.1 @@ -196,6 +197,18 @@ ${xtaudio.version} + + com.github.hypfvieh + dbus-java-core + ${dbus.java.version} + + + + com.github.hypfvieh + dbus-java-transport-junixsocket + ${dbus.java.version} + + diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index d0145d397..feefb6e16 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -16,11 +16,11 @@ requires java.net.http; requires org.slf4j; requires ch.qos.logback.classic; + requires org.freedesktop.dbus; opens org.dpsoftware to javafx.fxml, javafx.web; opens org.dpsoftware.gui to javafx.fxml, javafx.web; opens org.dpsoftware.gui.controllers to javafx.fxml; - opens org.dpsoftware.grabber to javafx.fxml; opens org.dpsoftware.managers.dto.mqttdiscovery to com.fasterxml.jackson.databind; exports org.dpsoftware; @@ -36,4 +36,7 @@ exports org.dpsoftware.utilities; exports org.dpsoftware.network; + opens org.dpsoftware.audio to javafx.fxml, javafx.web; + opens org.dpsoftware.grabber to javafx.fxml, javafx.web; + } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/FireflyLuciferin.java b/src/main/java/org/dpsoftware/FireflyLuciferin.java index bebf9c285..35c07ce61 100644 --- a/src/main/java/org/dpsoftware/FireflyLuciferin.java +++ b/src/main/java/org/dpsoftware/FireflyLuciferin.java @@ -23,22 +23,20 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.LoggerContext; -import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import javafx.application.Application; -import javafx.application.HostServices; import javafx.stage.Stage; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.grabber.GrabberManager; import org.dpsoftware.grabber.ImageProcessor; -import org.dpsoftware.gui.GUIManager; +import org.dpsoftware.gui.GuiManager; import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.PowerSavingManager; import org.dpsoftware.managers.SerialManager; @@ -46,7 +44,7 @@ import org.dpsoftware.managers.dto.StateDto; import org.dpsoftware.network.MessageClient; import org.dpsoftware.network.MessageServer; -import org.dpsoftware.network.tcpUdp.UdpClient; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.network.tcpUdp.UdpServer; import org.dpsoftware.utilities.CommonUtility; import org.dpsoftware.utilities.PropertiesLoader; @@ -55,9 +53,6 @@ import javax.swing.*; import java.awt.*; import java.io.IOException; -import java.io.OutputStream; -import java.net.SocketException; -import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.LocalTime; @@ -77,44 +72,6 @@ @Getter public class FireflyLuciferin extends Application implements SerialPortEventListener { - // Calculate Screen Capture Framerate and how fast your microcontroller can consume it - public static float FPS_CONSUMER_COUNTER; - public static float FPS_PRODUCER_COUNTER; - public static float FPS_CONSUMER = 0; - public static float FPS_PRODUCER = 0; - public static float FPS_GW_CONSUMER = 0; - public static SimpleDateFormat formatter; - public static SerialPort serial; - public static OutputStream output; - public static boolean serialConnected = false; - public static int baudRate = 0; - // LED strip, monitor and microcontroller config - public static Configuration config; - // Start and Stop threads - public static boolean RUNNING = false; - // This queue orders elements FIFO. Producer offers some data, consumer throws data to the Serial port - public static BlockingQueue sharedQueue; - // Number of LEDs on the strip - public static int ledNumber; - public static int ledNumHighLowCount; - public static int ledNumHighLowCountSecondPart; - public static GUIManager guiManager; - public static boolean communicationError = false; - public static Color colorInUse; - public static int gpio = 0; // 0 means not set, firmware discards this value - public static int colorOrder = 0; // 1 means GRB, 2 RGB, 3 BGR - public static int ldrAction = 0; // 1 no action, 2 calibrate, 3 reset, 4 save - public static int fireflyEffect = 0; - public static int relayPin = -1; - public static int sbPin = -1; - public static int ldrPin = -1; - public static int gpioClockPin = 0; - public static boolean nightMode = false; - public static String version = ""; - public static String minimumFirmwareVersion = ""; - public static ResourceBundle bundle; - public static String profileArgs; - public static HostServices hostServices; // Image processing private final ImageProcessor imageProcessor; private final GrabberManager grabberManager; @@ -129,49 +86,47 @@ public class FireflyLuciferin extends Application implements SerialPortEventList // 3 thread is enough for 30FPS with GPU Hardware Acceleration and uses nearly no CPU private int threadPoolNumber; private int executorNumber; - // UDP - private UdpClient udpClient; /** * Constructor */ public FireflyLuciferin() { PropertiesLoader propertiesLoader = new PropertiesLoader(); - formatter = new SimpleDateFormat(Constants.DATE_FORMAT); + MainSingleton.getInstance().formatter = new SimpleDateFormat(Constants.DATE_FORMAT); // Extract project version computed from Continuous Integration (GitHub Actions) - version = propertiesLoader.retrieveProperties(Constants.PROP_VERSION); + MainSingleton.getInstance().version = propertiesLoader.retrieveProperties(Constants.PROP_VERSION); Locale currentLocale = Locale.getDefault(); - bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, currentLocale); - if (bundle.getLocale().toString().isEmpty()) { - bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, Locale.ENGLISH); + MainSingleton.getInstance().bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, currentLocale); + if (MainSingleton.getInstance().bundle.getLocale().toString().isEmpty()) { + MainSingleton.getInstance().bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, Locale.ENGLISH); } String ledMatrixInUse = ""; try { StorageManager storageManager = new StorageManager(); - config = storageManager.loadConfigurationYaml(); - ledMatrixInUse = config.getDefaultLedMatrix(); + MainSingleton.getInstance().config = storageManager.loadConfigurationYaml(); + ledMatrixInUse = MainSingleton.getInstance().config.getDefaultLedMatrix(); } catch (NullPointerException e) { log.error("Please configure the app."); NativeExecutor.exit(); } manageLocale(); - sharedQueue = new LinkedBlockingQueue<>(config.getLedMatrixInUse(ledMatrixInUse).size() * 30); + MainSingleton.getInstance().sharedQueue = new LinkedBlockingQueue<>(MainSingleton.getInstance().config.getLedMatrixInUse(ledMatrixInUse).size() * 30); imageProcessor = new ImageProcessor(true); serialManager = new SerialManager(); grabberManager = new GrabberManager(); if (CommonUtility.isSingleDeviceMainInstance()) { - MessageServer.messageServer = new MessageServer(); - MessageServer.initNumLed(); + NetworkSingleton.getInstance().messageServer = new MessageServer(); + NetworkSingleton.getInstance().messageServer.initNumLed(); } setLedNumber(ledMatrixInUse); - baudRate = Enums.BaudRate.valueOf(Constants.BAUD_RATE_PLACEHOLDER + config.getBaudRate()).getBaudRateValue(); + MainSingleton.getInstance().baudRate = Enums.BaudRate.valueOf(Constants.BAUD_RATE_PLACEHOLDER + MainSingleton.getInstance().config.getBaudRate()).getBaudRateValue(); // Check if I'm the main program, if yes and multi monitor, spawn other guys NativeExecutor.spawnNewInstances(); initThreadPool(); - hostServices = this.getHostServices(); + MainSingleton.getInstance().hostServices = this.getHostServices(); powerSavingManager = new PowerSavingManager(); powerSavingManager.setLastFrameTime(LocalDateTime.now()); - NativeExecutor.setHighPriorityThreads(config.getThreadPriority()); + NativeExecutor.setHighPriorityThreads(MainSingleton.getInstance().config.getThreadPriority()); } /** @@ -180,9 +135,9 @@ public FireflyLuciferin() { * @param tempNightMode previous value */ private static void setNightBrightness(boolean tempNightMode) { - if (tempNightMode != nightMode) { - log.info("Night Mode: " + nightMode); - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { + if (tempNightMode != MainSingleton.getInstance().nightMode) { + log.info("Night Mode: " + MainSingleton.getInstance().nightMode); + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { StateDto stateDto = new StateDto(); stateDto.setState(Constants.ON); stateDto.setBrightness(CommonUtility.getNightBrightness()); @@ -190,8 +145,8 @@ private static void setNightBrightness(boolean tempNightMode) { if (CommonUtility.getDeviceToUse() != null) { stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); } - stateDto.setWhitetemp(FireflyLuciferin.config.getWhiteTemperature()); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + stateDto.setWhitetemp(MainSingleton.getInstance().config.getWhiteTemperature()); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } } } @@ -204,16 +159,16 @@ private static void setNightBrightness(boolean tempNightMode) { * @param ledMatrixInUse led matrix in use */ public static void setLedNumber(String ledMatrixInUse) { - ledNumber = CommonUtility.isSingleDeviceMultiScreen() ? MessageServer.totalLedNum : config.getLedMatrixInUse(ledMatrixInUse).size(); - int multiplier = (int) Math.floor((double) ledNumber / Constants.SERIAL_CHUNK_SIZE); - int lastPart = ledNumber - (Constants.SERIAL_CHUNK_SIZE * multiplier); + MainSingleton.getInstance().ledNumber = CommonUtility.isSingleDeviceMultiScreen() ? NetworkSingleton.getInstance().totalLedNum : MainSingleton.getInstance().config.getLedMatrixInUse(ledMatrixInUse).size(); + int multiplier = (int) Math.floor((double) MainSingleton.getInstance().ledNumber / Constants.SERIAL_CHUNK_SIZE); + int lastPart = MainSingleton.getInstance().ledNumber - (Constants.SERIAL_CHUNK_SIZE * multiplier); if (lastPart < 1) { multiplier--; - ledNumHighLowCount = Constants.SERIAL_CHUNK_SIZE - 1; + MainSingleton.getInstance().ledNumHighLowCount = Constants.SERIAL_CHUNK_SIZE - 1; } else { - ledNumHighLowCount = ledNumber > Constants.SERIAL_CHUNK_SIZE ? lastPart - 1 : ledNumber - 1; + MainSingleton.getInstance().ledNumHighLowCount = MainSingleton.getInstance().ledNumber > Constants.SERIAL_CHUNK_SIZE ? lastPart - 1 : MainSingleton.getInstance().ledNumber - 1; } - ledNumHighLowCountSecondPart = ledNumber > Constants.SERIAL_CHUNK_SIZE ? multiplier : 0; + MainSingleton.getInstance().ledNumHighLowCountSecondPart = MainSingleton.getInstance().ledNumber > Constants.SERIAL_CHUNK_SIZE ? multiplier : 0; } /** @@ -222,9 +177,9 @@ public static void setLedNumber(String ledMatrixInUse) { * @param args startup args */ public static void main(String[] args) { - profileArgs = Constants.DEFAULT; + MainSingleton.getInstance().profileArgs = Constants.DEFAULT; if (args.length > 1) { - profileArgs = args[1]; + MainSingleton.getInstance().profileArgs = args[1]; } NativeExecutor.createStartWMClass(); StorageManager sm = new StorageManager(); @@ -236,18 +191,18 @@ public static void main(String[] args) { * Activate/deactivate night mode */ public static void checkForNightMode() { - var tempNightMode = nightMode; - if (!(FireflyLuciferin.config.getNightModeBrightness().equals(Constants.NIGHT_MODE_OFF)) && FireflyLuciferin.config.isToggleLed()) { + var tempNightMode = MainSingleton.getInstance().nightMode; + if (!(MainSingleton.getInstance().config.getNightModeBrightness().equals(Constants.NIGHT_MODE_OFF)) && MainSingleton.getInstance().config.isToggleLed()) { LocalTime from = LocalTime.now(); LocalTime to = LocalTime.now(); - from = from.withHour(LocalTime.parse(FireflyLuciferin.config.getNightModeFrom()).getHour()); - from = from.withMinute(LocalTime.parse(FireflyLuciferin.config.getNightModeFrom()).getMinute()); - to = to.withHour(LocalTime.parse(FireflyLuciferin.config.getNightModeTo()).getHour()); - to = to.withMinute(LocalTime.parse(FireflyLuciferin.config.getNightModeTo()).getMinute()); - nightMode = (LocalTime.now().isAfter(from) || LocalTime.now().isBefore(to)); + from = from.withHour(LocalTime.parse(MainSingleton.getInstance().config.getNightModeFrom()).getHour()); + from = from.withMinute(LocalTime.parse(MainSingleton.getInstance().config.getNightModeFrom()).getMinute()); + to = to.withHour(LocalTime.parse(MainSingleton.getInstance().config.getNightModeTo()).getHour()); + to = to.withMinute(LocalTime.parse(MainSingleton.getInstance().config.getNightModeTo()).getMinute()); + MainSingleton.getInstance().nightMode = (LocalTime.now().isAfter(from) || LocalTime.now().isBefore(to)); setNightBrightness(tempNightMode); } else { - nightMode = false; + MainSingleton.getInstance().nightMode = false; } } @@ -256,8 +211,8 @@ public static void checkForNightMode() { */ private void setRuntimeLogLevel() { LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - log.info("** Log level -> " + config.getRuntimeLogLevel() + " **"); - loggerContext.getLogger(Constants.LOG_LEVEL_ROOT).setLevel(Level.toLevel(config.getRuntimeLogLevel())); + log.info("** Log level -> " + MainSingleton.getInstance().config.getRuntimeLogLevel() + " **"); + loggerContext.getLogger(Constants.LOG_LEVEL_ROOT).setLevel(Level.toLevel(MainSingleton.getInstance().config.getRuntimeLogLevel())); } /** @@ -269,49 +224,57 @@ public void start(Stage stage) throws Exception { if (!NativeExecutor.isLinux()) { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } - launchGrabberAndConsumers(); scheduleCheckForNightMode(); StorageManager storageManager = new StorageManager(); - storageManager.updateConfigFile(config); + storageManager.updateConfigFile(MainSingleton.getInstance().config); setRuntimeLogLevel(); // Manage tray icon and framerate dialog - guiManager = new GUIManager(stage); - guiManager.trayIconManager.initTray(); - guiManager.showSettingsAndCheckForUpgrade(); + MainSingleton.getInstance().guiManager = new GuiManager(stage); + MainSingleton.getInstance().guiManager.trayIconManager.initTray(); + MainSingleton.getInstance().guiManager.showSettingsAndCheckForUpgrade(); if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { serialManager.initSerial(this); serialManager.initOutputStream(); } - if (config.isMqttEnable()) { + if (MainSingleton.getInstance().config.isMqttEnable()) { connectToMqttServer(); } else { log.info(Constants.MQTT_DISABLED); - if (config.isFullFirmware()) { + if (MainSingleton.getInstance().config.isFullFirmware()) { UdpServer udpServer = new UdpServer(); - UdpServer.udpBroadcastReceiverRunning = true; + NetworkSingleton.getInstance().udpBroadcastReceiverRunning = true; udpServer.receiveBroadcastUDPPacket(); } } grabberManager.getFPS(); imageProcessor.calculateBorders(); + // If this instance spawns new instances, don't launch grabbers here. + if (!(MainSingleton.getInstance().spawnInstances && MainSingleton.getInstance().config.getMultiMonitor() > 1)) { + launchGrabberAndConsumers(); + } // If multi monitor, first instance, single instance, start message server if (CommonUtility.isSingleDeviceMainInstance()) { - MessageServer.startMessageServer(); + MessageServer messageServer = new MessageServer(); + messageServer.startMessageServer(); } if (CommonUtility.isSingleDeviceOtherInstance()) { MessageClient.getSingleInstanceMultiScreenStatus(); } - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, config.getEffect()); - if (config.isToggleLed()) { + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); + if (MainSingleton.getInstance().config.isToggleLed()) { switch (effectInUse) { case BIAS_LIGHT, MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> manageAutoStart(); } } - if (!config.isMqttEnable() && !config.isFullFirmware()) { + if (!MainSingleton.getInstance().config.isMqttEnable() && !MainSingleton.getInstance().config.isFullFirmware()) { serialManager.manageSolidLed(); } scheduleBackgroundTasks(stage); + // Preload main dialog that requires 1.8s to laod the FXML (more or less on a 13900K CPU) + if (MainSingleton.getInstance().config.getRuntimeLogLevel().equals("DEBUG")) { + MainSingleton.getInstance().guiManager.showSettingsDialog(true); + } } /** @@ -322,9 +285,12 @@ public void start(Stage stage) throws Exception { private void launchGrabberAndConsumers() throws AWTException { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(threadPoolNumber); // Desktop Duplication API producers - if ((config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) - || (config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) - || (config.getCaptureMethod().equals(Configuration.CaptureMethod.AVFVIDEOSRC.name()))) { + if ((MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC_NVIDIA.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.AVFVIDEOSRC.name()))) { grabberManager.launchAdvancedGrabber(imageProcessor); } else { // Standard Producers grabberManager.launchStandardGrabber(scheduledExecutorService, executorNumber); @@ -370,20 +336,33 @@ private void connectToMqttServer() { * * @param stage main stage */ - @SuppressWarnings("unused") + @SuppressWarnings("all") private void scheduleBackgroundTasks(Stage stage) { // Create a task that runs every 5 seconds, reconnect serial devices when needed ScheduledExecutorService serialscheduledExecutorService = Executors.newScheduledThreadPool(1); Runnable framerateTask = () -> { - if (!serialConnected && !config.isWirelessStream()) { + if (!MainSingleton.getInstance().serialConnected && !MainSingleton.getInstance().config.isWirelessStream()) { if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { serialManager.initSerial(this); } } }; serialscheduledExecutorService.scheduleAtFixedRate(framerateTask, 0, 5, TimeUnit.SECONDS); + // Wayland only, create a task that pings Glow Worm device every 2 seconds, this is needed because wayland stops sending + // updates to the device when the image on the screen is still. + if (NativeExecutor.isWayland()) { + ScheduledExecutorService waylandScheduledExecutorService = Executors.newScheduledThreadPool(1); + Runnable waylandTask = () -> { + if (MainSingleton.getInstance().RUNNING && MainSingleton.getInstance().FPS_PRODUCER == 0 + && MainSingleton.getInstance().lastLedColor != null && MainSingleton.getInstance().lastLedColor.length > 0) { + Collections.reverse(Arrays.asList(MainSingleton.getInstance().lastLedColor)); + MainSingleton.getInstance().sharedQueue.offer(MainSingleton.getInstance().lastLedColor); + } + }; + waylandScheduledExecutorService.scheduleAtFixedRate(waylandTask, 0, 200, TimeUnit.MILLISECONDS); + } NativeExecutor.addShutdownHook(); - if (!FireflyLuciferin.config.isMultiScreenSingleDevice() || CommonUtility.isSingleDeviceMainInstance()) { + if (!MainSingleton.getInstance().config.isMultiScreenSingleDevice() || CommonUtility.isSingleDeviceMainInstance()) { powerSavingManager.addPowerSavingTask(); } } @@ -393,11 +372,11 @@ private void scheduleBackgroundTasks(Stage stage) { */ void manageAutoStart() { int timeToWait = 0; - if ((config.getMultiMonitor() == 2 && JavaFXStarter.whoAmI == 2) - || (config.getMultiMonitor() == 3 && JavaFXStarter.whoAmI == 3)) { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 2 && MainSingleton.getInstance().whoAmI == 2) + || (MainSingleton.getInstance().config.getMultiMonitor() == 3 && MainSingleton.getInstance().whoAmI == 3)) { timeToWait = 15; } - CommonUtility.delaySeconds(() -> guiManager.startCapturingThreads(), timeToWait); + CommonUtility.delaySeconds(() -> MainSingleton.getInstance().guiManager.startCapturingThreads(), timeToWait); } /** @@ -405,19 +384,20 @@ void manageAutoStart() { */ private void manageLocale() { Locale currentLocale; - if (config.getLanguage() != null) { - currentLocale = Locale.forLanguageTag(LocalizedEnum.fromBaseStr(Enums.Language.class, config.getLanguage()).name().toLowerCase()); + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.getLanguage() != null) { + currentLocale = Locale.forLanguageTag(LocalizedEnum.fromBaseStr(Enums.Language.class, MainSingleton.getInstance().config.getLanguage()).name().toLowerCase()); } else { currentLocale = Locale.ENGLISH; - config.setLanguage(Enums.Language.EN.getBaseI18n()); + assert MainSingleton.getInstance().config != null; + MainSingleton.getInstance().config.setLanguage(Enums.Language.EN.getBaseI18n()); for (Enums.Language lang : Enums.Language.values()) { if (lang.name().equalsIgnoreCase(Locale.getDefault().getLanguage())) { currentLocale = Locale.forLanguageTag(lang.name().toLowerCase()); - config.setLanguage(lang.getBaseI18n()); + MainSingleton.getInstance().config.setLanguage(lang.getBaseI18n()); } } } - bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, currentLocale); + MainSingleton.getInstance().bundle = ResourceBundle.getBundle(Constants.MSG_BUNDLE, currentLocale); } /** @@ -443,10 +423,10 @@ public synchronized void serialEvent(SerialPortEvent event) { * Initialize how many Threads to use in the ThreadPool and how many Executor to use */ private void initThreadPool() { - int numberOfCPUThreads = config.getNumberOfCPUThreads(); + int numberOfCPUThreads = MainSingleton.getInstance().config.getNumberOfCPUThreads(); threadPoolNumber = numberOfCPUThreads * 2; if (numberOfCPUThreads > 1) { - if (!(config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name()))) { + if (!(MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name()))) { executorNumber = numberOfCPUThreads; } else { executorNumber = numberOfCPUThreads * 3; @@ -463,7 +443,7 @@ private void initThreadPool() { * @param leds array of LEDs containing the average color to display on the LED */ private void sendColors(Color[] leds) throws IOException { - if (!Enums.PowerSaving.DISABLED.equals(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, config.getPowerSaving()))) { + if (!Enums.PowerSaving.DISABLED.equals(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, MainSingleton.getInstance().config.getPowerSaving()))) { if (powerSavingManager.isUnlockCheckLedDuplication()) { powerSavingManager.setUnlockCheckLedDuplication(false); powerSavingManager.checkForLedDuplication(leds); @@ -472,22 +452,22 @@ private void sendColors(Color[] leds) throws IOException { Arrays.fill(leds, new Color(0, 0, 0)); } } - if (Enums.Orientation.CLOCKWISE.equals((LocalizedEnum.fromBaseStr(Enums.Orientation.class, config.getOrientation())))) { + if (Enums.Orientation.CLOCKWISE.equals((LocalizedEnum.fromBaseStr(Enums.Orientation.class, MainSingleton.getInstance().config.getOrientation())))) { Collections.reverse(Arrays.asList(leds)); } - if (config.getLedStartOffset() > 0) { + if (MainSingleton.getInstance().config.getLedStartOffset() > 0) { List tempList = new ArrayList<>(); - List tempListHead = Arrays.asList(leds).subList(config.getLedStartOffset(), leds.length); - List tempListTail = Arrays.asList(leds).subList(0, config.getLedStartOffset()); + List tempListHead = Arrays.asList(leds).subList(MainSingleton.getInstance().config.getLedStartOffset(), leds.length); + List tempListTail = Arrays.asList(leds).subList(0, MainSingleton.getInstance().config.getLedStartOffset()); tempList.addAll(tempListHead); tempList.addAll(tempListTail); leds = tempList.toArray(leds); } int i = 0; if (leds != null && leds[0] != null) { - if (config.isFullFirmware() && config.isWirelessStream()) { + if (MainSingleton.getInstance().config.isFullFirmware() && MainSingleton.getInstance().config.isWirelessStream()) { // Single part stream - if (ledNumber < Constants.FIRST_CHUNK || !Constants.JSON_STREAM) { + if (MainSingleton.getInstance().ledNumber < Constants.FIRST_CHUNK || !Constants.JSON_STREAM) { sendChunck(i, leds, 1); } else { // Multi part stream // First Chunk @@ -499,7 +479,7 @@ private void sendColors(Color[] leds) throws IOException { i = sendChunck(i, leds, 3); } // Fourth Chunk - if (i >= Constants.THIRD_CHUNK && i < ledNumber) { + if (i >= Constants.THIRD_CHUNK && i < MainSingleton.getInstance().ledNumber) { sendChunck(i, leds, 4); } } @@ -507,7 +487,7 @@ private void sendColors(Color[] leds) throws IOException { serialManager.sendColorsViaUSB(leds); } } - FPS_CONSUMER_COUNTER++; + MainSingleton.getInstance().FPS_CONSUMER_COUNTER++; } /** @@ -528,7 +508,7 @@ int sendChunck(int i, Color[] leds, int chunkNumber) { ledStr.append(Constants.STREAM); } else { ledStr.append(ledNum).append(","); - ledStr.append((AudioLoopback.AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioLoopback.AUDIO_BRIGHTNESS)).append(","); + ledStr.append((AudioSingleton.getInstance().AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioSingleton.getInstance().AUDIO_BRIGHTNESS)).append(","); firstChunk = Constants.MAX_CHUNK; } switch (chunkNumber) { @@ -566,21 +546,7 @@ int sendChunck(int i, Color[] leds, int chunkNumber) { ledStr.append("."); NetworkManager.stream(ledStr.toString().replace(",.", "") + "]}"); } else { - // UDP stream or MQTT stream - if (config.getStreamType().equals(Enums.StreamType.UDP.getStreamType())) { - if (udpClient == null || udpClient.socket.isClosed()) { - try { - udpClient = new UdpClient(CommonUtility.getDeviceToUse().getDeviceIP()); - } catch (SocketException | UnknownHostException e) { - udpClient = null; - } - } - assert udpClient != null; - udpClient.manageStream(leds); - } else { - ledStr.append("0"); - NetworkManager.stream(ledStr.toString()); - } + NetworkManager.streamColors(leds, ledStr); } return i; } @@ -590,15 +556,17 @@ int sendChunck(int i, Color[] leds, int chunkNumber) { */ @SuppressWarnings("InfiniteLoopStatement") void consume() throws InterruptedException, IOException { + boolean isWayland = NativeExecutor.isWayland(); while (true) { - Color[] num = sharedQueue.take(); - if (RUNNING) { + Color[] colorArray = MainSingleton.getInstance().sharedQueue.take(); + if (isWayland) MainSingleton.getInstance().lastLedColor = colorArray; + if (MainSingleton.getInstance().RUNNING) { if (CommonUtility.isSingleDeviceMultiScreen()) { - if (num.length == MessageServer.totalLedNum) { - sendColors(num); + if (colorArray.length == NetworkSingleton.getInstance().totalLedNum) { + sendColors(colorArray); } - } else if (num.length == ledNumber) { - sendColors(num); + } else if (colorArray.length == MainSingleton.getInstance().ledNumber) { + sendColors(colorArray); } } } @@ -608,15 +576,15 @@ void consume() throws InterruptedException, IOException { * Clean and Close Serial Output Stream */ private void clean() { - if (output != null) { + if (MainSingleton.getInstance().output != null) { try { - output.close(); + MainSingleton.getInstance().output.close(); } catch (IOException e) { log.error(e.getMessage()); } } - if (serial != null) { - serial.close(); + if (MainSingleton.getInstance().serial != null) { + MainSingleton.getInstance().serial.close(); } } diff --git a/src/main/java/org/dpsoftware/JavaFXStarter.java b/src/main/java/org/dpsoftware/JavaFXStarter.java index 4d4fbe617..72ce0f479 100644 --- a/src/main/java/org/dpsoftware/JavaFXStarter.java +++ b/src/main/java/org/dpsoftware/JavaFXStarter.java @@ -37,10 +37,6 @@ @Slf4j public class JavaFXStarter { - // Who am I supposed to be? Used to manage multiple instances of Luciferin running at the same time - public static int whoAmI = 1; - public static boolean spawnInstances = true; // set this to false to avoid spawning new instances on multi monitor setup - /** * Let's play! * @@ -52,8 +48,8 @@ public static void main(String... args) { if (args.length > 1) { log.info("Profile to use: " + args[1]); } - whoAmI = Integer.parseInt(args[0]); - spawnInstances = false; + MainSingleton.getInstance().whoAmI = Integer.parseInt(args[0]); + MainSingleton.getInstance().spawnInstances = false; CommonUtility.sleepMilliseconds(Constants.SPAWN_INSTANCE_WAIT_START_DELAY); } else { log.info("Starting default instance"); diff --git a/src/main/java/org/dpsoftware/LEDCoordinate.java b/src/main/java/org/dpsoftware/LEDCoordinate.java index a5f1da7ba..8d5d6137e 100644 --- a/src/main/java/org/dpsoftware/LEDCoordinate.java +++ b/src/main/java/org/dpsoftware/LEDCoordinate.java @@ -28,10 +28,13 @@ import lombok.extern.slf4j.Slf4j; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; +import org.dpsoftware.gui.elements.Satellite; import org.dpsoftware.managers.dto.LedMatrixInfo; import org.dpsoftware.utilities.CommonUtility; import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** @@ -49,6 +52,7 @@ public class LEDCoordinate { private int width; private int height; private boolean groupedLed; + private String zone; /** * Calculate tale border size @@ -60,6 +64,67 @@ public static int calculateTaleBorder(int width) { return (Constants.TEST_CANVAS_BORDER_RATIO * width) / 3840; } + /** + * Calculated start end of the satellite + * + * @param sat satellite where to do the calculation + * @return record with start and end + */ + public static getStartEndLeds getGetStartEndLeds(Satellite sat) { + int start, end; + LinkedHashMap ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(MainSingleton.getInstance().config.getDefaultLedMatrix()); + if (sat.getZone().equals(Enums.SatelliteZone.ENTIRE_SCREEN.getBaseI18n())) { + start = 1; + end = MainSingleton.getInstance().ledNumber; + } else { + // If bottom row is splitted and sat uses BOTTOM zone force to BOTTOM_LEFT + if (CommonUtility.isSplitBottomRow(MainSingleton.getInstance().config.getSplitBottomMargin())) { + if (sat.getZone().equals(Enums.SatelliteZone.BOTTOM.getBaseI18n())) { + sat.setZone(Enums.SatelliteZone.BOTTOM_LEFT.getBaseI18n()); + } + } + String correctedColor = sat.getZone(); + if (sat.getZone().equals(Enums.SatelliteZone.TOP_RIGHT.getBaseI18n()) || sat.getZone().equals(Enums.SatelliteZone.TOP_LEFT.getBaseI18n())) { + correctedColor = Enums.SatelliteZone.TOP.getBaseI18n(); + } + if (!CommonUtility.isSplitBottomRow(MainSingleton.getInstance().config.getSplitBottomMargin())) { + if (sat.getZone().equals(Enums.SatelliteZone.BOTTOM_RIGHT.getBaseI18n()) || sat.getZone().equals(Enums.SatelliteZone.BOTTOM_LEFT.getBaseI18n())) { + correctedColor = Enums.SatelliteZone.BOTTOM.getBaseI18n(); + } + } + String finalCorrectedColor = correctedColor; + List filteredList = ledMatrix.entrySet().stream() + .filter(e -> e.getValue().getZone().equals(finalCorrectedColor)) + .map(Map.Entry::getKey) + .toList(); + start = filteredList + .stream() + .mapToInt(v -> v) + .min().orElse(0); + end = filteredList + .stream() + .mapToInt(v -> v) + .max().orElse(0); + if (sat.getZone().equals(Enums.SatelliteZone.TOP_RIGHT.getBaseI18n())) { + end = start + ((end - start) / 3); + } + if (sat.getZone().equals(Enums.SatelliteZone.TOP_LEFT.getBaseI18n())) { + int segment = (end - start) / 3; + start = start + (segment * 2); + } + if (!CommonUtility.isSplitBottomRow(MainSingleton.getInstance().config.getSplitBottomMargin())) { + if (sat.getZone().equals(Enums.SatelliteZone.BOTTOM_LEFT.getBaseI18n())) { + end = start + ((end - start) / 3); + } + if (sat.getZone().equals(Enums.SatelliteZone.BOTTOM_RIGHT.getBaseI18n())) { + int segment = (end - start) / 3; + start = start + (segment * 2); + } + } + } + return new getStartEndLeds(start, end); + } + /** * Init FullScreen LED Matrix with a default general purpose config * @@ -118,7 +183,7 @@ int calculateBorders(int screenWidth, int screenHeight) { * @param defaultLedMatrix matrix to store * @param ledMatrixInfo infos used to create the LED matrix */ - @SuppressWarnings("IntegerDivisionInFloatingPointContext") + @SuppressWarnings({"All"}) void initializeLedMatrix(LinkedHashMap defaultLedMatrix, Enums.AspectRatio aspectRatio, LedMatrixInfo ledMatrixInfo) { // Store original values before grouping them ledMatrixInfo.setBottomRightLedOriginal(ledMatrixInfo.getBottomRightLed()); @@ -186,12 +251,12 @@ private int leftLed(LinkedHashMap defaultLedMatrix, LedM y = Math.max(0, (((ledMatrixInfo.getScreenHeight() - (leftLedDistance * i)) - cornerGapTopBottomAccurate) + ledMatrixInfo.getLetterboxBorder()) - calculateTaleBorder(ledMatrixInfo.getScreenWidth())); taleWidth = ledMatrixInfo.getSideAreaWidth(); taleHeight = leftLedDistance; - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.LEFT.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getLeftLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.LEFT.getBaseI18n())); ledInsertionNumber++; } } @@ -217,15 +282,17 @@ private void bottomLeft(LinkedHashMap defaultLedMatrix, taleWidth = bottomLedLeftDistance; taleHeight = ledMatrixInfo.getTopBottomAreaHeight(); for (int groupIndex = 0; groupIndex < ledMatrixInfo.getGroupBy(); groupIndex++) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.BOTTOM_LEFT.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getBottomLeftLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.BOTTOM_LEFT.getBaseI18n())); ledInsertionNumber++; } } + + } } @@ -250,12 +317,12 @@ private int topLed(LinkedHashMap defaultLedMatrix, LedMa taleWidth = topLedDistance; taleHeight = ledMatrixInfo.getTopBottomAreaHeight(); for (int groupIndex = 0; groupIndex < ledMatrixInfo.getGroupBy(); groupIndex++) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.TOP.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getTopLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.TOP.getBaseI18n())); ledInsertionNumber++; } } @@ -283,12 +350,12 @@ private int rightLed(LinkedHashMap defaultLedMatrix, Led taleWidth = ledMatrixInfo.getSideAreaWidth(); taleHeight = rightLedDistance; for (int groupIndex = 0; groupIndex < ledMatrixInfo.getGroupBy(); groupIndex++) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.RIGHT.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getRightLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.RIGHT.getBaseI18n())); ledInsertionNumber++; } } @@ -314,12 +381,12 @@ private int bottomLed(LinkedHashMap defaultLedMatrix, Le taleWidth = ledMatrixInfo.getBottomLedDistance(); taleHeight = ledMatrixInfo.getTopBottomAreaHeight(); for (int groupIndex = 0; groupIndex < ledMatrixInfo.getGroupBy(); groupIndex++) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.BOTTOM.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getBottomRowLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.BOTTOM.getBaseI18n())); ledInsertionNumber++; } } @@ -344,15 +411,26 @@ private int bottomRightLed(LinkedHashMap defaultLedMatri taleWidth = ledMatrixInfo.getBottomLedDistance(); taleHeight = ledMatrixInfo.getTopBottomAreaHeight(); for (int groupIndex = 0; groupIndex < ledMatrixInfo.getGroupBy(); groupIndex++) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, groupIndex != 0, Enums.SatelliteZone.BOTTOM_RIGHT.getBaseI18n())); ledInsertionNumber++; } } while (ledInsertionNumber < ledMatrixInfo.getBottomRightLedOriginal()) { - defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true)); + defaultLedMatrix.put(++ledNum, new LEDCoordinate(x, y, taleWidth, taleHeight, true, Enums.SatelliteZone.BOTTOM_RIGHT.getBaseI18n())); ledInsertionNumber++; } } return ledNum; } + + /** + * + + * Small record for satellites + * + * @param start zone where satellite starts + * @param end zone where satellite ends + */ + public record getStartEndLeds(int start, int end) { + } + } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/MainSingleton.java b/src/main/java/org/dpsoftware/MainSingleton.java new file mode 100644 index 000000000..04c773498 --- /dev/null +++ b/src/main/java/org/dpsoftware/MainSingleton.java @@ -0,0 +1,102 @@ +/* + MainSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware; + +import gnu.io.SerialPort; +import javafx.application.HostServices; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.config.Configuration; +import org.dpsoftware.gui.GuiManager; + +import java.awt.*; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.ResourceBundle; +import java.util.concurrent.BlockingQueue; + +/** + * Main singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +public class MainSingleton { + + @Getter + private final static MainSingleton instance; + + static { + instance = new MainSingleton(); + } + + // Who am I supposed to be? Used to manage multiple instances of Luciferin running at the same time + public int whoAmI = 1; + public boolean spawnInstances = true; // set this to false to avoid spawning new instances on multi monitor setup + // Calculate Screen Capture Framerate and how fast your microcontroller can consume it + public float FPS_CONSUMER_COUNTER; + public float FPS_PRODUCER_COUNTER; + public float FPS_CONSUMER = 0; + public float FPS_PRODUCER = 0; + public float FPS_GW_CONSUMER = 0; + public SimpleDateFormat formatter; + public SerialPort serial; + public OutputStream output; + public boolean serialConnected = false; + public int baudRate = 0; + // LED strip, monitor and microcontroller config + public Configuration config; + // Start and Stop threads + public boolean RUNNING = false; + // This queue orders elements FIFO. Producer offers some data, consumer throws data to the Serial port + public BlockingQueue sharedQueue; + public Color[] lastLedColor; + // Number of LEDs on the strip + public int ledNumber; + public int ledNumHighLowCount; + public int ledNumHighLowCountSecondPart; + public GuiManager guiManager; + public boolean communicationError = false; + public Color colorInUse; + public int gpio = 0; // 0 means not set, firmware discards this value + public int colorOrder = 0; // 1 means GRB, 2 RGB, 3 BGR + public int ldrAction = 0; // 1 no action, 2 calibrate, 3 reset, 4 save + public int fireflyEffect = 0; + public int relayPin = -1; + public int sbPin = -1; + public int ldrPin = -1; + public int gpioClockPin = 0; + public boolean nightMode = false; + public String version = ""; + public String minimumFirmwareVersion = ""; + public ResourceBundle bundle; + public String profileArgs; + public HostServices hostServices; + public boolean closeOtherInstaces = false; + public int wifiStrength = 0; + public int ldrStrength = 0; + public boolean restartOnly = false; + public boolean exitTriggered = false; + +} + diff --git a/src/main/java/org/dpsoftware/NativeExecutor.java b/src/main/java/org/dpsoftware/NativeExecutor.java index 55321ce45..ae5514393 100644 --- a/src/main/java/org/dpsoftware/NativeExecutor.java +++ b/src/main/java/org/dpsoftware/NativeExecutor.java @@ -25,14 +25,13 @@ import com.sun.jna.platform.win32.WinReg; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.managers.dto.StateStatusDto; +import org.dpsoftware.managers.PipelineManager; import org.dpsoftware.managers.dto.mqttdiscovery.SensorProducingDiscovery; -import org.dpsoftware.network.MessageClient; -import org.dpsoftware.network.tcpUdp.UdpServer; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.utilities.CommonUtility; import java.awt.*; @@ -53,9 +52,6 @@ @NoArgsConstructor public final class NativeExecutor { - public static boolean restartOnly = false; - public static boolean exitTriggered = false; - /** * This is the real runner that executes command. * Don't use this method directly and prefer the runNativeWaitForOutput() or runNativeNoWaitForOutput() shortcut. @@ -111,14 +107,14 @@ public static void spawnNewInstance(int whoAmISupposedToBe) { * Check if I'm the main program, if yes and multi monitor, spawn other guys */ public static void spawnNewInstances() { - if (JavaFXStarter.spawnInstances && FireflyLuciferin.config.getMultiMonitor() > 1) { - if (FireflyLuciferin.config.getMultiMonitor() == 3) { + if (MainSingleton.getInstance().spawnInstances && MainSingleton.getInstance().config.getMultiMonitor() > 1) { + if (MainSingleton.getInstance().config.getMultiMonitor() == 3) { NativeExecutor.spawnNewInstance(1); NativeExecutor.spawnNewInstance(2); NativeExecutor.spawnNewInstance(3); } else { NativeExecutor.spawnNewInstance(1); - if (FireflyLuciferin.config.getMultiMonitor() == 2) { + if (MainSingleton.getInstance().config.getMultiMonitor() == 2) { NativeExecutor.spawnNewInstance(2); } } @@ -143,13 +139,13 @@ public static void restartNativeInstance(String profileToUse) { log.info("Installation path from restart={}", getInstallationPath()); List execCommand = new ArrayList<>(); execCommand.add(getInstallationPath()); - execCommand.add(String.valueOf(JavaFXStarter.whoAmI)); + execCommand.add(String.valueOf(MainSingleton.getInstance().whoAmI)); if (profileToUse != null) { execCommand.add(profileToUse); } runNative(execCommand.toArray(String[]::new), 0); if (CommonUtility.isSingleDeviceMultiScreen()) { - restartOnly = true; + MainSingleton.getInstance().restartOnly = true; } NativeExecutor.exit(); } @@ -208,6 +204,15 @@ public static boolean isLinux() { return com.sun.jna.Platform.isLinux(); } + /** + * Check if Wayland + * + * @return if it's Wayland + */ + public static boolean isWayland() { + return isLinux() && System.getenv(Constants.DISPLAY_MANAGER_CHK).equalsIgnoreCase(Constants.WAYLAND); + } + /** * Single point to fake the OS if needed * @@ -240,9 +245,9 @@ public static boolean isSystemTraySupported() { */ public static void addShutdownHook() { Thread hook = new Thread(() -> { - if (!exitTriggered) { + if (!MainSingleton.getInstance().exitTriggered) { log.info("Exit hook triggered."); - exitTriggered = true; + MainSingleton.getInstance().exitTriggered = true; lastWill(); } }); @@ -255,13 +260,15 @@ public static void addShutdownHook() { * when the OS entered the shutdown/reboot phase. */ private static void lastWill() { - if (!Enums.PowerSaving.DISABLED.equals(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, - FireflyLuciferin.config.getPowerSaving()))) { - CommonUtility.turnOffLEDs(FireflyLuciferin.config, 1); - } - if (FireflyLuciferin.config.isMqttEnable()) { - SensorProducingDiscovery sensorProducingDiscovery = new SensorProducingDiscovery(); - sensorProducingDiscovery.setZeroValue(); + if (MainSingleton.getInstance().config.getSatellites().isEmpty() || PipelineManager.isSatellitesEngaged()) { + if (!Enums.PowerSaving.DISABLED.equals(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, + MainSingleton.getInstance().config.getPowerSaving()))) { + CommonUtility.turnOffLEDs(MainSingleton.getInstance().config, 1); + } + if (MainSingleton.getInstance().config.isMqttEnable()) { + SensorProducingDiscovery sensorProducingDiscovery = new SensorProducingDiscovery(); + sensorProducingDiscovery.setZeroValue(); + } } } @@ -269,33 +276,34 @@ private static void lastWill() { * Gracefully exit the app, this method is called manually. */ public static void exit() { - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } - exitTriggered = true; + MainSingleton.getInstance().exitTriggered = true; log.info(Constants.CLEAN_EXIT); - UdpServer.udpBroadcastReceiverRunning = false; + NetworkSingleton.getInstance().udpBroadcastReceiverRunning = false; exitOtherInstances(); - if (FireflyLuciferin.serial != null) { - FireflyLuciferin.serial.removeEventListener(); - FireflyLuciferin.serial.close(); + if (MainSingleton.getInstance().serial != null) { + MainSingleton.getInstance().serial.removeEventListener(); + MainSingleton.getInstance().serial.close(); } - AudioLoopback.RUNNING_AUDIO = false; - lastWill(); - CommonUtility.sleepSeconds(2); - System.exit(0); + AudioSingleton.getInstance().RUNNING_AUDIO = false; + CommonUtility.delaySeconds(() -> { + lastWill(); + System.exit(0); + }, 2); } /** * Exit single device instances */ static void exitOtherInstances() { - if (!NativeExecutor.restartOnly) { + if (!MainSingleton.getInstance().restartOnly) { if (CommonUtility.isSingleDeviceMainInstance()) { - StateStatusDto.closeOtherInstaces = true; + MainSingleton.getInstance().closeOtherInstaces = true; CommonUtility.sleepSeconds(6); } else if (CommonUtility.isSingleDeviceOtherInstance()) { - MessageClient.msgClient.sendMessage(Constants.EXIT); + NetworkSingleton.getInstance().msgClient.sendMessage(Constants.EXIT); CommonUtility.sleepSeconds(6); } } @@ -324,6 +332,20 @@ public static boolean isScreenSaverEnabled() { Constants.REGISTRY_KEY_NAME_SCREEN_SAVER); } + /** + * Change thread priority to high = 128 + */ + public static void setHighPriorityThreads(String priority) { + if (isWindows()) { + CommonUtility.delaySeconds(() -> { + log.info("Changing thread priority to -> " + priority); + String[] cmd = {Constants.CMD_POWERSHELL, Constants.CMD_SET_PRIORITY + .replace("{0}", String.valueOf(Enums.ThreadPriority.valueOf(priority).getValue()))}; + NativeExecutor.runNative(cmd, 0); + }, 1); + } + } + /** * Write Windows registry key to Launch Firefly Luciferin when system starts */ @@ -349,18 +371,4 @@ public void deleteRegistryKey() { } } - /** - * Change thread priority to high = 128 - */ - public static void setHighPriorityThreads(String priority) { - if (isWindows()) { - CommonUtility.delaySeconds(() -> { - log.info("Changing thread priority to -> " + priority); - String[] cmd = {Constants.CMD_POWERSHELL, Constants.CMD_SET_PRIORITY - .replace("{0}", String.valueOf(Enums.ThreadPriority.valueOf(priority).getValue()))}; - NativeExecutor.runNative(cmd, 0); - }, 1); - } - } - } diff --git a/src/main/java/org/dpsoftware/audio/AudioLoopback.java b/src/main/java/org/dpsoftware/audio/AudioLoopback.java index 5bfba47c0..56b10e13f 100644 --- a/src/main/java/org/dpsoftware/audio/AudioLoopback.java +++ b/src/main/java/org/dpsoftware/audio/AudioLoopback.java @@ -22,16 +22,13 @@ package org.dpsoftware.audio; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.managers.dto.AudioDevice; -import org.dpsoftware.network.MessageServer; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.utilities.CommonUtility; import java.awt.*; -import java.util.LinkedHashMap; -import java.util.Map; /** * Manage Audio loopback and retrieve peaks and RMS values @@ -39,13 +36,59 @@ @Slf4j public class AudioLoopback { - public static volatile boolean RUNNING_AUDIO = false; - public static int AUDIO_BRIGHTNESS = 255; - public static Map audioDevices = new LinkedHashMap<>(); - public static float rainbowHue = 0; - static float maxPeak, maxRms = 0; - static float maxPeakLeft, maxRmsLeft = 0; - static float maxPeakRight, maxRmsRight = 0; + private float maxPeak, maxRms = 0; + private float maxPeakLeft, maxRmsLeft = 0; + private float maxPeakRight, maxRmsRight = 0; + private float rainbowHue = 0; + + /** + * To right rotate arr[] by offset + * + * @param arr array to rotate + * @param offset rotate by offset + */ + void rightRotate(Color[] arr, int offset) { + int length = arr.length; + // If arr is rotated length times then you get the same array + while (offset > length) { + offset = offset - length; + } + // Creating a temporary array of size offset + Color[] temp = new Color[length - offset]; + // Now copying first length-offset element in array temp + if (length - offset >= 0) { + System.arraycopy(arr, 0, temp, 0, length - offset); + } + // Moving the rest element to index zero to offset + if (length - (length - offset) >= 0) { + System.arraycopy(arr, length - offset, arr, -offset + offset, length - (length - offset)); + } + // Copying the temp array element in original array + if (length - offset >= 0) { + System.arraycopy(temp, 0, arr, offset, length - offset); + } + } + + /** + * To left rotate arr[] by offset + * + * @param arr array to rotate + * @param offset rotate by offset + */ + @SuppressWarnings("unused") + void leftRotate(Color[] arr, int offset) { + int length = arr.length; + // Creating temp array of size offset + Color[] temp = new Color[offset]; + // Copying first offset element in array temp + System.arraycopy(arr, 0, temp, 0, offset); + // Moving the rest element to index zero to length-offset + if (length - offset >= 0) { + System.arraycopy(arr, offset, arr, 0, length - offset); + } + // Copying the temp array element in original array + System.arraycopy(temp, 0, arr, length - offset, offset); + } /** * Choose what to send to the LED strip @@ -54,10 +97,10 @@ public class AudioLoopback { * @param rms RMS value on the sine wave * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ - public static void driveLedStrip(float lastPeak, float rms, float tolerance) { - if (Enums.Effect.MUSIC_MODE_VU_METER.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + public void driveLedStrip(float lastPeak, float rms, float tolerance) { + if (Enums.Effect.MUSIC_MODE_VU_METER.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { sendAudioInfoToStrip(lastPeak, rms, tolerance); - } else if (Enums.Effect.MUSIC_MODE_RAINBOW.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + } else if (Enums.Effect.MUSIC_MODE_RAINBOW.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { sendAudioInfoToStrip(lastPeak, rms, tolerance); setAudioBrightness(lastPeak); } else { @@ -74,7 +117,7 @@ public static void driveLedStrip(float lastPeak, float rms, float tolerance) { * @param rmsRight RMS value on the sine wave * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ - public static void driveLedStrip(float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { + public void driveLedStrip(float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { sendAudioInfoToStrip(lastPeakLeft, rmsLeft, lastPeakRight, rmsRight, tolerance); } @@ -86,21 +129,21 @@ public static void driveLedStrip(float lastPeakLeft, float rmsLeft, float lastPe * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ @SuppressWarnings("ResultOfMethodCallIgnored") - public static void sendAudioInfoToStrip(float lastPeak, float rms, float tolerance) { + public void sendAudioInfoToStrip(float lastPeak, float rms, float tolerance) { maxRms = Math.max(rms, maxRms); maxPeak = Math.max(lastPeak, maxPeak); // log.info("Peak: {} RMS: {} - MaxPeak: {} MaxRMS: {}", lastPeak, rms, maxPeak, maxRms); - Color[] leds = new Color[MessageServer.totalLedNum]; + Color[] leds = new Color[NetworkSingleton.getInstance().totalLedNum]; - if (Enums.Effect.MUSIC_MODE_VU_METER.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + if (Enums.Effect.MUSIC_MODE_VU_METER.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { calculateVuMeterEffect(leds, lastPeak, rms, tolerance); - } else if (Enums.Effect.MUSIC_MODE_RAINBOW.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + } else if (Enums.Effect.MUSIC_MODE_RAINBOW.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { calculateRainbowEffect(leds); } - FireflyLuciferin.FPS_PRODUCER_COUNTER++; + MainSingleton.getInstance().FPS_PRODUCER_COUNTER++; if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { - FireflyLuciferin.sharedQueue.offer(leds); + MainSingleton.getInstance().sharedQueue.offer(leds); } } @@ -114,17 +157,17 @@ public static void sendAudioInfoToStrip(float lastPeak, float rms, float toleran * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ @SuppressWarnings("ResultOfMethodCallIgnored") - public static void sendAudioInfoToStrip(float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { + public void sendAudioInfoToStrip(float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { maxRmsLeft = Math.max(rmsLeft, maxRmsLeft); maxPeakLeft = Math.max(lastPeakLeft, maxPeakLeft); maxRmsRight = Math.max(rmsLeft, maxRmsRight); maxPeakRight = Math.max(lastPeakLeft, maxPeakRight); // log.info("Peak: {} RMS: {} - MaxPeak: {} MaxRMS: {}", lastPeak, rms, maxPeak, maxRms); - Color[] leds = new Color[MessageServer.totalLedNum]; + Color[] leds = new Color[NetworkSingleton.getInstance().totalLedNum]; calculateVuMeterEffectDual(leds, lastPeakLeft, rmsLeft, lastPeakRight, rmsRight, tolerance); - FireflyLuciferin.FPS_PRODUCER_COUNTER++; + MainSingleton.getInstance().FPS_PRODUCER_COUNTER++; if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { - FireflyLuciferin.sharedQueue.offer(leds); + MainSingleton.getInstance().sharedQueue.offer(leds); } } @@ -133,9 +176,9 @@ public static void sendAudioInfoToStrip(float lastPeakLeft, float rmsLeft, float * * @param lastPeak lastPeak during audio recording */ - public static void setAudioBrightness(float lastPeak) { + public void setAudioBrightness(float lastPeak) { int brigthness = (int) (254f * lastPeak); - AUDIO_BRIGHTNESS = Math.min(brigthness, 254); + AudioSingleton.getInstance().AUDIO_BRIGHTNESS = Math.min(brigthness, 254); } /** @@ -146,18 +189,18 @@ public static void setAudioBrightness(float lastPeak) { * @param rms RMS value on the sine wave * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ - private static void calculateVuMeterEffect(Color[] leds, float lastPeak, float rms, float tolerance) { - for (int i = 0; i < MessageServer.totalLedNum; i++) { + private void calculateVuMeterEffect(Color[] leds, float lastPeak, float rms, float tolerance) { + for (int i = 0; i < NetworkSingleton.getInstance().totalLedNum; i++) { leds[i] = new Color(0, 0, 255); } - int peakLeds = (int) ((MessageServer.totalLedNum * lastPeak) * tolerance); + int peakLeds = (int) ((NetworkSingleton.getInstance().totalLedNum * lastPeak) * tolerance); int peakYellowLeds = ((peakLeds * 30) / 100); - int rmsLeds = (int) ((MessageServer.totalLedNum * rms) * tolerance); - if (peakLeds > MessageServer.totalLedNum) { - peakLeds = MessageServer.totalLedNum; + int rmsLeds = (int) ((NetworkSingleton.getInstance().totalLedNum * rms) * tolerance); + if (peakLeds > NetworkSingleton.getInstance().totalLedNum) { + peakLeds = NetworkSingleton.getInstance().totalLedNum; } - if (rmsLeds > MessageServer.totalLedNum) { - rmsLeds = MessageServer.totalLedNum; + if (rmsLeds > NetworkSingleton.getInstance().totalLedNum) { + rmsLeds = NetworkSingleton.getInstance().totalLedNum; } setLedsColor(leds, peakLeds, peakYellowLeds, rmsLeds); } @@ -172,9 +215,9 @@ private static void calculateVuMeterEffect(Color[] leds, float lastPeak, float r * @param rmsRight RMS value on the sine wave * @param tolerance lower the gain, we don't want to set volume to 100% to use all the strip */ - private static void calculateVuMeterEffectDual(Color[] leds, float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { - int ledNumDual = ((MessageServer.totalLedNum % 2) == 0) ? (MessageServer.totalLedNum / 2) : ((MessageServer.totalLedNum / 2) + 1); - for (int i = 0; i < MessageServer.totalLedNum; i++) { + private void calculateVuMeterEffectDual(Color[] leds, float lastPeakLeft, float rmsLeft, float lastPeakRight, float rmsRight, float tolerance) { + int ledNumDual = ((NetworkSingleton.getInstance().totalLedNum % 2) == 0) ? (NetworkSingleton.getInstance().totalLedNum / 2) : ((NetworkSingleton.getInstance().totalLedNum / 2) + 1); + for (int i = 0; i < NetworkSingleton.getInstance().totalLedNum; i++) { leds[i] = new Color(0, 0, 255); } int peakLeds = (int) ((ledNumDual * lastPeakRight) * tolerance); @@ -187,7 +230,7 @@ private static void calculateVuMeterEffectDual(Color[] leds, float lastPeakLeft, rmsLeds = ledNumDual; } setLedsColor(leds, peakLeds, peakYellowLeds, rmsLeds); - ledNumDual = MessageServer.totalLedNum / 2; + ledNumDual = NetworkSingleton.getInstance().totalLedNum / 2; peakLeds = (int) ((ledNumDual * lastPeakLeft) * tolerance); peakYellowLeds = ((peakLeds * 30) / 100); rmsLeds = (int) ((ledNumDual * rmsLeft) * tolerance); @@ -199,68 +242,19 @@ private static void calculateVuMeterEffectDual(Color[] leds, float lastPeakLeft, } for (int i = 1; i <= peakLeds; i++) { if (i <= (peakLeds - peakYellowLeds)) { - leds[MessageServer.totalLedNum - i] = new Color(255, 255, 0); + leds[NetworkSingleton.getInstance().totalLedNum - i] = new Color(255, 255, 0); } else { - leds[MessageServer.totalLedNum - i] = new Color(255, 0, 0); + leds[NetworkSingleton.getInstance().totalLedNum - i] = new Color(255, 0, 0); } } for (int i = 1; i <= rmsLeds; i++) { - leds[MessageServer.totalLedNum - i] = new Color(0, 255, 0); + leds[NetworkSingleton.getInstance().totalLedNum - i] = new Color(0, 255, 0); } - if (!CommonUtility.isSplitBottomRow(FireflyLuciferin.config.getSplitBottomMargin())) { - rightRotate(leds, FireflyLuciferin.config.getBottomRowLed() / 2); + if (!CommonUtility.isSplitBottomRow(MainSingleton.getInstance().config.getSplitBottomMargin())) { + rightRotate(leds, MainSingleton.getInstance().config.getBottomRowLed() / 2); } } - /** - * To right rotate arr[] by offset - * - * @param arr array to rotate - * @param offset rotate by offset - */ - static void rightRotate(Color[] arr, int offset) { - int length = arr.length; - // If arr is rotated length times then you get the same array - while (offset > length) { - offset = offset - length; - } - // Creating a temporary array of size offset - Color[] temp = new Color[length - offset]; - // Now copying first length-offset element in array temp - if (length - offset >= 0) { - System.arraycopy(arr, 0, temp, 0, length - offset); - } - // Moving the rest element to index zero to offset - if (length - (length - offset) >= 0) { - System.arraycopy(arr, length - offset, arr, -offset + offset, length - (length - offset)); - } - // Copying the temp array element in original array - if (length - offset >= 0) { - System.arraycopy(temp, 0, arr, offset, length - offset); - } - } - - /** - * To left rotate arr[] by offset - * - * @param arr array to rotate - * @param offset rotate by offset - */ - @SuppressWarnings("unused") - static void leftRotate(Color[] arr, int offset) { - int length = arr.length; - // Creating temp array of size offset - Color[] temp = new Color[offset]; - // Copying first offset element in array temp - System.arraycopy(arr, 0, temp, 0, offset); - // Moving the rest element to index zero to length-offset - if (length - offset >= 0) { - System.arraycopy(arr, offset, arr, 0, length - offset); - } - // Copying the temp array element in original array - System.arraycopy(temp, 0, arr, length - offset, offset); - } - /** * Set LEDs color based on peaks and rms * @@ -269,7 +263,7 @@ static void leftRotate(Color[] arr, int offset) { * @param peakYellowLeds yellow audio peaks * @param rmsLeds rms audio */ - private static void setLedsColor(Color[] leds, int peakLeds, int peakYellowLeds, int rmsLeds) { + private void setLedsColor(Color[] leds, int peakLeds, int peakYellowLeds, int rmsLeds) { for (int i = 0; i < peakLeds; i++) { if (i < (peakLeds - peakYellowLeds)) { leds[i] = new Color(255, 255, 0); @@ -287,8 +281,8 @@ private static void setLedsColor(Color[] leds, int peakLeds, int peakYellowLeds, * * @param leds LEDs array to send to the strip */ - private static void calculateRainbowEffect(Color[] leds) { - for (int i = 0; i < MessageServer.totalLedNum; i++) { + private void calculateRainbowEffect(Color[] leds) { + for (int i = 0; i < NetworkSingleton.getInstance().totalLedNum; i++) { leds[i] = Color.getHSBColor(rainbowHue, 1.0f, 1.0f); } if (rainbowHue >= 1) rainbowHue = 0; @@ -299,7 +293,7 @@ private static void calculateRainbowEffect(Color[] leds) { * Stop capturing audio levels */ public void stopVolumeLevelMeter() { - RUNNING_AUDIO = false; + AudioSingleton.getInstance().RUNNING_AUDIO = false; } } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/audio/AudioLoopbackNative.java b/src/main/java/org/dpsoftware/audio/AudioLoopbackNative.java index 1cddaa6d2..d96aa49b4 100644 --- a/src/main/java/org/dpsoftware/audio/AudioLoopbackNative.java +++ b/src/main/java/org/dpsoftware/audio/AudioLoopbackNative.java @@ -22,7 +22,7 @@ package org.dpsoftware.audio; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; @@ -46,8 +46,8 @@ public class AudioLoopbackNative extends AudioLoopback implements AudioUtility { final int bufferByteSize = 2048; - AudioFormat fmt = new AudioFormat(FireflyLuciferin.config.getSampleRate() == 0 ? Constants.DEFAULT_SAMPLE_RATE_NATIVE : FireflyLuciferin.config.getSampleRate(), - 16, Integer.parseInt(FireflyLuciferin.config.getAudioChannels().substring(0, 1)), true, true); + AudioFormat fmt = new AudioFormat(MainSingleton.getInstance().config.getSampleRate() == 0 ? Constants.DEFAULT_SAMPLE_RATE_NATIVE : MainSingleton.getInstance().config.getSampleRate(), + 16, Integer.parseInt(MainSingleton.getInstance().config.getAudioChannels().substring(0, 1)), true, true); TargetDataLine line; /** @@ -58,7 +58,7 @@ public class AudioLoopbackNative extends AudioLoopback implements AudioUtility { * @param channel audio channels 0 = Left, 1 = Right * @return peaks, rms and tolerance */ - private static AudioVuMeter calculatePeakAndRMS(byte[] buf, float[] samples, int channel) { + private AudioVuMeter calculatePeakAndRMS(byte[] buf, float[] samples, int channel) { float lastPeak = 0f; for (int i = 0, s = 0; i < buf.length; i += 4) { int sample; @@ -82,7 +82,7 @@ private static AudioVuMeter calculatePeakAndRMS(byte[] buf, float[] samples, int peak = lastPeak * 0.875f; } lastPeak = peak; - float tolerance = 1.3f + ((FireflyLuciferin.config.getAudioLoopbackGain() * 0.1f) * 2); + float tolerance = 1.3f + ((MainSingleton.getInstance().config.getAudioLoopbackGain() * 0.1f) * 2); if (lastPeak > tolerance) lastPeak = tolerance; if (rms > tolerance) rms = tolerance; @@ -94,7 +94,7 @@ private static AudioVuMeter calculatePeakAndRMS(byte[] buf, float[] samples, int * RMS and Peaks from the stream and send it to the strip */ public void startVolumeLevelMeter() { - RUNNING_AUDIO = true; + AudioSingleton.getInstance().RUNNING_AUDIO = true; ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledExecutorService.schedule(() -> { @@ -104,16 +104,16 @@ public void startVolumeLevelMeter() { } catch (LineUnavailableException | IllegalArgumentException e) { log.error(e.getMessage()); - RUNNING_AUDIO = false; - FireflyLuciferin.guiManager.stopCapturingThreads(true); + AudioSingleton.getInstance().RUNNING_AUDIO = false; + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } byte[] buf = new byte[bufferByteSize]; float[] samples = new float[bufferByteSize / 2]; line.start(); - while (((line.read(buf, 0, buf.length)) > -1) && RUNNING_AUDIO) { + while (((line.read(buf, 0, buf.length)) > -1) && AudioSingleton.getInstance().RUNNING_AUDIO) { AudioVuMeter audioVuMeterLeft; AudioVuMeter audioVuMeterRight; - if (Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + if (Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { audioVuMeterLeft = calculatePeakAndRMS(buf, samples, 0); audioVuMeterRight = calculatePeakAndRMS(buf, samples, 1); driveLedStrip(audioVuMeterLeft.getPeak(), audioVuMeterLeft.getRms(), audioVuMeterRight.getPeak(), diff --git a/src/main/java/org/dpsoftware/audio/AudioLoopbackSoftware.java b/src/main/java/org/dpsoftware/audio/AudioLoopbackSoftware.java index 178ed616e..e67e78cea 100644 --- a/src/main/java/org/dpsoftware/audio/AudioLoopbackSoftware.java +++ b/src/main/java/org/dpsoftware/audio/AudioLoopbackSoftware.java @@ -23,7 +23,7 @@ import com.sun.jna.Pointer; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; import org.dpsoftware.config.LocalizedEnum; @@ -45,9 +45,18 @@ @Slf4j public class AudioLoopbackSoftware extends AudioLoopback implements AudioUtility { - static int runNumber = 0; - static float lastRmsRun = 0, lastRmsRunLeft = 0, lastRmsRunRight = 0; - static float lastPeackRun = 0, lastPeackRunLeft = 0, lastPeackRunRight = 0; + int runNumber = 0; + float lastRmsRun = 0, lastRmsRunLeft = 0, lastRmsRunRight = 0; + float lastPeackRun = 0, lastPeackRunLeft = 0, lastPeackRunRight = 0; + + /** + * Log the error message + * + * @param message error msg + */ + static void onError(String message) { + log.trace(message); + } /** * Callback called ever 10ms containing the audio stream, calculate RMS and Peaks from the stream @@ -58,7 +67,7 @@ public class AudioLoopbackSoftware extends AudioLoopback implements AudioUtility * @param audioData audio data * @return non significative one */ - static int onBuffer(XtStream stream, Structs.XtBuffer buffer, Object audioData) { + int onBuffer(XtStream stream, Structs.XtBuffer buffer, Object audioData) { XtSafeBuffer safe = XtSafeBuffer.get(stream); if (safe != null) { safe.lock(buffer); @@ -76,7 +85,7 @@ static int onBuffer(XtStream stream, Structs.XtBuffer buffer, Object audioData) * @param buffer audio buffer * @param samples audio samples */ - static void buildStereoPeaks(Structs.XtBuffer buffer, float[] samples) { + void buildStereoPeaks(Structs.XtBuffer buffer, float[] samples) { float lastPeak = 0f; float rms = 0f; float peak = 0f; @@ -121,7 +130,7 @@ static void buildStereoPeaks(Structs.XtBuffer buffer, float[] samples) { lastPeak = peak; lastPeakLeft = peakLeft; lastPeakRight = peakRight; - float tolerance = 1.0f + ((FireflyLuciferin.config.getAudioLoopbackGain() * 0.1f) * 2); + float tolerance = 1.0f + ((MainSingleton.getInstance().config.getAudioLoopbackGain() * 0.1f) * 2); // WASAPI runs every 10ms giving 100FPS, average reading and reduce it by 5 for 20FPS if (runNumber < 5) { if (lastPeak > lastPeackRun) { @@ -151,7 +160,7 @@ static void buildStereoPeaks(Structs.XtBuffer buffer, float[] samples) { lastRmsRunRight = 0f; lastPeackRunRight = 0f; // Send RMS and Peaks value to the LED strip - if (org.dpsoftware.config.Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(LocalizedEnum.fromBaseStr(org.dpsoftware.config.Enums.Effect.class, FireflyLuciferin.config.getEffect()))) { + if (org.dpsoftware.config.Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(LocalizedEnum.fromBaseStr(org.dpsoftware.config.Enums.Effect.class, MainSingleton.getInstance().config.getEffect()))) { driveLedStrip(lastPeakLeft, rmsLeft, lastPeakRight, rmsRight, tolerance); } else { driveLedStrip(lastPeak, rms, tolerance); @@ -167,14 +176,14 @@ static void buildStereoPeaks(Structs.XtBuffer buffer, float[] samples) { * @param addDevice add device to the system device list * @param defaultOutputId default output to use */ - static void printDevices(XtService service, XtDeviceList list, boolean addDevice, String defaultOutputId) { + void printDevices(XtService service, XtDeviceList list, boolean addDevice, String defaultOutputId) { for (int d = 0; d < list.getCount(); d++) { String id = list.getId(d); try (XtDevice device = service.openDevice(id)) { Optional mix = device.getMix(); String deviceName = list.getName(id); - AtomicInteger sampleRate = new AtomicInteger(FireflyLuciferin.config.getSampleRate() == 0 ? - Constants.DEFAULT_SAMPLE_RATE : FireflyLuciferin.config.getSampleRate()); + AtomicInteger sampleRate = new AtomicInteger(MainSingleton.getInstance().config.getSampleRate() == 0 ? + Constants.DEFAULT_SAMPLE_RATE : MainSingleton.getInstance().config.getSampleRate()); log.trace(" Device " + id + ":"); log.trace(" Name: " + deviceName); log.trace(" Capabilities: " + list.getCapabilities(id)); @@ -187,10 +196,10 @@ static void printDevices(XtService service, XtDeviceList list, boolean addDevice sampleRate.set(xtMix.rate); }); if (id.equals(defaultOutputId)) { - AudioLoopback.audioDevices.get(id).setSampleRate(sampleRate.get()); + AudioSingleton.getInstance().audioDevices.get(id).setSampleRate(sampleRate.get()); } if (addDevice && deviceName.contains(Constants.LOOPBACK)) { - AudioLoopback.audioDevices.put(id, new AudioDevice(deviceName, sampleRate.get())); + AudioSingleton.getInstance().audioDevices.put(id, new AudioDevice(deviceName, sampleRate.get())); } } catch (XtException e) { log.trace(String.valueOf(XtAudio.getErrorInfo(e.getError()))); @@ -198,22 +207,13 @@ static void printDevices(XtService service, XtDeviceList list, boolean addDevice } } - /** - * Log the error message - * - * @param message error msg - */ - static void onError(String message) { - log.trace(message); - } - /** * Start software capturing audio levels, does not require a native audio loopback in the OS */ @SuppressWarnings("unused") public void startVolumeLevelMeter() { AtomicBoolean audioEngaged = new AtomicBoolean(false); - RUNNING_AUDIO = true; + AudioSingleton.getInstance().RUNNING_AUDIO = true; ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledExecutorService.scheduleAtFixedRate(() -> { @@ -227,20 +227,20 @@ public void startVolumeLevelMeter() { String id = list.getId(count); String devi = list.getName(id); EnumSet caps = list.getCapabilities(id); - String defaultDeviceStr = audioDevices.entrySet().iterator().next().getValue().getDeviceName(); - int sampleRate = audioDevices.entrySet().iterator().next().getValue().getSampleRate(); - String idd = audioDevices.entrySet().iterator().next().getKey(); + String defaultDeviceStr = AudioSingleton.getInstance().audioDevices.entrySet().iterator().next().getValue().getDeviceName(); + int sampleRate = AudioSingleton.getInstance().audioDevices.entrySet().iterator().next().getValue().getSampleRate(); + String idd = AudioSingleton.getInstance().audioDevices.entrySet().iterator().next().getKey(); - if (FireflyLuciferin.config.getAudioDevice().equals(org.dpsoftware.config.Enums.Audio.DEFAULT_AUDIO_OUTPUT_WASAPI.getBaseI18n())) { + if (MainSingleton.getInstance().config.getAudioDevice().equals(org.dpsoftware.config.Enums.Audio.DEFAULT_AUDIO_OUTPUT_WASAPI.getBaseI18n())) { defaultDeviceStr = defaultDeviceStr.substring(0, defaultDeviceStr.lastIndexOf("(")); } else { - defaultDeviceStr = FireflyLuciferin.config.getAudioDevice().substring(0, FireflyLuciferin.config.getAudioDevice().lastIndexOf("(")); + defaultDeviceStr = MainSingleton.getInstance().config.getAudioDevice().substring(0, MainSingleton.getInstance().config.getAudioDevice().lastIndexOf("(")); } if (caps.contains(Enums.XtDeviceCaps.LOOPBACK) && (devi.substring(0, devi.lastIndexOf("(")).equals(defaultDeviceStr))) { try (XtDevice device = service.openDevice(id)) { - Structs.XtStreamParams streamParams = new Structs.XtStreamParams(true, AudioLoopbackSoftware::onBuffer, null, null); + Structs.XtStreamParams streamParams = new Structs.XtStreamParams(true, this::onBuffer, null, null); Structs.XtFormat format = new Structs.XtFormat(new Structs.XtMix(sampleRate, Enums.XtSample.FLOAT32), - new Structs.XtChannels(Integer.parseInt(FireflyLuciferin.config.getAudioChannels().substring(0, 1)), 0, 0, 0)); + new Structs.XtChannels(Integer.parseInt(MainSingleton.getInstance().config.getAudioChannels().substring(0, 1)), 0, 0, 0)); log.info(defaultDeviceStr); log.trace("Device Key: " + idd); if (device.supportsFormat(format)) { @@ -252,7 +252,7 @@ public void startVolumeLevelMeter() { log.info("Audio device engaged, using: {}", devi); stream.start(); audioEngaged.set(true); - while (RUNNING_AUDIO) { + while (AudioSingleton.getInstance().RUNNING_AUDIO) { Thread.onSpinWait(); } log.trace(("Stopping audio recording")); @@ -305,11 +305,11 @@ public Map getLoopbackDevices() { if (defaultOutputId != null) { String name = all.getName(defaultOutputId); log.trace(" Default output: " + name + " (" + defaultOutputId + ")"); - if (FireflyLuciferin.config.getAudioDevice().equals(org.dpsoftware.config.Enums.Audio.DEFAULT_AUDIO_OUTPUT_WASAPI.getBaseI18n())) { + if (MainSingleton.getInstance().config.getAudioDevice().equals(org.dpsoftware.config.Enums.Audio.DEFAULT_AUDIO_OUTPUT_WASAPI.getBaseI18n())) { if (NativeExecutor.isWindows() && systemName.name().equals(Constants.WASAPI)) { defaultOutputWASAPIId = defaultOutputId; - audioDevices.put(defaultOutputId, new AudioDevice(name, FireflyLuciferin.config.getSampleRate() == 0 ? - Constants.DEFAULT_SAMPLE_RATE : FireflyLuciferin.config.getSampleRate())); + AudioSingleton.getInstance().audioDevices.put(defaultOutputId, new AudioDevice(name, MainSingleton.getInstance().config.getSampleRate() == 0 ? + Constants.DEFAULT_SAMPLE_RATE : MainSingleton.getInstance().config.getSampleRate())); } } } @@ -328,7 +328,7 @@ public Map getLoopbackDevices() { } catch (Throwable t) { log.error(t.getMessage()); } - return audioDevices; + return AudioSingleton.getInstance().audioDevices; } } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/audio/AudioSingleton.java b/src/main/java/org/dpsoftware/audio/AudioSingleton.java new file mode 100644 index 000000000..d1c1dc1ab --- /dev/null +++ b/src/main/java/org/dpsoftware/audio/AudioSingleton.java @@ -0,0 +1,52 @@ +/* + AudioSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.audio; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.managers.dto.AudioDevice; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Audio singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +public class AudioSingleton { + + @Getter + private final static AudioSingleton instance; + + static { + instance = new AudioSingleton(); + } + + public volatile boolean RUNNING_AUDIO = false; + public int AUDIO_BRIGHTNESS = 255; + public Map audioDevices = new LinkedHashMap<>(); + +} + diff --git a/src/main/java/org/dpsoftware/config/Configuration.java b/src/main/java/org/dpsoftware/config/Configuration.java index 23ee43b4a..1261640a5 100644 --- a/src/main/java/org/dpsoftware/config/Configuration.java +++ b/src/main/java/org/dpsoftware/config/Configuration.java @@ -29,6 +29,7 @@ import lombok.Setter; import org.dpsoftware.LEDCoordinate; import org.dpsoftware.NativeExecutor; +import org.dpsoftware.gui.elements.Satellite; import org.dpsoftware.managers.dto.HSLColor; import java.time.LocalTime; @@ -44,7 +45,7 @@ @NoArgsConstructor @Getter @Setter -@JsonPropertyOrder({"mqttStream", "wifiEnable", "serialPort", "baudRate", "extendedLog"}) +@JsonPropertyOrder({"mqttStream", "wifiEnable", "mqttEnable", "serialPort", "staticGlowWormIp", "baudRate", "extendedLog"}) public class Configuration implements Cloneable { private String audioChannels = Enums.AudioChannels.AUDIO_CHANNEL_2.getBaseI18n(); @@ -117,6 +118,7 @@ public class Configuration implements Cloneable { // NOTE: for full firmware this contains the deviceName of the MQTT device where to stream @JsonProperty("serialPort") private String outputDevice; + private String staticGlowWormIp; private String powerSaving = ""; private int rightLed; @JsonProperty("extendedLog") @@ -140,10 +142,14 @@ public class Configuration implements Cloneable { private int topLed; // White temperature for color correction (Kelvin) private int whiteTemperature = Constants.DEFAULT_WHITE_TEMP; + private Map satellites = new LinkedHashMap<>(); @JsonProperty("mqttStream") private boolean wirelessStream = false; // this refers to wireless stream (MQTT or UDP), old name for compatibility with previous version + private String algo = Enums.Algo.AVG_COLOR.getBaseI18n(); // Color correction, Hue-Saturation (using HSV 360° wheel) private Map hueMap; + // DBUS ScreenCast Restore Token (XDG Portal) + private String screenCastRestoreToken; // LED Matrix Map private Map> ledMatrix; @@ -178,14 +184,26 @@ public LinkedHashMap getLedMatrixInUse(String ledMatrixI return ledMatrix.get(ledMatrixInUse); } - // WinAPI and DDUPL enables GPU Hardware Acceleration, CPU uses CPU brute force only, - // DDUPL (Desktop Duplication API) is recommended in Win8/Win10/Win11 + /** + * WinAPI and DDUPL enables GPU Hardware Acceleration on Windows, CPU uses CPU brute force only. + * DDUPL (Desktop Duplication API) is recommended in Win8/Win10/Win11 and it uses DX11 + * CUDA is used in Linux only, it needs additional libs and it works on Nvidia GPUs only. + */ + @Getter public enum CaptureMethod { - CPU, - WinAPI, - DDUPL, - XIMAGESRC, - AVFVIDEOSRC + CPU("CPU"), + WinAPI("WinAPI"), + DDUPL("DDUPL"), + XIMAGESRC("XIMAGESRC"), + XIMAGESRC_NVIDIA("XIMAGESRC (NVIDIA)"), + PIPEWIREXDG("PIPEWIREXDG"), + PIPEWIREXDG_NVIDIA("PIPEWIREXDG (NVIDIA)"), + AVFVIDEOSRC("AVFVIDEOSRC"); + private final String captureMethod; + + CaptureMethod(String captureMethod) { + this.captureMethod = captureMethod; + } } } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/config/Constants.java b/src/main/java/org/dpsoftware/config/Constants.java index 29daabcaa..a0a7c8c69 100644 --- a/src/main/java/org/dpsoftware/config/Constants.java +++ b/src/main/java/org/dpsoftware/config/Constants.java @@ -23,6 +23,9 @@ import javafx.scene.paint.Color; +import java.util.ArrayList; +import java.util.Arrays; + /** * Constants and Strings */ @@ -46,7 +49,7 @@ public class Constants { public static final String DATE_FORMAT = "EEEE, MMM dd, yyyy HH:mm:ss a"; public static final String SETTING_LED_SERIAL = "Setting LEDs"; public static final int NUMBER_OF_BENCHMARK_ITERATION = 15; - public static final int BENCHMARK_ERROR_MARGIN = 3; + public static final int BENCHMARK_ERROR_MARGIN = 4; public static final String MULTIMONITOR_1 = "multimonitor.disabled"; public static final String MULTIMONITOR_2 = "multimonitor.dual"; public static final String MULTIMONITOR_3 = "multimonitor.triple"; @@ -141,10 +144,15 @@ public class Constants { public static final String IMAGE_CONTROL_LOGO_LEFT = "/org/dpsoftware/gui/img/luciferin_logo_left.png"; public static final String IMAGE_CONTROL_LOGO_RIGHT = "/org/dpsoftware/gui/img/luciferin_logo_right.png"; public static final String IMAGE_CONTROL_LOGO_RIGHT_GOLD = "/org/dpsoftware/gui/img/luciferin_logo_right_gold.png"; + public static final String UNICODE_X = "✖"; + public static final int REMOVE_BTN_TABLE = 35; public static final String FXML = ".fxml"; public static final String FXML_SETTINGS = "settings"; + public static final String FXML_SETTINGS_CUSTOM_BAR = "settingsCustomBar"; public static final String FXML_INFO = "info"; + public static final String FXML_INFO_CUSTOM_BAR = "infoCustomBar"; public static final String FXML_COLOR_CORRECTION_DIALOG = "colorCorrectionDialog"; + public static final String FXML_SATELLITES_DIALOG = "satellitesDialog"; public static final String FXML_EYE_CARE_DIALOG = "eyeCareDialog"; public static final String CONFIG_FILENAME = "FireflyLuciferin.yaml"; public static final String CONFIG_FILENAME_2 = "FireflyLuciferin_2.yaml"; @@ -163,21 +171,21 @@ public class Constants { public static final String STATE_ON_GLOWWORMWIFI = "GlowWormWifi"; public static final String DEFAULT_MQTT_HOST = "tcp://192.168.1.3"; public static final String DEFAULT_MQTT_PORT = "1883"; - public static final String DEFAULT_MQTT_TOPIC = "lights/glowwormluciferin/set"; - public static final String DEFAULT_MQTT_STATE_TOPIC = "lights/glowwormluciferin"; - public static final String UPDATE_MQTT_TOPIC = "lights/glowwormluciferin/update"; - public static final String UPDATE_RESULT_MQTT_TOPIC = "lights/glowwormluciferin/update/result"; - public static final String FIREFLY_LUCIFERIN_FRAMERATE = "lights/firelyluciferin/framerate"; - public static final String FIREFLY_LUCIFERIN_EFFECT_TOPIC = "lights/glowwormluciferin/effectToFf"; - public static final String FIREFLY_LUCIFERIN_GAMMA = "lights/firelyluciferin/gamma"; - public static final String FIREFLY_LUCIFERIN_PROFILE_SET = "lights/firelyluciferin/profile/set"; + public static final String TOPIC_DEFAULT_MQTT = "lights/glowwormluciferin/set"; + public static final String TOPIC_DEFAULT_MQTT_STATE = "lights/glowwormluciferin"; + public static final String TOPIC_UPDATE_MQTT = "lights/glowwormluciferin/update"; + public static final String TOPIC_UPDATE_RESULT_MQTT = "lights/glowwormluciferin/update/result"; + public static final String TOPIC_FIREFLY_LUCIFERIN_FRAMERATE = "lights/firelyluciferin/framerate"; + public static final String TOPIC_FIREFLY_LUCIFERIN_EFFECT = "lights/glowwormluciferin/effectToFf"; + public static final String TOPIC_FIREFLY_LUCIFERIN_GAMMA = "lights/firelyluciferin/gamma"; + public static final String TOPIC_FIREFLY_LUCIFERIN_PROFILE_SET = "lights/firelyluciferin/profile/set"; // No swap because that topic needs MAC, no need to swap topic. Some topics are HTTP only via IP. - public static final String GLOW_WORM_FIRM_CONFIG_TOPIC = "lights/glowwormluciferin/firmwareconfig"; - public static final String UNSUBSCRIBE_STREAM_TOPIC = "lights/glowwormluciferin/unsubscribe"; - public static final String ASPECT_RATIO_TOPIC = "lights/firelyluciferin/aspectratio"; - public static final String SET_ASPECT_RATIO_TOPIC = "lights/firelyluciferin/setaspectratio"; - public static final String SET_SMOOTHING_TOPIC = "lights/firelyluciferin/smoothing/set"; - public static final String LDR_TOPIC = "ldr"; + public static final String TOPIC_GLOW_WORM_FIRM_CONFIG = "lights/glowwormluciferin/firmwareconfig"; + public static final String TOPIC_UNSUBSCRIBE_STREAM = "lights/glowwormluciferin/unsubscribe"; + public static final String TOPIC_ASPECT_RATIO = "lights/firelyluciferin/aspectratio"; + public static final String TOPIC_SET_ASPECT_RATIO = "lights/firelyluciferin/setaspectratio"; + public static final String TOPIC_SET_SMOOTHING = "lights/firelyluciferin/smoothing/set"; + public static final String HTTP_SET_LDR = "ldr"; public static final String STATE_IP = "IP"; public static final String STATE_DHCP = "dhcp"; public static final String COLOR_ORDER = "colorOrder"; @@ -251,6 +259,10 @@ public class Constants { public static final String EDITABLE_PIN_GPIO_CLOCK = "gpioClockColumn"; public static final String CDC_DEVICE = "_CDC"; // GUI + public static final String TRANSPARENT = "TRANSPARENT"; + public static final String FXML_TRANSPARENT = "-fx-background-color:transparent"; + public static final int TITLE_BAR_HEIGHT = 35; + public static final int DBL_CLK_DELAY = 350; public static final String SAVE = "fxml.save"; public static final String SAVE_AND_CLOSE = "fxml.save.and.close"; public static final String FRAMERATE_TITLE = "framerate.title"; @@ -275,6 +287,11 @@ public class Constants { public static final String MQTT_ERROR_TITLE = "mqtt.error.title"; public static final String MQTT_ERROR_HEADER = "mqtt.error.header"; public static final String MQTT_ERROR_CONTEXT = "mqtt.error.context"; + public static final String CUDA_ERROR_TITLE = "cuda.error.title"; + public static final String CUDA_ERROR_HEADER = "cuda.error.header"; + public static final String CUDA_ERROR_CONTEXT = "cuda.error.context"; + public static final String WAYLAND_SCREEN_REC_PERMISSION = "wayland.screen.rec.permission"; + public static final String WAYLAND_SCREEN_REC_PERMISSION_CONTEXT = "wayland.screen.rec.permission.context"; public static final String START = "tray.icon.start"; public static final String STOP = "tray.icon.stop"; public static final String STOP_STR = "STOP"; @@ -304,6 +321,8 @@ public class Constants { public static final String CAPTURE_MODE_CHANGED = "capture.mode.changed"; public static final String GITHUB_URL = "https://github.com/sblantipodi/firefly_luciferin/releases"; public static final String WEB_INSTALLER_URL = "https://sblantipodi.github.io/glow_worm_luciferin"; + public static final String LINUX_WIKI_URL = "https://github.com/sblantipodi/firefly_luciferin/wiki/Linux-support#nvidia-cuda"; + public static final String TITLE_BAR_SELECTOR = "#titleBarLabel"; @SuppressWarnings("all") public static final String HTTP = "http://"; public static final int HTTP_SUCCESS = 200; @@ -350,6 +369,7 @@ public class Constants { public static final String TOOLTIP_BOTTOMROWLED = "tooltip.bottomrowled"; public static final String TOOLTIP_ORIENTATION = "tooltip.orientation"; public static final String TOOLTIP_SCREENWIDTH = "tooltip.screenwidth"; + public static final String TOOLTIP_RESET_WAYLAND = "tooltip.reset.wayland"; public static final String TOOLTIP_SCREENHEIGHT = "tooltip.screenheight"; public static final String TOOLTIP_LEDSTARTOFFSET = "tooltip.ledstartoffset"; public static final String TOOLTIP_SCALING = "tooltip.scaling"; @@ -368,6 +388,7 @@ public class Constants { public static final String TOOLTIP_FRAME_INSERTION = "tooltip.frame.insertion"; public static final String TOOLTIP_MQTTHOST = "tooltip.mqtthost"; public static final String TOOLTIP_POWER_SAVING = "tooltip.power.saving"; + public static final String TOOLTIP_SAT_BTN = "tooltip.sat.btn"; public static final String TOOLTIP_MULTIMONITOR = "tooltip.multimonitor"; public static final String TOOLTIP_MONITORNUMBER = "tooltip.monitornumber"; public static final String TOOLTIP_MQTTPORT = "tooltip.mqttport"; @@ -448,6 +469,12 @@ public class Constants { public static final String TOOLTIP_EYEC_CAL = "tooltip.ldr.calibrateldr"; public static final String TOOLTIP_EYEC_RESET = "tooltip.ldr.resetldr"; public static final String TOOLTIP_VAL = "tooltip.ldr.ldrlabel"; + public static final String TOOLTIP_SAT_IP = "tooltip.sat.manager.ip"; + public static final String TOOLTIP_SAT_ZONE = "tooltip.sat.manager.zone"; + public static final String TOOLTIP_SAT_ORIENT = "tooltip.sat.manager.orientation"; + public static final String TOOLTIP_SAT_NUM = "tooltip.sat.manager.num.led"; + public static final String TOOLTIP_SAT_ALGO = "tooltip.sat.manager.algo"; + public static final String TOOLTIP_SAT_ADD = "tooltip.sat.manager.add"; // Grabber public static final String INTERNAL_SCALING_X = "INTERNAL_SCALING_X"; public static final String INTERNAL_SCALING_Y = "INTERNAL_SCALING_Y"; @@ -469,10 +496,13 @@ public class Constants { public static final String SCREEN_GRABBER = "FireflyLuciferin"; // ./gst-device-monitor-1.0.exe "Source/Monitor" // ./gst-launch-1.0 d3d11screencapturesrc monitor-handle=221948 ! d3d11convert ! d3d11download ! autovideosink - // ./gst-launch-1.0 ximagesrc startx=0 endx=3839 starty=0 endy=2159 ! videoscale ! videoconvert ! autovideosink + // ./gst-launch-1.0 ximagesrc startx=0 endx=3839 starty=0 endy=2159 use-damage=0 ! videoscale ! videoconvert ! autovideosink public static final String GSTREAMER_PIPELINE_WINDOWS_HARDWARE_HANDLE_SM = "d3d11screencapturesrc monitor-handle={0} ! d3d11convert ! d3d11download"; public static final String GSTREAMER_PIPELINE_WINDOWS_HARDWARE_HANDLE = "d3d11screencapturesrc monitor-handle={0} ! d3d11convert"; - public static final String GSTREAMER_PIPELINE_LINUX = "ximagesrc startx={0} endx={1} starty={2} endy={3} ! videoscale ! videoconvert"; + public static final String GSTREAMER_PIPELINE_XIMAGESRC = "ximagesrc startx={0} endx={1} starty={2} endy={3} use-damage=0 ! videoscale ! videoconvert"; + public static final String GSTREAMER_PIPELINE_XIMAGESRC_CUDA = "ximagesrc startx={0} endx={1} starty={2} endy={3} use-damage=0 ! cudaupload ! cudascale ! cudaconvert ! cudadownload"; + public static final String GSTREAMER_PIPELINE_PIPEWIREXDG = "pipewiresrc fd={1} path={2} ! videorate ! videoscale ! videoconvert"; + public static final String GSTREAMER_PIPELINE_PIPEWIREXDG_CUDA = "pipewiresrc fd={1} path={2} ! videorate ! cudaupload ! cudascale ! cudaconvert ! cudadownload"; public static final String GSTREAMER_PIPELINE_MAC = "avfvideosrc capture-screen=true ! videoscale ! videoconvert"; public static final String FRAMERATE_PLACEHOLDER = "framerate=FRAMERATE_PLACEHOLDER/1,"; public static final String FPS_PLACEHOLDER = "FRAMERATE_PLACEHOLDER"; @@ -526,6 +556,7 @@ public class Constants { public static final String UDP_IP_FOR_PREFERRED_OUTBOUND = "8.8.8.8"; public static final String UDP_PING = "PING"; public static final String UDP_DEVICE_NAME = "DN"; + public static final String UDP_DEVICE_NAME_STATIC = "DNStatic"; public static final String UDP_PONG = "PONG"; public static final double UDP_CHUNK_SIZE = 140; public static final int UDP_MAX_BUFFER_SIZE = 4096; @@ -565,6 +596,10 @@ public class Constants { public static final String LDR_ALERT_HEADER_ERROR = "ldr.alert.header.error"; public static final String LDR_ALERT_HEADER_CONTENT = "ldr.alert.content.error"; public static final String LDR_ALERT_CONTINUE = "ldr.alert.continue"; + // SATELLITES + public static final String SAT_ALERT_IP_TITLE = "satellite.ip.error.title"; + public static final String SAT_ALERT_IP_HEADER = "satellite.ip.error.header"; + public static final String SAT_ALERT_IP_CONTENT = "satellite.ip.error.content"; //Style sheets public static final String CSS_LINUX = "css/linux.css"; public static final String CSS_THEME_DARK = "css/theme-dark.css"; @@ -616,13 +651,20 @@ public class Constants { public static final int CMD_WAIT_DELAY = 10000; public static final int SPAWN_INSTANCE_WAIT_DELAY = 1000; public static final int SPAWN_INSTANCE_WAIT_START_DELAY = 3000; + public static final String[] CMD_CUDA_CHECK = {"/bin/sh", "-c", "gst-inspect-1.0 nvcodec | grep cuda"}; + public static final String[] CUDA_REQUIRED_PLUGINS = {"cudaupload", "cudascale", "cudaconvert", "cudadownload"}; // Native executor public static final String CANT_RUN_CMD = "cant.run.cmd"; public static final String NO_OUTPUT = "no.output"; public static final String INTERRUPTED_WHEN_READING = "interrupted.when.reading"; public static final String DPKG_CHECK_CMD = "dpkg --version"; + public static final String DISPLAY_MANAGER_CHK = "XDG_SESSION_TYPE"; + public static final String WAYLAND = "wayland"; // Log level root public static final String LOG_LEVEL_ROOT = "org.dpsoftware"; + // HTTP or MQTT topic to skip + public static final ArrayList HTTP_TOPIC_TO_SKIP_FOR_SATELLITES = new ArrayList<>(Arrays + .asList(TOPIC_GLOW_WORM_FIRM_CONFIG, HTTP_SETTING, HTTP_SET_LDR)); public static int GROUP_BY_LEDS = 1; } diff --git a/src/main/java/org/dpsoftware/config/Enums.java b/src/main/java/org/dpsoftware/config/Enums.java index c67cf8d6d..8b8534b9b 100644 --- a/src/main/java/org/dpsoftware/config/Enums.java +++ b/src/main/java/org/dpsoftware/config/Enums.java @@ -117,6 +117,20 @@ public String getValue() { } } + public enum Direction implements LocalizedEnum { + NORMAL("enum.direction.normal"), + INVERSE("enum.direction.inverse"); + private final String direction; + + Direction(String direction) { + this.direction = direction; + } + + public String getValue() { + return direction; + } + } + public enum AspectRatio implements LocalizedEnum { FULLSCREEN("enum.aspect.ratio.fullscreen"), LETTERBOX("enum.aspect.ratio.letterbox"), @@ -174,6 +188,7 @@ public String getValue() { } } + @Getter public enum BaudRate { BAUD_RATE_115200("115200", 8), BAUD_RATE_230400("230400", 1), @@ -199,13 +214,6 @@ public static BaudRate findByExtendedVal(final String baudRateToSearch) { return Arrays.stream(values()).filter(value -> value.getBaudRate().equals(baudRateToSearch)).findFirst().orElse(null); } - public String getBaudRate() { - return baudRate; - } - - public int getBaudRateValue() { - return baudRateValue; - } } public enum Framerate implements LocalizedEnum { @@ -242,6 +250,7 @@ public enum FrameInsertion implements LocalizedEnum { SMOOTHING_LVL_5("enum.frame.insertion.smoothing.lvl.5", 5), SMOOTHING_LVL_6("enum.frame.insertion.smoothing.lvl.6", 2); private final String frameInsertionStr; + @Getter private final int frameInsertionFramerate; FrameInsertion(String frameInsertionStr, int frameInsertionFramerate) { @@ -253,11 +262,9 @@ public String getValue() { return frameInsertionStr; } - public int getFrameInsertionFramerate() { - return frameInsertionFramerate; - } } + @Getter public enum ScalingRatio { RATIO_100("100%"), RATIO_125("125%"), @@ -274,11 +281,9 @@ public enum ScalingRatio { this.scalingRatio = scalingRatio; } - public String getScalingRatio() { - return scalingRatio; - } } + @Getter public enum Gamma { GAMMA_10("1.0"), GAMMA_12("1.2"), @@ -302,9 +307,6 @@ public enum Gamma { this.gamma = gamma; } - public String getGamma() { - return gamma; - } } public enum AudioChannels implements LocalizedEnum { @@ -368,6 +370,7 @@ public enum BrightnessLimiter implements LocalizedEnum { BRIGHTNESS_LIMIT_40("40%", 0.4F), BRIGHTNESS_LIMIT_30("30%", 0.3F); private final String brightnessLimit; + @Getter private final float brightnessLimitFloat; BrightnessLimiter(String brightnessLimit, float brightnessLimitFloat) { @@ -383,9 +386,6 @@ public String getValue() { return brightnessLimit; } - public float getBrightnessLimitFloat() { - return brightnessLimitFloat; - } } public enum PowerSaving implements LocalizedEnum { @@ -450,6 +450,7 @@ public String getValue() { } } + @Getter public enum StreamType { UDP("UDP stream"), MQTT("MQTT stream"); @@ -459,9 +460,6 @@ public enum StreamType { this.streamType = streamType; } - public String getStreamType() { - return streamType; - } } public enum Audio implements LocalizedEnum { @@ -536,4 +534,39 @@ public int getValue() { } } + public enum Algo implements LocalizedEnum { + AVG_COLOR("enum.color.algo.avg"), + AVG_ALL_COLOR("enum.color.algo.avg.all"); + private final String algo; + + Algo(String algo) { + this.algo = algo; + } + + public String getValue() { + return algo; + } + } + + public enum SatelliteZone implements LocalizedEnum { + ENTIRE_SCREEN("enum.satellite.zone.entire.screen"), + TOP("enum.satellite.zone.top"), + TOP_RIGHT("enum.satellite.zone.top.right"), + RIGHT("enum.satellite.zone.right"), + BOTTOM_RIGHT("enum.satellite.zone.bottom.right"), + BOTTOM("enum.satellite.zone.bottom"), + BOTTOM_LEFT("enum.satellite.zone.bottom.left"), + LEFT("enum.satellite.zone.left"), + TOP_LEFT("enum.satellite.zone.top.left"); + private final String zone; + + SatelliteZone(String zone) { + this.zone = zone; + } + + public String getValue() { + return zone; + } + } + } diff --git a/src/main/java/org/dpsoftware/config/InstanceConverter.java b/src/main/java/org/dpsoftware/config/InstanceConverter.java index 569773aa1..3a0766d79 100644 --- a/src/main/java/org/dpsoftware/config/InstanceConverter.java +++ b/src/main/java/org/dpsoftware/config/InstanceConverter.java @@ -23,7 +23,7 @@ import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.ILoggingEvent; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; /** * Simple converter used to log the instance number. @@ -35,7 +35,7 @@ public class InstanceConverter extends ClassicConverter { */ @Override public String convert(ILoggingEvent event) { - return "[Instance #" + JavaFXStarter.whoAmI + "]"; + return "[Instance #" + MainSingleton.getInstance().whoAmI + "]"; } } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/grabber/DbusScreenCast.java b/src/main/java/org/dpsoftware/grabber/DbusScreenCast.java new file mode 100644 index 000000000..26aaf4001 --- /dev/null +++ b/src/main/java/org/dpsoftware/grabber/DbusScreenCast.java @@ -0,0 +1,52 @@ +/* + DbusScreenCast.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.grabber; + +import org.freedesktop.dbus.DBusPath; +import org.freedesktop.dbus.FileDescriptor; +import org.freedesktop.dbus.annotations.DBusInterfaceName; +import org.freedesktop.dbus.annotations.DBusProperty; +import org.freedesktop.dbus.annotations.DBusProperty.Access; +import org.freedesktop.dbus.interfaces.DBusInterface; +import org.freedesktop.dbus.types.UInt32; +import org.freedesktop.dbus.types.Variant; + +import java.util.Map; + +/** + * Auto-generated class. + */ +@DBusProperty(name = "AvailableSourceTypes", type = UInt32.class, access = Access.READ) +@DBusProperty(name = "AvailableCursorModes", type = UInt32.class, access = Access.READ) +@DBusProperty(name = "version", type = UInt32.class, access = Access.READ) +@DBusInterfaceName(value = "org.freedesktop.portal.ScreenCast") +public interface DbusScreenCast extends DBusInterface { + + void CreateSession(Map> options); + + void SelectSources(DBusPath sessionHandle, Map> options); + + DBusPath Start(DBusPath sessionHandle, String parentWindow, Map> options); + + FileDescriptor OpenPipeWireRemote(DBusPath sessionHandle, Map> options); + +} diff --git a/src/main/java/org/dpsoftware/grabber/GStreamerGrabber.java b/src/main/java/org/dpsoftware/grabber/GStreamerGrabber.java index 103b9a10f..bd5f3010c 100644 --- a/src/main/java/org/dpsoftware/grabber/GStreamerGrabber.java +++ b/src/main/java/org/dpsoftware/grabber/GStreamerGrabber.java @@ -23,10 +23,9 @@ import ch.qos.logback.classic.Level; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; import org.dpsoftware.LEDCoordinate; -import org.dpsoftware.NativeExecutor; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.MainSingleton; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; @@ -69,7 +68,7 @@ public class GStreamerGrabber extends javax.swing.JComponent { */ public GStreamerGrabber() { this(new AppSink("GstVideoComponent")); - ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(FireflyLuciferin.config.getDefaultLedMatrix()); + ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(MainSingleton.getInstance().config.getDefaultLedMatrix()); previousFrame = new Color[ledMatrix.size()]; for (int i = 0; i < previousFrame.length; i++) { previousFrame[i] = new Color(0, 0, 0); @@ -85,26 +84,26 @@ public GStreamerGrabber(AppSink appsink) { AppSinkListener listener = new AppSinkListener(); videosink.connect(listener); String gstreamerPipeline; - if (FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) { + if (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) { // Scale image inside the GPU by RESAMPLING_FACTOR, Constants.GSTREAMER_MEMORY_DIVIDER tells if resolution is compatible with D3D11Memory with no padding. - if ((FireflyLuciferin.config.getScreenResX() / Constants.GSTREAMER_MEMORY_DIVIDER) % 2 == 0) { + if ((MainSingleton.getInstance().config.getScreenResX() / Constants.GSTREAMER_MEMORY_DIVIDER) % 2 == 0) { gstreamerPipeline = Constants.GSTREAMER_PIPELINE_DDUPL - .replace(Constants.INTERNAL_SCALING_X, String.valueOf(FireflyLuciferin.config.getScreenResX() / Constants.RESAMPLING_FACTOR)) - .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(FireflyLuciferin.config.getScreenResY() / Constants.RESAMPLING_FACTOR)); + .replace(Constants.INTERNAL_SCALING_X, String.valueOf(MainSingleton.getInstance().config.getScreenResX() / Constants.RESAMPLING_FACTOR)) + .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(MainSingleton.getInstance().config.getScreenResY() / Constants.RESAMPLING_FACTOR)); } else { gstreamerPipeline = Constants.GSTREAMER_PIPELINE_DDUPL_SM - .replace(Constants.INTERNAL_SCALING_X, String.valueOf(FireflyLuciferin.config.getScreenResX() / Constants.RESAMPLING_FACTOR)) - .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(FireflyLuciferin.config.getScreenResY() / Constants.RESAMPLING_FACTOR)); + .replace(Constants.INTERNAL_SCALING_X, String.valueOf(MainSingleton.getInstance().config.getScreenResX() / Constants.RESAMPLING_FACTOR)) + .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(MainSingleton.getInstance().config.getScreenResY() / Constants.RESAMPLING_FACTOR)); } } else { gstreamerPipeline = Constants.GSTREAMER_PIPELINE - .replace(Constants.INTERNAL_SCALING_X, String.valueOf(FireflyLuciferin.config.getScreenResX() / Constants.RESAMPLING_FACTOR)) - .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(FireflyLuciferin.config.getScreenResY() / Constants.RESAMPLING_FACTOR)); + .replace(Constants.INTERNAL_SCALING_X, String.valueOf(MainSingleton.getInstance().config.getScreenResX() / Constants.RESAMPLING_FACTOR)) + .replace(Constants.INTERNAL_SCALING_Y, String.valueOf(MainSingleton.getInstance().config.getScreenResY() / Constants.RESAMPLING_FACTOR)); } gstreamerPipeline = setFramerate(gstreamerPipeline); StringBuilder caps = new StringBuilder(gstreamerPipeline); // JNA creates ByteBuffer using native byte order, set masks according to that. - if (!(FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name()))) { + if (!(MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name()))) { if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) { caps.append(Constants.BYTE_ORDER_BGR); } else { @@ -125,14 +124,14 @@ public GStreamerGrabber(AppSink appsink) { */ private String setFramerate(String gstreamerPipeline) { // Huge amount of LEDs requires slower framerate - if (!Enums.Framerate.UNLOCKED.equals(LocalizedEnum.fromBaseStr(Enums.Framerate.class, FireflyLuciferin.config.getDesiredFramerate()))) { - Enums.Framerate framerateToSave = LocalizedEnum.fromStr(Enums.Framerate.class, FireflyLuciferin.config.getDesiredFramerate()); - gstreamerPipeline += Constants.FRAMERATE_PLACEHOLDER.replaceAll(Constants.FPS_PLACEHOLDER, framerateToSave != null ? framerateToSave.getBaseI18n() : FireflyLuciferin.config.getDesiredFramerate()); + if (!Enums.Framerate.UNLOCKED.equals(LocalizedEnum.fromBaseStr(Enums.Framerate.class, MainSingleton.getInstance().config.getDesiredFramerate()))) { + Enums.Framerate framerateToSave = LocalizedEnum.fromStr(Enums.Framerate.class, MainSingleton.getInstance().config.getDesiredFramerate()); + gstreamerPipeline += Constants.FRAMERATE_PLACEHOLDER.replaceAll(Constants.FPS_PLACEHOLDER, framerateToSave != null ? framerateToSave.getBaseI18n() : MainSingleton.getInstance().config.getDesiredFramerate()); } else { gstreamerPipeline += Constants.FRAMERATE_PLACEHOLDER.replaceAll(Constants.FPS_PLACEHOLDER, Constants.FRAMERATE_CAP); } - if (!FireflyLuciferin.config.getFrameInsertion().equals(Enums.FrameInsertion.NO_SMOOTHING.getBaseI18n())) { - gstreamerPipeline += Constants.FRAMERATE_PLACEHOLDER.replaceAll(Constants.FPS_PLACEHOLDER, String.valueOf(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, FireflyLuciferin.config.getFrameInsertion()).getFrameInsertionFramerate())); + if (!MainSingleton.getInstance().config.getFrameInsertion().equals(Enums.FrameInsertion.NO_SMOOTHING.getBaseI18n())) { + gstreamerPipeline += Constants.FRAMERATE_PLACEHOLDER.replaceAll(Constants.FPS_PLACEHOLDER, String.valueOf(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, MainSingleton.getInstance().config.getFrameInsertion()).getFrameInsertionFramerate())); } return gstreamerPipeline; } @@ -153,8 +152,8 @@ public Element getElement() { */ private void intBufferRgbToImage(IntBuffer rgbBuffer) { capturedFrames++; - BufferedImage img = new BufferedImage(FireflyLuciferin.config.getScreenResX() / Constants.RESAMPLING_FACTOR, - FireflyLuciferin.config.getScreenResY() / Constants.RESAMPLING_FACTOR, 1); + BufferedImage img = new BufferedImage(MainSingleton.getInstance().config.getScreenResX() / Constants.RESAMPLING_FACTOR, + MainSingleton.getInstance().config.getScreenResY() / Constants.RESAMPLING_FACTOR, 1); int[] rgbArray = new int[rgbBuffer.capacity()]; rgbBuffer.rewind(); rgbBuffer.get(rgbArray); @@ -182,15 +181,15 @@ public void rgbFrame(int width, int height, IntBuffer rgbBuffer) { } int intBufferSize = (width * height) - 1; // CHECK_ASPECT_RATIO is true 10 times per second, if true and black bars auto detection is on, auto detect black bars - if (FireflyLuciferin.config.isAutoDetectBlackBars()) { - if (ImageProcessor.CHECK_ASPECT_RATIO) { - ImageProcessor.CHECK_ASPECT_RATIO = false; + if (MainSingleton.getInstance().config.isAutoDetectBlackBars()) { + if (GrabberSingleton.getInstance().CHECK_ASPECT_RATIO) { + GrabberSingleton.getInstance().CHECK_ASPECT_RATIO = false; ImageProcessor.autodetectBlackBars(width, height, rgbBuffer); } } try { Color[] leds = new Color[ledMatrix.size()]; - if (FireflyLuciferin.config.getRuntimeLogLevel().equals(Level.TRACE.levelStr)) { + if (MainSingleton.getInstance().config.getRuntimeLogLevel().equals(Level.TRACE.levelStr)) { intBufferRgbToImage(rgbBuffer); } // We need an ordered collection so no parallelStream here @@ -223,10 +222,12 @@ public void rgbFrame(int width, int height, IntBuffer rgbBuffer) { leds[key - 1] = leds[key - 2]; } }); + ImageProcessor.averageOnAllLeds(leds); + // Put the image in the queue or send it via socket to the main instance server - if (!NativeExecutor.exitTriggered && (!AudioLoopback.RUNNING_AUDIO - || Enums.Effect.MUSIC_MODE_BRIGHT.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect())))) { - if (!FireflyLuciferin.config.getFrameInsertion().equals(Enums.FrameInsertion.NO_SMOOTHING.getBaseI18n())) { + if (!MainSingleton.getInstance().exitTriggered && (!AudioSingleton.getInstance().RUNNING_AUDIO + || Enums.Effect.MUSIC_MODE_BRIGHT.equals(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect())))) { + if (!MainSingleton.getInstance().config.getFrameInsertion().equals(Enums.FrameInsertion.NO_SMOOTHING.getBaseI18n())) { if (previousFrame != null) { frameInsertion(leds); } @@ -234,7 +235,7 @@ public void rgbFrame(int width, int height, IntBuffer rgbBuffer) { PipelineManager.offerToTheQueue(leds); } // Increase the FPS counter - FireflyLuciferin.FPS_PRODUCER_COUNTER++; + MainSingleton.getInstance().FPS_PRODUCER_COUNTER++; } } finally { bufferLock.unlock(); @@ -251,7 +252,7 @@ void frameInsertion(Color[] leds) { Color[] frameInsertion = new Color[ledMatrix.size()]; int totalElapsed = 0; // Framerate we asks to the GPU, less FPS = smoother but less response, more FPS = less smooth but faster to changes. - int gpuFramerateFps = LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, FireflyLuciferin.config.getFrameInsertion()).getFrameInsertionFramerate(); + int gpuFramerateFps = LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, MainSingleton.getInstance().config.getFrameInsertion()).getFrameInsertionFramerate(); // Total number of frames to compute. int totalFrameToAdd = Constants.SMOOTHING_TARGET_FRAMERATE - gpuFramerateFps; // Number of frames to compute every time a frame is received from the GPU. @@ -277,7 +278,7 @@ void frameInsertion(Color[] leds) { long finish = System.currentTimeMillis(); if (frameInsertion.length == leds.length) { long timeElapsed = finish - start; - totalElapsed += timeElapsed; + totalElapsed += (int) timeElapsed; if (timeElapsed > Constants.SMOOTHING_SKIP_FAST_FRAMES) { PipelineManager.offerToTheQueue(frameInsertion); } else { diff --git a/src/main/java/org/dpsoftware/grabber/GrabberManager.java b/src/main/java/org/dpsoftware/grabber/GrabberManager.java index 14892ee81..dc717de77 100644 --- a/src/main/java/org/dpsoftware/grabber/GrabberManager.java +++ b/src/main/java/org/dpsoftware/grabber/GrabberManager.java @@ -24,18 +24,15 @@ import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.gui.controllers.SettingsController; -import org.dpsoftware.managers.DisplayManager; -import org.dpsoftware.managers.NetworkManager; -import org.dpsoftware.managers.PipelineManager; -import org.dpsoftware.managers.StorageManager; +import org.dpsoftware.managers.*; import org.dpsoftware.managers.dto.MqttFramerateDto; import org.dpsoftware.utilities.CommonUtility; import org.freedesktop.gstreamer.Bin; @@ -52,16 +49,12 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import static org.dpsoftware.FireflyLuciferin.*; - /** * Screen grabbing manager */ @Slf4j public class GrabberManager { - // GStreamer Rendering pipeline - public static Pipeline pipe; public Bin bin; GStreamerGrabber vc; @@ -81,20 +74,20 @@ public void launchAdvancedGrabber(ImageProcessor imageProcessor) { } String finalLinuxParams = linuxParams; Gst.getExecutor().scheduleAtFixedRate(() -> { - if (!PipelineManager.pipelineStopping && RUNNING && FPS_PRODUCER_COUNTER == 0) { + if (!ManagerSingleton.getInstance().pipelineStopping && MainSingleton.getInstance().RUNNING && MainSingleton.getInstance().FPS_PRODUCER_COUNTER == 0) { pipelineRetry.getAndIncrement(); - if (pipe == null || !pipe.isPlaying() || pipelineRetry.get() >= 2) { - if (pipe != null) { + if (GrabberSingleton.getInstance().pipe == null || !GrabberSingleton.getInstance().pipe.isPlaying() || pipelineRetry.get() >= 2) { + if (GrabberSingleton.getInstance().pipe != null) { log.info("Restarting pipeline"); - pipe.stop(); + GrabberSingleton.getInstance().pipe.stop(); } else { log.info("Starting a new pipeline"); - pipe = new Pipeline(); + GrabberSingleton.getInstance().pipe = new Pipeline(); if (NativeExecutor.isWindows()) { DisplayManager displayManager = new DisplayManager(); - String monitorNativePeer = String.valueOf(displayManager.getDisplayInfo(FireflyLuciferin.config.getMonitorNumber()).getNativePeer()); + String monitorNativePeer = String.valueOf(displayManager.getDisplayInfo(MainSingleton.getInstance().config.getMonitorNumber()).getNativePeer()); // Constants.GSTREAMER_MEMORY_DIVIDER tells if resolution is compatible with D3D11Memory with no padding. - if ((FireflyLuciferin.config.getScreenResX() / Constants.GSTREAMER_MEMORY_DIVIDER) % 2 == 0) { + if ((MainSingleton.getInstance().config.getScreenResX() / Constants.GSTREAMER_MEMORY_DIVIDER) % 2 == 0) { bin = Gst.parseBinFromDescription(Constants.GSTREAMER_PIPELINE_WINDOWS_HARDWARE_HANDLE.replace("{0}", monitorNativePeer), true); } else { bin = Gst.parseBinFromDescription(Constants.GSTREAMER_PIPELINE_WINDOWS_HARDWARE_HANDLE_SM.replace("{0}", monitorNativePeer), true); @@ -106,14 +99,14 @@ public void launchAdvancedGrabber(ImageProcessor imageProcessor) { } } vc = new GStreamerGrabber(); - pipe.addMany(bin, vc.getElement()); + GrabberSingleton.getInstance().pipe.addMany(bin, vc.getElement()); Pipeline.linkMany(bin, vc.getElement()); JFrame f = new JFrame(Constants.SCREEN_GRABBER); f.add(vc); - vc.setPreferredSize(new Dimension(config.getScreenResX(), config.getScreenResY())); + vc.setPreferredSize(new Dimension(MainSingleton.getInstance().config.getScreenResX(), MainSingleton.getInstance().config.getScreenResY())); f.pack(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - pipe.play(); + GrabberSingleton.getInstance().pipe.play(); f.setVisible(false); } } else { @@ -127,17 +120,17 @@ public void launchAdvancedGrabber(ImageProcessor imageProcessor) { * Old pipeline is not needed anymore, dispose the pipeline and all the related objects to free up system memory. */ private void disposePipeline() { - if (pipe != null && !pipe.isPlaying() && !PipelineManager.pipelineStarting) { + if (GrabberSingleton.getInstance().pipe != null && !GrabberSingleton.getInstance().pipe.isPlaying() && !ManagerSingleton.getInstance().pipelineStarting) { log.info("Free up system memory"); Gst.invokeLater(bin::dispose); Gst.invokeLater(vc.videosink::dispose); Gst.invokeLater(vc.getElement()::dispose); - Gst.invokeLater(pipe::dispose); + Gst.invokeLater(GrabberSingleton.getInstance().pipe::dispose); GStreamerGrabber.ledMatrix = null; bin = null; vc.videosink = null; vc = null; - pipe = null; + GrabberSingleton.getInstance().pipe = null; System.gc(); } } @@ -153,14 +146,14 @@ public void launchStandardGrabber(ScheduledExecutorService scheduledExecutorServ Robot robot = null; for (int i = 0; i < executorNumber; i++) { // One AWT Robot instance every 3 threads seems to be the sweet spot for performance/memory. - if (!(config.getCaptureMethod().equals(Configuration.CaptureMethod.WinAPI.name())) && i % 3 == 0) { + if (!(MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.WinAPI.name())) && i % 3 == 0) { robot = new Robot(); log.info(CommonUtility.getWord(Constants.SPAWNING_ROBOTS)); } Robot finalRobot = robot; // No need for completablefuture here, we wrote the queue with a producer and we forget it scheduledExecutorService.scheduleAtFixedRate(() -> { - if (RUNNING) { + if (MainSingleton.getInstance().RUNNING) { producerTask(finalRobot); } }, 0, 25, TimeUnit.MILLISECONDS); @@ -174,10 +167,10 @@ public void launchStandardGrabber(ScheduledExecutorService scheduledExecutorServ * One instance every three threads seems to be the hot spot for performance. */ private void producerTask(Robot robot) { - if (!AudioLoopback.RUNNING_AUDIO || Enums.Effect.MUSIC_MODE_BRIGHT.getBaseI18n().equals(FireflyLuciferin.config.getEffect()) - || Enums.Effect.MUSIC_MODE_RAINBOW.getBaseI18n().equals(FireflyLuciferin.config.getEffect())) { + if (!AudioSingleton.getInstance().RUNNING_AUDIO || Enums.Effect.MUSIC_MODE_BRIGHT.getBaseI18n().equals(MainSingleton.getInstance().config.getEffect()) + || Enums.Effect.MUSIC_MODE_RAINBOW.getBaseI18n().equals(MainSingleton.getInstance().config.getEffect())) { PipelineManager.offerToTheQueue(ImageProcessor.getColors(robot, null)); - FPS_PRODUCER_COUNTER++; + MainSingleton.getInstance().FPS_PRODUCER_COUNTER++; } //System.gc(); // uncomment when hammering the JVM } @@ -191,33 +184,33 @@ public void getFPS() { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); // Create a task that runs every 5 seconds Runnable framerateTask = () -> { - if (FPS_PRODUCER_COUNTER > 0 || FPS_CONSUMER_COUNTER > 0) { - if (CommonUtility.isSingleDeviceOtherInstance() && FireflyLuciferin.config.getEffect().contains(Constants.MUSIC_MODE)) { - FPS_PRODUCER = FPS_GW_CONSUMER; + if (MainSingleton.getInstance().FPS_PRODUCER_COUNTER > 0 || MainSingleton.getInstance().FPS_CONSUMER_COUNTER > 0) { + if (CommonUtility.isSingleDeviceOtherInstance() && MainSingleton.getInstance().config.getEffect().contains(Constants.MUSIC_MODE)) { + MainSingleton.getInstance().FPS_PRODUCER = MainSingleton.getInstance().FPS_GW_CONSUMER; } else { - FPS_PRODUCER = FPS_PRODUCER_COUNTER / 5; + MainSingleton.getInstance().FPS_PRODUCER = MainSingleton.getInstance().FPS_PRODUCER_COUNTER / 5; } - FPS_CONSUMER = FPS_CONSUMER_COUNTER / 5; - log.trace(" --* Producing @ " + FPS_PRODUCER + " FPS *-- " + " --* Consuming @ " + FPS_GW_CONSUMER + " FPS *-- "); - FPS_CONSUMER_COUNTER = FPS_PRODUCER_COUNTER = 0; + MainSingleton.getInstance().FPS_CONSUMER = MainSingleton.getInstance().FPS_CONSUMER_COUNTER / 5; + log.trace(" --* Producing @ " + MainSingleton.getInstance().FPS_PRODUCER + " FPS *-- " + " --* Consuming @ " + MainSingleton.getInstance().FPS_GW_CONSUMER + " FPS *-- "); + MainSingleton.getInstance().FPS_CONSUMER_COUNTER = MainSingleton.getInstance().FPS_PRODUCER_COUNTER = 0; } else { - FPS_PRODUCER = FPS_CONSUMER = 0; + MainSingleton.getInstance().FPS_PRODUCER = MainSingleton.getInstance().FPS_CONSUMER = 0; } runBenchmark(framerateAlert, notified); - if (config.isMqttEnable()) { - if (!NativeExecutor.exitTriggered) { + if (MainSingleton.getInstance().config.isMqttEnable()) { + if (!MainSingleton.getInstance().exitTriggered) { MqttFramerateDto mqttFramerateDto = new MqttFramerateDto(); - mqttFramerateDto.setProducing(String.valueOf(FPS_PRODUCER)); - mqttFramerateDto.setConsuming(String.valueOf(FPS_CONSUMER)); - mqttFramerateDto.setEffect(config.getEffect()); - mqttFramerateDto.setColorMode(String.valueOf(Enums.ColorMode.values()[config.getColorMode() - 1].getBaseI18n())); - mqttFramerateDto.setAspectRatio(config.isAutoDetectBlackBars() ? - CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS) : config.getDefaultLedMatrix()); - mqttFramerateDto.setGamma(String.valueOf(config.getGamma())); - mqttFramerateDto.setSmoothingLvl(config.getFrameInsertion()); - mqttFramerateDto.setProfile(Constants.DEFAULT.equals(FireflyLuciferin.profileArgs) ? - CommonUtility.getWord(Constants.DEFAULT) : FireflyLuciferin.profileArgs); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.FIREFLY_LUCIFERIN_FRAMERATE), + mqttFramerateDto.setProducing(String.valueOf(MainSingleton.getInstance().FPS_PRODUCER)); + mqttFramerateDto.setConsuming(String.valueOf(MainSingleton.getInstance().FPS_CONSUMER)); + mqttFramerateDto.setEffect(MainSingleton.getInstance().config.getEffect()); + mqttFramerateDto.setColorMode(String.valueOf(Enums.ColorMode.values()[MainSingleton.getInstance().config.getColorMode() - 1].getBaseI18n())); + mqttFramerateDto.setAspectRatio(MainSingleton.getInstance().config.isAutoDetectBlackBars() ? + CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS) : MainSingleton.getInstance().config.getDefaultLedMatrix()); + mqttFramerateDto.setGamma(String.valueOf(MainSingleton.getInstance().config.getGamma())); + mqttFramerateDto.setSmoothingLvl(MainSingleton.getInstance().config.getFrameInsertion()); + mqttFramerateDto.setProfile(Constants.DEFAULT.equals(MainSingleton.getInstance().profileArgs) ? + CommonUtility.getWord(Constants.DEFAULT) : MainSingleton.getInstance().profileArgs); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_FRAMERATE), CommonUtility.toJsonString(mqttFramerateDto)); } } @@ -225,6 +218,41 @@ public void getFPS() { scheduledExecutorService.scheduleAtFixedRate(framerateTask, 0, 5, TimeUnit.SECONDS); } + /** + * Get suggested framerate + * + * @return suggested framerate + */ + private static int getSuggestedFramerate() { + int suggestedFramerate; + if (MainSingleton.getInstance().FPS_GW_CONSUMER > (144 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 144; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (120 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 120; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (90 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 90; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (60 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 60; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (50 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 50; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (40 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 40; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (30 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 30; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (25 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 25; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (20 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 20; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (15 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 15; + } else if (MainSingleton.getInstance().FPS_GW_CONSUMER > (10 + Constants.BENCHMARK_ERROR_MARGIN)) { + suggestedFramerate = 10; + } else { + suggestedFramerate = 5; + } + return suggestedFramerate; + } + /** * Small benchmark to check if Glow Worm Luciferin firmware can keep up with Firefly Luciferin PC software * @@ -232,63 +260,43 @@ public void getFPS() { * @param notified don't alert user more than one time */ private void runBenchmark(AtomicInteger framerateAlert, AtomicBoolean notified) { + int benchIteration = Constants.NUMBER_OF_BENCHMARK_ITERATION; + // Wayland has a more swinging frame rate due to the fact that it doesn't capture an image if frame is still, give it some more room for error. + if (NativeExecutor.isWayland()) { + benchIteration = Constants.NUMBER_OF_BENCHMARK_ITERATION * 4; + } if (!notified.get()) { - if ((FPS_PRODUCER > 0) && (framerateAlert.get() < Constants.NUMBER_OF_BENCHMARK_ITERATION) - && (FPS_GW_CONSUMER < FPS_PRODUCER - Constants.BENCHMARK_ERROR_MARGIN)) { + if ((MainSingleton.getInstance().FPS_PRODUCER > 0) && (framerateAlert.get() < benchIteration) + && (MainSingleton.getInstance().FPS_GW_CONSUMER < MainSingleton.getInstance().FPS_PRODUCER - Constants.BENCHMARK_ERROR_MARGIN)) { framerateAlert.getAndIncrement(); } else { framerateAlert.set(0); } int iterationNumber; - if (config.isMultiScreenSingleDevice()) { - iterationNumber = 15; + if (MainSingleton.getInstance().config.isMultiScreenSingleDevice()) { + iterationNumber = benchIteration; } else { - iterationNumber = 6; + iterationNumber = benchIteration / 2; } - if (FPS_GW_CONSUMER == 0 && framerateAlert.get() == iterationNumber && config.isFullFirmware()) { + if (MainSingleton.getInstance().FPS_GW_CONSUMER == 0 && framerateAlert.get() == iterationNumber && MainSingleton.getInstance().config.isFullFirmware()) { log.info("Glow Worm Luciferin is not responding, restarting..."); NativeExecutor.restartNativeInstance(); } - if (framerateAlert.get() == Constants.NUMBER_OF_BENCHMARK_ITERATION && !notified.get() && FPS_GW_CONSUMER > 0) { + if (framerateAlert.get() == benchIteration && !notified.get() && MainSingleton.getInstance().FPS_GW_CONSUMER > 0) { notified.set(true); javafx.application.Platform.runLater(() -> { - int suggestedFramerate; - if (FPS_GW_CONSUMER > (144 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 144; - } else if (FPS_GW_CONSUMER > (120 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 120; - } else if (FPS_GW_CONSUMER > (90 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 90; - } else if (FPS_GW_CONSUMER > (60 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 60; - } else if (FPS_GW_CONSUMER > (50 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 50; - } else if (FPS_GW_CONSUMER > (40 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 40; - } else if (FPS_GW_CONSUMER > (30 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 30; - } else if (FPS_GW_CONSUMER > (25 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 25; - } else if (FPS_GW_CONSUMER > (20 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 20; - } else if (FPS_GW_CONSUMER > (15 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 15; - } else if (FPS_GW_CONSUMER > (10 + Constants.BENCHMARK_ERROR_MARGIN)) { - suggestedFramerate = 10; - } else { - suggestedFramerate = 5; - } + int suggestedFramerate = getSuggestedFramerate(); log.error(CommonUtility.getWord(Constants.FRAMERATE_HEADER) + ". " + CommonUtility.getWord(Constants.FRAMERATE_CONTEXT) .replace("{0}", String.valueOf(suggestedFramerate))); - if (config.isSyncCheck() && LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, FireflyLuciferin.config.getFrameInsertion()).equals(Enums.FrameInsertion.NO_SMOOTHING)) { - Optional result = guiManager.showAlert(CommonUtility.getWord(Constants.FRAMERATE_TITLE), CommonUtility.getWord(Constants.FRAMERATE_HEADER), + if (MainSingleton.getInstance().config.isSyncCheck() && LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, MainSingleton.getInstance().config.getFrameInsertion()).equals(Enums.FrameInsertion.NO_SMOOTHING)) { + Optional result = MainSingleton.getInstance().guiManager.showAlert(CommonUtility.getWord(Constants.FRAMERATE_TITLE), CommonUtility.getWord(Constants.FRAMERATE_HEADER), CommonUtility.getWord(Constants.FRAMERATE_CONTEXT).replace("{0}", String.valueOf(suggestedFramerate)), Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { try { StorageManager sm = new StorageManager(); - config.setDesiredFramerate(String.valueOf(suggestedFramerate)); - sm.writeConfig(config, null); + MainSingleton.getInstance().config.setDesiredFramerate(String.valueOf(suggestedFramerate)); + sm.writeConfig(MainSingleton.getInstance().config, null); SettingsController settingsController = new SettingsController(); settingsController.exit(null); } catch (IOException ioException) { @@ -300,4 +308,5 @@ private void runBenchmark(AtomicInteger framerateAlert, AtomicBoolean notified) } } } + } diff --git a/src/main/java/org/dpsoftware/grabber/GrabberSingleton.java b/src/main/java/org/dpsoftware/grabber/GrabberSingleton.java new file mode 100644 index 000000000..2ef570f91 --- /dev/null +++ b/src/main/java/org/dpsoftware/grabber/GrabberSingleton.java @@ -0,0 +1,75 @@ +/* + GrabberSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.grabber; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.managers.dto.AudioDevice; +import org.freedesktop.gstreamer.Pipeline; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Grabber singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +@SuppressWarnings("all") +public class GrabberSingleton { + + @Getter + private final static GrabberSingleton instance; + + static { + instance = new GrabberSingleton(); + } + + public volatile boolean RUNNING_AUDIO = false; + public int AUDIO_BRIGHTNESS = 255; + public Map audioDevices = new LinkedHashMap<>(); + public float rainbowHue = 0; + public boolean CHECK_ASPECT_RATIO = true; + // Only one instace must be used, Java Garbage Collector will not be fast enough in freeing memory with more instances + public BufferedImage screen; + // LED Matrix Map + public LinkedHashMap ledMatrix; + // Screen capture rectangle + public Rectangle rect; + // GStreamer Rendering pipeline + public Pipeline pipe; + float maxPeak, maxRms = 0; + float maxPeakLeft, maxRmsLeft = 0; + float maxPeakRight, maxRmsRight = 0; + int runNumber = 0; + float lastRmsRun = 0, lastRmsRunLeft = 0, lastRmsRunRight = 0; + float lastPeackRun = 0, lastPeackRunLeft = 0, lastPeackRunRight = 0; + // Custom JNA Class for GDI32Util + CustomGDI32Util customGDI32Util; + +} + diff --git a/src/main/java/org/dpsoftware/grabber/ImageProcessor.java b/src/main/java/org/dpsoftware/grabber/ImageProcessor.java index a6765a826..df1d6ac36 100644 --- a/src/main/java/org/dpsoftware/grabber/ImageProcessor.java +++ b/src/main/java/org/dpsoftware/grabber/ImageProcessor.java @@ -26,10 +26,12 @@ import lombok.extern.slf4j.Slf4j; import org.dpsoftware.FireflyLuciferin; import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; +import org.dpsoftware.gui.elements.Satellite; import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.dto.HSLColor; import org.dpsoftware.utilities.ColorUtilities; @@ -40,7 +42,9 @@ import java.io.File; import java.nio.IntBuffer; import java.util.Arrays; -import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -53,15 +57,6 @@ @Slf4j public class ImageProcessor { - public static boolean CHECK_ASPECT_RATIO = true; - // Only one instace must be used, Java Garbage Collector will not be fast enough in freeing memory with more instances - public static BufferedImage screen; - // LED Matrix Map - public static LinkedHashMap ledMatrix; - // Screen capture rectangle - public static Rectangle rect; - // Custom JNA Class for GDI32Util - static CustomGDI32Util customGDI32Util; //Get JNA User32 Instace com.sun.jna.platform.win32.User32 user32; //Get desktop windows handler @@ -74,11 +69,12 @@ public ImageProcessor(boolean initLedMatrix) { if (NativeExecutor.isWindows()) { user32 = com.sun.jna.platform.win32.User32.INSTANCE; hwnd = user32.GetDesktopWindow(); - customGDI32Util = new CustomGDI32Util(hwnd); + GrabberSingleton.getInstance().customGDI32Util = new CustomGDI32Util(hwnd); } if (initLedMatrix) { - ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(FireflyLuciferin.config.getDefaultLedMatrix()); - rect = new Rectangle(new Dimension((FireflyLuciferin.config.getScreenResX() * 100) / FireflyLuciferin.config.getOsScaling(), (FireflyLuciferin.config.getScreenResY() * 100) / FireflyLuciferin.config.getOsScaling())); + GrabberSingleton.getInstance().ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(MainSingleton.getInstance().config.getDefaultLedMatrix()); + GrabberSingleton.getInstance().rect = new Rectangle(new Dimension((MainSingleton.getInstance().config.getScreenResX() * 100) / MainSingleton.getInstance().config.getOsScaling(), + (MainSingleton.getInstance().config.getScreenResY() * 100) / MainSingleton.getInstance().config.getOsScaling())); } } @@ -93,36 +89,48 @@ public ImageProcessor(boolean initLedMatrix) { public static Color[] getColors(Robot robot, BufferedImage image) { // Choose between CPU and GPU acceleration if (image == null) { - if (FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.WinAPI.name())) { - screen = customGDI32Util.getScreenshot(); + if (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.WinAPI.name())) { + GrabberSingleton.getInstance().screen = GrabberSingleton.getInstance().customGDI32Util.getScreenshot(); } else { - screen = robot.createScreenCapture(rect); + GrabberSingleton.getInstance().screen = robot.createScreenCapture(GrabberSingleton.getInstance().rect); } //ImageIO.write(bi, "png", new java.io.File("screenshot.png")); } else { - screen = image; + GrabberSingleton.getInstance().screen = image; } // CHECK_ASPECT_RATIO is true 10 times per second, if true and black bars auto detection is on, auto detect black bars - if (FireflyLuciferin.config.isAutoDetectBlackBars()) { - if (ImageProcessor.CHECK_ASPECT_RATIO) { - ImageProcessor.CHECK_ASPECT_RATIO = false; - ImageProcessor.autodetectBlackBars(screen.getWidth(), screen.getHeight(), null); - ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(FireflyLuciferin.config.getDefaultLedMatrix()); + if (MainSingleton.getInstance().config.isAutoDetectBlackBars()) { + if (GrabberSingleton.getInstance().CHECK_ASPECT_RATIO) { + GrabberSingleton.getInstance().CHECK_ASPECT_RATIO = false; + ImageProcessor.autodetectBlackBars(GrabberSingleton.getInstance().screen.getWidth(), GrabberSingleton.getInstance().screen.getHeight(), null); + GrabberSingleton.getInstance().ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(MainSingleton.getInstance().config.getDefaultLedMatrix()); } } - int osScaling = FireflyLuciferin.config.getOsScaling(); - Color[] leds = new Color[ledMatrix.size()]; + int osScaling = MainSingleton.getInstance().config.getOsScaling(); + Color[] leds = new Color[GrabberSingleton.getInstance().ledMatrix.size()]; // We need an ordered collection so no parallelStream here - ledMatrix.forEach((key, value) -> + GrabberSingleton.getInstance().ledMatrix.forEach((key, value) -> leds[key - 1] = getAverageColor(value, osScaling) ); - + averageOnAllLeds(leds); return leds; } + /** + * Set the average color on all leds + * + * @param leds color array + */ + public static void averageOnAllLeds(Color[] leds) { + if (Enums.Algo.AVG_ALL_COLOR.getBaseI18n().equals(MainSingleton.getInstance().config.getAlgo())) { + Color avgColor = ImageProcessor.getAverageForAllZones(leds, 0, leds.length); + Arrays.fill(leds, avgColor); + } + } + /** * Get the average color from the screen buffer section * @@ -136,17 +144,17 @@ public static Color getAverageColor(LEDCoordinate ledCoordinate, int osScaling) // 6 pixel for X axis and 6 pixel for Y axis int pixelToUse = 6; int pickNumber = 0; - int width = screen.getWidth() - (skipPixel * pixelToUse); - int height = screen.getHeight() - (skipPixel * pixelToUse); - int xCoordinate = !(FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name())) ? ledCoordinate.getX() : ((ledCoordinate.getX() * 100) / osScaling); - int yCoordinate = !(FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name())) ? ledCoordinate.getY() : ((ledCoordinate.getY() * 100) / osScaling); + int width = GrabberSingleton.getInstance().screen.getWidth() - (skipPixel * pixelToUse); + int height = GrabberSingleton.getInstance().screen.getHeight() - (skipPixel * pixelToUse); + int xCoordinate = !(MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name())) ? ledCoordinate.getX() : ((ledCoordinate.getX() * 100) / osScaling); + int yCoordinate = !(MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.CPU.name())) ? ledCoordinate.getY() : ((ledCoordinate.getY() * 100) / osScaling); // We start with a negative offset for (int x = 0; x < pixelToUse; x++) { for (int y = 0; y < pixelToUse; y++) { int offsetX = (xCoordinate + (skipPixel * x)); int offsetY = (yCoordinate + (skipPixel * y)); - int rgb = screen.getRGB(Math.min(offsetX, width), Math.min(offsetY, height)); + int rgb = GrabberSingleton.getInstance().screen.getRGB(Math.min(offsetX, width), Math.min(offsetY, height)); Color color = new Color(rgb); r += color.getRed(); g += color.getGreen(); @@ -188,14 +196,14 @@ public static Color correctColors(int r, int g, int b, int pickNumber) { g = gammaCorrection(g); b = gammaCorrection(b); // Don't turn off LEDs when they are black (eye care) - if (FireflyLuciferin.config.isEyeCare() && (r + g + b) < 10) { + if (MainSingleton.getInstance().config.isEyeCare() && (r + g + b) < 10) { r = g = b = (Constants.DEEP_BLACK_CHANNEL_TOLERANCE * 2); } // Brightness limiter to limit strobo effect - if (FireflyLuciferin.config.getBrightnessLimiter() != 1.0F) { + if (MainSingleton.getInstance().config.getBrightnessLimiter() != 1.0F) { float[] brightnessLimitedRGB = ColorUtilities.RGBtoHSL(r, g, b, null); - if (brightnessLimitedRGB[2] >= FireflyLuciferin.config.getBrightnessLimiter()) { - brightnessLimitedRGB[2] = FireflyLuciferin.config.getBrightnessLimiter(); + if (brightnessLimitedRGB[2] >= MainSingleton.getInstance().config.getBrightnessLimiter()) { + brightnessLimitedRGB[2] = MainSingleton.getInstance().config.getBrightnessLimiter(); } return ColorUtilities.HSLtoRGB(brightnessLimitedRGB[0], brightnessLimitedRGB[1], brightnessLimitedRGB[2]); } @@ -209,7 +217,7 @@ public static Color correctColors(int r, int g, int b, int pickNumber) { * @return the average color */ public static int gammaCorrection(int color) { - return (int) (255.0 * Math.pow((color / 255.0), FireflyLuciferin.config.getGamma())); + return (int) (255.0 * Math.pow((color / 255.0), MainSingleton.getInstance().config.getGamma())); } /** @@ -284,7 +292,7 @@ static int[][] calculateBlackPixels(Enums.AspectRatio aspectRatio, int width, in g = rgb >> 8 & 0xFF; b = rgb & 0xFF; } else { // Other methods - int rgb = screen.getRGB(Math.min(offsetX, width), Math.min(offsetY, height)); + int rgb = GrabberSingleton.getInstance().screen.getRGB(Math.min(offsetX, width), Math.min(offsetY, height)); Color color = new Color(rgb); r = color.getRed(); g = color.getGreen(); @@ -316,25 +324,25 @@ static boolean switchAspectRatio(Enums.AspectRatio aspectRatio, int[][] blackPix boolean enoughWhitePixelForTheChange = centerMatrix < (Constants.NUMBER_OF_AREA_TO_CHECK - whitePixelPercentage); // NUMBER_OF_AREA_TO_CHECK must be black on botton/top left/right, center pixels must be less than NUMBER_OF_AREA_TO_CHECK (at least on NON black pixel in the center) if (topMatrix == Constants.NUMBER_OF_AREA_TO_CHECK && centerMatrix < Constants.NUMBER_OF_AREA_TO_CHECK && bottomMatrix == Constants.NUMBER_OF_AREA_TO_CHECK) { - if (!FireflyLuciferin.config.getDefaultLedMatrix().equals(aspectRatio.getBaseI18n())) { + if (!MainSingleton.getInstance().config.getDefaultLedMatrix().equals(aspectRatio.getBaseI18n())) { if (enoughWhitePixelForTheChange) { - FireflyLuciferin.config.setDefaultLedMatrix(aspectRatio.getBaseI18n()); - GStreamerGrabber.ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(aspectRatio.getBaseI18n()); + MainSingleton.getInstance().config.setDefaultLedMatrix(aspectRatio.getBaseI18n()); + GStreamerGrabber.ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(aspectRatio.getBaseI18n()); log.info("Switching to " + aspectRatio.getBaseI18n() + " aspect ratio."); - if (FireflyLuciferin.config.isMqttEnable()) { - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.ASPECT_RATIO_TOPIC), aspectRatio.getBaseI18n()); + if (MainSingleton.getInstance().config.isMqttEnable()) { + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_ASPECT_RATIO), aspectRatio.getBaseI18n()); } } } isPillarboxLetterbox = true; } else { - if (!FireflyLuciferin.config.getDefaultLedMatrix().equals(Enums.AspectRatio.FULLSCREEN.getBaseI18n())) { + if (!MainSingleton.getInstance().config.getDefaultLedMatrix().equals(Enums.AspectRatio.FULLSCREEN.getBaseI18n())) { if (setFullscreen && enoughWhitePixelForTheChange) { - FireflyLuciferin.config.setDefaultLedMatrix(Enums.AspectRatio.FULLSCREEN.getBaseI18n()); - GStreamerGrabber.ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(Enums.AspectRatio.FULLSCREEN.getBaseI18n()); + MainSingleton.getInstance().config.setDefaultLedMatrix(Enums.AspectRatio.FULLSCREEN.getBaseI18n()); + GStreamerGrabber.ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(Enums.AspectRatio.FULLSCREEN.getBaseI18n()); log.info("Switching to " + Enums.AspectRatio.FULLSCREEN.getBaseI18n() + " aspect ratio."); - if (FireflyLuciferin.config.isMqttEnable()) { - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.ASPECT_RATIO_TOPIC), Enums.AspectRatio.FULLSCREEN.getBaseI18n()); + if (MainSingleton.getInstance().config.isMqttEnable()) { + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_ASPECT_RATIO), Enums.AspectRatio.FULLSCREEN.getBaseI18n()); } } } @@ -351,9 +359,9 @@ static boolean switchAspectRatio(Enums.AspectRatio aspectRatio, int[][] blackPix */ public static int calculateBorders(Enums.AspectRatio aspectRatio) { if (aspectRatio == Enums.AspectRatio.LETTERBOX) { - return Math.max(0, (((FireflyLuciferin.config.getScreenResY() * Constants.AR_LETTERBOX_GAP) / 2160) / Constants.RESAMPLING_FACTOR) - 5); + return Math.max(0, (((MainSingleton.getInstance().config.getScreenResY() * Constants.AR_LETTERBOX_GAP) / 2160) / Constants.RESAMPLING_FACTOR) - 5); } else { - return Math.max(0, (((FireflyLuciferin.config.getScreenResY() * Constants.AR_PILLARBOX_GAP) / 2160) / Constants.RESAMPLING_FACTOR) - 5); + return Math.max(0, (((MainSingleton.getInstance().config.getScreenResY() * Constants.AR_PILLARBOX_GAP) / 2160) / Constants.RESAMPLING_FACTOR) - 5); } } @@ -380,17 +388,17 @@ public static Color manageColors(int r, int g, int b) { hslCorrectedColor.setLightness(null); float hsvDegree = hslColor.getHue() * Constants.DEGREE_360; // Master channel adds to all color channels - if (FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).getSaturation() != 0.0F - || FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).getLightness() != 0.0F) { - hslCorrectedColor.setSaturation((float) hslColor.getSaturation() + FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).getSaturation()); + if (MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).getSaturation() != 0.0F + || MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).getLightness() != 0.0F) { + hslCorrectedColor.setSaturation((float) hslColor.getSaturation() + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).getSaturation()); hslColor.setSaturation(hslCorrectedColor.getSaturation()); - hslCorrectedColor.setLightness((float) hslColor.getLightness() + FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).getLightness()); + hslCorrectedColor.setLightness((float) hslColor.getLightness() + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).getLightness()); hslColor.setLightness(hslCorrectedColor.getLightness()); } // Colors channels boolean greyDetected = (hslColor.getSaturation() <= Constants.GREY_TOLERANCE); if (greyDetected) { - if (FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() != 0.0F) { + if (MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() != 0.0F) { correctGreyColors(hslColor, hslCorrectedColor); } } else if (hsvDegree >= Enums.ColorEnum.RED.getMin() || hsvDegree <= Enums.ColorEnum.RED.getMax() && !greyDetected) { @@ -428,10 +436,10 @@ public static Color manageColors(int r, int g, int b) { * @param currentColor current color enum */ private static void correctColors(HSLColor hslColor, HSLColor hslCorrectedColor, float hsvDegree, Enums.ColorEnum currentColor) { - hslCorrectedColor.setHue(hslCorrectedColor.getHue() + (FireflyLuciferin.config.getHueMap().get(currentColor).getHue() / Constants.DEGREE_360)); - if (FireflyLuciferin.config.getHueMap().get(currentColor).getSaturation() != 0.0F || FireflyLuciferin.config.getHueMap().get(currentColor).getLightness() != 0.0F) { - hslCorrectedColor.setSaturation((float) hslColor.getSaturation() + FireflyLuciferin.config.getHueMap().get(currentColor).getSaturation()); - hslCorrectedColor.setLightness((float) hslColor.getLightness() + FireflyLuciferin.config.getHueMap().get(currentColor).getLightness()); + hslCorrectedColor.setHue(hslCorrectedColor.getHue() + (MainSingleton.getInstance().config.getHueMap().get(currentColor).getHue() / Constants.DEGREE_360)); + if (MainSingleton.getInstance().config.getHueMap().get(currentColor).getSaturation() != 0.0F || MainSingleton.getInstance().config.getHueMap().get(currentColor).getLightness() != 0.0F) { + hslCorrectedColor.setSaturation((float) hslColor.getSaturation() + MainSingleton.getInstance().config.getHueMap().get(currentColor).getSaturation()); + hslCorrectedColor.setLightness((float) hslColor.getLightness() + MainSingleton.getInstance().config.getHueMap().get(currentColor).getLightness()); } hslCorrectedColor.setHue(neighboringColors(hslCorrectedColor.getHue(), hsvDegree, hslCorrectedColor.getHue(), currentColor, Enums.HSL.H)); hslCorrectedColor.setSaturation(neighboringColors(hslColor.getSaturation(), hsvDegree, hslCorrectedColor.getSaturation(), currentColor, Enums.HSL.S)); @@ -445,9 +453,9 @@ private static void correctColors(HSLColor hslColor, HSLColor hslCorrectedColor, * @param hslCorrectedColor contains current HSL values corrections */ private static void correctGreyColors(HSLColor hslColor, HSLColor hslCorrectedColor) { - if (FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() != 0.0F) { + if (MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() != 0.0F) { // Add lightness as percentage to the current ones - hslCorrectedColor.setLightness(hslColor.getLightness() * (FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() + 1.0F)); + hslCorrectedColor.setLightness(hslColor.getLightness() * (MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREY).getLightness() + 1.0F)); } } @@ -467,16 +475,16 @@ private static Float neighboringColors(float value, float hsvDegree, Float value float nextColorSetting = 0, prevColorSetting = 0; switch (hslToUse) { case H -> { - nextColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.next()).getHue() / Constants.DEGREE_360; - prevColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.prev()).getHue() / Constants.DEGREE_360; + nextColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.next()).getHue() / Constants.DEGREE_360; + prevColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.prev()).getHue() / Constants.DEGREE_360; } case S -> { - nextColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.next()).getSaturation(); - prevColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.prev()).getSaturation(); + nextColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.next()).getSaturation(); + prevColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.prev()).getSaturation(); } case L -> { - nextColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.next()).getLightness(); - prevColorSetting = FireflyLuciferin.config.getHueMap().get(currentColor.prev()).getLightness(); + nextColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.next()).getLightness(); + prevColorSetting = MainSingleton.getInstance().config.getHueMap().get(currentColor.prev()).getLightness(); } } // Next color @@ -499,6 +507,150 @@ private static Float neighboringColors(float value, float hsvDegree, Float value return valueToUse; } + /** + * Add N colors for every Zone + * + * @param leds array of colors to send + * @param sat satellite where to send colors + * @param zoneDetail record with start end position + * @return color array + */ + public static java.util.List padColors(Color[] leds, Satellite sat, LEDCoordinate.getStartEndLeds zoneDetail) { + int zoneStart = zoneDetail.start() - 1; + int zoneNumLed = (zoneDetail.end() - zoneDetail.start()) + 1; + int satNumLed = Integer.parseInt(sat.getLedNum()); + List clonedLeds; + clonedLeds = new LinkedList<>(); + int multiplier = (int) Math.abs((double) satNumLed / zoneNumLed); + for (int lIdx = 0; lIdx < zoneNumLed; lIdx++) { + clonedLeds.add(leds[zoneStart + lIdx]); + for (int j = 0; j < multiplier - 1; j++) { + clonedLeds.add(leds[zoneStart + lIdx]); + } + } + return addLeds(satNumLed, clonedLeds); + } + + /** + * Add colors on the head and the tail of the color list + * + * @param satNumLed max number of LEDs on the satellite + * @param clonedLeds array to use for the satellite + * @return color array + */ + private static List addLeds(int satNumLed, List clonedLeds) { + int colorToAdd = satNumLed - clonedLeds.size(); + int colorAdded = 0; + if (colorToAdd > 0) { + int addEveryLed = Math.abs(clonedLeds.size() / colorToAdd); + int addIdx = 0; + ListIterator iterator = clonedLeds.listIterator(); + while (iterator.hasNext() && colorAdded < colorToAdd) { + Color c = iterator.next(); + if (addIdx == addEveryLed) { + colorAdded++; + iterator.add(c); + addIdx = 0; + } + addIdx++; + } + for (int i = clonedLeds.size(); i < satNumLed; i++) { + clonedLeds.add(clonedLeds.get(clonedLeds.size() - 1)); + } + } + return clonedLeds; + } + + /** + * When a satellite has less LEDs than the number of captured zones, reduce colors on the array + * + * @param leds array of colors to send + * @param sat satellite where to send colors + * @param zoneDetail record with start end position + * @return reduced array + */ + public static java.util.List reduceColors(Color[] leds, Satellite sat, LEDCoordinate.getStartEndLeds zoneDetail) { + int zoneStart = zoneDetail.start() - 1; + int zoneNumLed = (zoneDetail.end() - zoneDetail.start()) + 1; + int satNumLed = Integer.parseInt(sat.getLedNum()); + List clonedLeds; + clonedLeds = new LinkedList<>(); + int divider = (int) Math.ceil((double) zoneNumLed / satNumLed); + int r = 0, g = 0, b = 0; + for (int i = 0; i < zoneNumLed; i++) { + r += leds[zoneStart + i].getRed(); + g += leds[zoneStart + i].getGreen(); + b += leds[zoneStart + i].getBlue(); + if (i % divider == 0) { + clonedLeds.add(new Color(r / divider, g / divider, b / divider)); + r = 0; + g = 0; + b = 0; + } + } + return addLeds(satNumLed, clonedLeds); + } + + /** + * Returns an array of colors containing the average for all zones + * + * @param leds original array of colors + * @param zoneStart captured zone, start + * @param zoneEnd captured zone, end + * @return avg color from every capture zones + */ + public static Color getAverageForAllZones(Color[] leds, int zoneStart, int zoneEnd) { + int rAccumulator = 0; + int gAccumulator = 0; + int bAccumulator = 0; + for (int i = zoneStart; i < zoneEnd; i++) { + rAccumulator += leds[i].getRed(); + gAccumulator += leds[i].getGreen(); + bAccumulator += leds[i].getBlue(); + } + int zoneNum = (zoneEnd - zoneStart) + 1; + return new Color(rAccumulator / zoneNum, + gAccumulator / zoneNum, + bAccumulator / zoneNum); + } + + /** + * Round to the nearest number + * + * @param nearestNumberToUse if 10, it rounds to the nearest 10, if 5, it rounds to the nearest five + * example: 6 = 10, 4 = 0, 234 = 230 + * @param numberToRound number to round + * @return rounded number, 255 is rounded to 260 so it retuns max 255 for RGB + */ + @SuppressWarnings("unused") + private static int roundToTheNearestNumber(int nearestNumberToUse, int numberToRound) { + int roundedNum = (int) (Math.round(numberToRound / (double) nearestNumberToUse) * nearestNumberToUse); + return Math.min(roundedNum, 255); + } + + /** + * Find the distance between two colors + * + * @param r1 rgb channel + * @param g1 rgb channel + * @param b1 rgb channel + * @param r2 rgb channel + * @param g2 rgb channel + * @param b2 rgb channel + * @return distance + */ + @SuppressWarnings("unused") + private double colorDistance(int r1, int g1, int b1, int r2, int g2, int b2) { + double rmean = (double) (r1 + r2) / 2; + int r = r1 - r2; + int g = g1 - g2; + int b = b1 - b2; + double weightR = 2 + rmean / 256; + double weightG = 4.0; + double weightB = 2 + (255 - rmean) / 256; + return Math.sqrt(weightR * r * r + weightG * g * g + weightB * b * b); + } + /** * Load GStreamer libraries */ @@ -558,7 +710,7 @@ public String getInstallationPath() { */ public void calculateBorders() { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); - Runnable framerateTask = () -> ImageProcessor.CHECK_ASPECT_RATIO = true; + Runnable framerateTask = () -> GrabberSingleton.getInstance().CHECK_ASPECT_RATIO = true; scheduledExecutorService.scheduleAtFixedRate(framerateTask, 1, 100, TimeUnit.MILLISECONDS); } diff --git a/src/main/java/org/dpsoftware/gui/GUIManager.java b/src/main/java/org/dpsoftware/gui/GuiManager.java similarity index 54% rename from src/main/java/org/dpsoftware/gui/GUIManager.java rename to src/main/java/org/dpsoftware/gui/GuiManager.java index 1c6df37b3..0a6d6ed3e 100644 --- a/src/main/java/org/dpsoftware/gui/GUIManager.java +++ b/src/main/java/org/dpsoftware/gui/GuiManager.java @@ -1,5 +1,5 @@ /* - GUIManager.java + GuiManager.java Firefly Luciferin, very fast Java Screen Capture software designed for Glow Worm Luciferin firmware. @@ -21,6 +21,8 @@ */ package org.dpsoftware.gui; +import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WinUser; import javafx.application.Platform; import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; @@ -38,22 +40,23 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.gui.controllers.ColorCorrectionDialogController; import org.dpsoftware.gui.controllers.EyeCareDialogController; +import org.dpsoftware.gui.controllers.SatellitesDialogController; import org.dpsoftware.gui.controllers.SettingsController; +import org.dpsoftware.managers.ManagerSingleton; import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.PipelineManager; import org.dpsoftware.managers.UpgradeManager; import org.dpsoftware.managers.dto.ColorDto; import org.dpsoftware.managers.dto.StateDto; import org.dpsoftware.managers.dto.StateStatusDto; -import org.dpsoftware.network.MessageClient; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.utilities.CommonUtility; import javax.swing.*; @@ -68,16 +71,17 @@ */ @Slf4j @NoArgsConstructor -public class GUIManager extends JFrame { +public class GuiManager { public PipelineManager pipelineManager; public TrayIconManager trayIconManager; // Label and framerate dialog @Getter JEditorPane jep = new JEditorPane(); - @Getter - JFrame jFrame = new JFrame(Constants.FIREFLY_LUCIFERIN); private Stage stage; + private Scene mainScene; + private double xOffset = 0; + private double yOffset = 0; /** * Constructor @@ -85,7 +89,7 @@ public class GUIManager extends JFrame { * @param stage JavaFX stage * @throws HeadlessException GUI exception */ - public GUIManager(Stage stage) throws HeadlessException, UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { + public GuiManager(Stage stage) throws HeadlessException, UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { this.stage = stage; UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); pipelineManager = new PipelineManager(); @@ -100,7 +104,7 @@ public GUIManager(Stage stage) throws HeadlessException, UnsupportedLookAndFeelE * @throws IOException file exception */ public static Parent loadFXML(String fxml) throws IOException { - FXMLLoader fxmlLoader = new FXMLLoader(GUIManager.class.getResource(fxml + Constants.FXML), FireflyLuciferin.bundle); + FXMLLoader fxmlLoader = new FXMLLoader(GuiManager.class.getResource(fxml + Constants.FXML), MainSingleton.getInstance().bundle); return fxmlLoader.load(); } @@ -110,7 +114,32 @@ public static Parent loadFXML(String fxml) throws IOException { * @param stage in use */ public static void setStageIcon(Stage stage) { - stage.getIcons().add(new javafx.scene.image.Image(String.valueOf(GUIManager.class.getResource(Constants.IMAGE_TRAY_STOP)))); + stage.getIcons().add(new javafx.scene.image.Image(String.valueOf(GuiManager.class.getResource(Constants.IMAGE_TRAY_STOP)))); + } + + /** + * Create window title + * + * @return title + */ + public static String createWindowTitle() { + String title = " " + Constants.FIREFLY_LUCIFERIN; + switch (MainSingleton.getInstance().whoAmI) { + case 1 -> { + if ((MainSingleton.getInstance().config.getMultiMonitor() != 1)) { + title += " (" + CommonUtility.getWord(Constants.RIGHT_DISPLAY) + ")"; + } + } + case 2 -> { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 2)) { + title += " (" + CommonUtility.getWord(Constants.LEFT_DISPLAY) + ")"; + } else { + title += " (" + CommonUtility.getWord(Constants.CENTER_DISPLAY) + ")"; + } + } + case 3 -> title += " (" + CommonUtility.getWord(Constants.LEFT_DISPLAY) + ")"; + } + return title; } /** @@ -153,7 +182,7 @@ public Optional showLocalizedAlert(String title, String header, Stri * @param notificationType notification type */ public void showNotification(String title, String content, TrayIcon.MessageType notificationType) { - FireflyLuciferin.guiManager.trayIconManager.getTrayIcon().displayMessage(title, content, notificationType); + MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon().displayMessage(title, content, notificationType); } /** @@ -164,7 +193,7 @@ public void showNotification(String title, String content, TrayIcon.MessageType * @param notificationType notification type */ public void showLocalizedNotification(String title, String content, TrayIcon.MessageType notificationType) { - FireflyLuciferin.guiManager.trayIconManager.getTrayIcon().displayMessage(CommonUtility.getWord(title), + MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon().displayMessage(CommonUtility.getWord(title), CommonUtility.getWord(content), notificationType); } @@ -186,7 +215,7 @@ private void setAlertTheme(Alert alert) { * @param scene where to apply the style */ private void setStylesheet(ObservableList stylesheets, Scene scene) { - var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, FireflyLuciferin.config.getTheme()); + var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, MainSingleton.getInstance().config.getTheme()); switch (theme) { case DARK_THEME_CYAN -> { stylesheets.add(Objects.requireNonNull(getClass().getResource(Constants.CSS_THEME_DARK)).toExternalForm()); @@ -252,18 +281,20 @@ private Alert createAlert(String title, String header, Alert.AlertType alertType /** * Show a dialog with all the settings + * + * @param preloadFxml if true, it preload the fxml without showing it */ - void showSettingsDialog() { + public void showSettingsDialog(boolean preloadFxml) { String fxml; fxml = Constants.FXML_SETTINGS; - showStage(fxml); + showStage(fxml, preloadFxml); } /** * Show a dialog with a framerate counter */ public void showFramerateDialog() { - showStage(Constants.FXML_INFO); + showStage(Constants.FXML_INFO, false); } /** @@ -274,24 +305,17 @@ public void showFramerateDialog() { */ public void showColorCorrectionDialog(SettingsController settingsController, InputEvent event) { Platform.runLater(() -> { - Scene scene; try { TestCanvas testCanvas = new TestCanvas(); testCanvas.buildAndShowTestImage(event); - FXMLLoader fxmlLoader = new FXMLLoader(GUIManager.class.getResource(Constants.FXML_COLOR_CORRECTION_DIALOG + Constants.FXML), FireflyLuciferin.bundle); + FXMLLoader fxmlLoader = new FXMLLoader(GuiManager.class.getResource(Constants.FXML_COLOR_CORRECTION_DIALOG + Constants.FXML), MainSingleton.getInstance().bundle); Parent root = fxmlLoader.load(); ColorCorrectionDialogController controller = fxmlLoader.getController(); controller.injectSettingsController(settingsController); controller.injectTestCanvas(testCanvas); - controller.initValuesFromSettingsFile(FireflyLuciferin.config); - scene = new Scene(root); - setStylesheet(scene.getStylesheets(), scene); - scene.setFill(Color.TRANSPARENT); - Stage stage = new Stage(); - stage.initStyle(StageStyle.UNDECORATED); - stage.initModality(Modality.APPLICATION_MODAL); - stage.setScene(scene); - Platform.runLater(() -> TestCanvas.setDialogMargin(stage)); + controller.initValuesFromSettingsFile(MainSingleton.getInstance().config); + Stage stage = initStage(root); + Platform.runLater(() -> new TestCanvas().setDialogMargin(stage)); stage.initStyle(StageStyle.TRANSPARENT); stage.setAlwaysOnTop(true); stage.showAndWait(); @@ -301,6 +325,68 @@ public void showColorCorrectionDialog(SettingsController settingsController, Inp }); } + /** + * Initialize stage + * @param root parent root + * @return initialized stage + */ + private Stage initStage(Parent root) { + Scene scene; + scene = new Scene(root); + setStylesheet(scene.getStylesheets(), scene); + scene.setFill(Color.TRANSPARENT); + Stage stage = new Stage(); + stage.initStyle(StageStyle.UNDECORATED); + stage.initModality(Modality.APPLICATION_MODAL); + stage.setScene(scene); + return stage; + } + + /** + * Show a secondary stage dialog + * + * @param settingsController controller + * @param fxmlLoader fxml loader + * @throws IOException error + */ + private void showSecondaryStage(Class classForCast, SettingsController settingsController, FXMLLoader fxmlLoader) throws IOException { + Parent root = fxmlLoader.load(); + Object controller; + controller = fxmlLoader.getController(); + if (classForCast == EyeCareDialogController.class) { + ((EyeCareDialogController) controller).injectSettingsController(settingsController); + ((EyeCareDialogController) controller).initValuesFromSettingsFile(MainSingleton.getInstance().config); + } else if (classForCast == SatellitesDialogController.class) { + ((SatellitesDialogController) controller).injectSettingsController(settingsController); + ((SatellitesDialogController) controller).setTooltips(); + } + Stage stage = initStage(root); + stage.initStyle(StageStyle.TRANSPARENT); + stage.setAlwaysOnTop(true); + Platform.runLater(() -> { + Stage parentStage = this.stage; + stage.setX(parentStage.getX() + (parentStage.getWidth() / 2) - (stage.getWidth() / 2)); + stage.setY(parentStage.getY() + (parentStage.getHeight() / 2) - (stage.getHeight() / 2)); + }); + stage.showAndWait(); + } + + /** + * Show satellites dialog + * + * @param settingsController we need to manually inject dialog controller in the main controller + */ + public void showSatellitesDialog(SettingsController settingsController) { + Platform.runLater(() -> { + try { + FXMLLoader fxmlLoader = new FXMLLoader(GuiManager.class.getResource(Constants.FXML_SATELLITES_DIALOG + Constants.FXML), MainSingleton.getInstance().bundle); + showSecondaryStage(SatellitesDialogController.class, settingsController, fxmlLoader); + } catch (IOException e) { + log.error(e.getMessage()); + } + }); + } + /** * Show eye care dialog * @@ -308,28 +394,9 @@ public void showColorCorrectionDialog(SettingsController settingsController, Inp */ public void showEyeCareDialog(SettingsController settingsController) { Platform.runLater(() -> { - Scene scene; try { - FXMLLoader fxmlLoader = new FXMLLoader(GUIManager.class.getResource(Constants.FXML_EYE_CARE_DIALOG + Constants.FXML), FireflyLuciferin.bundle); - Parent root = fxmlLoader.load(); - EyeCareDialogController controller = fxmlLoader.getController(); - controller.injectSettingsController(settingsController); - controller.initValuesFromSettingsFile(FireflyLuciferin.config); - scene = new Scene(root); - setStylesheet(scene.getStylesheets(), scene); - scene.setFill(Color.TRANSPARENT); - Stage stage = new Stage(); - stage.initStyle(StageStyle.UNDECORATED); - stage.initModality(Modality.APPLICATION_MODAL); - stage.setScene(scene); - stage.initStyle(StageStyle.TRANSPARENT); - stage.setAlwaysOnTop(true); - Platform.runLater(() -> { - Stage parentStage = this.stage; - stage.setX(parentStage.getX() + (parentStage.getWidth() / 2) - (stage.getWidth() / 2)); - stage.setY(parentStage.getY() + (parentStage.getHeight() / 2) - (stage.getHeight() / 2)); - }); - stage.showAndWait(); + FXMLLoader fxmlLoader = new FXMLLoader(GuiManager.class.getResource(Constants.FXML_EYE_CARE_DIALOG + Constants.FXML), MainSingleton.getInstance().bundle); + showSecondaryStage(EyeCareDialogController.class, settingsController, fxmlLoader); } catch (IOException e) { log.error(e.getMessage()); } @@ -339,82 +406,176 @@ public void showEyeCareDialog(SettingsController settingsController) { /** * Show a stage * - * @param stageName stage to show + * @param stageName stage to show + * @param preloadFxml if true, it preload the fxml without showing it */ - void showStage(String stageName) { + void showStage(String stageName, boolean preloadFxml) { Platform.runLater(() -> { try { + boolean isDefaultTheme = LocalizedEnum.fromBaseStr(Enums.Theme.class, MainSingleton.getInstance().config.getTheme()).equals(Enums.Theme.DEFAULT); + boolean isMainStage = stageName.equals(Constants.FXML_SETTINGS) || stageName.equals(Constants.FXML_SETTINGS_CUSTOM_BAR); if (NativeExecutor.isLinux() && stageName.equals(Constants.FXML_INFO)) { stage = new Stage(); + if (!(NativeExecutor.isWindows() && !isDefaultTheme)) { + stage.initStyle(StageStyle.DECORATED); + } } - Scene scene = new Scene(loadFXML(stageName)); - setStylesheet(scene.getStylesheets(), scene); if (stage == null) { stage = new Stage(); } stage.resizableProperty().setValue(Boolean.FALSE); - stage.setScene(scene); - String title = " " + Constants.FIREFLY_LUCIFERIN; - switch (JavaFXStarter.whoAmI) { - case 1 -> { - if ((FireflyLuciferin.config.getMultiMonitor() != 1)) { - title += " (" + CommonUtility.getWord(Constants.RIGHT_DISPLAY) + ")"; - } - } - case 2 -> { - if ((FireflyLuciferin.config.getMultiMonitor() == 2)) { - title += " (" + CommonUtility.getWord(Constants.LEFT_DISPLAY) + ")"; - } else { - title += " (" + CommonUtility.getWord(Constants.CENTER_DISPLAY) + ")"; - } - } - case 3 -> title += " (" + CommonUtility.getWord(Constants.LEFT_DISPLAY) + ")"; - } + setScene(stageName, isMainStage, isDefaultTheme); + String title = createWindowTitle(); stage.setTitle(title); setStageIcon(stage); - if (stageName.equals(Constants.FXML_SETTINGS) && NativeExecutor.isLinux()) { + if (isMainStage && NativeExecutor.isLinux()) { stage.setIconified(true); } - stage.show(); + if (NativeExecutor.isWindows() && !isDefaultTheme) { + manageNativeWindow(stage.getScene(), title, preloadFxml); + } else { + showWithPreload(preloadFxml); + } } catch (IOException e) { log.error(e.getMessage()); } }); } + /** + * Setting scene into main stage, main scene is preloaded and stored in memory + * + * @param stageName stage name to load + * @param isMainStage true if settings.fxml is passed as parameter + * @param isDefaultTheme true if using classic theme + * @throws IOException error + */ + private void setScene(String stageName, boolean isMainStage, boolean isDefaultTheme) throws IOException { + if (isMainStage && mainScene != null) { + stage.getScene().setRoot(mainScene.getRoot()); + } else { + log.debug("Loading FXML"); + Parent root; + if (NativeExecutor.isWindows() && !isDefaultTheme) { + if (stageName.equals(Constants.FXML_SETTINGS)) { + root = loadFXML(Constants.FXML_SETTINGS_CUSTOM_BAR); + root.setStyle(Constants.FXML_TRANSPARENT); + } else if (stageName.equals(Constants.FXML_INFO)) { + root = loadFXML(Constants.FXML_INFO_CUSTOM_BAR); + root.setStyle(Constants.FXML_TRANSPARENT); + } else { + root = loadFXML(stageName); + } + manageWindowDragging(root); + } else { + root = loadFXML(stageName); + } + Scene scene = new Scene(root); + setStylesheet(scene.getStylesheets(), scene); + stage.setScene(scene); + if (isMainStage) { + mainScene = scene; + } else { + mainScene = null; + } + log.debug("FXML loaded"); + } + } + + /** + * Add Windows animations (minimize/maximize) for the undecorated window using JNA + * + * @param scene in use + * @param finalTitle window title to target + * @param preloadFxml if true, it preload the fxml without showing it + */ + private void manageNativeWindow(Scene scene, String finalTitle, boolean preloadFxml) { + if (!stage.isShowing() && !stage.getStyle().name().equals(Constants.TRANSPARENT)) { + stage.initStyle(StageStyle.TRANSPARENT); + } + scene.setFill(Color.TRANSPARENT); + showWithPreload(preloadFxml); + var user32 = User32.INSTANCE; + var hWnd = user32.FindWindow(null, finalTitle); + var oldStyle = user32.GetWindowLong(hWnd, WinUser.GWL_STYLE); + stage.iconifiedProperty().addListener((ov, t, t1) -> { + if (t1) { + int newStyle = oldStyle | 0x00020000 | 0x00C00000; + user32.SetWindowLong(hWnd, WinUser.GWL_STYLE, newStyle); + } else { + user32.SetWindowLong(hWnd, WinUser.GWL_STYLE, oldStyle); + } + }); + } + + /** + * Show a stage considering the main stage has been preloaded + * + * @param preloadFxml true if the main stage has been preloaded + */ + private void showWithPreload(boolean preloadFxml) { + if (preloadFxml) { + log.debug("Preloading stage"); + stage.setOpacity(0); + stage.show(); + stage.close(); + stage.setOpacity(1); + } else { + stage.show(); + } + } + + /** + * Manage window dragging + * + * @param root parent + */ + private void manageWindowDragging(Parent root) { + root.setOnMousePressed(event -> { + xOffset = event.getSceneX(); + yOffset = event.getSceneY(); + }); + root.setOnMouseDragged(event -> { + if (yOffset < Constants.TITLE_BAR_HEIGHT) { + stage.setX(event.getScreenX() - xOffset); + stage.setY(event.getScreenY() - yOffset); + } + }); + } + /** * Stop capturing threads * * @param publishToTopic send info to the microcontroller via MQTT or via HTTP GET */ public void stopCapturingThreads(boolean publishToTopic) { - if (((NetworkManager.client != null) || FireflyLuciferin.config.isFullFirmware()) && publishToTopic) { + if (((ManagerSingleton.getInstance().client != null) || MainSingleton.getInstance().config.isFullFirmware()) && publishToTopic) { StateDto stateDto = new StateDto(); stateDto.setEffect(Constants.SOLID); - stateDto.setState(FireflyLuciferin.config.isToggleLed() ? Constants.ON : Constants.OFF); + stateDto.setState(MainSingleton.getInstance().config.isToggleLed() ? Constants.ON : Constants.OFF); ColorDto colorDto = new ColorDto(); - String[] color = FireflyLuciferin.config.getColorChooser().split(","); + String[] color = MainSingleton.getInstance().config.getColorChooser().split(","); colorDto.setR(Integer.parseInt(color[0])); colorDto.setG(Integer.parseInt(color[1])); colorDto.setB(Integer.parseInt(color[2])); stateDto.setColor(colorDto); stateDto.setBrightness(CommonUtility.getNightBrightness()); - stateDto.setWhitetemp(FireflyLuciferin.config.getWhiteTemperature()); + stateDto.setWhitetemp(MainSingleton.getInstance().config.getWhiteTemperature()); if (CommonUtility.getDeviceToUse() != null) { stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); } stateDto.setStartStopInstances(Enums.PlayerStatus.STOP.name()); CommonUtility.sleepMilliseconds(300); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } - if (!NativeExecutor.exitTriggered) { + if (!MainSingleton.getInstance().exitTriggered) { pipelineManager.stopCapturePipeline(); } if (CommonUtility.isSingleDeviceOtherInstance()) { StateStatusDto stateStatusDto = new StateStatusDto(); stateStatusDto.setAction(Constants.CLIENT_ACTION); stateStatusDto.setRunning(false); - MessageClient.msgClient.sendMessage(CommonUtility.toJsonString(stateStatusDto)); + NetworkSingleton.getInstance().msgClient.sendMessage(CommonUtility.toJsonString(stateStatusDto)); } } @@ -422,22 +583,22 @@ public void stopCapturingThreads(boolean publishToTopic) { * Start capturing threads */ public void startCapturingThreads() { - if (!FireflyLuciferin.communicationError) { + if (!MainSingleton.getInstance().communicationError) { if (trayIconManager.trayIcon != null) { - TrayIconManager.popupMenu.remove(0); - TrayIconManager.popupMenu.add(trayIconManager.createMenuItem(CommonUtility.getWord(Constants.STOP)), 0); - if (!FireflyLuciferin.RUNNING) { + GuiSingleton.getInstance().popupMenu.remove(0); + GuiSingleton.getInstance().popupMenu.add(trayIconManager.createMenuItem(CommonUtility.getWord(Constants.STOP)), 0); + if (!MainSingleton.getInstance().RUNNING) { trayIconManager.setTrayIconImage(Enums.PlayerStatus.PLAY_WAITING); } } - if (!PipelineManager.pipelineStarting) { + if (!ManagerSingleton.getInstance().pipelineStarting) { pipelineManager.startCapturePipeline(); } if (CommonUtility.isSingleDeviceOtherInstance()) { StateStatusDto stateStatusDto = new StateStatusDto(); stateStatusDto.setAction(Constants.CLIENT_ACTION); stateStatusDto.setRunning(true); - MessageClient.msgClient.sendMessage(CommonUtility.toJsonString(stateStatusDto)); + NetworkSingleton.getInstance().msgClient.sendMessage(CommonUtility.toJsonString(stateStatusDto)); } } } @@ -449,7 +610,7 @@ public void startCapturingThreads() { */ public void surfToURL(String url) { try { - FireflyLuciferin.hostServices.showDocument(url); + MainSingleton.getInstance().hostServices.showDocument(url); } catch (Exception ex) { log.error(ex.getMessage()); } @@ -460,7 +621,7 @@ public void surfToURL(String url) { */ public void showSettingsAndCheckForUpgrade() { if (!NativeExecutor.isWindows() && !NativeExecutor.isMac()) { - showSettingsDialog(); + showSettingsDialog(false); } UpgradeManager upgradeManager = new UpgradeManager(); upgradeManager.checkForUpdates(stage); diff --git a/src/main/java/org/dpsoftware/gui/GuiSingleton.java b/src/main/java/org/dpsoftware/gui/GuiSingleton.java new file mode 100644 index 000000000..deed2605c --- /dev/null +++ b/src/main/java/org/dpsoftware/gui/GuiSingleton.java @@ -0,0 +1,58 @@ +/* + GuiSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.gui; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.gui.elements.GlowWormDevice; +import org.dpsoftware.gui.elements.Satellite; + +import javax.swing.*; +import java.awt.*; + +/** + * GUI singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +public class GuiSingleton { + + @Getter + private final static GuiSingleton instance; + + static { + instance = new GuiSingleton(); + } + + public JPopupMenu popupMenu; + public float hueTestImageValue = 0.0F; + public Color selectedChannel = Color.BLACK; + public ObservableList deviceTableData = FXCollections.observableArrayList(); + public ObservableList deviceTableDataTemp = FXCollections.observableArrayList(); + public boolean oldFirmwareDevice = false; + public ObservableList satellitesTableData = FXCollections.observableArrayList(); +} + diff --git a/src/main/java/org/dpsoftware/gui/TestCanvas.java b/src/main/java/org/dpsoftware/gui/TestCanvas.java index 41794b68e..f6846d083 100644 --- a/src/main/java/org/dpsoftware/gui/TestCanvas.java +++ b/src/main/java/org/dpsoftware/gui/TestCanvas.java @@ -38,15 +38,14 @@ import javafx.stage.Stage; import javafx.stage.StageStyle; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.grabber.ImageProcessor; -import org.dpsoftware.gui.controllers.ColorCorrectionDialogController; import org.dpsoftware.gui.elements.DisplayInfo; import org.dpsoftware.managers.DisplayManager; import org.dpsoftware.managers.StorageManager; @@ -77,11 +76,11 @@ public class TestCanvas { * * @param stage current stage */ - public static void setDialogMargin(Stage stage) { + public void setDialogMargin(Stage stage) { int index = 0; DisplayManager displayManager = new DisplayManager(); for (DisplayInfo displayInfo : displayManager.getDisplayList()) { - if (index == FireflyLuciferin.config.getMonitorNumber()) { + if (index == MainSingleton.getInstance().config.getMonitorNumber()) { CommonUtility.toJsonString(displayInfo); stage.setX((displayInfo.getMinX() + (displayInfo.getWidth() / 2)) - (stage.getWidth() / 2)); stage.setY((displayInfo.getMinY() + displayInfo.getHeight()) - calculateDialogY(stage)); @@ -95,21 +94,44 @@ public static void setDialogMargin(Stage stage) { * * @return pixels */ - public static int calculateDialogY(Stage stage) { - var monitorAR = CommonUtility.checkMonitorAspectRatio(FireflyLuciferin.config.getScreenResX(), FireflyLuciferin.config.getScreenResY()); - int rowHeight = (scaleDownResolution(FireflyLuciferin.config.getScreenResY(), FireflyLuciferin.config.getOsScaling()) / Constants.HEIGHT_ROWS); + public int calculateDialogY(Stage stage) { + var monitorAR = CommonUtility.checkMonitorAspectRatio(MainSingleton.getInstance().config.getScreenResX(), MainSingleton.getInstance().config.getScreenResY()); + int rowHeight = (scaleDownResolution(MainSingleton.getInstance().config.getScreenResY(), MainSingleton.getInstance().config.getOsScaling()) / Constants.HEIGHT_ROWS); int itemPositionY = 0; switch (monitorAR) { case AR_43, AR_169 -> itemPositionY = rowHeight * 3; case AR_219 -> itemPositionY = rowHeight * 4; case AR_329 -> itemPositionY = rowHeight * 2; } - if (FireflyLuciferin.config.getDefaultLedMatrix().equals(Enums.AspectRatio.LETTERBOX.getBaseI18n())) { + if (MainSingleton.getInstance().config.getDefaultLedMatrix().equals(Enums.AspectRatio.LETTERBOX.getBaseI18n())) { itemPositionY += rowHeight; } return (int) (stage.getHeight() + itemPositionY); } + /** + * Draw LED label on the canvas + * + * @param conf in memory config + * @param key led matrix key + */ + public String drawNumLabel(Configuration conf, Integer key) { + int lenNumInt; + if (Enums.Orientation.CLOCKWISE.equals((LocalizedEnum.fromBaseStr(Enums.Orientation.class, conf.getOrientation())))) { + lenNumInt = (MainSingleton.getInstance().ledNumber - (key - 1) - MainSingleton.getInstance().config.getLedStartOffset()); + if (lenNumInt <= 0) { + lenNumInt = (MainSingleton.getInstance().ledNumber + lenNumInt); + } + } else { + if (key <= MainSingleton.getInstance().config.getLedStartOffset()) { + lenNumInt = (MainSingleton.getInstance().ledNumber - (MainSingleton.getInstance().config.getLedStartOffset() - (key))); + } else { + lenNumInt = ((key) - MainSingleton.getInstance().config.getLedStartOffset()); + } + } + return "#" + lenNumInt; + } + /** * Show a canvas containing a test image for the LED Matrix in use * @@ -145,7 +167,7 @@ public void buildAndShowTestImage(InputEvent e) { stage.initModality(Modality.APPLICATION_MODAL); // Hide canvas on key pressed canvas.setOnKeyPressed(t -> hideCanvas()); - ColorCorrectionDialogController.selectedChannel = java.awt.Color.BLACK; + GuiSingleton.getInstance().selectedChannel = java.awt.Color.BLACK; drawTestShapes(currentConfig, null, false); Text fireflyLuciferin = new Text(Constants.FIREFLY_LUCIFERIN); fireflyLuciferin.setFill(Color.CHOCOLATE); @@ -164,7 +186,7 @@ public void buildAndShowTestImage(InputEvent e) { int index = 0; DisplayManager displayManager = new DisplayManager(); for (DisplayInfo displayInfo : displayManager.getDisplayList()) { - if (index == FireflyLuciferin.config.getMonitorNumber()) { + if (index == MainSingleton.getInstance().config.getMonitorNumber()) { stage.setX(displayInfo.getMinX()); stage.setY(displayInfo.getMinY()); stage.setWidth(displayInfo.getWidth()); @@ -186,7 +208,7 @@ public void hideCanvas() { stage.hide(); stage.setX(stageX); stage.setY(stageY); - FireflyLuciferin.guiManager.showSettingsDialog(); + MainSingleton.getInstance().guiManager.showSettingsDialog(false); } /** @@ -198,13 +220,13 @@ public void hideCanvas() { public void drawTestShapes(Configuration conf, LinkedHashMap ledMatrixToUse, boolean useHalfSaturation) { LinkedHashMap ledMatrix; float saturationToUse; - if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.GRAY)) { + if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.GRAY)) { saturationToUse = useHalfSaturation ? 0.25F : 0.5F; } else { saturationToUse = useHalfSaturation ? 0.5F : 1.0F; } boolean draw = ledMatrixToUse == null; - ledMatrix = conf.getLedMatrixInUse(Objects.requireNonNullElse(FireflyLuciferin.config, conf).getDefaultLedMatrix()); + ledMatrix = conf.getLedMatrixInUse(Objects.requireNonNullElse(MainSingleton.getInstance().config, conf).getDefaultLedMatrix()); gc.setFill(Color.GREEN); gc.setStroke(Color.BLUE); gc.setLineWidth(10); @@ -252,16 +274,16 @@ private int drawTiles(Configuration conf, float saturationToUse, boolean draw, L gc.setFill(Color.BLACK); gc.fillRect(x + taleBorder, y + taleBorder, width - taleBorder, height - taleBorder); if (draw) { - if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.BLACK)) { + if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.BLACK)) { switch (colorToUse) { case 1 -> gc.setFill(new Color(1.0F, 0F, 0F, saturationToUse)); case 2 -> gc.setFill(new Color(0F, 0.8F, 0F, saturationToUse)); default -> gc.setFill(new Color(0F, 0F, 1.0F, saturationToUse)); } - } else if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.WHITE)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.WHITE)) { gc.setFill(new Color(1.0F, 1.0F, 1.0F, saturationToUse)); - } else if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.GRAY)) { - java.awt.Color awtTileColor = ColorUtilities.HSLtoRGB(0, 0, saturationToUse + ((ColorCorrectionDialogController.hueTestImageValue / 30F) / 2F)); + } else if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.GRAY)) { + java.awt.Color awtTileColor = ColorUtilities.HSLtoRGB(0, 0, saturationToUse + ((GuiSingleton.getInstance().hueTestImageValue / 30F) / 2F)); Color javafxTileColor = new Color(awtTileColor.getRed() / 255F, awtTileColor.getGreen() / 255F, awtTileColor.getBlue() / 255F, 1); // Prevent to trigger pillarbox aspect ratio if tiles are too black if (javafxTileColor.getRed() == 0 && javafxTileColor.getGreen() == 0 && javafxTileColor.getBlue() == 0) { @@ -269,7 +291,7 @@ private int drawTiles(Configuration conf, float saturationToUse, boolean draw, L } gc.setFill(javafxTileColor); } else { - java.awt.Color awtTileColor = ColorUtilities.HSLtoRGB(ColorCorrectionDialogController.hueTestImageValue / Constants.DEGREE_360, saturationToUse, 0.5F); + java.awt.Color awtTileColor = ColorUtilities.HSLtoRGB(GuiSingleton.getInstance().hueTestImageValue / Constants.DEGREE_360, saturationToUse, 0.5F); Color javafxTileColor = new Color(awtTileColor.getRed() / 255F, awtTileColor.getGreen() / 255F, awtTileColor.getBlue() / 255F, 1); gc.setFill(javafxTileColor); } @@ -293,18 +315,18 @@ private void drawBeforeAfterText(Configuration conf, int scaleRatio, float satur gc.setFill(Color.BLACK); gc.fillRect((scaleDownResolution((conf.getScreenResX()), scaleRatio) / 2) - Constants.BEFORE_AFTER_TEXT_SIZE * 1.5, textPos - (Constants.BEFORE_AFTER_TEXT_MARGIN / 2), Constants.BEFORE_AFTER_TEXT_SIZE * 3, Constants.BEFORE_AFTER_TEXT_SIZE); - if (!ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.BLACK)) { + if (!GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.BLACK)) { var ta = gc.getTextAlign(); gc.setTextAlign(TextAlignment.CENTER); Effect glow = new Glow(1.0); gc.setEffect(glow); java.awt.Color hslBefore; - if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.WHITE)) { + if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.WHITE)) { hslBefore = new java.awt.Color(1.0F, 1.0F, 1.0F); - } else if (ColorCorrectionDialogController.selectedChannel.equals(java.awt.Color.GRAY)) { - hslBefore = ColorUtilities.HSLtoRGB(0.0F, 0.0F, saturationToUse + ((ColorCorrectionDialogController.hueTestImageValue / 30F) / 2F)); + } else if (GuiSingleton.getInstance().selectedChannel.equals(java.awt.Color.GRAY)) { + hslBefore = ColorUtilities.HSLtoRGB(0.0F, 0.0F, saturationToUse + ((GuiSingleton.getInstance().hueTestImageValue / 30F) / 2F)); } else { - hslBefore = ColorUtilities.HSLtoRGB(ColorCorrectionDialogController.hueTestImageValue / Constants.DEGREE_360, saturationToUse, 0.5F); + hslBefore = ColorUtilities.HSLtoRGB(GuiSingleton.getInstance().hueTestImageValue / Constants.DEGREE_360, saturationToUse, 0.5F); } gc.setFill(new Color(hslBefore.getRed() / 255F, hslBefore.getGreen() / 255F, hslBefore.getBlue() / 255F, 1)); gc.fillText(CommonUtility.getWord(Constants.TC_BEFORE_TEXT) @@ -340,7 +362,7 @@ private void drawAfterText(Configuration conf, int scaleRatio, int textPos, Colo } else { gc.setFill(new Color(colorRGBW.getRed() / 255F, colorRGBW.getGreen() / 255F, colorRGBW.getBlue() / 255F, 1)); } - String afterString = (FireflyLuciferin.config.getColorMode() > 1) ? + String afterString = (MainSingleton.getInstance().config.getColorMode() > 1) ? CommonUtility.getWord(Constants.TC_AFTER_TEXT_RGBW) : CommonUtility.getWord(Constants.TC_AFTER_TEXT); afterString = afterString.replace("{0}", String.valueOf(colorRGBW.getRed())); afterString = afterString.replace("{1}", String.valueOf(colorRGBW.getGreen())); @@ -364,29 +386,6 @@ private void drawLogo(Configuration conf, int scaleRatio) { gc.drawImage(image, scaleDownResolution((conf.getScreenResX() / 2), scaleRatio) - (image.getWidth() / 2), itemsPositionY); } - /** - * Draw LED label on the canvas - * - * @param conf in memory config - * @param key led matrix key - */ - String drawNumLabel(Configuration conf, Integer key) { - int lenNumInt; - if (Enums.Orientation.CLOCKWISE.equals((LocalizedEnum.fromBaseStr(Enums.Orientation.class, conf.getOrientation())))) { - lenNumInt = (FireflyLuciferin.ledNumber - (key - 1) - FireflyLuciferin.config.getLedStartOffset()); - if (lenNumInt <= 0) { - lenNumInt = (FireflyLuciferin.ledNumber + lenNumInt); - } - } else { - if (key <= FireflyLuciferin.config.getLedStartOffset()) { - lenNumInt = (FireflyLuciferin.ledNumber - (FireflyLuciferin.config.getLedStartOffset() - (key))); - } else { - lenNumInt = ((key) - FireflyLuciferin.config.getLedStartOffset()); - } - } - return "#" + lenNumInt; - } - /** * Calculate logo and text position Y * @@ -401,7 +400,7 @@ private void calculateLogoTextPositionY(Configuration conf, int scaleRatio) { case AR_219 -> itemsPositionY = rowHeight * 4; case AR_329 -> itemsPositionY = rowHeight * 3; } - if (FireflyLuciferin.config.getDefaultLedMatrix().equals(Enums.AspectRatio.LETTERBOX.getBaseI18n())) { + if (MainSingleton.getInstance().config.getDefaultLedMatrix().equals(Enums.AspectRatio.LETTERBOX.getBaseI18n())) { itemsPositionY += rowHeight; } } diff --git a/src/main/java/org/dpsoftware/gui/TrayIconManager.java b/src/main/java/org/dpsoftware/gui/TrayIconManager.java index 719fe8998..f82918419 100644 --- a/src/main/java/org/dpsoftware/gui/TrayIconManager.java +++ b/src/main/java/org/dpsoftware/gui/TrayIconManager.java @@ -25,7 +25,7 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; @@ -50,7 +50,6 @@ @Slf4j public class TrayIconManager { - public static JPopupMenu popupMenu; // hidden dialog displayed behing the system tray to auto hide the popup menu when clicking somewhere else on the screen final JDialog hiddenDialog = new JDialog(); public JMenu profilesSubMenu; @@ -64,14 +63,15 @@ public class TrayIconManager { Image imagePlay, imagePlayCenter, imagePlayLeft, imagePlayRight, imagePlayWaiting, imagePlayWaitingCenter, imagePlayWaitingLeft, imagePlayWaitingRight; Image imageStop, imageStopCenter, imageStopLeft, imageStopRight; Image imageGreyStop, imageGreyStopCenter, imageGreyStopLeft, imageGreyStopRight; + int mouseClickCnt; /** * Constructor */ public TrayIconManager() { setMenuItemStyle(null, null, null); - popupMenu = new JPopupMenu(); - popupMenu.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(160, 160, 160))); + GuiSingleton.getInstance().popupMenu = new JPopupMenu(); + GuiSingleton.getInstance().popupMenu.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(160, 160, 160))); aspectRatioSubMenu = createSubMenuItem(CommonUtility.getWord(Constants.ASPECT_RATIO) + " "); profilesSubMenu = createSubMenuItem(CommonUtility.getWord(Constants.PROFILES) + " "); initMenuListener(); @@ -86,13 +86,13 @@ private void initMenuListener() { JMenuItem jMenuItem = (JMenuItem) e.getSource(); String menuItemText = getMenuString(jMenuItem); if (CommonUtility.getWord(Constants.STOP).equals(menuItemText)) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } else if (CommonUtility.getWord(Constants.START).equals(menuItemText)) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else if (CommonUtility.getWord(Constants.SETTINGS).equals(menuItemText)) { - FireflyLuciferin.guiManager.showSettingsDialog(); + MainSingleton.getInstance().guiManager.showSettingsDialog(false); } else if (CommonUtility.getWord(Constants.INFO).equals(menuItemText)) { - FireflyLuciferin.guiManager.showFramerateDialog(); + MainSingleton.getInstance().guiManager.showFramerateDialog(); } else { StorageManager sm = new StorageManager(); if (sm.listProfilesForThisInstance().stream().anyMatch(profile -> profile.equals(menuItemText)) @@ -114,8 +114,8 @@ private void initMenuListener() { * @param sendSetCmd send mqtt msg back */ public void manageAspectRatioListener(String menuItemText, boolean sendSetCmd) { - if (FireflyLuciferin.config != null && (!menuItemText.equals(FireflyLuciferin.config.getDefaultLedMatrix()) - || (FireflyLuciferin.config.isAutoDetectBlackBars() && !CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS).equals(menuItemText)))) { + if (MainSingleton.getInstance().config != null && (!menuItemText.equals(MainSingleton.getInstance().config.getDefaultLedMatrix()) + || (MainSingleton.getInstance().config.isAutoDetectBlackBars() && !CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS).equals(menuItemText)))) { if (Enums.AspectRatio.FULLSCREEN.getBaseI18n().equals(menuItemText) || Enums.AspectRatio.LETTERBOX.getBaseI18n().equals(menuItemText) || Enums.AspectRatio.PILLARBOX.getBaseI18n().equals(menuItemText)) { @@ -125,11 +125,11 @@ public void manageAspectRatioListener(String menuItemText, boolean sendSetCmd) { } else if (CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS).equals(menuItemText) || CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS, Locale.ENGLISH).equals(menuItemText)) { log.info(CommonUtility.getWord(Constants.CAPTURE_MODE_CHANGED) + CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS)); - FireflyLuciferin.config.setAutoDetectBlackBars(true); - if (FireflyLuciferin.config.isMqttEnable()) { - CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.ASPECT_RATIO_TOPIC), CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS, Locale.ENGLISH)), 1); + MainSingleton.getInstance().config.setAutoDetectBlackBars(true); + if (MainSingleton.getInstance().config.isMqttEnable()) { + CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_ASPECT_RATIO), CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS, Locale.ENGLISH)), 1); if (sendSetCmd) { - CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.SET_ASPECT_RATIO_TOPIC), CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS, Locale.ENGLISH)), 1); + CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_SET_ASPECT_RATIO), CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS, Locale.ENGLISH)), 1); } } aspectRatioSubMenu.removeAll(); @@ -144,13 +144,13 @@ public void manageAspectRatioListener(String menuItemText, boolean sendSetCmd) { * @param menuItemText item text */ public void manageProfileListener(String menuItemText) { - FireflyLuciferin.profileArgs = menuItemText; + MainSingleton.getInstance().profileArgs = menuItemText; setProfileAndRestart(menuItemText); - FireflyLuciferin.profileArgs = menuItemText; + MainSingleton.getInstance().profileArgs = menuItemText; updateLEDs(); profilesSubMenu.removeAll(); populateProfiles(); - FireflyLuciferin.setLedNumber(FireflyLuciferin.config.getDefaultLedMatrix()); + FireflyLuciferin.setLedNumber(MainSingleton.getInstance().config.getDefaultLedMatrix()); } /** @@ -158,18 +158,18 @@ public void manageProfileListener(String menuItemText) { */ private void updateLEDs() { CommonUtility.turnOnLEDs(); - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); boolean requirePipeline = Enums.Effect.BIAS_LIGHT.equals(effectInUse) || Enums.Effect.MUSIC_MODE_VU_METER.equals(effectInUse) || Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(effectInUse) || Enums.Effect.MUSIC_MODE_BRIGHT.equals(effectInUse) || Enums.Effect.MUSIC_MODE_RAINBOW.equals(effectInUse); - if (!FireflyLuciferin.RUNNING && requirePipeline) { - FireflyLuciferin.guiManager.startCapturingThreads(); - } else if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (!MainSingleton.getInstance().RUNNING && requirePipeline) { + MainSingleton.getInstance().guiManager.startCapturingThreads(); + } else if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); if (requirePipeline) { - CommonUtility.delaySeconds(() -> FireflyLuciferin.guiManager.startCapturingThreads(), 4); + CommonUtility.delaySeconds(() -> MainSingleton.getInstance().guiManager.startCapturingThreads(), 4); } } } @@ -178,9 +178,9 @@ private void updateLEDs() { * Udpate tray icon with new profiles */ public void updateTray() { - if (FireflyLuciferin.guiManager != null && FireflyLuciferin.guiManager.trayIconManager != null && FireflyLuciferin.guiManager.trayIconManager.profilesSubMenu != null) { - FireflyLuciferin.guiManager.trayIconManager.profilesSubMenu.removeAll(); - FireflyLuciferin.guiManager.trayIconManager.populateProfiles(); + if (MainSingleton.getInstance().guiManager != null && MainSingleton.getInstance().guiManager.trayIconManager != null && MainSingleton.getInstance().guiManager.trayIconManager.profilesSubMenu != null) { + MainSingleton.getInstance().guiManager.trayIconManager.profilesSubMenu.removeAll(); + MainSingleton.getInstance().guiManager.trayIconManager.populateProfiles(); } } @@ -191,7 +191,7 @@ public void updateTray() { */ private void setProfileAndRestart(String menuItemText) { StorageManager sm = new StorageManager(); - FireflyLuciferin.config = sm.readProfileAndCheckDifference(menuItemText, sm); + MainSingleton.getInstance().config = sm.readProfileAndCheckDifference(menuItemText, sm); if (sm.restartNeeded) { if (menuItemText.equals(CommonUtility.getWord(Constants.DEFAULT))) { NativeExecutor.restartNativeInstance(null); @@ -208,14 +208,14 @@ private void setProfileAndRestart(String menuItemText) { * @param sendSetCmd send mqtt msg back */ private void setAspectRatio(String jMenuItemStr, boolean sendSetCmd) { - FireflyLuciferin.config.setDefaultLedMatrix(jMenuItemStr); + MainSingleton.getInstance().config.setDefaultLedMatrix(jMenuItemStr); log.info(CommonUtility.getWord(Constants.CAPTURE_MODE_CHANGED) + jMenuItemStr); - GStreamerGrabber.ledMatrix = FireflyLuciferin.config.getLedMatrixInUse(jMenuItemStr); - FireflyLuciferin.config.setAutoDetectBlackBars(false); - if (FireflyLuciferin.config.isMqttEnable()) { - CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.ASPECT_RATIO_TOPIC), jMenuItemStr), 1); + GStreamerGrabber.ledMatrix = MainSingleton.getInstance().config.getLedMatrixInUse(jMenuItemStr); + MainSingleton.getInstance().config.setAutoDetectBlackBars(false); + if (MainSingleton.getInstance().config.isMqttEnable()) { + CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_ASPECT_RATIO), jMenuItemStr), 1); if (sendSetCmd) { - CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.SET_ASPECT_RATIO_TOPIC), jMenuItemStr), 1); + CommonUtility.delaySeconds(() -> NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_SET_ASPECT_RATIO), jMenuItemStr), 1); } } } @@ -243,12 +243,16 @@ public void windowGainedFocus(final WindowEvent e) { }); // construct a TrayIcon String tooltipStr; - if (FireflyLuciferin.config.getMultiMonitor() > 1) { - tooltipStr = FireflyLuciferin.config.getOutputDevice(); + if (MainSingleton.getInstance().config.getMultiMonitor() > 1) { + if (Constants.SERIAL_PORT_AUTO.equals(MainSingleton.getInstance().config.getOutputDevice()) && NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp())) { + tooltipStr = MainSingleton.getInstance().config.getStaticGlowWormIp(); + } else { + tooltipStr = MainSingleton.getInstance().config.getOutputDevice(); + } } else { tooltipStr = Constants.FIREFLY_LUCIFERIN; } - if (FireflyLuciferin.communicationError) { + if (MainSingleton.getInstance().communicationError) { trayIcon = new TrayIcon(setTrayIconImage(Enums.PlayerStatus.GREY), tooltipStr); } else { trayIcon = new TrayIcon(setTrayIconImage(Enums.PlayerStatus.STOP), tooltipStr); @@ -268,18 +272,18 @@ public void windowGainedFocus(final WindowEvent e) { */ private void populateTrayWithItems() { // create menu item for the default action - popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.START))); + GuiSingleton.getInstance().popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.START))); addSeparator(); populateAspectRatio(); aspectRatioSubMenu.getPopupMenu().setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(160, 160, 160))); populateProfiles(); profilesSubMenu.getPopupMenu().setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(160, 160, 160))); - popupMenu.add(aspectRatioSubMenu); - popupMenu.add(profilesSubMenu); - popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.SETTINGS))); - popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.INFO))); + GuiSingleton.getInstance().popupMenu.add(aspectRatioSubMenu); + GuiSingleton.getInstance().popupMenu.add(profilesSubMenu); + GuiSingleton.getInstance().popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.SETTINGS))); + GuiSingleton.getInstance().popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.INFO))); addSeparator(); - popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.TRAY_EXIT))); + GuiSingleton.getInstance().popupMenu.add(createMenuItem(CommonUtility.getWord(Constants.TRAY_EXIT))); } /** @@ -311,13 +315,24 @@ private void initTrayListener() { // add a listener to display the popupmenu and the hidden dialog box when the tray icon is clicked MouseListener ml = new MouseListener() { public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); - } else { - FireflyLuciferin.guiManager.startCapturingThreads(); - } + if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { + mouseClickCnt = e.getClickCount(); + } else if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON1) { + mouseClickCnt = e.getClickCount(); + } else { + mouseClickCnt = 0; } + CommonUtility.delayMilliseconds(() -> { + if (mouseClickCnt == 1) { + MainSingleton.getInstance().guiManager.showSettingsDialog(false); + } else if (mouseClickCnt == 2) { + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); + } else { + MainSingleton.getInstance().guiManager.startCapturingThreads(); + } + } + }, Constants.DBL_CLK_DELAY); } @Override @@ -325,18 +340,18 @@ public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { - if (e.getButton() == 3) { + if (e.getButton() == MouseEvent.BUTTON3) { DisplayManager displayManager = new DisplayManager(); int mainScreenOsScaling = (int) (displayManager.getPrimaryDisplay().getScaleX() * 100); // the dialog is also displayed at this position but it is behind the system tray - popupMenu.setLocation(scaleDownResolution(e.getX(), mainScreenOsScaling), + GuiSingleton.getInstance().popupMenu.setLocation(scaleDownResolution(e.getX(), mainScreenOsScaling), scaleDownResolution(e.getY(), mainScreenOsScaling)); hiddenDialog.setLocation(scaleDownResolution(e.getX(), mainScreenOsScaling), scaleDownResolution(Constants.FAKE_GUI_TRAY_ICON, mainScreenOsScaling)); // important: set the hidden dialog as the invoker to hide the menu with this dialog lost focus - popupMenu.setInvoker(hiddenDialog); + GuiSingleton.getInstance().popupMenu.setInvoker(hiddenDialog); hiddenDialog.setVisible(true); - popupMenu.setVisible(true); + GuiSingleton.getInstance().popupMenu.setVisible(true); } } @@ -426,7 +441,7 @@ public JMenu createSubMenuItem(String menuLabel) { * @return color based on the theme in use */ private Color getBackgroundColor() { - var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, FireflyLuciferin.config.getTheme()); + var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, MainSingleton.getInstance().config.getTheme()); Color color = Color.WHITE; switch (theme) { case DARK_THEME_CYAN -> color = new Color(80, 89, 96); @@ -447,7 +462,7 @@ private void addSeparator() { s.setBackground(new Color(215, 215, 215)); s.setForeground(new Color(215, 215, 215)); s.setBorder(new EmptyBorder(0, 0, 0, 0)); - popupMenu.add(s); + GuiSingleton.getInstance().popupMenu.add(s); } /** @@ -458,7 +473,7 @@ private void addSeparator() { * @param menuItemText used to color text when aspect ratio is set to Auto */ private void setMenuItemStyle(String menuLabel, JMenuItem jMenuItem, String menuItemText) { - var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, FireflyLuciferin.config.getTheme()); + var theme = LocalizedEnum.fromBaseStr(Enums.Theme.class, MainSingleton.getInstance().config.getTheme()); switch (theme) { case DARK_THEME_CYAN -> { UIManager.put("MenuItem.selectionBackground", new Color(0, 153, 255)); @@ -502,13 +517,13 @@ private void setMenuItemStyle(String menuLabel, JMenuItem jMenuItem, String menu } } if (menuLabel != null && menuItemText != null && jMenuItem != null) { - if ((menuItemText.equals(FireflyLuciferin.config.getDefaultLedMatrix()) && !FireflyLuciferin.config.isAutoDetectBlackBars()) - || (menuLabel.equals(CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS)) && FireflyLuciferin.config.isAutoDetectBlackBars())) { + if ((menuItemText.equals(MainSingleton.getInstance().config.getDefaultLedMatrix()) && !MainSingleton.getInstance().config.isAutoDetectBlackBars()) + || (menuLabel.equals(CommonUtility.getWord(Constants.AUTO_DETECT_BLACK_BARS)) && MainSingleton.getInstance().config.isAutoDetectBlackBars())) { jMenuItem.setForeground(new Color(0, 153, 255)); } - if (menuLabel.equals(FireflyLuciferin.profileArgs) + if (menuLabel.equals(MainSingleton.getInstance().profileArgs) || (menuLabel.equals(CommonUtility.getWord(Constants.DEFAULT)) - && FireflyLuciferin.profileArgs.equals(Constants.DEFAULT))) { + && MainSingleton.getInstance().profileArgs.equals(Constants.DEFAULT))) { jMenuItem.setForeground(new Color(0, 153, 255)); } } @@ -568,16 +583,16 @@ public Image setTrayIconImage(Enums.PlayerStatus playerStatus) { @SuppressWarnings("Duplicates") private Image setImage(Image imagePlay, Image imagePlayRight, Image imagePlayLeft, Image imagePlayCenter) { Image img = null; - switch (JavaFXStarter.whoAmI) { + switch (MainSingleton.getInstance().whoAmI) { case 1 -> { - if ((FireflyLuciferin.config.getMultiMonitor() == 1)) { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 1)) { img = imagePlay; } else { img = imagePlayRight; } } case 2 -> { - if ((FireflyLuciferin.config.getMultiMonitor() == 2)) { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 2)) { img = imagePlayLeft; } else { img = imagePlayCenter; diff --git a/src/main/java/org/dpsoftware/gui/WidgetFactory.java b/src/main/java/org/dpsoftware/gui/WidgetFactory.java index 2bcf33ce6..685e2108b 100644 --- a/src/main/java/org/dpsoftware/gui/WidgetFactory.java +++ b/src/main/java/org/dpsoftware/gui/WidgetFactory.java @@ -23,6 +23,7 @@ import javafx.scene.control.SpinnerValueFactory; import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import java.time.LocalTime; @@ -67,7 +68,7 @@ public void increment(int steps) { public SpinnerValueFactory spinnerNightModeValueFactory() { return new SpinnerValueFactory<>() { { - setValue(FireflyLuciferin.config != null ? FireflyLuciferin.config.getNightModeBrightness() : Constants.NIGHT_MODE_OFF); + setValue(MainSingleton.getInstance().config != null ? MainSingleton.getInstance().config.getNightModeBrightness() : Constants.NIGHT_MODE_OFF); } @Override diff --git a/src/main/java/org/dpsoftware/gui/controllers/ColorCorrectionDialogController.java b/src/main/java/org/dpsoftware/gui/controllers/ColorCorrectionDialogController.java index bf4a79bec..b7ee9eaf0 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/ColorCorrectionDialogController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/ColorCorrectionDialogController.java @@ -32,10 +32,11 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.TestCanvas; import org.dpsoftware.managers.dto.HSLColor; import org.dpsoftware.utilities.CommonUtility; @@ -50,8 +51,6 @@ @Slf4j public class ColorCorrectionDialogController { - public static float hueTestImageValue = 0.0F; - public static Color selectedChannel = Color.BLACK; @FXML public Slider redSaturation, redLightness, redHue; @FXML @@ -160,17 +159,17 @@ protected void initialize() { }); whiteTemp.setOnMouseReleased(event -> setWhiteTemperature()); whiteGreyLabel.setOnMouseReleased(event -> setWhiteGreyValue()); - whiteTemp.setValue(FireflyLuciferin.config.getWhiteTemperature() * 100); + whiteTemp.setValue(MainSingleton.getInstance().config.getWhiteTemperature() * 100); applyLabelClass(masterLabel, Constants.CSS_CLASS_LABEL); - selectedChannel = Color.BLACK; - hueTestImageValue = 0.0F; + GuiSingleton.getInstance().selectedChannel = Color.BLACK; + GuiSingleton.getInstance().hueTestImageValue = 0.0F; whiteGreyLabel.getStyleClass().add(Constants.CSS_SMALL_LINE_SPACING); halfFullSaturation.getItems().add(CommonUtility.getWord(Constants.TC_FULL_SATURATION)); halfFullSaturation.getItems().add(CommonUtility.getWord(Constants.TC_HALF_SATURATION)); halfFullSaturation.setValue(CommonUtility.getWord(Constants.TC_FULL_SATURATION)); halfFullSaturation.valueProperty().addListener((ov, oldVal, newVal) -> { useHalfSaturation = !newVal.equals(CommonUtility.getWord(Constants.TC_FULL_SATURATION)); - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); }); for (int i = 1; i <= 10; i++) { latencyTestSpeed.getItems().add(i + "x"); @@ -188,24 +187,24 @@ protected void initialize() { * Manage hue slider value */ private void manageHueSliderValue() { - hueTestImageValue = (int) hueMonitorSlider.getValue(); - if (Color.RED.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.RED.getVal(); - if (hueTestImageValue < 0) { - hueTestImageValue = Constants.DEGREE_360 + hueTestImageValue; // subtract a negative value + GuiSingleton.getInstance().hueTestImageValue = (int) hueMonitorSlider.getValue(); + if (Color.RED.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.RED.getVal(); + if (GuiSingleton.getInstance().hueTestImageValue < 0) { + GuiSingleton.getInstance().hueTestImageValue = Constants.DEGREE_360 + GuiSingleton.getInstance().hueTestImageValue; // subtract a negative value } - } else if (Color.YELLOW.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.YELLOW.getVal(); - } else if (Color.GREEN.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.GREEN.getVal(); - } else if (Color.CYAN.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.CYAN.getVal(); - } else if (Color.BLUE.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.BLUE.getVal(); - } else if (Color.MAGENTA.equals(selectedChannel)) { - hueTestImageValue += Enums.ColorEnum.MAGENTA.getVal(); + } else if (Color.YELLOW.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.YELLOW.getVal(); + } else if (Color.GREEN.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.GREEN.getVal(); + } else if (Color.CYAN.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.CYAN.getVal(); + } else if (Color.BLUE.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.BLUE.getVal(); + } else if (Color.MAGENTA.equals(GuiSingleton.getInstance().selectedChannel)) { + GuiSingleton.getInstance().hueTestImageValue += Enums.ColorEnum.MAGENTA.getVal(); } - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); } /** @@ -319,11 +318,11 @@ private void setWhiteGreyValue() { * Set White Temp */ private void setWhiteTemperature() { - selectedChannel = Color.WHITE; + GuiSingleton.getInstance().selectedChannel = Color.WHITE; settingsController.miscTabController.whiteTemp.setValue((int) whiteTemp.getValue()); - FireflyLuciferin.config.setWhiteTemperature((int) whiteTemp.getValue()); - settingsController.miscTabController.turnOnLEDs(FireflyLuciferin.config, false); - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + MainSingleton.getInstance().config.setWhiteTemperature((int) whiteTemp.getValue()); + settingsController.miscTabController.turnOnLEDs(MainSingleton.getInstance().config, false); + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_MASTER_HUE); hueMonitorSlider.setValue(0); } @@ -332,13 +331,13 @@ private void setWhiteTemperature() { * Set White Temp */ private void setGreyLightness() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREY).setLightness((float) greyChannel.getValue() / Constants.LIGHTNESS_PRECISION); - if (!selectedChannel.equals(Color.GRAY)) { - hueTestImageValue = Enums.ColorEnum.GREY.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREY).setLightness((float) greyChannel.getValue() / Constants.LIGHTNESS_PRECISION); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.GRAY)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.GREY.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.GRAY; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.GRAY; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_GREY_HUE_VERTICAL); } @@ -346,15 +345,15 @@ private void setGreyLightness() { * Set red channel */ private void setRedChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setSaturation((float) redSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setLightness((float) redLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setHue((float) redHue.getValue()); - if (!selectedChannel.equals(Color.RED)) { - hueTestImageValue = Enums.ColorEnum.RED.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setSaturation((float) redSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setLightness((float) redLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setHue((float) redHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.RED)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.RED.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.RED; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.RED; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_RED_HUE_VERTICAL); } @@ -362,15 +361,15 @@ private void setRedChannel() { * Set yellow channel */ private void setYellowChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setSaturation((float) yellowSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setLightness((float) yellowLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setHue((float) yellowHue.getValue()); - if (!selectedChannel.equals(Color.YELLOW)) { - hueTestImageValue = Enums.ColorEnum.YELLOW.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setSaturation((float) yellowSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setLightness((float) yellowLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setHue((float) yellowHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.YELLOW)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.YELLOW.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.YELLOW; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.YELLOW; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_YELLOW_HUE_VERTICAL); } @@ -378,15 +377,15 @@ private void setYellowChannel() { * Set green channel */ private void setGreenChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setSaturation((float) greenSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setLightness((float) greenLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setHue((float) greenHue.getValue()); - if (!selectedChannel.equals(Color.GREEN)) { - hueTestImageValue = Enums.ColorEnum.GREEN.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setSaturation((float) greenSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setLightness((float) greenLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setHue((float) greenHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.GREEN)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.GREEN.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.GREEN; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.GREEN; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_GREEN_HUE_VERTICAL); } @@ -394,15 +393,15 @@ private void setGreenChannel() { * Set cyan channel */ private void setCyanChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setSaturation((float) cyanSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setLightness((float) cyanLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setHue((float) cyanHue.getValue()); - if (!selectedChannel.equals(Color.CYAN)) { - hueTestImageValue = Enums.ColorEnum.CYAN.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setSaturation((float) cyanSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setLightness((float) cyanLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setHue((float) cyanHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.CYAN)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.CYAN.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.CYAN; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.CYAN; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_CYAN_HUE_VERTICAL); } @@ -410,15 +409,15 @@ private void setCyanChannel() { * Set blue channel */ private void setBlueChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setSaturation((float) blueSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setLightness((float) blueLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setHue((float) blueHue.getValue()); - if (!selectedChannel.equals(Color.BLUE)) { - hueTestImageValue = Enums.ColorEnum.BLUE.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setSaturation((float) blueSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setLightness((float) blueLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setHue((float) blueHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.BLUE)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.BLUE.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.BLUE; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.BLUE; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_BLUE_HUE_VERTICAL); } @@ -426,15 +425,15 @@ private void setBlueChannel() { * Set magenta channel */ private void setMagentaChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setSaturation((float) magentaSaturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setLightness((float) magentaLightness.getValue() / Constants.LIGHTNESS_PRECISION); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setHue((float) magentaHue.getValue()); - if (!selectedChannel.equals(Color.MAGENTA)) { - hueTestImageValue = Enums.ColorEnum.MAGENTA.getVal(); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setSaturation((float) magentaSaturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setLightness((float) magentaLightness.getValue() / Constants.LIGHTNESS_PRECISION); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setHue((float) magentaHue.getValue()); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.MAGENTA)) { + GuiSingleton.getInstance().hueTestImageValue = Enums.ColorEnum.MAGENTA.getVal(); hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.MAGENTA; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.MAGENTA; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_MAGENTA_HUE_VERTICAL); } @@ -442,14 +441,14 @@ private void setMagentaChannel() { * Set master channel */ private void setMasterChannel() { - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).setSaturation((float) saturation.getValue()); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).setLightness((float) saturationLightness.getValue() / Constants.LIGHTNESS_PRECISION); - if (!selectedChannel.equals(Color.BLACK)) { - hueTestImageValue = 0; + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).setSaturation((float) saturation.getValue()); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).setLightness((float) saturationLightness.getValue() / Constants.LIGHTNESS_PRECISION); + if (!GuiSingleton.getInstance().selectedChannel.equals(Color.BLACK)) { + GuiSingleton.getInstance().hueTestImageValue = 0; hueMonitorSlider.setValue(0.0F); } - selectedChannel = Color.BLACK; - testCanvas.drawTestShapes(FireflyLuciferin.config, null, useHalfSaturation); + GuiSingleton.getInstance().selectedChannel = Color.BLACK; + testCanvas.drawTestShapes(MainSingleton.getInstance().config, null, useHalfSaturation); setSliderAndLabelClass(Constants.CSS_STYLE_MASTER_HUE); } @@ -457,22 +456,22 @@ private void setMasterChannel() { * Set label class */ private void setLabelClass() { - if (selectedChannel.equals(Color.RED)) { + if (GuiSingleton.getInstance().selectedChannel.equals(Color.RED)) { applyLabelClass(redLabel, Constants.CSS_STYLE_REDTEXT); - } else if (selectedChannel.equals(Color.YELLOW)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.YELLOW)) { applyLabelClass(yellowLabel, Constants.CSS_STYLE_YELLOWTEXT); - } else if (selectedChannel.equals(Color.GREEN)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.GREEN)) { applyLabelClass(greenLabel, Constants.CSS_STYLE_GREENTEXT); - } else if (selectedChannel.equals(Color.CYAN)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.CYAN)) { applyLabelClass(cyanLabel, Constants.CSS_STYLE_CYANTEXT); - } else if (selectedChannel.equals(Color.BLUE)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.BLUE)) { applyLabelClass(blueLabel, Constants.CSS_STYLE_BLUETEXT); - } else if (selectedChannel.equals(Color.MAGENTA)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.MAGENTA)) { applyLabelClass(magentaLabel, Constants.CSS_STYLE_MAGENTATEXT); - } else if (selectedChannel.equals(Color.BLACK)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.BLACK)) { applyLabelClass(masterLabel, Constants.CSS_CLASS_LABEL); - } else if (selectedChannel.equals(Color.WHITE) || selectedChannel.equals(Color.GRAY)) { - if (selectedChannel.equals(Color.WHITE)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.WHITE) || GuiSingleton.getInstance().selectedChannel.equals(Color.GRAY)) { + if (GuiSingleton.getInstance().selectedChannel.equals(Color.WHITE)) { whiteGreyLabel.setText(CommonUtility.getWord(Constants.WHITE_LABEL_CORRECTION)); } else { whiteGreyLabel.setText(CommonUtility.getWord(Constants.GREY_LABEL_CORRECTION)); @@ -593,7 +592,7 @@ public void save(Configuration config) { saveSaturationValues(config); saveLightnessValues(config); saveHueValues(config); - config.setHueMap(FireflyLuciferin.config.getHueMap()); + config.setHueMap(MainSingleton.getInstance().config.getHueMap()); } /** @@ -612,19 +611,19 @@ public void handle(long now) { now = now / (latencyTestMilliseconds * 1_000_000L); if (now - lastUpdate >= 1) { lastUpdate = now; - if (selectedChannel.equals(Color.RED)) { + if (GuiSingleton.getInstance().selectedChannel.equals(Color.RED)) { setYellowChannel(); - } else if (selectedChannel.equals(Color.YELLOW)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.YELLOW)) { setGreenChannel(); - } else if (selectedChannel.equals(Color.GREEN)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.GREEN)) { setCyanChannel(); - } else if (selectedChannel.equals(Color.CYAN)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.CYAN)) { setBlueChannel(); - } else if (selectedChannel.equals(Color.BLUE)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.BLUE)) { setMagentaChannel(); - } else if (selectedChannel.equals(Color.MAGENTA)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.MAGENTA)) { setMasterChannel(); - } else if (selectedChannel.equals(Color.BLACK)) { + } else if (GuiSingleton.getInstance().selectedChannel.equals(Color.BLACK)) { setRedChannel(); } } @@ -704,8 +703,8 @@ public void reset() { hueMonitorSlider.setValue(0.0F); whiteTemp.setValue(Constants.DEFAULT_WHITE_TEMP * 100); setWhiteTemperature(); - FireflyLuciferin.config.setHueMap(initHSLMap()); - selectedChannel = Color.BLACK; + MainSingleton.getInstance().config.setHueMap(initHSLMap()); + GuiSingleton.getInstance().selectedChannel = Color.BLACK; applyLabelClass(masterLabel, Constants.CSS_CLASS_LABEL); manageHueSliderValue(); } @@ -715,19 +714,19 @@ public void reset() { */ private void resetSaturationValues() { redSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setSaturation(0.0F); yellowSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setSaturation(0.0F); greenSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setSaturation(0.0F); cyanSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setSaturation(0.0F); blueSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setSaturation(0.0F); magentaSaturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setSaturation(0.0F); saturation.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).setSaturation(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).setSaturation(0.0F); } /** @@ -735,21 +734,21 @@ private void resetSaturationValues() { */ private void resetLightnessValues() { redLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setLightness(0.0F); yellowLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setLightness(0.0F); greenLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setLightness(0.0F); cyanLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setLightness(0.0F); blueLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setLightness(0.0F); magentaLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setLightness(0.0F); saturationLightness.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MASTER).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MASTER).setLightness(0.0F); greyChannel.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREY).setLightness(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREY).setLightness(0.0F); } /** @@ -757,17 +756,17 @@ private void resetLightnessValues() { */ private void resetHueValues() { redHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.RED).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.RED).setHue(0.0F); yellowHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.YELLOW).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.YELLOW).setHue(0.0F); greenHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.GREEN).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.GREEN).setHue(0.0F); cyanHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.CYAN).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.CYAN).setHue(0.0F); blueHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.BLUE).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.BLUE).setHue(0.0F); magentaHue.setValue(0.0F); - FireflyLuciferin.config.getHueMap().get(Enums.ColorEnum.MAGENTA).setHue(0.0F); + MainSingleton.getInstance().config.getHueMap().get(Enums.ColorEnum.MAGENTA).setHue(0.0F); } /** diff --git a/src/main/java/org/dpsoftware/gui/controllers/ControlTabController.java b/src/main/java/org/dpsoftware/gui/controllers/ControlTabController.java index 0430097b3..cdf3d4e09 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/ControlTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/ControlTabController.java @@ -30,8 +30,7 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.InputEvent; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; @@ -88,14 +87,14 @@ protected void initialize() { if (NativeExecutor.isLinux()) { producerLabel.textProperty().bind(producerValueProperty()); consumerLabel.textProperty().bind(consumerValueProperty()); - if (FireflyLuciferin.communicationError) { + if (MainSingleton.getInstance().communicationError) { controlImage = setImage(Enums.PlayerStatus.GREY); - } else if (FireflyLuciferin.RUNNING) { + } else if (MainSingleton.getInstance().RUNNING) { controlImage = setImage(Enums.PlayerStatus.PLAY_WAITING); } else { controlImage = setImage(Enums.PlayerStatus.STOP); } - version.setText("by Davide Perini (VERSION)".replaceAll("VERSION", FireflyLuciferin.version)); + version.setText("by Davide Perini (VERSION)".replaceAll("VERSION", MainSingleton.getInstance().version)); setButtonImage(); initImages(); } @@ -133,8 +132,8 @@ public void initImages() { * Init form values by reading existing config file */ public void initValuesFromSettingsFile() { - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); - if (!NativeExecutor.isWindows() && FireflyLuciferin.config.isToggleLed()) { + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); + if (!NativeExecutor.isWindows() && MainSingleton.getInstance().config.isToggleLed()) { switch (effectInUse) { case BIAS_LIGHT, MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> { controlImage = setImage(Enums.PlayerStatus.PLAY_WAITING); @@ -153,17 +152,17 @@ public void initValuesFromSettingsFile() { @SuppressWarnings("unused") public void onMouseClickedPlay(InputEvent e) { controlImage = setImage(Enums.PlayerStatus.GREY); - if (!FireflyLuciferin.communicationError) { - if (FireflyLuciferin.RUNNING) { + if (!MainSingleton.getInstance().communicationError) { + if (MainSingleton.getInstance().RUNNING) { controlImage = setImage(Enums.PlayerStatus.STOP); } else { controlImage = setImage(Enums.PlayerStatus.PLAY_WAITING); } setButtonImage(); - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } else { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } } } @@ -176,7 +175,7 @@ public void onMouseClickedPlay(InputEvent e) { @FXML @SuppressWarnings("unused") public void onMouseClickedShowInfo(InputEvent e) { - FireflyLuciferin.guiManager.showFramerateDialog(); + MainSingleton.getInstance().guiManager.showFramerateDialog(); } /** @@ -188,7 +187,7 @@ public void onMouseClickedShowInfo(InputEvent e) { @SuppressWarnings("Duplicates") public Image setImage(Enums.PlayerStatus playerStatus) { Image imgControl; - if (FireflyLuciferin.config == null) { + if (MainSingleton.getInstance().config == null) { imgControl = imageGreyStop; } else { imgControl = switch (playerStatus) { @@ -214,16 +213,16 @@ public Image setImage(Enums.PlayerStatus playerStatus) { @SuppressWarnings("Duplicates") private Image setImage(Image imagePlay, Image imagePlayRight, Image imagePlayLeft, Image imagePlayCenter) { Image img = null; - switch (JavaFXStarter.whoAmI) { + switch (MainSingleton.getInstance().whoAmI) { case 1 -> { - if ((FireflyLuciferin.config.getMultiMonitor() == 1)) { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 1)) { img = imagePlay; } else { img = imagePlayRight; } } case 2 -> { - if ((FireflyLuciferin.config.getMultiMonitor() == 2)) { + if ((MainSingleton.getInstance().config.getMultiMonitor() == 2)) { img = imagePlayLeft; } else { img = imagePlayCenter; @@ -250,9 +249,9 @@ public void handle(long now) { settingsController.manageDeviceList(); } else { settingsController.manageDeviceList(); - setProducerValue(CommonUtility.getWord("fxml.controltab.producer") + " @ " + FireflyLuciferin.FPS_PRODUCER + " FPS"); - setConsumerValue(CommonUtility.getWord("fxml.controltab.consumer") + " @ " + FireflyLuciferin.FPS_GW_CONSUMER + " FPS"); - if (FireflyLuciferin.RUNNING && controlImage != null && controlImage.getUrl().contains("waiting")) { + setProducerValue(CommonUtility.getWord("fxml.controltab.producer") + " @ " + MainSingleton.getInstance().FPS_PRODUCER + " FPS"); + setConsumerValue(CommonUtility.getWord("fxml.controltab.consumer") + " @ " + MainSingleton.getInstance().FPS_GW_CONSUMER + " FPS"); + if (MainSingleton.getInstance().RUNNING && controlImage != null && controlImage.getUrl().contains("waiting")) { controlImage = setImage(Enums.PlayerStatus.PLAY); setButtonImage(); } diff --git a/src/main/java/org/dpsoftware/gui/controllers/DevicesTabController.java b/src/main/java/org/dpsoftware/gui/controllers/DevicesTabController.java index 98505dd88..b24b541be 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/DevicesTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/DevicesTabController.java @@ -29,11 +29,13 @@ import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.input.InputEvent; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; +import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.GlowWormDevice; import org.dpsoftware.managers.DisplayManager; import org.dpsoftware.managers.NetworkManager; @@ -52,9 +54,6 @@ @Slf4j public class DevicesTabController { - public static ObservableList deviceTableData = FXCollections.observableArrayList(); - public static ObservableList deviceTableDataTemp = FXCollections.observableArrayList(); - public static boolean oldFirmwareDevice = false; // FXML binding @FXML public CheckBox checkForUpdates; @@ -63,6 +62,8 @@ public class DevicesTabController { @FXML public Button saveDeviceButton; @FXML + public Button manageSatButton; + @FXML public ComboBox powerSaving; @FXML public ComboBox multiMonitor; @@ -127,6 +128,7 @@ public void injectSettingsController(SettingsController settingsController) { */ @FXML protected void initialize() { + manageSatButton.setDisable(true); // Device table deviceNameColumn.setCellValueFactory(cellData -> cellData.getValue().deviceNameProperty()); deviceBoardColumn.setCellValueFactory(cellData -> cellData.getValue().deviceBoardProperty()); @@ -142,7 +144,7 @@ protected void updateItem(Hyperlink item, boolean empty) { if (glowWormDevice.getWifi().contains(Constants.DASH)) { link.setStyle(Constants.CSS_NO_UNDERLINE + Constants.TC_NO_BOLD_TEXT); } else { - link.setOnAction(evt -> FireflyLuciferin.guiManager.surfToURL(Constants.HTTP + getTableRow().getItem().getDeviceIP())); + link.setOnAction(evt -> MainSingleton.getInstance().guiManager.surfToURL(Constants.HTTP + getTableRow().getItem().getDeviceIP())); } setGraphic(link); } @@ -157,32 +159,8 @@ protected void updateItem(Hyperlink item, boolean empty) { firmwareColumn.setCellValueFactory(cellData -> cellData.getValue().firmwareTypeProperty()); baudrateColumn.setCellValueFactory(cellData -> cellData.getValue().baudRateProperty()); mqttTopicColumn.setCellValueFactory(cellData -> cellData.getValue().mqttTopicProperty()); - colorModeColumn.setCellValueFactory(cellData -> cellData.getValue().colorModeProperty()); - colorOrderColumn.setCellFactory(tc -> new ComboBoxTableCell<>(Enums.ColorOrder.GRB.name(), Enums.ColorOrder.RGB.name(), - Enums.ColorOrder.BGR.name(), Enums.ColorOrder.BRG.name(), Enums.ColorOrder.RBG.name(), Enums.ColorOrder.GBR.name())); - colorOrderColumn.setCellValueFactory(cellData -> cellData.getValue().colorOrderProperty()); - colorOrderColumn.setStyle(Constants.TC_BOLD_TEXT + Constants.CSS_UNDERLINE); - colorOrderColumn.setOnEditStart((TableColumn.CellEditEvent t) -> cellEdit = true); - colorOrderColumn.setOnEditCancel((TableColumn.CellEditEvent t) -> cellEdit = false); - colorOrderColumn.setOnEditCommit((TableColumn.CellEditEvent t) -> { - cellEdit = false; - GlowWormDevice device = t.getTableView().getItems().get(t.getTablePosition().getRow()); - log.info("Setting Color Order" + t.getNewValue() + " on " + device.getDeviceName()); - device.setColorOrder(t.getNewValue()); - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); - } - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { - FirmwareConfigDto firmwareConfigDto = new FirmwareConfigDto(); - firmwareConfigDto.setColorOrder(String.valueOf(Enums.ColorOrder.valueOf(t.getNewValue()).getValue())); - firmwareConfigDto.setMAC(device.getMac()); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC), - CommonUtility.toJsonString(firmwareConfigDto)); - } else if (FireflyLuciferin.config != null) { - FireflyLuciferin.colorOrder = Enums.ColorOrder.valueOf(t.getNewValue()).getValue(); - settingsController.sendSerialParams(); - } - }); + manageColorMode(); + manageColorOrder(); ldrColumn.setCellValueFactory(cellData -> cellData.getValue().ldrValueProperty()); ldrPinColumn.setCellValueFactory(cellData -> cellData.getValue().ldrPinProperty()); ldrPinColumn.setStyle(Constants.TC_BOLD_TEXT + Constants.CSS_UNDERLINE); @@ -213,6 +191,69 @@ protected void updateItem(Hyperlink item, boolean empty) { deviceTable.setItems(getDeviceTableData()); } + /** + * Manage color mode cell + */ + private void manageColorMode() { + colorModeColumn.setCellFactory(tc -> new ComboBoxTableCell<>(Enums.ColorMode.RGB_MODE.getI18n(), Enums.ColorMode.RGBW_MODE_ACCURATE.getI18n(), + Enums.ColorMode.RGBW_MODE_BRIGHTER.getI18n(), Enums.ColorMode.RGBW_RGB.getI18n(), Enums.ColorMode.DOTSTAR.getI18n())); + colorModeColumn.setCellValueFactory(cellData -> cellData.getValue().colorModeProperty()); + colorModeColumn.setStyle(Constants.TC_BOLD_TEXT + Constants.CSS_UNDERLINE); + colorModeColumn.setOnEditStart((TableColumn.CellEditEvent t) -> cellEdit = true); + colorModeColumn.setOnEditCancel((TableColumn.CellEditEvent t) -> cellEdit = false); + colorModeColumn.setOnEditCommit((TableColumn.CellEditEvent t) -> { + cellEdit = false; + GlowWormDevice device = t.getTableView().getItems().get(t.getTablePosition().getRow()); + log.info("Setting Color Mode" + t.getNewValue() + " on " + device.getDeviceName()); + device.setColorMode(t.getNewValue()); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); + } + MainSingleton.getInstance().config.setColorMode(LocalizedEnum.fromStr(Enums.ColorMode.class, t.getNewValue()).ordinal() + 1); + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { + FirmwareConfigDto firmwareConfigDto = new FirmwareConfigDto(); + firmwareConfigDto.setColorMode(String.valueOf(MainSingleton.getInstance().config.getColorMode())); + firmwareConfigDto.setMAC(device.getMac()); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG), + CommonUtility.toJsonString(firmwareConfigDto)); + } else if (MainSingleton.getInstance().config != null) { + settingsController.sendSerialParams(); + } + }); + } + + + /** + * Manage color order cell + */ + private void manageColorOrder() { + colorOrderColumn.setCellFactory(tc -> new ComboBoxTableCell<>(Enums.ColorOrder.GRB.name(), Enums.ColorOrder.RGB.name(), + Enums.ColorOrder.BGR.name(), Enums.ColorOrder.BRG.name(), Enums.ColorOrder.RBG.name(), Enums.ColorOrder.GBR.name())); + colorOrderColumn.setCellValueFactory(cellData -> cellData.getValue().colorOrderProperty()); + colorOrderColumn.setStyle(Constants.TC_BOLD_TEXT + Constants.CSS_UNDERLINE); + colorOrderColumn.setOnEditStart((TableColumn.CellEditEvent t) -> cellEdit = true); + colorOrderColumn.setOnEditCancel((TableColumn.CellEditEvent t) -> cellEdit = false); + colorOrderColumn.setOnEditCommit((TableColumn.CellEditEvent t) -> { + cellEdit = false; + GlowWormDevice device = t.getTableView().getItems().get(t.getTablePosition().getRow()); + log.info("Setting Color Order" + t.getNewValue() + " on " + device.getDeviceName()); + device.setColorOrder(t.getNewValue()); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); + } + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { + FirmwareConfigDto firmwareConfigDto = new FirmwareConfigDto(); + firmwareConfigDto.setColorOrder(String.valueOf(Enums.ColorOrder.valueOf(t.getNewValue()).getValue())); + firmwareConfigDto.setMAC(device.getMac()); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG), + CommonUtility.toJsonString(firmwareConfigDto)); + } else if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().colorOrder = Enums.ColorOrder.valueOf(t.getNewValue()).getValue(); + settingsController.sendSerialParams(); + } + }); + } + /** * Set GPIO pins: relay pin, smart button pin, ldr pin * @@ -221,7 +262,7 @@ protected void updateItem(Hyperlink item, boolean empty) { private void setPins(TableColumn.CellEditEvent t) { cellEdit = false; GlowWormDevice device = t.getTableView().getItems().get(t.getTablePosition().getRow()); - Optional result = FireflyLuciferin.guiManager.showLocalizedAlert(Constants.GPIO_OK_TITLE, Constants.GPIO_OK_HEADER, + Optional result = MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.GPIO_OK_TITLE, Constants.GPIO_OK_HEADER, Constants.GPIO_OK_CONTEXT, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { @@ -236,23 +277,23 @@ private void setPins(TableColumn.CellEditEvent t) { } else if (t.getTableColumn().getId().equals(Constants.EDITABLE_PIN_GPIO_CLOCK)) { device.setGpioClock(t.getNewValue()); } - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { FirmwareConfigDto firmwareConfigDto = new FirmwareConfigDto(); firmwareConfigDto.setMAC(device.getMac()); firmwareConfigDto.setLdrPin(Integer.parseInt(device.getLdrPin())); firmwareConfigDto.setRelayPin(Integer.parseInt(device.getRelayPin())); firmwareConfigDto.setSbPin(Integer.parseInt(device.getSbPin())); firmwareConfigDto.setGpioClock(Integer.parseInt(device.getGpioClock())); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC), + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG), CommonUtility.toJsonString(firmwareConfigDto)); - } else if (FireflyLuciferin.config != null) { - FireflyLuciferin.ldrPin = Integer.parseInt(device.getLdrPin()); - FireflyLuciferin.relayPin = Integer.parseInt(device.getRelayPin()); - FireflyLuciferin.sbPin = Integer.parseInt(device.getSbPin()); - FireflyLuciferin.gpioClockPin = Integer.parseInt(device.getGpioClock()); + } else if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().ldrPin = Integer.parseInt(device.getLdrPin()); + MainSingleton.getInstance().relayPin = Integer.parseInt(device.getRelayPin()); + MainSingleton.getInstance().sbPin = Integer.parseInt(device.getSbPin()); + MainSingleton.getInstance().gpioClockPin = Integer.parseInt(device.getGpioClock()); settingsController.sendSerialParams(); } } @@ -262,7 +303,7 @@ private void setPins(TableColumn.CellEditEvent t) { * Init form values */ void initDefaultValues() { - versionLabel.setText(Constants.FIREFLY_LUCIFERIN + " (v" + FireflyLuciferin.version + ")"); + versionLabel.setText(Constants.FIREFLY_LUCIFERIN + " (v" + MainSingleton.getInstance().version + ")"); powerSaving.setValue(Enums.PowerSaving.DISABLED.getI18n()); multiMonitor.setValue(CommonUtility.getWord(Constants.MULTIMONITOR_1)); checkForUpdates.setSelected(true); @@ -279,7 +320,8 @@ void initDefaultValues() { * @param currentConfig stored config */ public void initValuesFromSettingsFile(Configuration currentConfig) { - versionLabel.setText(Constants.FIREFLY_LUCIFERIN + " (v" + FireflyLuciferin.version + ")"); + evaluateSatelliteBtn(currentConfig.isFullFirmware()); + versionLabel.setText(Constants.FIREFLY_LUCIFERIN + " (v" + MainSingleton.getInstance().version + ")"); if (!currentConfig.getPowerSaving().isEmpty()) { powerSaving.setValue(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, currentConfig.getPowerSaving()).getI18n()); } else { @@ -298,6 +340,15 @@ public void initValuesFromSettingsFile(Configuration currentConfig) { syncCheck.setSelected(currentConfig.isSyncCheck()); } + /** + * Method used to enable disable sat button + * + * @param isFullFirmware true if full firmware + */ + public void evaluateSatelliteBtn(boolean isFullFirmware) { + manageSatButton.setDisable(!isFullFirmware); + } + /** * Init combo boxes */ @@ -316,23 +367,23 @@ public void setTableEdit() { gpioColumn.setOnEditCommit(t -> { cellEdit = false; GlowWormDevice device = t.getTableView().getItems().get(t.getTablePosition().getRow()); - Optional result = FireflyLuciferin.guiManager.showLocalizedAlert(Constants.GPIO_OK_TITLE, Constants.GPIO_OK_HEADER, + Optional result = MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.GPIO_OK_TITLE, Constants.GPIO_OK_HEADER, Constants.GPIO_OK_CONTEXT, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { log.info("Setting GPIO" + t.getNewValue() + " on " + device.getDeviceName()); device.setGpio(t.getNewValue()); - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { FirmwareConfigDto gpioDto = new FirmwareConfigDto(); gpioDto.setGpio(Integer.parseInt(t.getNewValue())); gpioDto.setMAC(device.getMac()); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC), + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG), CommonUtility.toJsonString(gpioDto)); - } else if (FireflyLuciferin.config != null) { - FireflyLuciferin.gpio = Integer.parseInt(t.getNewValue()); + } else if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().gpio = Integer.parseInt(t.getNewValue()); settingsController.sendSerialParams(); } } @@ -348,7 +399,7 @@ public void manageDeviceList() { Calendar calendarTemp = Calendar.getInstance(); ObservableList deviceTableDataToRemove = FXCollections.observableArrayList(); AtomicBoolean showClockColumn = new AtomicBoolean(false); - deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (Enums.ColorMode.DOTSTAR.name().equalsIgnoreCase(glowWormDevice.getColorMode())) { showClockColumn.set(true); } @@ -357,11 +408,17 @@ public void manageDeviceList() { calendar.add(Calendar.SECOND, -20); calendarTemp.add(Calendar.SECOND, -60); try { - if (calendar.getTime().after(FireflyLuciferin.formatter.parse(glowWormDevice.getLastSeen())) - && FireflyLuciferin.formatter.parse(glowWormDevice.getLastSeen()).after(calendarTemp.getTime())) { - if (!(Constants.SERIAL_PORT_AUTO.equals(FireflyLuciferin.config.getOutputDevice()) - && FireflyLuciferin.config.getMultiMonitor() > 1) && !oldFirmwareDevice) { + if (calendar.getTime().after(MainSingleton.getInstance().formatter.parse(glowWormDevice.getLastSeen())) + && MainSingleton.getInstance().formatter.parse(glowWormDevice.getLastSeen()).after(calendarTemp.getTime())) { + if (!(Constants.SERIAL_PORT_AUTO.equals(MainSingleton.getInstance().config.getOutputDevice()) + && MainSingleton.getInstance().config.getMultiMonitor() > 1) && !GuiSingleton.getInstance().oldFirmwareDevice) { deviceTableDataToRemove.add(glowWormDevice); + if (MainSingleton.getInstance().config.getOutputDevice().equals(glowWormDevice.getDeviceIP())) { + log.info("USB device disconnected, restarting."); + NativeExecutor.restartNativeInstance(); + } else { + log.info("Device disconnected: " + glowWormDevice.getDeviceName()); + } } } } catch (ParseException e) { @@ -369,13 +426,23 @@ public void manageDeviceList() { } }); // Temp list contains the removed devices, they will be readded if a microcontroller restart occurs, and if the capture is runnning. - deviceTableDataTemp.addAll(deviceTableDataToRemove); - deviceTableData.removeAll(deviceTableDataToRemove); + GuiSingleton.getInstance().deviceTableDataTemp.addAll(deviceTableDataToRemove); + GuiSingleton.getInstance().deviceTableData.removeAll(deviceTableDataToRemove); gpioClockColumn.setVisible(showClockColumn.get()); deviceTable.refresh(); } } + /** + * Manage satellites action button + */ + @FXML + public void satButtonAction() { + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.showSatellitesDialog(settingsController); + } + } + /** * Save button event * @@ -414,6 +481,7 @@ public void saveButtonHover() { * @param currentConfig stored config */ void setTooltips(Configuration currentConfig) { + manageSatButton.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_BTN)); powerSaving.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_POWER_SAVING)); multiMonitor.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_MULTIMONITOR)); checkForUpdates.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_CHECK_UPDATES)); @@ -429,7 +497,7 @@ void setTooltips(Configuration currentConfig) { * @return devices list */ public ObservableList getDeviceTableData() { - return deviceTableData; + return GuiSingleton.getInstance().deviceTableData; } /** @@ -437,7 +505,7 @@ public ObservableList getDeviceTableData() { */ @FXML public void onMouseClickedGitHubLink() { - FireflyLuciferin.guiManager.surfToURL(Constants.GITHUB_URL); + MainSingleton.getInstance().guiManager.surfToURL(Constants.GITHUB_URL); } } diff --git a/src/main/java/org/dpsoftware/gui/controllers/EyeCareDialogController.java b/src/main/java/org/dpsoftware/gui/controllers/EyeCareDialogController.java index 2100beb7d..7aff040ee 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/EyeCareDialogController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/EyeCareDialogController.java @@ -31,7 +31,7 @@ import javafx.scene.control.*; import javafx.scene.input.InputEvent; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; @@ -110,7 +110,7 @@ protected void initialize() { ldrInterval.getItems().add(ldrVal.getI18n()); } try { - if (FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config.isFullFirmware()) { TcpResponse tcp = NetworkManager.publishToTopic(Constants.HTTP_LDR, "", true); JsonNode ldrDto = CommonUtility.fromJsonToObject(Objects.requireNonNull(tcp).getResponse()); enableLDR.setSelected(Objects.requireNonNull(ldrDto).get(Constants.HTTP_LDR_ENABLED).asText().equals("1")); @@ -193,7 +193,7 @@ private void evaluateValues() { private void startAnimationTimer() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(() -> Platform.runLater(() -> - setLdrValue(CommonUtility.ldrStrength + Constants.PERCENT)), 0, 1, TimeUnit.SECONDS); + setLdrValue(MainSingleton.getInstance().ldrStrength + Constants.PERCENT)), 0, 1, TimeUnit.SECONDS); } /** @@ -226,16 +226,16 @@ public void saveAndClose(InputEvent e) { */ @FXML public void apply(InputEvent e) { - boolean showApplyAlert = FireflyLuciferin.config.isEnableLDR() != enableLDR.isSelected() && enableLDR.isSelected(); + boolean showApplyAlert = MainSingleton.getInstance().config.isEnableLDR() != enableLDR.isSelected() && enableLDR.isSelected(); settingsController.injectEyeCareController(this); settingsController.save(e); setLdrDto(4); if (showApplyAlert) { if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.LDR_ALERT_ENABLED, + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.LDR_ALERT_ENABLED, Constants.TOOLTIP_EYEC_ENABLE_LDR, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_ENABLED, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_ENABLED, Constants.TOOLTIP_EYEC_ENABLE_LDR, Alert.AlertType.INFORMATION); } } @@ -262,7 +262,7 @@ public void save(Configuration config) { */ @FXML public void calibrateLDR() { - Optional result = FireflyLuciferin.guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_CONTINUE, + Optional result = MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_CONTINUE, Constants.TOOLTIP_EYEC_CAL, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { @@ -275,7 +275,7 @@ public void calibrateLDR() { */ @FXML public void resetLDR() { - Optional result = FireflyLuciferin.guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_CONTINUE, + Optional result = MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_CONTINUE, Constants.TOOLTIP_EYEC_RESET, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { @@ -292,20 +292,20 @@ public void resetLDR() { */ private void programMicrocontroller(int ldrAction, String ldrAlertResetHeader, String ldrAlertResetContent) { TcpResponse tcpResponse = setLdrDto(ldrAction); - if (!FireflyLuciferin.config.isFullFirmware() || tcpResponse.getErrorCode() == Constants.HTTP_SUCCESS) { + if (!MainSingleton.getInstance().config.isFullFirmware() || tcpResponse.getErrorCode() == Constants.HTTP_SUCCESS) { if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(ldrAlertResetHeader, + MainSingleton.getInstance().guiManager.showLocalizedNotification(ldrAlertResetHeader, ldrAlertResetContent, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, ldrAlertResetHeader, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, ldrAlertResetHeader, ldrAlertResetContent, Alert.AlertType.INFORMATION); } } else { if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.LDR_ALERT_HEADER_ERROR, + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.LDR_ALERT_HEADER_ERROR, Constants.LDR_ALERT_HEADER_CONTENT, TrayIcon.MessageType.ERROR); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_HEADER_ERROR, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.LDR_ALERT_TITLE, Constants.LDR_ALERT_HEADER_ERROR, Constants.LDR_ALERT_HEADER_CONTENT, Alert.AlertType.ERROR); } } @@ -324,10 +324,10 @@ private TcpResponse setLdrDto(int ldrAction) { ldrDto.setLdrInterval(LocalizedEnum.fromStr(Enums.LdrInterval.class, ldrInterval.getValue()).getLdrIntervalInteger()); ldrDto.setLdrMin(Integer.parseInt(minimumBrightness.getValue().replace(Constants.PERCENT, ""))); ldrDto.setLdrAction(ldrAction); - FireflyLuciferin.config.setEnableLDR(ldrDto.isLdrEnabled()); - FireflyLuciferin.config.setLdrTurnOff(ldrDto.isLdrTurnOff()); - FireflyLuciferin.config.setLdrInterval(ldrDto.getLdrInterval()); - FireflyLuciferin.config.setLdrMin(Integer.parseInt(minimumBrightness.getValue().replace(Constants.PERCENT, ""))); + MainSingleton.getInstance().config.setEnableLDR(ldrDto.isLdrEnabled()); + MainSingleton.getInstance().config.setLdrTurnOff(ldrDto.isLdrTurnOff()); + MainSingleton.getInstance().config.setLdrInterval(ldrDto.getLdrInterval()); + MainSingleton.getInstance().config.setLdrMin(Integer.parseInt(minimumBrightness.getValue().replace(Constants.PERCENT, ""))); boolean toggleLed = false; if (ldrAction == 2 && settingsController.miscTabController.toggleLed.isSelected()) { if (ldrTurnOff.isSelected()) { @@ -337,10 +337,10 @@ private TcpResponse setLdrDto(int ldrAction) { CommonUtility.sleepSeconds(4); } TcpResponse tcpResponse = null; - FireflyLuciferin.ldrAction = ldrAction; - if (FireflyLuciferin.config.isFullFirmware()) { + MainSingleton.getInstance().ldrAction = ldrAction; + if (MainSingleton.getInstance().config.isFullFirmware()) { // Note: this is HTTP only not MQTT. - tcpResponse = NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.LDR_TOPIC), CommonUtility.toJsonString(ldrDto), true); + tcpResponse = NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.HTTP_SET_LDR), CommonUtility.toJsonString(ldrDto), true); } else { settingsController.sendSerialParams(); } diff --git a/src/main/java/org/dpsoftware/gui/controllers/InfoController.java b/src/main/java/org/dpsoftware/gui/controllers/InfoController.java index 5e8c4f134..143648ff1 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/InfoController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/InfoController.java @@ -29,11 +29,13 @@ import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; +import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.SplitPane; +import javafx.scene.input.InputEvent; import javafx.stage.Stage; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; import org.dpsoftware.utilities.CommonUtility; @@ -60,6 +62,10 @@ public class InfoController { private final StringProperty consumerValue = new SimpleStringProperty(""); @FXML private final StringProperty wifiLdrValue = new SimpleStringProperty(""); + @FXML + public Button closeWindowBtn; + @FXML + public Button minimizeWindowBtn; XYChart.Series producingSeries = new XYChart.Series<>(); XYChart.Series consumingSeries = new XYChart.Series<>(); XYChart.Series wifiSeries = new XYChart.Series<>(); @@ -97,7 +103,7 @@ protected void initialize() { producerLabel.textProperty().bind(producerValueProperty()); consumerLabel.textProperty().bind(consumerValueProperty()); wifiLdrLabel.textProperty().bind(wifiLdrValueProperty()); - version.setText(Constants.INFO_VERSION.replaceAll("VERSION", FireflyLuciferin.version)); + version.setText(Constants.INFO_VERSION.replaceAll("VERSION", MainSingleton.getInstance().version)); runLater(); startAnimationTimer(); if (NativeExecutor.isLinux()) { @@ -124,9 +130,9 @@ private void startAnimationTimer() { scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); scheduledExecutorService.scheduleAtFixedRate(() -> Platform.runLater(() -> { String now = LocalDateTime.now().toString(); - producingSeries.getData().add(new XYChart.Data<>(now, FireflyLuciferin.FPS_PRODUCER)); - consumingSeries.getData().add(new XYChart.Data<>(now, FireflyLuciferin.FPS_GW_CONSUMER)); - wifiSeries.getData().add(new XYChart.Data<>(now, CommonUtility.wifiStrength)); + producingSeries.getData().add(new XYChart.Data<>(now, MainSingleton.getInstance().FPS_PRODUCER)); + consumingSeries.getData().add(new XYChart.Data<>(now, MainSingleton.getInstance().FPS_GW_CONSUMER)); + wifiSeries.getData().add(new XYChart.Data<>(now, MainSingleton.getInstance().wifiStrength)); if (producingSeries.getData().size() > WINDOW_SIZE) { producingSeries.getData().remove(0); } @@ -136,22 +142,39 @@ private void startAnimationTimer() { if (wifiSeries.getData().size() > WINDOW_SIZE) { wifiSeries.getData().remove(0); } - setProducerValue(CommonUtility.getWord(Constants.INFO_PRODUCING) + FireflyLuciferin.FPS_PRODUCER + Constants.FPS_VAL); - setConsumerValue(CommonUtility.getWord(Constants.INFO_CONSUMING) + FireflyLuciferin.FPS_GW_CONSUMER + Constants.FPS_VAL); - String wifiLdr = Constants.INFO_WIFI + CommonUtility.wifiStrength + Constants.PERCENT; - if (FireflyLuciferin.config.isEnableLDR()) { - wifiLdr += Constants.INFO_LDR + CommonUtility.ldrStrength + Constants.PERCENT; + setProducerValue(CommonUtility.getWord(Constants.INFO_PRODUCING) + MainSingleton.getInstance().FPS_PRODUCER + Constants.FPS_VAL); + setConsumerValue(CommonUtility.getWord(Constants.INFO_CONSUMING) + MainSingleton.getInstance().FPS_GW_CONSUMER + Constants.FPS_VAL); + String wifiLdr = Constants.INFO_WIFI + MainSingleton.getInstance().wifiStrength + Constants.PERCENT; + if (MainSingleton.getInstance().config.isEnableLDR()) { + wifiLdr += Constants.INFO_LDR + MainSingleton.getInstance().ldrStrength + Constants.PERCENT; } setWifiLdrValue(wifiLdr); }), 0, 1, TimeUnit.SECONDS); } + /** + * Minimize window + */ + @FXML + public void minimizeWindow() { + Stage obj = (Stage) closeWindowBtn.getScene().getWindow(); + obj.setIconified(true); + } + + /** + * Close window + */ + @FXML + public void closeWindow(InputEvent e) { + CommonUtility.closeCurrentStage(e); + } + /** * Open browser to the GitHub project page */ @FXML public void onMouseClickedGitHubLink() { - FireflyLuciferin.guiManager.surfToURL(Constants.GITHUB_URL); + MainSingleton.getInstance().guiManager.surfToURL(Constants.GITHUB_URL); } public StringProperty producerValueProperty() { diff --git a/src/main/java/org/dpsoftware/gui/controllers/LedsConfigTabController.java b/src/main/java/org/dpsoftware/gui/controllers/LedsConfigTabController.java index 1e07c3f98..154a44686 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/LedsConfigTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/LedsConfigTabController.java @@ -28,8 +28,7 @@ import javafx.scene.control.TextField; import javafx.scene.input.InputEvent; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; @@ -93,6 +92,24 @@ public class LedsConfigTabController { @FXML private Label cornerGapTopLabel, cornerGapRightLabel, cornerGapBottomLabel, cornerGapLeftLabel; + /** + * Set led matrix info + * + * @param config stored config + * @return matrix infos + */ + private static LedMatrixInfo getLedMatrixInfo(Configuration config) { + LedMatrixInfo ledMatrixInfo = new LedMatrixInfo(); + ledMatrixInfo.setTopLedOriginal(config.getTopLed()); + ledMatrixInfo.setRightLedOriginal(config.getRightLed()); + ledMatrixInfo.setBottomRightLedOriginal(config.getBottomRightLed()); + ledMatrixInfo.setBottomLeftLedOriginal(config.getBottomLeftLed()); + ledMatrixInfo.setBottomRowLedOriginal(config.getBottomRowLed()); + ledMatrixInfo.setLeftLedOriginal(config.getLeftLed()); + ledMatrixInfo.setSplitBottomRow(config.getSplitBottomMargin()); + ledMatrixInfo.setGroupBy(config.getGroupBy()); + return ledMatrixInfo; + } /** * Inject main controller containing the TabPane @@ -192,7 +209,7 @@ void initDefaultValues() { * @param currentConfig stored config */ public void initValuesFromSettingsFile(Configuration currentConfig) { - switch (JavaFXStarter.whoAmI) { + switch (MainSingleton.getInstance().whoAmI) { case 1 -> { if ((currentConfig.getMultiMonitor() == 1)) { displayLabel.setText(CommonUtility.getWord(Constants.MAIN_DISPLAY)); @@ -291,15 +308,7 @@ public void save(Configuration config) { config.setBottomRowLed(Integer.parseInt(bottomRowLed.getText())); config.setOrientation(LocalizedEnum.fromStr(Enums.Orientation.class, orientation.getValue()).getBaseI18n()); config.setLedStartOffset(Integer.parseInt(ledStartOffset.getValue())); - LedMatrixInfo ledMatrixInfo = new LedMatrixInfo(); - ledMatrixInfo.setTopLedOriginal(config.getTopLed()); - ledMatrixInfo.setRightLedOriginal(config.getRightLed()); - ledMatrixInfo.setBottomRightLedOriginal(config.getBottomRightLed()); - ledMatrixInfo.setBottomLeftLedOriginal(config.getBottomLeftLed()); - ledMatrixInfo.setBottomRowLedOriginal(config.getBottomRowLed()); - ledMatrixInfo.setLeftLedOriginal(config.getLeftLed()); - ledMatrixInfo.setSplitBottomRow(config.getSplitBottomMargin()); - ledMatrixInfo.setGroupBy(config.getGroupBy()); + LedMatrixInfo ledMatrixInfo = getLedMatrixInfo(config); CommonUtility.groupByCalc(ledMatrixInfo); config.setGroupBy(ledMatrixInfo.getGroupBy()); if (ledMatrixInfo.getTotaleNumOfLeds() == 0) { @@ -314,7 +323,7 @@ public void save(Configuration config) { */ @FXML public void showTestImage(InputEvent e) { - FireflyLuciferin.guiManager.showColorCorrectionDialog(settingsController, e); + MainSingleton.getInstance().guiManager.showColorCorrectionDialog(settingsController, e); } /** @@ -405,7 +414,7 @@ private void calcLedOffset(String newValue, String val, String ledDistance1, int */ private void forceLedOffsetValidation(String newValue) { ledStartOffset.cancelEdit(); - if (newValue.length() == 0) { + if (newValue.isEmpty()) { setLedOffset("0"); } else { String val = CommonUtility.removeChars(newValue); @@ -429,11 +438,11 @@ void setLedOffset(String val) { */ void setNumericTextField() { addLedOffsetListener(); - settingsController.addTextFieldListener(topLed); - settingsController.addTextFieldListener(leftLed); - settingsController.addTextFieldListener(rightLed); - settingsController.addTextFieldListener(bottomLeftLed); - settingsController.addTextFieldListener(bottomRightLed); - settingsController.addTextFieldListener(bottomRowLed); + SettingsController.addTextFieldListener(topLed); + SettingsController.addTextFieldListener(leftLed); + SettingsController.addTextFieldListener(rightLed); + SettingsController.addTextFieldListener(bottomLeftLed); + SettingsController.addTextFieldListener(bottomRightLed); + SettingsController.addTextFieldListener(bottomRowLed); } } diff --git a/src/main/java/org/dpsoftware/gui/controllers/MiscTabController.java b/src/main/java/org/dpsoftware/gui/controllers/MiscTabController.java index e06131d67..5ab5177cb 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/MiscTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/MiscTabController.java @@ -32,11 +32,10 @@ import javafx.scene.layout.RowConstraints; import javafx.scene.paint.Color; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; -import org.dpsoftware.audio.AudioLoopback; import org.dpsoftware.audio.AudioLoopbackSoftware; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.audio.AudioUtility; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; @@ -44,8 +43,8 @@ import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.gui.WidgetFactory; import org.dpsoftware.gui.elements.GlowWormDevice; +import org.dpsoftware.managers.ManagerSingleton; import org.dpsoftware.managers.NetworkManager; -import org.dpsoftware.managers.PipelineManager; import org.dpsoftware.managers.SerialManager; import org.dpsoftware.managers.StorageManager; import org.dpsoftware.managers.dto.AudioDevice; @@ -136,7 +135,7 @@ public void injectSettingsController(SettingsController settingsController) { */ @FXML protected void initialize() { - if (FireflyLuciferin.config == null) { + if (MainSingleton.getInstance().config == null) { colorMode.setDisable(true); whiteTemp.setDisable(true); } @@ -147,26 +146,39 @@ protected void initialize() { runAtLoginLabel.setVisible(false); startWithSystem.setVisible(false); } + if (MainSingleton.getInstance().config != null) { + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); + if (effectInUse == Enums.Effect.MUSIC_MODE_RAINBOW || effectInUse == Enums.Effect.MUSIC_MODE_VU_METER + || effectInUse == Enums.Effect.MUSIC_MODE_VU_METER_DUAL || effectInUse == Enums.Effect.MUSIC_MODE_BRIGHT) { + initAudioCombo(); + } + } + manageFramerate(); + for (Enums.FrameInsertion frameIns : Enums.FrameInsertion.values()) { + frameInsertion.getItems().add(frameIns.getI18n()); + } + } + + /** + * Init audio combo + */ + private void initAudioCombo() { if (NativeExecutor.isWindows()) { audioDevice.getItems().add(Enums.Audio.DEFAULT_AUDIO_OUTPUT_WASAPI.getI18n()); } audioDevice.getItems().add(Enums.Audio.DEFAULT_AUDIO_OUTPUT_NATIVE.getI18n()); - if (FireflyLuciferin.config != null && AudioLoopback.audioDevices.isEmpty()) { + if (MainSingleton.getInstance().config != null && AudioSingleton.getInstance().audioDevices.isEmpty()) { AudioUtility audioLoopback = new AudioLoopbackSoftware(); for (AudioDevice device : audioLoopback.getLoopbackDevices().values()) { if (device.getDeviceName().contains(Constants.LOOPBACK)) audioDevice.getItems().add(device.getDeviceName()); } } else { - for (AudioDevice device : AudioLoopback.audioDevices.values()) { + for (AudioDevice device : AudioSingleton.getInstance().audioDevices.values()) { if (device.getDeviceName().contains(Constants.LOOPBACK)) audioDevice.getItems().add(device.getDeviceName()); } } - manageFramerate(); - for (Enums.FrameInsertion frameIns : Enums.FrameInsertion.values()) { - frameInsertion.getItems().add(frameIns.getI18n()); - } } /** @@ -187,16 +199,16 @@ private void manageFramerate() { if (LocalizedEnum.fromStr(Enums.Framerate.class, framerate.getValue()) != Enums.Framerate.UNLOCKED) { framerate.setValue((CommonUtility.removeChars(framerate.getValue())) + Constants.FPS_VAL); } - if (FireflyLuciferin.RUNNING && !framerate.getValue().equals(FireflyLuciferin.config.getDesiredFramerate())) { + if (MainSingleton.getInstance().RUNNING && !framerate.getValue().equals(MainSingleton.getInstance().config.getDesiredFramerate())) { Platform.runLater(() -> { - FireflyLuciferin.guiManager.stopCapturingThreads(FireflyLuciferin.RUNNING); + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); CommonUtility.delaySeconds(() -> { if (LocalizedEnum.fromStr(Enums.Framerate.class, framerate.getValue()) != Enums.Framerate.UNLOCKED) { - FireflyLuciferin.config.setDesiredFramerate(framerate.getValue().replaceAll(Constants.FPS_VAL, "")); + MainSingleton.getInstance().config.setDesiredFramerate(framerate.getValue().replaceAll(Constants.FPS_VAL, "")); } else { - FireflyLuciferin.config.setDesiredFramerate(Enums.Framerate.UNLOCKED.getBaseI18n()); + MainSingleton.getInstance().config.setDesiredFramerate(Enums.Framerate.UNLOCKED.getBaseI18n()); } - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); }, 4); }); } @@ -285,50 +297,53 @@ public void initValuesFromSettingsFile(Configuration currentConfig) { */ public void initValuesFromSettingsFile(Configuration currentConfig, boolean updateProfiles) { if (NativeExecutor.isWindows()) { - startWithSystem.setSelected(FireflyLuciferin.config.isStartWithSystem()); + startWithSystem.setSelected(MainSingleton.getInstance().config.isStartWithSystem()); } frameInsertion.setDisable((!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) && (!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) + && (!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC_NVIDIA.name())) + && (!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG.name())) + && (!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA.name())) && (!currentConfig.getCaptureMethod().equals(Configuration.CaptureMethod.AVFVIDEOSRC.name()))); - gamma.setValue(String.valueOf(FireflyLuciferin.config.getGamma())); - colorMode.setValue(Enums.ColorMode.values()[FireflyLuciferin.config.getColorMode() - 1].getI18n()); - if (!FireflyLuciferin.config.getDesiredFramerate().equals(Enums.Framerate.UNLOCKED.getBaseI18n())) { - framerate.setValue(FireflyLuciferin.config.getDesiredFramerate() + Constants.FPS_VAL); + gamma.setValue(String.valueOf(MainSingleton.getInstance().config.getGamma())); + colorMode.setValue(Enums.ColorMode.values()[MainSingleton.getInstance().config.getColorMode() - 1].getI18n()); + if (!MainSingleton.getInstance().config.getDesiredFramerate().equals(Enums.Framerate.UNLOCKED.getBaseI18n())) { + framerate.setValue(MainSingleton.getInstance().config.getDesiredFramerate() + Constants.FPS_VAL); } else { - framerate.setValue(LocalizedEnum.fromBaseStr(Enums.Framerate.class, FireflyLuciferin.config.getDesiredFramerate()).getI18n()); + framerate.setValue(LocalizedEnum.fromBaseStr(Enums.Framerate.class, MainSingleton.getInstance().config.getDesiredFramerate()).getI18n()); } - frameInsertion.setValue(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, FireflyLuciferin.config.getFrameInsertion()).getI18n()); - framerate.setDisable(!LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, FireflyLuciferin.config.getFrameInsertion()).equals(Enums.FrameInsertion.NO_SMOOTHING)); - eyeCare.setSelected(FireflyLuciferin.config.isEyeCare()); - String[] color = (FireflyLuciferin.config.getColorChooser().equals(Constants.DEFAULT_COLOR_CHOOSER)) ? - currentConfig.getColorChooser().split(",") : FireflyLuciferin.config.getColorChooser().split(","); + frameInsertion.setValue(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, MainSingleton.getInstance().config.getFrameInsertion()).getI18n()); + framerate.setDisable(!LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, MainSingleton.getInstance().config.getFrameInsertion()).equals(Enums.FrameInsertion.NO_SMOOTHING)); + eyeCare.setSelected(MainSingleton.getInstance().config.isEyeCare()); + String[] color = (MainSingleton.getInstance().config.getColorChooser().equals(Constants.DEFAULT_COLOR_CHOOSER)) ? + currentConfig.getColorChooser().split(",") : MainSingleton.getInstance().config.getColorChooser().split(","); colorPicker.setValue(Color.rgb(Integer.parseInt(color[0]), Integer.parseInt(color[1]), Integer.parseInt(color[2]), Double.parseDouble(color[3]) / 255)); brightness.setValue((Double.parseDouble(color[3]) / 255) * 100); - whiteTemp.setValue(FireflyLuciferin.config.getWhiteTemperature() * 100); - audioGain.setValue(FireflyLuciferin.config.getAudioLoopbackGain()); - audioChannels.setValue(LocalizedEnum.fromBaseStr(Enums.AudioChannels.class, FireflyLuciferin.config.getAudioChannels()).getI18n()); - var audioDeviceFromStore = LocalizedEnum.fromBaseStr(Enums.Audio.class, FireflyLuciferin.config.getAudioDevice()); + whiteTemp.setValue(MainSingleton.getInstance().config.getWhiteTemperature() * 100); + audioGain.setValue(MainSingleton.getInstance().config.getAudioLoopbackGain()); + audioChannels.setValue(LocalizedEnum.fromBaseStr(Enums.AudioChannels.class, MainSingleton.getInstance().config.getAudioChannels()).getI18n()); + var audioDeviceFromStore = LocalizedEnum.fromBaseStr(Enums.Audio.class, MainSingleton.getInstance().config.getAudioDevice()); String audioDeviceToDisplay; if (audioDeviceFromStore != null) { audioDeviceToDisplay = audioDeviceFromStore.getI18n(); } else { - audioDeviceToDisplay = FireflyLuciferin.config.getAudioDevice(); + audioDeviceToDisplay = MainSingleton.getInstance().config.getAudioDevice(); } audioDevice.setValue(audioDeviceToDisplay); - if (!Constants.OFF.equals(FireflyLuciferin.config.getEffect())) { - effect.setValue(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()).getI18n()); + if (!Constants.OFF.equals(MainSingleton.getInstance().config.getEffect())) { + effect.setValue(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()).getI18n()); } else { effect.setValue(Enums.Effect.SOLID.getI18n()); } - if (FireflyLuciferin.config.isToggleLed()) { + if (MainSingleton.getInstance().config.isToggleLed()) { toggleLed.setText(CommonUtility.getWord(Constants.TURN_LED_OFF)); } else { toggleLed.setText(CommonUtility.getWord(Constants.TURN_LED_ON)); } - toggleLed.setSelected(FireflyLuciferin.config.isToggleLed()); + toggleLed.setSelected(MainSingleton.getInstance().config.isToggleLed()); WidgetFactory widgetFactory = new WidgetFactory(); - nightModeFrom.setValueFactory(widgetFactory.timeSpinnerValueFactory(LocalTime.parse(FireflyLuciferin.config.getNightModeFrom()))); - nightModeTo.setValueFactory(widgetFactory.timeSpinnerValueFactory(LocalTime.parse(FireflyLuciferin.config.getNightModeTo()))); + nightModeFrom.setValueFactory(widgetFactory.timeSpinnerValueFactory(LocalTime.parse(MainSingleton.getInstance().config.getNightModeFrom()))); + nightModeTo.setValueFactory(widgetFactory.timeSpinnerValueFactory(LocalTime.parse(MainSingleton.getInstance().config.getNightModeTo()))); nightModeBrightness.setValueFactory(widgetFactory.spinnerNightModeValueFactory()); enableDisableNightMode(nightModeBrightness.getValue()); if (updateProfiles) { @@ -336,10 +351,10 @@ public void initValuesFromSettingsFile(Configuration currentConfig, boolean upda profiles.getItems().addAll(sm.listProfilesForThisInstance()); profiles.getItems().add(CommonUtility.getWord(Constants.DEFAULT)); } - if (FireflyLuciferin.profileArgs.equals(Constants.DEFAULT)) { + if (MainSingleton.getInstance().profileArgs.equals(Constants.DEFAULT)) { profiles.setValue(CommonUtility.getWord(Constants.DEFAULT)); } else { - profiles.setValue(FireflyLuciferin.profileArgs); + profiles.setValue(MainSingleton.getInstance().profileArgs); } enableDisableProfileButtons(); evaluateLDRConnectedFeatures(); @@ -349,7 +364,7 @@ public void initValuesFromSettingsFile(Configuration currentConfig, boolean upda * Setup the context menu based on the selected effect */ public void setContextMenu() { - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); if (Enums.Effect.MUSIC_MODE_VU_METER.equals(effectInUse) || Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(effectInUse) || Enums.Effect.MUSIC_MODE_BRIGHT.equals(effectInUse) @@ -386,7 +401,7 @@ public void initListeners(Configuration currentConfig) { audioGain.valueProperty().addListener((ov, oldVal, newVal) -> { DecimalFormat df = new DecimalFormat(Constants.NUMBER_FORMAT); float selectedGain = Float.parseFloat(df.format(newVal).replace(",", ".")); - FireflyLuciferin.config.setAudioLoopbackGain(selectedGain); + MainSingleton.getInstance().config.setAudioLoopbackGain(selectedGain); }); initNightModeListeners(); initColorModeListeners(currentConfig); @@ -450,17 +465,17 @@ private void enableDisableProfileButtons() { */ private void initColorModeListeners(Configuration currentConfig) { colorMode.valueProperty().addListener((ov, oldVal, newVal) -> { - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setColorMode(colorMode.getSelectionModel().getSelectedIndex() + 1); - FireflyLuciferin.guiManager.stopCapturingThreads(FireflyLuciferin.RUNNING); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setColorMode(colorMode.getSelectionModel().getSelectedIndex() + 1); + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); CommonUtility.delayMilliseconds(() -> { - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { GlowWormDevice deviceToUse = CommonUtility.getDeviceToUse(); log.info("Setting Color Mode"); FirmwareConfigDto colorModeDto = new FirmwareConfigDto(); colorModeDto.setColorMode(String.valueOf(colorMode.getSelectionModel().getSelectedIndex() + 1)); colorModeDto.setMAC(deviceToUse.getMac()); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC), CommonUtility.toJsonString(colorModeDto)); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG), CommonUtility.toJsonString(colorModeDto)); } CommonUtility.sleepMilliseconds(200); turnOnLEDs(currentConfig, true); @@ -480,14 +495,14 @@ private void initColorListeners(Configuration currentConfig) { if ((toggleLed.isSelected())) { toggleLed.setText(CommonUtility.getWord(Constants.TURN_LED_OFF)); turnOnLEDs(currentConfig, true); - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setToggleLed(true); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setToggleLed(true); } } else { toggleLed.setText(CommonUtility.getWord(Constants.TURN_LED_ON)); CommonUtility.turnOffLEDs(currentConfig); - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setToggleLed(false); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setToggleLed(false); } } }); @@ -496,18 +511,21 @@ private void initColorListeners(Configuration currentConfig) { colorPicker.setOnAction(colorPickerEvent); effect.valueProperty().addListener((ov, oldVal, newVal) -> { newVal = LocalizedEnum.fromStr(Enums.Effect.class, newVal).getBaseI18n(); - if (FireflyLuciferin.config != null) { + if (MainSingleton.getInstance().config != null) { if (!oldVal.equals(newVal)) { - FireflyLuciferin.guiManager.stopCapturingThreads(FireflyLuciferin.RUNNING); + if (audioDevice.getItems().isEmpty()) { + initAudioCombo(); + } + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); String finalNewVal = newVal; CommonUtility.delayMilliseconds(() -> { - FireflyLuciferin.config.setEffect(finalNewVal); - PipelineManager.lastEffectInUse = finalNewVal; - FireflyLuciferin.config.setToggleLed(true); + MainSingleton.getInstance().config.setEffect(finalNewVal); + ManagerSingleton.getInstance().lastEffectInUse = finalNewVal; + MainSingleton.getInstance().config.setToggleLed(true); turnOnLEDs(currentConfig, true); }, currentConfig.isFullFirmware() ? 200 : 0); } - FireflyLuciferin.config.setEffect(newVal); + MainSingleton.getInstance().config.setEffect(newVal); setContextMenu(); } }); @@ -520,7 +538,7 @@ private void initColorListeners(Configuration currentConfig) { */ private void initBrightnessGammaListeners(Configuration currentConfig) { // Gamma can be changed on the fly - gamma.valueProperty().addListener((ov, t, gamma) -> FireflyLuciferin.config.setGamma(Double.parseDouble(gamma))); + gamma.valueProperty().addListener((ov, t, gamma) -> MainSingleton.getInstance().config.setGamma(Double.parseDouble(gamma))); brightness.valueProperty().addListener((ov, oldVal, newVal) -> turnOnLEDs(currentConfig, false, true)); } @@ -544,18 +562,18 @@ private void initWhiteTempListeners(Configuration currentConfig) { */ private void initNightModeListeners() { nightModeFrom.valueProperty().addListener((obs, oldValue, newValue) -> { - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setNightModeFrom(newValue.toString()); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setNightModeFrom(newValue.toString()); } }); nightModeTo.valueProperty().addListener((obs, oldValue, newValue) -> { - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setNightModeTo(newValue.toString()); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setNightModeTo(newValue.toString()); } }); nightModeBrightness.valueProperty().addListener((obs, oldValue, newValue) -> { - if (FireflyLuciferin.config != null) { - FireflyLuciferin.config.setNightModeBrightness(newValue); + if (MainSingleton.getInstance().config != null) { + MainSingleton.getInstance().config.setNightModeBrightness(newValue); } enableDisableNightMode(newValue); }); @@ -588,52 +606,75 @@ public void turnOnLEDs(Configuration currentConfig, boolean setBrightness, boole if (toggleLed.isSelected() || !setBrightness) { CommonUtility.sleepMilliseconds(100); Enums.Effect effectInUse = LocalizedEnum.fromStr(Enums.Effect.class, effect.getValue()); - if (!FireflyLuciferin.RUNNING && (Enums.Effect.BIAS_LIGHT.equals(effectInUse) + if (!MainSingleton.getInstance().RUNNING && (Enums.Effect.BIAS_LIGHT.equals(effectInUse) || Enums.Effect.MUSIC_MODE_VU_METER.equals(effectInUse) || Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(effectInUse) || Enums.Effect.MUSIC_MODE_BRIGHT.equals(effectInUse) || Enums.Effect.MUSIC_MODE_RAINBOW.equals(effectInUse))) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else { - FireflyLuciferin.config.setBrightness((int) ((brightness.getValue() / 100) * 255)); + MainSingleton.getInstance().config.setBrightness((int) ((brightness.getValue() / 100) * 255)); if (currentConfig.isFullFirmware()) { - StateDto stateDto = new StateDto(); - stateDto.setState(Constants.ON); - if (!FireflyLuciferin.RUNNING) { - stateDto.setEffect(effectInUse.getBaseI18n()); - } - ColorDto colorDto = new ColorDto(); - int r = (int) (colorPicker.getValue().getRed() * 255); - int g = (int) (colorPicker.getValue().getGreen() * 255); - int b = (int) (colorPicker.getValue().getBlue() * 255); - if (r == 0 && g == 0 && b == 0 || (changeBrightness && FireflyLuciferin.RUNNING)) { - colorDto.setR(255); - colorDto.setG(255); - colorDto.setB(255); - } else { - colorDto.setR(r); - colorDto.setG(g); - colorDto.setB(b); - } - stateDto.setColor(colorDto); - stateDto.setBrightness(CommonUtility.getNightBrightness()); - stateDto.setWhitetemp((int) (whiteTemp.getValue() / 100)); - if (CommonUtility.getDeviceToUse() != null) { - stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); - } - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + StateDto stateDto = getStateDto(changeBrightness, effectInUse); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } else { SerialManager serialManager = new SerialManager(); serialManager.sendSerialParams((int) (colorPicker.getValue().getRed() * 255), (int) (colorPicker.getValue().getGreen() * 255), (int) (colorPicker.getValue().getBlue() * 255)); } - FireflyLuciferin.config.setWhiteTemperature((int) (whiteTemp.getValue() / 100)); + MainSingleton.getInstance().config.setWhiteTemperature((int) (whiteTemp.getValue() / 100)); } } } } + /** + * Set state dto + * + * @param changeBrightness true or false if a brightness change is needed + * @param effectInUse name of the effect to use + * @return state dto + */ + private StateDto getStateDto(boolean changeBrightness, Enums.Effect effectInUse) { + StateDto stateDto = new StateDto(); + stateDto.setState(Constants.ON); + if (!MainSingleton.getInstance().RUNNING) { + stateDto.setEffect(effectInUse.getBaseI18n()); + } + ColorDto colorDto = getColorDto(changeBrightness); + stateDto.setColor(colorDto); + stateDto.setBrightness(CommonUtility.getNightBrightness()); + stateDto.setWhitetemp((int) (whiteTemp.getValue() / 100)); + if (CommonUtility.getDeviceToUse() != null) { + stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); + } + return stateDto; + } + + /** + * Set color dto + * + * @param changeBrightness true or false if a brightness change is needed + * @return color dto + */ + private ColorDto getColorDto(boolean changeBrightness) { + ColorDto colorDto = new ColorDto(); + int r = (int) (colorPicker.getValue().getRed() * 255); + int g = (int) (colorPicker.getValue().getGreen() * 255); + int b = (int) (colorPicker.getValue().getBlue() * 255); + if (r == 0 && g == 0 && b == 0 || (changeBrightness && MainSingleton.getInstance().RUNNING)) { + colorDto.setR(255); + colorDto.setG(255); + colorDto.setB(255); + } else { + colorDto.setR(r); + colorDto.setG(g); + colorDto.setB(b); + } + return colorDto; + } + /** * Save button event * @@ -654,7 +695,7 @@ public void save(InputEvent e) { public void save(Configuration config) { config.setGamma(Double.parseDouble(gamma.getValue())); config.setColorMode(colorMode.getSelectionModel().getSelectedIndex() + 1); - if (framerate.getValue().length() == 0) { + if (framerate.getValue().isEmpty()) { framerate.setValue(Constants.DEFAULT_FRAMERATE); config.setDesiredFramerate(Constants.DEFAULT_FRAMERATE); } else { @@ -697,7 +738,7 @@ public void save(Configuration config) { public void addProfile(InputEvent e) { profiles.commitValue(); saveUsingProfile(e); - if (FireflyLuciferin.config.isMqttEnable()) { + if (MainSingleton.getInstance().config.isMqttEnable()) { MqttTabController.publishDiscoveryTopic(new SelectProfileDiscovery(), false); MqttTabController.publishDiscoveryTopic(new SelectProfileDiscovery(), true); } @@ -717,10 +758,10 @@ public void removeProfile(InputEvent e) { profiles.commitValue(); StorageManager sm = new StorageManager(); if (sm.deleteProfile(profileName)) { - FireflyLuciferin.guiManager.trayIconManager.updateTray(); + MainSingleton.getInstance().guiManager.trayIconManager.updateTray(); } } - if (FireflyLuciferin.config.isMqttEnable()) { + if (MainSingleton.getInstance().config.isMqttEnable()) { MqttTabController.publishDiscoveryTopic(new SelectProfileDiscovery(), false); MqttTabController.publishDiscoveryTopic(new SelectProfileDiscovery(), true); } @@ -737,7 +778,7 @@ public void applyProfile(InputEvent e) { String profileName = profiles.getValue(); int selectedIndex = profiles.getSelectionModel().getSelectedIndex(); if (selectedIndex >= 0) { - FireflyLuciferin.guiManager.trayIconManager.manageProfileListener(getFormattedProfileName()); + MainSingleton.getInstance().guiManager.trayIconManager.manageProfileListener(getFormattedProfileName()); settingsController.refreshValuesOnScene(); } } @@ -747,8 +788,8 @@ public void applyProfile(InputEvent e) { */ @FXML public void openCCDialog(InputEvent e) { - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.showColorCorrectionDialog(settingsController, e); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.showColorCorrectionDialog(settingsController, e); } } @@ -757,8 +798,8 @@ public void openCCDialog(InputEvent e) { */ @FXML public void openEyeCareDialog() { - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.showEyeCareDialog(settingsController); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.showEyeCareDialog(settingsController); } } @@ -772,20 +813,20 @@ private void saveUsingProfile(InputEvent e) { if (!profileName.isEmpty()) { String fileToWrite = profileName; if (profileName.equals(CommonUtility.getWord(Constants.DEFAULT))) { - switch (JavaFXStarter.whoAmI) { + switch (MainSingleton.getInstance().whoAmI) { case 1 -> fileToWrite = Constants.CONFIG_FILENAME; case 2 -> fileToWrite = Constants.CONFIG_FILENAME_2; case 3 -> fileToWrite = Constants.CONFIG_FILENAME_3; } } else { - fileToWrite = JavaFXStarter.whoAmI + "_" + fileToWrite + Constants.YAML_EXTENSION; + fileToWrite = MainSingleton.getInstance().whoAmI + "_" + fileToWrite + Constants.YAML_EXTENSION; } settingsController.save(e, fileToWrite); profiles.getItems().removeIf(value -> value.equals(profileName)); profiles.getItems().add(profileName); profiles.setValue(profileName); profiles.commitValue(); - FireflyLuciferin.guiManager.trayIconManager.updateTray(); + MainSingleton.getInstance().guiManager.trayIconManager.updateTray(); } } @@ -810,10 +851,10 @@ private String getFormattedProfileName() { * Enable or disable features if a LDR is in use */ public void evaluateLDRConnectedFeatures() { - if (FireflyLuciferin.config.isEnableLDR()) { + if (MainSingleton.getInstance().config.isEnableLDR()) { brightness.setDisable(true); WidgetFactory widgetFactory = new WidgetFactory(); - FireflyLuciferin.config.setNightModeBrightness(Constants.NIGHT_MODE_OFF); + MainSingleton.getInstance().config.setNightModeBrightness(Constants.NIGHT_MODE_OFF); nightModeBrightness.setValueFactory(widgetFactory.spinnerNightModeValueFactory()); nightModeBrightness.setDisable(true); enableDisableNightMode(Constants.NIGHT_MODE_OFF); @@ -862,7 +903,7 @@ void setTooltips(Configuration currentConfig) { * @param newValue combobox new value */ private void forceFramerateValidation(String newValue) { - if (FireflyLuciferin.config != null && !CommonUtility.removeChars(newValue).equals(FireflyLuciferin.config.getDesiredFramerate())) { + if (MainSingleton.getInstance().config != null && !CommonUtility.removeChars(newValue).equals(MainSingleton.getInstance().config.getDesiredFramerate())) { framerate.cancelEdit(); if (LocalizedEnum.fromStr(Enums.Framerate.class, framerate.getValue()) != Enums.Framerate.UNLOCKED) { String val = CommonUtility.removeChars(newValue); @@ -881,14 +922,14 @@ private void forceFramerateValidation(String newValue) { * Manage frame insertion combo */ private void manageFrameInsertionCombo() { - if (FireflyLuciferin.config != null) { + if (MainSingleton.getInstance().config != null) { framerate.setDisable(!LocalizedEnum.fromStr(Enums.FrameInsertion.class, frameInsertion.getValue()).equals(Enums.FrameInsertion.NO_SMOOTHING)); - if (FireflyLuciferin.RUNNING) { + if (MainSingleton.getInstance().RUNNING) { Platform.runLater(() -> { - FireflyLuciferin.guiManager.stopCapturingThreads(FireflyLuciferin.RUNNING); + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); CommonUtility.delaySeconds(() -> { - FireflyLuciferin.config.setFrameInsertion(LocalizedEnum.fromStr(Enums.FrameInsertion.class, frameInsertion.getValue()).getBaseI18n()); - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().config.setFrameInsertion(LocalizedEnum.fromStr(Enums.FrameInsertion.class, frameInsertion.getValue()).getBaseI18n()); + MainSingleton.getInstance().guiManager.startCapturingThreads(); }, 4); }); } diff --git a/src/main/java/org/dpsoftware/gui/controllers/ModeTabController.java b/src/main/java/org/dpsoftware/gui/controllers/ModeTabController.java index 3664a586d..866542cd6 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/ModeTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/ModeTabController.java @@ -22,22 +22,23 @@ package org.dpsoftware.gui.controllers; import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; +import javafx.scene.control.*; import javafx.scene.input.InputEvent; -import org.dpsoftware.FireflyLuciferin; +import javafx.util.StringConverter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; import org.dpsoftware.gui.elements.DisplayInfo; +import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.StorageManager; import org.dpsoftware.utilities.CommonUtility; +import java.util.List; import java.util.Locale; +import java.util.Optional; /** * Mode Tab controller @@ -56,12 +57,16 @@ public class ModeTabController { @FXML public ComboBox captureMethod; @FXML + public ComboBox algo; + @FXML public TextField numberOfThreads; @FXML public Label comWirelessLabel; @FXML public Button saveSettingsButton; @FXML + public Button resetButton; + @FXML public ComboBox monitorNumber; @FXML public ComboBox baudRate; @@ -90,8 +95,8 @@ public void injectSettingsController(SettingsController settingsController) { */ @FXML protected void initialize() { - if (NativeExecutor.isLinux()) { - captureMethod.getItems().addAll(Configuration.CaptureMethod.XIMAGESRC); + for (Enums.Algo al : Enums.Algo.values()) { + algo.getItems().add(al.getI18n()); } for (Enums.AspectRatio ar : Enums.AspectRatio.values()) { aspectRatio.getItems().add(ar.getI18n()); @@ -105,6 +110,32 @@ protected void initialize() { } } + /** + * Handle key valye combo box + */ + public void setCaptureMethodConverter() { + captureMethod.setConverter(new StringConverter<>() { + @Override + public String toString(Configuration.CaptureMethod object) { + return switch (object) { + case CPU -> Configuration.CaptureMethod.CPU.name(); + case WinAPI -> Configuration.CaptureMethod.WinAPI.name(); + case DDUPL -> Configuration.CaptureMethod.DDUPL.name(); + case XIMAGESRC -> Configuration.CaptureMethod.XIMAGESRC.name(); + case XIMAGESRC_NVIDIA -> Configuration.CaptureMethod.XIMAGESRC_NVIDIA.getCaptureMethod(); + case PIPEWIREXDG -> Configuration.CaptureMethod.PIPEWIREXDG.name(); + case PIPEWIREXDG_NVIDIA -> Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA.getCaptureMethod(); + default -> null; + }; + } + + @Override + public Configuration.CaptureMethod fromString(String string) { + return null; + } + }); + } + /** * Init combo boxes */ @@ -131,6 +162,7 @@ void initDefaultValues() { monitorNumber.setValue(settingsController.displayManager.getDisplayName(monitorIndex)); comWirelessLabel.setText(CommonUtility.getWord(Constants.SERIAL_PORT)); theme.setValue(Enums.Theme.DEFAULT.getI18n()); + algo.setValue(Enums.Algo.AVG_COLOR.getI18n()); language.setValue(Enums.Language.EN.getI18n()); for (Enums.Language lang : Enums.Language.values()) { if (lang.name().equalsIgnoreCase(Locale.getDefault().getLanguage())) { @@ -149,9 +181,13 @@ void initDefaultValues() { if (NativeExecutor.isWindows()) { captureMethod.setValue(Configuration.CaptureMethod.DDUPL); } else if (NativeExecutor.isMac()) { - captureMethod.setValue(Configuration.CaptureMethod.DDUPL); + captureMethod.setValue(Configuration.CaptureMethod.AVFVIDEOSRC); } else { - captureMethod.setValue(Configuration.CaptureMethod.XIMAGESRC); + if (NativeExecutor.isWayland()) { + captureMethod.setValue(Configuration.CaptureMethod.PIPEWIREXDG); + } else { + captureMethod.setValue(Configuration.CaptureMethod.XIMAGESRC); + } } } } @@ -177,17 +213,26 @@ private void setDispInfo(DisplayInfo screenInfo) { */ public void initValuesFromSettingsFile(Configuration currentConfig) { if ((currentConfig.getMultiMonitor() == 2 || currentConfig.getMultiMonitor() == 3) - && serialPort.getItems() != null && serialPort.getItems().size() > 0) { + && serialPort.getItems() != null && !serialPort.getItems().isEmpty()) { serialPort.getItems().remove(0); } screenWidth.setText(String.valueOf(currentConfig.getScreenResX())); screenHeight.setText(String.valueOf(currentConfig.getScreenResY())); scaling.setValue(currentConfig.getOsScaling() + Constants.PERCENT); captureMethod.setValue(Configuration.CaptureMethod.valueOf(currentConfig.getCaptureMethod())); - if (currentConfig.isWirelessStream() && currentConfig.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO) && currentConfig.getMultiMonitor() == 1) { - serialPort.setValue(FireflyLuciferin.config.getOutputDevice()); + if (currentConfig.isWirelessStream() && currentConfig.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO) + && ((currentConfig.getMultiMonitor() == 1) || (currentConfig.isMultiScreenSingleDevice()))) { + if (NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp())) { + serialPort.setValue(MainSingleton.getInstance().config.getStaticGlowWormIp()); + } else { + serialPort.setValue(MainSingleton.getInstance().config.getOutputDevice()); + } } else { - serialPort.setValue(currentConfig.getOutputDevice()); + if (NetworkManager.isValidIp(currentConfig.getStaticGlowWormIp())) { + serialPort.setValue(currentConfig.getStaticGlowWormIp()); + } else { + serialPort.setValue(currentConfig.getOutputDevice()); + } } numberOfThreads.setText(String.valueOf(currentConfig.getNumberOfCPUThreads())); if (currentConfig.isAutoDetectBlackBars()) { @@ -195,12 +240,15 @@ public void initValuesFromSettingsFile(Configuration currentConfig) { } else { aspectRatio.setValue(LocalizedEnum.fromBaseStr(Enums.AspectRatio.class, currentConfig.getDefaultLedMatrix()).getI18n()); } + algo.setValue(LocalizedEnum.fromBaseStr(Enums.Algo.class, currentConfig.getAlgo()).getI18n()); monitorIndex = currentConfig.getMonitorNumber(); monitorNumber.setValue(settingsController.displayManager.getDisplayName(monitorIndex)); baudRate.setValue(currentConfig.getBaudRate()); baudRate.setDisable(CommonUtility.isSingleDeviceOtherInstance()); theme.setValue(LocalizedEnum.fromBaseStr(Enums.Theme.class, currentConfig.getTheme()).getI18n()); - language.setValue(LocalizedEnum.fromBaseStr(Enums.Language.class, currentConfig.getLanguage() == null ? FireflyLuciferin.config.getLanguage() : currentConfig.getLanguage()).getI18n()); + language.setValue(LocalizedEnum.fromBaseStr(Enums.Language.class, currentConfig.getLanguage() == null ? MainSingleton.getInstance().config.getLanguage() : currentConfig.getLanguage()).getI18n()); + resetButton.setVisible(Configuration.CaptureMethod.valueOf(currentConfig.getCaptureMethod()).equals(Configuration.CaptureMethod.PIPEWIREXDG) + || Configuration.CaptureMethod.valueOf(currentConfig.getCaptureMethod()).equals(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA)); } /** @@ -217,6 +265,37 @@ public void initListeners() { settingsController.checkProfileDifferences(); } }); + captureMethod.valueProperty().addListener((ov, oldVal, newVal) -> { + if (newVal.equals(Configuration.CaptureMethod.XIMAGESRC_NVIDIA) || newVal.equals(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA)) { + List scrProcess = NativeExecutor.runNative(Constants.CMD_CUDA_CHECK, Constants.CMD_WAIT_DELAY); + boolean pluginsFound = true; + for (String plugin : Constants.CUDA_REQUIRED_PLUGINS) { + if (scrProcess.stream().noneMatch(str -> str.trim().contains(plugin))) { + pluginsFound = false; + } + } + if (!pluginsFound) { + Optional result = MainSingleton.getInstance().guiManager.showAlert(CommonUtility.getWord(Constants.CUDA_ERROR_TITLE), CommonUtility.getWord(Constants.CUDA_ERROR_HEADER), + CommonUtility.getWord(Constants.CUDA_ERROR_CONTEXT), Alert.AlertType.CONFIRMATION); + ButtonType button = result.orElse(ButtonType.OK); + if (button == ButtonType.OK) { + MainSingleton.getInstance().guiManager.surfToURL(Constants.LINUX_WIKI_URL); + } + } + } + }); + } + + /** + * Reset button event + * + * @param e event + */ + @FXML + public void reset(InputEvent e) { + MainSingleton.getInstance().config.setScreenCastRestoreToken(""); + settingsController.save(e); + NativeExecutor.restartNativeInstance(); } /** @@ -236,8 +315,17 @@ public void save(InputEvent e) { */ @FXML public void save(Configuration config) { + if (MainSingleton.getInstance() != null && MainSingleton.getInstance().config != null) { + config.setScreenCastRestoreToken(MainSingleton.getInstance().config.getScreenCastRestoreToken()); + } config.setNumberOfCPUThreads(Integer.parseInt(numberOfThreads.getText())); - config.setOutputDevice(serialPort.getValue()); + if (NetworkManager.isValidIp(serialPort.getValue())) { + config.setOutputDevice(Constants.SERIAL_PORT_AUTO); + config.setStaticGlowWormIp(serialPort.getValue()); + } else { + config.setOutputDevice(serialPort.getValue()); + config.setStaticGlowWormIp(Constants.DASH); + } config.setScreenResX(Integer.parseInt(screenWidth.getText())); config.setScreenResY(Integer.parseInt(screenHeight.getText())); config.setOsScaling(Integer.parseInt((scaling.getValue()).replace(Constants.PERCENT, ""))); @@ -252,6 +340,7 @@ public void save(Configuration config) { || captureMethod.getValue().name().equals(Configuration.CaptureMethod.WinAPI.name())) { config.setGroupBy(Constants.GROUP_BY_LEDS); } + config.setAlgo(LocalizedEnum.fromStr(Enums.Algo.class, algo.getValue()).getBaseI18n()); } /** @@ -268,6 +357,7 @@ public void saveButtonHover() { * @param currentConfig stored config */ void setTooltips(Configuration currentConfig) { + resetButton.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_RESET_WAYLAND)); screenWidth.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SCREENWIDTH)); screenHeight.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SCREENHEIGHT)); scaling.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SCALING)); @@ -296,8 +386,8 @@ void setTooltips(Configuration currentConfig) { * Lock TextField in a numeric state */ void setNumericTextField() { - settingsController.addTextFieldListener(screenWidth); - settingsController.addTextFieldListener(screenHeight); - settingsController.addTextFieldListener(numberOfThreads); + SettingsController.addTextFieldListener(screenWidth); + SettingsController.addTextFieldListener(screenHeight); + SettingsController.addTextFieldListener(numberOfThreads); } } diff --git a/src/main/java/org/dpsoftware/gui/controllers/MqttTabController.java b/src/main/java/org/dpsoftware/gui/controllers/MqttTabController.java index 8230e8cc4..6f9a7713f 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/MqttTabController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/MqttTabController.java @@ -27,7 +27,7 @@ import javafx.scene.control.*; import javafx.scene.input.InputEvent; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; @@ -165,7 +165,7 @@ void initDefaultValues() { public void initValuesFromSettingsFile(Configuration currentConfig) { mqttHost.setText(currentConfig.getMqttServer().substring(0, currentConfig.getMqttServer().lastIndexOf(":"))); mqttPort.setText(currentConfig.getMqttServer().substring(currentConfig.getMqttServer().lastIndexOf(":") + 1)); - mqttTopic.setText(currentConfig.getMqttTopic().equals(Constants.DEFAULT_MQTT_TOPIC) ? Constants.MQTT_BASE_TOPIC : currentConfig.getMqttTopic()); + mqttTopic.setText(currentConfig.getMqttTopic().equals(Constants.TOPIC_DEFAULT_MQTT) ? Constants.MQTT_BASE_TOPIC : currentConfig.getMqttTopic()); mqttDiscoveryTopic.setText(currentConfig.getMqttDiscoveryTopic()); mqttUser.setText(currentConfig.getMqttUsername()); mqttPwd.setText(currentConfig.getMqttPwd()); @@ -219,6 +219,7 @@ public void initListeners() { mqttStream.setDisable(false); streamType.setDisable(false); } + settingsController.evaluateSatBtn(wifiEnable.isSelected()); settingsController.initOutputDeviceChooser(false); }); mqttStream.setOnAction(e -> { @@ -246,7 +247,7 @@ public void initListeners() { mqttUser.setDisable(false); mqttPwd.setDisable(false); } - if (FireflyLuciferin.config == null) { + if (MainSingleton.getInstance().config == null) { addButton.setDisable(true); removeButton.setDisable(true); } @@ -313,10 +314,10 @@ public void discoveryAdd() { log.info("Sending entities for MQTT auto discovery..."); publishDiscoveryTopics(true); if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.MQTT_DISCOVERY, + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.MQTT_DISCOVERY, Constants.MQTT_ADD_DEVICE, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.MQTT_DISCOVERY, Constants.MQTT_DISCOVERY, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.MQTT_DISCOVERY, Constants.MQTT_DISCOVERY, Constants.MQTT_ADD_DEVICE, Alert.AlertType.INFORMATION); } } @@ -329,10 +330,10 @@ public void discoveryRemove() { log.info("Removing entities using MQTT auto discovery..."); publishDiscoveryTopics(false); if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.MQTT_DISCOVERY, + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.MQTT_DISCOVERY, Constants.MQTT_REMOVE_DEVICE, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.MQTT_DISCOVERY, Constants.MQTT_DISCOVERY, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.MQTT_DISCOVERY, Constants.MQTT_DISCOVERY, Constants.MQTT_REMOVE_DEVICE, Alert.AlertType.INFORMATION); } } @@ -364,6 +365,6 @@ void setTooltips(Configuration currentConfig) { * Lock TextField in a numeric state */ void setNumericTextField() { - settingsController.addTextFieldListener(mqttPort); + SettingsController.addTextFieldListener(mqttPort); } } diff --git a/src/main/java/org/dpsoftware/gui/controllers/SatellitesDialogController.java b/src/main/java/org/dpsoftware/gui/controllers/SatellitesDialogController.java new file mode 100644 index 000000000..a1e4fda85 --- /dev/null +++ b/src/main/java/org/dpsoftware/gui/controllers/SatellitesDialogController.java @@ -0,0 +1,369 @@ +/* + SatellitesDialogController.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.gui.controllers; + +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.control.*; +import javafx.scene.input.InputEvent; +import javafx.util.Callback; +import lombok.extern.slf4j.Slf4j; +import org.dpsoftware.MainSingleton; +import org.dpsoftware.NativeExecutor; +import org.dpsoftware.config.Configuration; +import org.dpsoftware.config.Constants; +import org.dpsoftware.config.Enums; +import org.dpsoftware.config.LocalizedEnum; +import org.dpsoftware.gui.GuiSingleton; +import org.dpsoftware.gui.elements.GlowWormDevice; +import org.dpsoftware.gui.elements.Satellite; +import org.dpsoftware.managers.NetworkManager; +import org.dpsoftware.utilities.CommonUtility; + +import java.awt.*; +import java.util.Map; +import java.util.Objects; + +/** + * Satellite manager dialog controller + */ +@Slf4j +public class SatellitesDialogController { + + @FXML + public Button okButton; + @FXML + public Button applyButton; + @FXML + public Button cancelButton; + @FXML + public Button addButton; + @FXML + public ComboBox zone; + @FXML + public ComboBox orientation; + @FXML + public TextField ledNum; + @FXML + public ComboBox deviceIp; + @FXML + public ComboBox algo; + boolean changeInternally; + @FXML + private TableView satelliteTable; + @FXML + private TableColumn zoneColumn; + @FXML + private TableColumn orientationColumn; + @FXML + private TableColumn ledNumColumn; + @FXML + private TableColumn deviceIpColumn; + @FXML + private TableColumn algoColumn; + // Inject main controller + @FXML + private SettingsController settingsController; + + /** + * Add remove button from table view + * + * @return button + */ + private TableColumn getSatelliteVoidTableColumn() { + TableColumn colBtn = new TableColumn<>(""); + colBtn.setMaxWidth(Constants.REMOVE_BTN_TABLE); + Callback, TableCell> cellFactory = new Callback<>() { + @Override + public TableCell call(final TableColumn param) { + return new TableCell<>() { + private final Button btn = new Button(Constants.UNICODE_X); + + { + btn.setOnAction((ActionEvent event) -> { + Satellite data = getTableView().getItems().get(getIndex()); + populateFields(data); + GuiSingleton.getInstance().satellitesTableData.remove(data); + satelliteTable.refresh(); + }); + } + + @Override + public void updateItem(Void item, boolean empty) { + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + setGraphic(btn); + } + } + }; + } + }; + colBtn.setCellFactory(cellFactory); + return colBtn; + } + + /** + * Populate fields for editing once removing a satellite + * + * @param sat satellite + */ + private void populateFields(Satellite sat) { + deviceIp.getItems().add("IP (" + sat.getDeviceIp() + ")"); + deviceIp.setValue(sat.getDeviceIp()); + algo.setValue(sat.getAlgo()); + ledNum.setText(sat.getLedNum()); + zone.setValue(sat.getZone()); + orientation.setValue(sat.getOrientation()); + } + + /** + * Inject main controller containing the TabPane + * + * @param settingsController TabPane controller + */ + public void injectSettingsController(SettingsController settingsController) { + this.settingsController = settingsController; + } + + /** + * Initialize controller with system's specs + */ + @FXML + protected void initialize() { + setNumericTextField(); + deviceIp.valueProperty().addListener((ov, t, t1) -> Platform.runLater(() -> { + try { + String str = ov.getValue().substring(ov.getValue().indexOf("(") + 1, ov.getValue().indexOf(")")); + deviceIp.setValue(str); + } catch (StringIndexOutOfBoundsException e) { + deviceIp.setValue(ov.getValue()); + } + })); + initCombos(); + zone.setValue(Enums.SatelliteZone.TOP.getI18n()); + orientation.setValue(Enums.Direction.NORMAL.getI18n()); + algo.setValue(Enums.Algo.AVG_COLOR.getI18n()); + ledNum.setText("1"); + Platform.runLater(() -> { + for (GlowWormDevice gwd : GuiSingleton.getInstance().deviceTableData) { + if (!gwd.getDeviceIP().equals(MainSingleton.getInstance().config.getStaticGlowWormIp()) + && !gwd.getDeviceName().equals(MainSingleton.getInstance().config.getOutputDevice()) + && MainSingleton.getInstance().config.getSatellites().values().stream().noneMatch(s -> s.getDeviceIp().equals(gwd.getDeviceIP()))) { + deviceIp.getItems().add(gwd.getDeviceName() + " (" + gwd.getDeviceIP() + ")"); + } + } + initTable(); + deviceIp.requestFocus(); + }); + } + + /** + * Init satellite table + */ + private void initTable() { + TableColumn colBtn = getSatelliteVoidTableColumn(); + satelliteTable.getColumns().add(0, colBtn); + zoneColumn.setCellValueFactory(cellData -> cellData.getValue().zoneProperty()); + orientationColumn.setCellValueFactory(cellData -> cellData.getValue().orientationProperty()); + ledNumColumn.setCellValueFactory(cellData -> cellData.getValue().ledNumProperty()); + deviceIpColumn.setCellFactory(e -> new TableCell<>() { + @Override + protected void updateItem(Hyperlink item, boolean empty) { + super.updateItem(item, empty); + final Hyperlink link; + if (!empty) { + Satellite glowWormDevice = getTableRow().getItem(); + if (glowWormDevice != null) { + link = new Hyperlink(item != null ? item.getText() : glowWormDevice.getDeviceIp()); + link.setOnAction(evt -> MainSingleton.getInstance().guiManager.surfToURL(Constants.HTTP + getTableRow().getItem().getDeviceIp())); + setGraphic(link); + } + } + } + }); + algoColumn.setCellValueFactory(cellData -> cellData.getValue().algoProperty()); + satelliteTable.setItems(getSatellitesTableData()); + GuiSingleton.getInstance().satellitesTableData.clear(); + for (Map.Entry storedSat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + Satellite sat = new Satellite(); + sat.setZone(LocalizedEnum.fromBaseStr(Enums.SatelliteZone.class, storedSat.getValue().getZone()).getI18n()); + sat.setOrientation(LocalizedEnum.fromBaseStr(Enums.Direction.class, storedSat.getValue().getOrientation()).getI18n()); + sat.setAlgo(LocalizedEnum.fromBaseStr(Enums.Algo.class, storedSat.getValue().getAlgo()).getI18n()); + sat.setLedNum(storedSat.getValue().getLedNum()); + sat.setDeviceIp(storedSat.getValue().getDeviceIp()); + GuiSingleton.getInstance().satellitesTableData.add(sat); + } + satelliteTable.refresh(); + } + + /** + * Init combos + */ + private void initCombos() { + for (Enums.Direction or : Enums.Direction.values()) { + orientation.getItems().add(or.getI18n()); + } + for (Enums.Algo al : Enums.Algo.values()) { + algo.getItems().add(al.getI18n()); + } + for (Enums.SatelliteZone zo : Enums.SatelliteZone.values()) { + if (CommonUtility.isSplitBottomRow(MainSingleton.getInstance().config.getSplitBottomMargin())) { + if (!zo.getBaseI18n().equals(Enums.SatelliteZone.BOTTOM.getBaseI18n())) { + zone.getItems().add(zo.getI18n()); + } + } else { + zone.getItems().add(zo.getI18n()); + } + } + } + + /** + * Return the observable satellites list + * + * @return satellites list + */ + public ObservableList getSatellitesTableData() { + return GuiSingleton.getInstance().satellitesTableData; + } + + /** + * Set tooltips + */ + public void setTooltips() { + deviceIp.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_IP)); + zone.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_ZONE)); + orientation.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_ORIENT)); + ledNum.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_NUM)); + algo.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_ALGO)); + addButton.setTooltip(settingsController.createTooltip(Constants.TOOLTIP_SAT_ADD)); + } + + /** + * Close dialog + * + * @param e event + */ + @FXML + public void close(InputEvent e) { + CommonUtility.closeCurrentStage(e); + } + + /** + * Save button from main controller + * + * @param config stored config + */ + @FXML + @SuppressWarnings("Duplicates") + public void save(Configuration config) { + if (changeInternally) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); + CommonUtility.delaySeconds(() -> MainSingleton.getInstance().guiManager.startCapturingThreads(), 4); + config.getSatellites().clear(); + for (Satellite sat : GuiSingleton.getInstance().satellitesTableData) { + Satellite updatedSat = new Satellite(); + updatedSat.setLedNum(sat.getLedNum()); + updatedSat.setDeviceIp(sat.getDeviceIp()); + updatedSat.setZone(LocalizedEnum.fromStr(Enums.SatelliteZone.class, sat.getZone()).getBaseI18n()); + updatedSat.setOrientation(LocalizedEnum.fromStr(Enums.Direction.class, sat.getOrientation()).getBaseI18n()); + updatedSat.setAlgo(LocalizedEnum.fromStr(Enums.Algo.class, sat.getAlgo()).getBaseI18n()); + String deviceName = Objects.requireNonNull(GuiSingleton.getInstance().deviceTableData.stream() + .filter(s -> s.getDeviceIP().equals(sat.getDeviceIp())) + .findFirst() + .orElse(null)).getDeviceName(); + updatedSat.setDeviceName(deviceName); + config.getSatellites().put(updatedSat.getDeviceIp(), updatedSat); + } + MainSingleton.getInstance().config.getSatellites().clear(); + MainSingleton.getInstance().config.getSatellites().putAll(config.getSatellites()); + } else { + config.getSatellites().clear(); + config.getSatellites().putAll(MainSingleton.getInstance().config.getSatellites()); + } + } + + /** + * Save button from main controller + * + * @param e event + */ + @FXML + @SuppressWarnings("Duplicates") + public void save(InputEvent e) { + changeInternally = true; + settingsController.injectSatellitesController(this); + settingsController.save(e); + changeInternally = false; + } + + /** + * Save and close dialog + * + * @param e event + */ + @FXML + public void saveAndClose(InputEvent e) { + changeInternally = true; + settingsController.injectSatellitesController(this); + settingsController.save(e); + CommonUtility.closeCurrentStage(e); + changeInternally = false; + } + + /** + * Save button from main controller + */ + @FXML + public void addSatellite() { + if (Integer.parseInt(ledNum.getText()) <= 0) { + ledNum.setText("1"); + } + if (NetworkManager.isValidIp(deviceIp.getValue())) { + deviceIp.getItems().removeIf(s -> s.contains("(" + deviceIp.getValue() + ")")); + GuiSingleton.getInstance().satellitesTableData.removeIf(producer -> producer.getDeviceIp().equals(deviceIp.getValue())); + GuiSingleton.getInstance().satellitesTableData.add(new Satellite(zone.getValue(), orientation.getValue(), + ledNum.getText(), deviceIp.getValue(), "", algo.getValue())); + } else { + if (NativeExecutor.isWindows()) { + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.SAT_ALERT_IP_HEADER, + Constants.SAT_ALERT_IP_CONTENT, TrayIcon.MessageType.ERROR); + } else { + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.SAT_ALERT_IP_TITLE, Constants.SAT_ALERT_IP_HEADER, + Constants.SAT_ALERT_IP_CONTENT, Alert.AlertType.ERROR); + } + } + } + + /** + * Lock TextField in a numeric state + */ + void setNumericTextField() { + SettingsController.addTextFieldListener(ledNum); + } + +} diff --git a/src/main/java/org/dpsoftware/gui/controllers/SettingsController.java b/src/main/java/org/dpsoftware/gui/controllers/SettingsController.java index 4baf8038d..73897cbb5 100644 --- a/src/main/java/org/dpsoftware/gui/controllers/SettingsController.java +++ b/src/main/java/org/dpsoftware/gui/controllers/SettingsController.java @@ -24,6 +24,8 @@ import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.control.*; import javafx.scene.input.InputEvent; @@ -33,13 +35,15 @@ import javafx.util.Duration; import lombok.extern.slf4j.Slf4j; import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; +import org.dpsoftware.gui.GuiManager; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.DisplayInfo; import org.dpsoftware.managers.DisplayManager; import org.dpsoftware.managers.NetworkManager; @@ -69,6 +73,8 @@ public class SettingsController { public MiscTabController miscTabController; // FXML binding @FXML + public AnchorPane shadowPane; + @FXML public TabPane mainTabPane; @FXML public AnchorPane ledsConfigTab; @@ -82,6 +88,10 @@ public class SettingsController { public AnchorPane miscTab; @FXML public AnchorPane devicesTab; + @FXML + public Button closeWindowBtn; + @FXML + public Button minimizeWindowBtn; Configuration currentConfig; StorageManager sm; DisplayManager displayManager; @@ -100,6 +110,23 @@ public class SettingsController { private ColorCorrectionDialogController colorCorrectionDialogController; @FXML private EyeCareDialogController eyeCareDialogController; + @FXML + private SatellitesDialogController satellitesDialogController; + + /** + * Force TextField to be numeric + * + * @param textField numeric fields + */ + public static void addTextFieldListener(TextField textField) { + textField.textProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.isEmpty()) { + textField.setText("0"); + } else { + textField.setText(CommonUtility.removeChars(newValue)); + } + }); + } /** * Initialize controller with system's specs @@ -113,7 +140,6 @@ protected void initialize() { miscTabController.injectSettingsController(this); ledsConfigTabController.injectSettingsController(this); controlTabController.injectSettingsController(this); - Platform.setImplicitExit(false); sm = new StorageManager(); displayManager = new DisplayManager(); @@ -131,13 +157,12 @@ protected void initialize() { } currentConfig = sm.readProfileInUseConfig(); ledsConfigTabController.showTestImageButton.setVisible(currentConfig != null); - initComboBox(); if (NativeExecutor.isWindows()) { mainTabPane.getTabs().remove(0); } if (currentConfig != null && CommonUtility.isSingleDeviceMultiScreen()) { - if (JavaFXStarter.whoAmI > 1) { + if (MainSingleton.getInstance().whoAmI > 1) { if (NativeExecutor.isLinux()) { mainTabPane.getTabs().remove(3, 6); } else if (NativeExecutor.isWindows()) { @@ -154,6 +179,10 @@ protected void initialize() { runLater(); initListeners(); controlTabController.startAnimationTimer(); + Label titleBarLabel = (Label) shadowPane.lookup(Constants.TITLE_BAR_SELECTOR); + if (titleBarLabel != null) { + titleBarLabel.setText(GuiManager.createWindowTitle().trim()); + } } /** @@ -231,7 +260,7 @@ private void initListeners() { devicesTabController.multiMonitor.valueProperty().addListener((ov, t, value) -> { if (!modeTabController.serialPort.isFocused()) { if (!value.equals(Constants.MULTIMONITOR_1)) { - if (modeTabController.serialPort.getItems().size() > 0 && modeTabController.serialPort.getItems().get(0).equals(Constants.SERIAL_PORT_AUTO)) { + if (!modeTabController.serialPort.getItems().isEmpty() && modeTabController.serialPort.getItems().get(0).equals(Constants.SERIAL_PORT_AUTO)) { modeTabController.serialPort.getItems().remove(0); if (NativeExecutor.isWindows()) { modeTabController.serialPort.setValue(Constants.SERIAL_PORT_COM + 1); @@ -326,33 +355,18 @@ public void save(InputEvent e, String profileName) { LinkedHashMap fitToScreenMatrix = ledCoordinate.initPillarboxMatrix(ledMatrixInfoPillarbox); Map hueMap = ColorCorrectionDialogController.initHSLMap(); Configuration config = new Configuration(ledFullScreenMatrix, ledLetterboxMatrix, fitToScreenMatrix, hueMap); - if (FireflyLuciferin.config != null) { - config.setRuntimeLogLevel(FireflyLuciferin.config.getRuntimeLogLevel()); + if (MainSingleton.getInstance().config != null) { + config.setRuntimeLogLevel(MainSingleton.getInstance().config.getRuntimeLogLevel()); } ledsConfigTabController.save(config); modeTabController.save(config); miscTabController.save(config); mqttTabController.save(config); devicesTabController.save(config); - if (colorCorrectionDialogController != null) { - colorCorrectionDialogController.save(config); - } else if (FireflyLuciferin.config != null) { - config.setHueMap(FireflyLuciferin.config.getHueMap()); - } - if (eyeCareDialogController != null) { - eyeCareDialogController.save(config); - } else { - if (FireflyLuciferin.config != null) { - config.setEnableLDR(FireflyLuciferin.config.isEnableLDR()); - config.setLdrTurnOff(FireflyLuciferin.config.isLdrTurnOff()); - config.setLdrInterval(FireflyLuciferin.config.getLdrInterval()); - config.setLdrMin(FireflyLuciferin.config.getLdrMin()); - config.setBrightnessLimiter(FireflyLuciferin.config.getBrightnessLimiter()); - } - } + saveDialogues(config); setCaptureMethod(config); - config.setConfigVersion(FireflyLuciferin.version); - boolean firstStartup = FireflyLuciferin.config == null; + config.setConfigVersion(MainSingleton.getInstance().version); + boolean firstStartup = MainSingleton.getInstance().config == null; if (config.isFullFirmware() && !config.isMqttEnable() && firstStartup) { config.setOutputDevice(Constants.SERIAL_PORT_AUTO); } @@ -373,6 +387,37 @@ public void save(InputEvent e, String profileName) { } } + /** + * Save settings from sub dialogues + * + * @param config from file + */ + private void saveDialogues(Configuration config) { + if (colorCorrectionDialogController != null) { + colorCorrectionDialogController.save(config); + } else if (MainSingleton.getInstance().config != null) { + config.setHueMap(MainSingleton.getInstance().config.getHueMap()); + } + if (eyeCareDialogController != null) { + eyeCareDialogController.save(config); + } else { + if (MainSingleton.getInstance().config != null) { + config.setEnableLDR(MainSingleton.getInstance().config.isEnableLDR()); + config.setLdrTurnOff(MainSingleton.getInstance().config.isLdrTurnOff()); + config.setLdrInterval(MainSingleton.getInstance().config.getLdrInterval()); + config.setLdrMin(MainSingleton.getInstance().config.getLdrMin()); + config.setBrightnessLimiter(MainSingleton.getInstance().config.getBrightnessLimiter()); + } + } + if (satellitesDialogController != null) { + satellitesDialogController.save(config); + } else { + if (MainSingleton.getInstance().config != null) { + config.setSatellites(MainSingleton.getInstance().config.getSatellites()); + } + } + } + /** * Write default config * @@ -384,7 +429,7 @@ public void save(InputEvent e, String profileName) { */ private void writeDefaultConfig(InputEvent e, Configuration config, boolean firstStartup) throws IOException, CloneNotSupportedException { // Manage settings from one instance to the other, for multi monitor setup - if (JavaFXStarter.whoAmI != 1) { + if (MainSingleton.getInstance().whoAmI != 1) { Configuration mainConfig = sm.readMainConfig(); mainConfig.setGamma(config.getGamma()); mainConfig.setWhiteTemperature(config.getWhiteTemperature()); @@ -394,7 +439,7 @@ private void writeDefaultConfig(InputEvent e, Configuration config, boolean firs sm.writeConfig(mainConfig, Constants.CONFIG_FILENAME); } if (config.getMultiMonitor() > 1) { - switch (JavaFXStarter.whoAmI) { + switch (MainSingleton.getInstance().whoAmI) { case 1 -> { writeOtherConfig(config, Constants.CONFIG_FILENAME_2); if (config.getMultiMonitor() == 3) writeOtherConfig(config, Constants.CONFIG_FILENAME_3); @@ -407,9 +452,9 @@ private void writeDefaultConfig(InputEvent e, Configuration config, boolean firs } Configuration defaultConfig = sm.readProfileInUseConfig(); sm.writeConfig(config, null); - FireflyLuciferin.config = config; - sm.checkProfileDifferences(defaultConfig, FireflyLuciferin.config); - if (firstStartup || (JavaFXStarter.whoAmI == 1 && ((config.getMultiMonitor() == 2 && !sm.checkIfFileExist(Constants.CONFIG_FILENAME_2)) + MainSingleton.getInstance().config = config; + sm.checkProfileDifferences(defaultConfig, MainSingleton.getInstance().config); + if (firstStartup || (MainSingleton.getInstance().whoAmI == 1 && ((config.getMultiMonitor() == 2 && !sm.checkIfFileExist(Constants.CONFIG_FILENAME_2)) || (config.getMultiMonitor() == 3 && (!sm.checkIfFileExist(Constants.CONFIG_FILENAME_2) || !sm.checkIfFileExist(Constants.CONFIG_FILENAME_3)))))) { writeOtherConfigNew(config); cancel(e); @@ -443,16 +488,16 @@ public boolean isMqttParamChanged() { * Refresh all the values displayed on the scene after save or profiles switch */ public void refreshValuesOnScene() { - mqttTabController.initValuesFromSettingsFile(FireflyLuciferin.config); - devicesTabController.initValuesFromSettingsFile(FireflyLuciferin.config); - miscTabController.initValuesFromSettingsFile(FireflyLuciferin.config, false); - ledsConfigTabController.initValuesFromSettingsFile(FireflyLuciferin.config); + mqttTabController.initValuesFromSettingsFile(MainSingleton.getInstance().config); + devicesTabController.initValuesFromSettingsFile(MainSingleton.getInstance().config); + miscTabController.initValuesFromSettingsFile(MainSingleton.getInstance().config, false); + ledsConfigTabController.initValuesFromSettingsFile(MainSingleton.getInstance().config); controlTabController.initValuesFromSettingsFile(); - modeTabController.initValuesFromSettingsFile(FireflyLuciferin.config); - ledsConfigTabController.splitBottomMargin.setValue(FireflyLuciferin.config.getSplitBottomMargin()); + modeTabController.initValuesFromSettingsFile(MainSingleton.getInstance().config); + ledsConfigTabController.splitBottomMargin.setValue(MainSingleton.getInstance().config.getSplitBottomMargin()); ledsConfigTabController.splitBottomRow(); miscTabController.setContextMenu(); - FireflyLuciferin.setLedNumber(FireflyLuciferin.config.getDefaultLedMatrix()); + FireflyLuciferin.setLedNumber(MainSingleton.getInstance().config.getDefaultLedMatrix()); } /** @@ -481,6 +526,12 @@ void setCaptureMethod(Configuration config) { } else { if (modeTabController.captureMethod.getValue() == Configuration.CaptureMethod.XIMAGESRC) { config.setCaptureMethod(Configuration.CaptureMethod.XIMAGESRC.name()); + } else if (modeTabController.captureMethod.getValue() == Configuration.CaptureMethod.XIMAGESRC_NVIDIA) { + config.setCaptureMethod(Configuration.CaptureMethod.XIMAGESRC_NVIDIA.name()); + } else if (modeTabController.captureMethod.getValue() == Configuration.CaptureMethod.PIPEWIREXDG) { + config.setCaptureMethod(Configuration.CaptureMethod.PIPEWIREXDG.name()); + } else if (modeTabController.captureMethod.getValue() == Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA) { + config.setCaptureMethod(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA.name()); } } } @@ -497,11 +548,11 @@ void setCaptureMethod(Configuration config) { void programFirmware(Configuration config, InputEvent e, String oldBaudrate, boolean isBaudRateChanged, boolean isMqttParamChanged) throws IOException { AtomicReference macToProgram = new AtomicReference<>(""); if (currentConfig.isFullFirmware()) { - if (DevicesTabController.deviceTableData != null && DevicesTabController.deviceTableData.size() > 0) { + if (GuiSingleton.getInstance().deviceTableData != null && !GuiSingleton.getInstance().deviceTableData.isEmpty()) { if (Constants.SERIAL_PORT_AUTO.equals(modeTabController.serialPort.getValue())) { - macToProgram.set(DevicesTabController.deviceTableData.get(0).getMac()); + macToProgram.set(GuiSingleton.getInstance().deviceTableData.get(0).getMac()); } - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (glowWormDevice.getDeviceName().equals(modeTabController.serialPort.getValue()) || glowWormDevice.getDeviceIP().equals(modeTabController.serialPort.getValue())) { macToProgram.set(glowWormDevice.getMac()); } @@ -512,14 +563,14 @@ void programFirmware(Configuration config, InputEvent e, String oldBaudrate, boo } } if (isBaudRateChanged) { - Optional result = FireflyLuciferin.guiManager.showLocalizedAlert(Constants.BAUDRATE_TITLE, Constants.BAUDRATE_HEADER, + Optional result = MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.BAUDRATE_TITLE, Constants.BAUDRATE_HEADER, Constants.BAUDRATE_CONTEXT, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); if (button == ButtonType.OK) { if (currentConfig.isFullFirmware()) { setFirmwareConfig(macToProgram.get(), true); } else { - FireflyLuciferin.baudRate = Enums.BaudRate.valueOf(Constants.BAUD_RATE_PLACEHOLDER + modeTabController.baudRate.getValue()).getBaudRateValue(); + MainSingleton.getInstance().baudRate = Enums.BaudRate.valueOf(Constants.BAUD_RATE_PLACEHOLDER + modeTabController.baudRate.getValue()).getBaudRateValue(); SerialManager serialManager = new SerialManager(); serialManager.sendSerialParams((int) (miscTabController.colorPicker.getValue().getRed() * 255), (int) (miscTabController.colorPicker.getValue().getGreen() * 255), @@ -544,7 +595,7 @@ void programFirmware(Configuration config, InputEvent e, String oldBaudrate, boo */ public void setFirmwareConfig(String macToProgram, boolean changeBaudrate) { if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getDeviceName() != null - && (CommonUtility.getDeviceToUse().getDeviceName().equals(FireflyLuciferin.config.getOutputDevice()) + && (CommonUtility.getDeviceToUse().getDeviceName().equals(MainSingleton.getInstance().config.getOutputDevice()) || CommonUtility.getDeviceToUse().getMac().equals(macToProgram))) { var device = CommonUtility.getDeviceToUse(); FirmwareConfigDto firmwareConfigDto = new FirmwareConfigDto(); @@ -570,7 +621,7 @@ public void setFirmwareConfig(String macToProgram, boolean changeBaudrate) { if (tcpResponse.getErrorCode() == Constants.HTTP_SUCCESS) { log.info(CommonUtility.getWord(Constants.FIRMWARE_PROGRAM_NOTIFY_HEADER)); if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(CommonUtility.getWord(Constants.FIRMWARE_PROGRAM_NOTIFY), + MainSingleton.getInstance().guiManager.showLocalizedNotification(CommonUtility.getWord(Constants.FIRMWARE_PROGRAM_NOTIFY), CommonUtility.getWord(Constants.FIRMWARE_PROGRAM_NOTIFY_HEADER), TrayIcon.MessageType.INFO); } } @@ -636,6 +687,7 @@ private void setConfig(Configuration config, Configuration otherConfig) { } if (config.isMultiScreenSingleDevice() && config.getMultiMonitor() > 1) { otherConfig.setOutputDevice(config.getOutputDevice()); + otherConfig.setStaticGlowWormIp(config.getStaticGlowWormIp()); otherConfig.setBaudRate(config.getBaudRate()); otherConfig.setMqttServer(config.getMqttServer()); otherConfig.setMqttTopic(config.getMqttTopic()); @@ -707,8 +759,12 @@ public void initOutputDeviceChooser(boolean initCaptureMethod) { modeTabController.captureMethod.getItems().addAll(Configuration.CaptureMethod.DDUPL, Configuration.CaptureMethod.WinAPI, Configuration.CaptureMethod.CPU); } else if (NativeExecutor.isMac()) { modeTabController.captureMethod.getItems().addAll(Configuration.CaptureMethod.AVFVIDEOSRC); + } else { + modeTabController.captureMethod.getItems().addAll(Configuration.CaptureMethod.XIMAGESRC, Configuration.CaptureMethod.XIMAGESRC_NVIDIA, + Configuration.CaptureMethod.PIPEWIREXDG, Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA); } } + modeTabController.setCaptureMethodConverter(); if (NativeExecutor.isWindows()) { SerialManager serialManager = new SerialManager(); Map availableDevices = serialManager.getAvailableDevices(); @@ -724,12 +780,21 @@ public void initOutputDeviceChooser(boolean initCaptureMethod) { if (!modeTabController.serialPort.isFocused()) { String deviceInUse = modeTabController.serialPort.getValue(); modeTabController.serialPort.getItems().clear(); - DevicesTabController.deviceTableData.forEach(glowWormDevice -> modeTabController.serialPort.getItems().add(glowWormDevice.getDeviceName())); + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> modeTabController.serialPort.getItems().add(glowWormDevice.getDeviceName())); modeTabController.serialPort.setValue(deviceInUse); } } } + /** + * Method used to enable disable sat button + * + * @param isFullFirmware true if full firmware + */ + public void evaluateSatBtn(boolean isFullFirmware) { + devicesTabController.evaluateSatelliteBtn(isFullFirmware); + } + /** * Save and Exit button event * @@ -754,21 +819,6 @@ public void cancel(InputEvent event) { } } - /** - * Force TextField to be numeric - * - * @param textField numeric fields - */ - void addTextFieldListener(TextField textField) { - textField.textProperty().addListener((observable, oldValue, newValue) -> { - if (newValue.length() == 0) { - textField.setText("0"); - } else { - textField.setText(CommonUtility.removeChars(newValue)); - } - }); - } - /** * Set form tooltips */ @@ -977,4 +1027,30 @@ public void injectEyeCareController(EyeCareDialogController eyeCareDialogControl this.eyeCareDialogController = eyeCareDialogController; } + /** + * Inject satellites dialogue controller into the main controller + * + * @param satellitesDialogController dialog controller + */ + public void injectSatellitesController(SatellitesDialogController satellitesDialogController) { + this.satellitesDialogController = satellitesDialogController; + } + + /** + * Minimize window + */ + @FXML + public void minimizeWindow() { + Stage obj = (Stage) closeWindowBtn.getScene().getWindow(); + obj.setIconified(true); + } + + /** + * Close window + */ + @FXML + public void closeWindow(InputEvent e) { + CommonUtility.closeCurrentStage(e); + } + } diff --git a/src/main/java/org/dpsoftware/gui/elements/GlowWormDevice.java b/src/main/java/org/dpsoftware/gui/elements/GlowWormDevice.java index 4e35f25ec..39fe70d4d 100644 --- a/src/main/java/org/dpsoftware/gui/elements/GlowWormDevice.java +++ b/src/main/java/org/dpsoftware/gui/elements/GlowWormDevice.java @@ -24,6 +24,7 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.scene.control.Hyperlink; +import lombok.Getter; /** * A class that map a device running Glow Worm Luciferin firmware @@ -50,6 +51,7 @@ public class GlowWormDevice { private final SimpleStringProperty relayPin = new SimpleStringProperty(""); private final SimpleStringProperty sbPin = new SimpleStringProperty(""); private final SimpleStringProperty gpioClock = new SimpleStringProperty(""); + @Getter private boolean dhcpInUse; public GlowWormDevice() { @@ -107,10 +109,6 @@ public String deviceIPProperty() { return deviceIP.getText(); } - public boolean isDhcpInUse() { - return dhcpInUse; - } - public void setDhcpInUse(boolean dhcp) { dhcpInUse = dhcp; } diff --git a/src/main/java/org/dpsoftware/gui/elements/Satellite.java b/src/main/java/org/dpsoftware/gui/elements/Satellite.java new file mode 100644 index 000000000..e3d091e3a --- /dev/null +++ b/src/main/java/org/dpsoftware/gui/elements/Satellite.java @@ -0,0 +1,125 @@ +/* + Satellite.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.gui.elements; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +/** + * A class that map a Glow Worm satellite + */ +@SuppressWarnings("unused") +public class Satellite { + + private final SimpleStringProperty zone = new SimpleStringProperty(""); + private final SimpleStringProperty orientation = new SimpleStringProperty(""); + private final SimpleStringProperty ledNum = new SimpleStringProperty(""); + private final SimpleStringProperty deviceIp = new SimpleStringProperty(""); + private final SimpleStringProperty deviceName = new SimpleStringProperty(""); + private final SimpleStringProperty algo = new SimpleStringProperty(""); + + public Satellite() { + this("", "", "", "", "", ""); + } + + public Satellite(String zone, String orientation, String ledNum, String deviceIp, String deviceName, String algo) { + setZone(zone); + setOrientation(orientation); + setLedNum(ledNum); + setDeviceIp(deviceIp); + setDeviceName(deviceName); + setAlgo(algo); + } + + public String getZone() { + return zone.get(); + } + + public void setZone(String zoneStr) { + zone.set(zoneStr); + } + + public StringProperty zoneProperty() { + return zone; + } + + public String getOrientation() { + return orientation.get(); + } + + public void setOrientation(String orientationStr) { + orientation.set(orientationStr); + } + + public StringProperty orientationProperty() { + return orientation; + } + + public String getLedNum() { + return ledNum.get(); + } + + public void setLedNum(String ledNumStr) { + ledNum.set(ledNumStr); + } + + public StringProperty ledNumProperty() { + return ledNum; + } + + public String getDeviceName() { + return deviceName.get(); + } + + public void setDeviceName(String deviceNameStr) { + deviceName.set(deviceNameStr); + } + + public StringProperty deviceNameProperty() { + return deviceName; + } + + public String getDeviceIp() { + return deviceIp.get(); + } + + public void setDeviceIp(String deviceIpStr) { + deviceIp.set(deviceIpStr); + } + + public StringProperty deviceIpProperty() { + return deviceIp; + } + + public String getAlgo() { + return algo.get(); + } + + public void setAlgo(String algoStr) { + algo.set(algoStr); + } + + public StringProperty algoProperty() { + return algo; + } + +} diff --git a/src/main/java/org/dpsoftware/managers/DisplayManager.java b/src/main/java/org/dpsoftware/managers/DisplayManager.java index 6b68e4c45..000318aed 100644 --- a/src/main/java/org/dpsoftware/managers/DisplayManager.java +++ b/src/main/java/org/dpsoftware/managers/DisplayManager.java @@ -45,6 +45,27 @@ @NoArgsConstructor public class DisplayManager { + /** + * Set and get Display info + * + * @param gd graphics device + * @param mode display mode + * @return display info + */ + private static DisplayInfo getDisplayInfo(GraphicsDevice gd, DisplayMode mode) { + Rectangle bounds = gd.getDefaultConfiguration().getBounds(); + DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.setWidth(mode.getWidth()); + displayInfo.setHeight(mode.getHeight()); + displayInfo.setScaleX(gd.getDefaultConfiguration().getDefaultTransform().getScaleX()); + displayInfo.setScaleY(gd.getDefaultConfiguration().getDefaultTransform().getScaleY()); + displayInfo.setMinX(bounds.getMinX()); + displayInfo.setMinY(bounds.getMinY()); + displayInfo.setMaxX(bounds.getMaxX()); + displayInfo.setMaxY(bounds.getMaxY()); + return displayInfo; + } + /** * How many displays are available * @@ -109,21 +130,34 @@ private List getScreensWithJavaFX() { for (Screen screen : Screen.getScreens()) { Rectangle2D visualBounds = screen.getBounds(); Rectangle2D bounds = screen.getBounds(); - DisplayInfo displayInfo = new DisplayInfo(); - displayInfo.setWidth(bounds.getWidth()); - displayInfo.setHeight(bounds.getHeight()); - displayInfo.setScaleX(screen.getOutputScaleX()); - displayInfo.setScaleY(screen.getOutputScaleY()); - displayInfo.setMinX(visualBounds.getMinX()); - displayInfo.setMinY(visualBounds.getMinY()); - displayInfo.setMaxX(visualBounds.getMaxX()); - displayInfo.setMaxY(visualBounds.getMaxY()); + DisplayInfo displayInfo = getDisplayInfo(screen, bounds, visualBounds); displayInfoList.add(displayInfo); } displayInfoList.sort(comparing(DisplayInfo::getMinX).reversed()); return displayInfoList; } + /** + * Set and get Display info + * + * @param screen data + * @param bounds screen bound + * @param visualBounds visual + * @return display info + */ + private DisplayInfo getDisplayInfo(Screen screen, Rectangle2D bounds, Rectangle2D visualBounds) { + DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.setWidth(bounds.getWidth()); + displayInfo.setHeight(bounds.getHeight()); + displayInfo.setScaleX(screen.getOutputScaleX()); + displayInfo.setScaleY(screen.getOutputScaleY()); + displayInfo.setMinX(visualBounds.getMinX()); + displayInfo.setMinY(visualBounds.getMinY()); + displayInfo.setMaxX(visualBounds.getMaxX()); + displayInfo.setMaxY(visualBounds.getMaxY()); + return displayInfo; + } + /** * Utility method for retrieving screens infos using AWT * @@ -135,16 +169,7 @@ private List getScreensWithAWT() { GraphicsDevice[] gs = ge.getScreenDevices(); for (GraphicsDevice gd : gs) { DisplayMode mode = gd.getDisplayMode(); - Rectangle bounds = gd.getDefaultConfiguration().getBounds(); - DisplayInfo displayInfo = new DisplayInfo(); - displayInfo.setWidth(mode.getWidth()); - displayInfo.setHeight(mode.getHeight()); - displayInfo.setScaleX(gd.getDefaultConfiguration().getDefaultTransform().getScaleX()); - displayInfo.setScaleY(gd.getDefaultConfiguration().getDefaultTransform().getScaleY()); - displayInfo.setMinX(bounds.getMinX()); - displayInfo.setMinY(bounds.getMinY()); - displayInfo.setMaxX(bounds.getMaxX()); - displayInfo.setMaxY(bounds.getMaxY()); + DisplayInfo displayInfo = getDisplayInfo(gd, mode); displayInfoList.add(displayInfo); } displayInfoList.sort(comparing(DisplayInfo::getMinX).reversed()); @@ -254,7 +279,7 @@ public String getDisplayName(int monitorIndex) { if (dispInfo == null) { displayName = "Screen " + monitorIndex; } else { - if (dispInfo.getMonitorName() != null && dispInfo.getMonitorName().length() > 0) { + if (dispInfo.getMonitorName() != null && !dispInfo.getMonitorName().isEmpty()) { displayName = displayName.replace("{0}", dispInfo.getMonitorName()); } else { displayName = displayName.replace(" ({0})", ""); diff --git a/src/main/java/org/dpsoftware/managers/ManagerSingleton.java b/src/main/java/org/dpsoftware/managers/ManagerSingleton.java new file mode 100644 index 000000000..9e0792d50 --- /dev/null +++ b/src/main/java/org/dpsoftware/managers/ManagerSingleton.java @@ -0,0 +1,58 @@ +/* + ManagerSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.managers; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.network.tcpUdp.UdpClient; +import org.eclipse.paho.client.mqttv3.MqttClient; + +import java.util.Map; + +/** + * Manager singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +@SuppressWarnings("all") +public class ManagerSingleton { + + @Getter + private final static ManagerSingleton instance; + + static { + instance = new ManagerSingleton(); + } + + public MqttClient client; + public Map udpClient; + public boolean pipelineStarting = false; + public boolean pipelineStopping = false; + public String lastEffectInUse = ""; + public boolean updateMqttDiscovery = false; + public boolean serialVersionOk = false; + public String deviceNameForSerialDevice = ""; + +} + diff --git a/src/main/java/org/dpsoftware/managers/NetworkManager.java b/src/main/java/org/dpsoftware/managers/NetworkManager.java index 881a470e8..3035650f8 100644 --- a/src/main/java/org/dpsoftware/managers/NetworkManager.java +++ b/src/main/java/org/dpsoftware/managers/NetworkManager.java @@ -24,26 +24,33 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import javafx.application.Platform; import javafx.scene.control.Alert; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; +import org.dpsoftware.grabber.ImageProcessor; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.controllers.MqttTabController; +import org.dpsoftware.gui.elements.Satellite; import org.dpsoftware.managers.dto.TcpResponse; import org.dpsoftware.network.tcpUdp.TcpClient; +import org.dpsoftware.network.tcpUdp.UdpClient; import org.dpsoftware.utilities.CommonUtility; import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import java.awt.*; import java.io.IOException; -import java.util.Date; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadLocalRandom; @@ -57,7 +64,6 @@ @Slf4j public class NetworkManager implements MqttCallback { - public static MqttClient client; public boolean connected = false; String mqttDeviceName; Date lastActivity; @@ -76,9 +82,9 @@ public NetworkManager(boolean showErrorIfAny, AtomicInteger retryCounter) { connected = false; if (showErrorIfAny && retryCounter.get() == 3) { if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.MQTT_ERROR_TITLE, Constants.MQTT_ERROR_CONTEXT, TrayIcon.MessageType.ERROR); + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.MQTT_ERROR_TITLE, Constants.MQTT_ERROR_CONTEXT, TrayIcon.MessageType.ERROR); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.MQTT_ERROR_TITLE, Constants.MQTT_ERROR_HEADER, Constants.MQTT_ERROR_CONTEXT, Alert.AlertType.ERROR); + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.MQTT_ERROR_TITLE, Constants.MQTT_ERROR_HEADER, Constants.MQTT_ERROR_CONTEXT, Alert.AlertType.ERROR); } } log.error("Can't connect to the MQTT Server"); @@ -108,19 +114,19 @@ public static TcpResponse publishToTopic(String topic, String msg) { */ public static TcpResponse publishToTopic(String topic, String msg, boolean forceHttpRequest, boolean retainMsg, int qos) { if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { - if (FireflyLuciferin.config.isMqttEnable() && !forceHttpRequest && client != null) { - MqttMessage message = new MqttMessage(); - message.setPayload(msg.getBytes()); - message.setRetained(retainMsg); - message.setQos(qos); - log.trace("Topic=" + topic + "\n" + msg); - try { - client.publish(topic, message); - } catch (MqttException e) { - log.error(Constants.MQTT_CANT_SEND); + if (MainSingleton.getInstance().config.isMqttEnable() && !forceHttpRequest && ManagerSingleton.getInstance().client != null) { + String swappedMsg = swapMac(msg, null); + publishMqttMsq(topic, swappedMsg, retainMsg, qos); + if (MainSingleton.getInstance().config.getSatellites() != null) { + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + if (!Constants.HTTP_TOPIC_TO_SKIP_FOR_SATELLITES.contains(topic)) { + swappedMsg = swapMac(msg, sat.getValue()); + publishMqttMsq(topic, swappedMsg, retainMsg, qos); + } + } } } else { - if (!topic.contains("firelyluciferin")) { + if (!topic.contains(Constants.MQTT_FIREFLY_BASE_TOPIC)) { return TcpClient.httpGet(msg, topic); } } @@ -128,6 +134,58 @@ public static TcpResponse publishToTopic(String topic, String msg, boolean force return null; } + /** + * If targeting a satellite, swap MAC address + * + * @param msg to send to the device + * @param sat satellite + * @return original message with MAC swapped + */ + public static String swapMac(String msg, Satellite sat) { + if (sat == null) { + return msg; + } else { + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode jsonMsg = mapper.readTree(msg.getBytes()); + if (jsonMsg.get(Constants.MAC) != null) { + ObjectNode object = (ObjectNode) jsonMsg; + String satMac = Objects.requireNonNull(GuiSingleton.getInstance().deviceTableData.stream() + .filter(device -> sat.getDeviceIp().equals(device.getDeviceIP())) + .findFirst() + .orElse(null)).getMac(); + object.put(Constants.MAC, satMac); + return mapper.writeValueAsString(object); + } else { + return msg; + } + } catch (IOException e) { + return msg; + } + } + } + + /** + * Simple MQTT msg sender + * + * @param topic to use + * @param msg to send + * @param retainMsg retained + * @param qos quality of service + */ + private static void publishMqttMsq(String topic, String msg, boolean retainMsg, int qos) { + MqttMessage message = new MqttMessage(); + message.setPayload(msg.getBytes()); + message.setRetained(retainMsg); + message.setQos(qos); + log.trace("Topic=" + topic + "\n" + msg); + try { + ManagerSingleton.getInstance().client.publish(topic, message); + } catch (MqttException e) { + log.error(Constants.MQTT_CANT_SEND); + } + } + /** * Publish to a topic * @@ -148,16 +206,89 @@ public static TcpResponse publishToTopic(String topic, String msg, boolean force public static void stream(String msg) { try { // If multi display change stream topic - if (FireflyLuciferin.config.getMultiMonitor() > 1 && !CommonUtility.isSingleDeviceMultiScreen()) { - client.publish(getTopic(Constants.DEFAULT_MQTT_TOPIC) + Constants.MQTT_STREAM_TOPIC + JavaFXStarter.whoAmI, msg.getBytes(), 0, false); + if (MainSingleton.getInstance().config.getMultiMonitor() > 1 && !CommonUtility.isSingleDeviceMultiScreen()) { + ManagerSingleton.getInstance().client.publish(getTopic(Constants.TOPIC_DEFAULT_MQTT) + Constants.MQTT_STREAM_TOPIC + MainSingleton.getInstance().whoAmI, msg.getBytes(), 0, false); } else { - client.publish(getTopic(Constants.DEFAULT_MQTT_TOPIC) + Constants.MQTT_STREAM_TOPIC, msg.getBytes(), 0, false); + ManagerSingleton.getInstance().client.publish(getTopic(Constants.TOPIC_DEFAULT_MQTT) + Constants.MQTT_STREAM_TOPIC, msg.getBytes(), 0, false); } } catch (MqttException e) { log.error(Constants.MQTT_CANT_SEND); } } + /** + * Stream colors to main instance or to satellites + * + * @param leds array of colors to send + * @param ledStr string to send + */ + public static void streamColors(Color[] leds, StringBuilder ledStr) { + // UDP stream or MQTT stream + if (MainSingleton.getInstance().config.getStreamType().equals(Enums.StreamType.UDP.getStreamType())) { + if (ManagerSingleton.getInstance().udpClient == null) { + ManagerSingleton.getInstance().udpClient = new LinkedHashMap<>(); + } + try { + ManagerSingleton.getInstance().udpClient.put(CommonUtility.getDeviceToUse().getDeviceIP(), new UdpClient(CommonUtility.getDeviceToUse().getDeviceIP())); + ManagerSingleton.getInstance().udpClient.get(CommonUtility.getDeviceToUse().getDeviceIP()).manageStream(leds); + ManagerSingleton.getInstance().udpClient.get(CommonUtility.getDeviceToUse().getDeviceIP()).close(); + if (MainSingleton.getInstance().config.getSatellites() != null) { + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + if ((ManagerSingleton.getInstance().udpClient == null || ManagerSingleton.getInstance().udpClient.isEmpty()) + || ManagerSingleton.getInstance().udpClient.get(sat.getKey()) == null || ManagerSingleton.getInstance().udpClient.get(sat.getKey()).socket.isClosed()) { + assert ManagerSingleton.getInstance().udpClient != null; + ManagerSingleton.getInstance().udpClient.put(sat.getValue().getDeviceIp(), new UdpClient(sat.getValue().getDeviceIp())); + } + assert ManagerSingleton.getInstance().udpClient != null; + assert ManagerSingleton.getInstance().udpClient.get(sat.getKey()) == null; + sendColorToSatellites(leds, sat.getValue()); + } + } + } catch (SocketException | UnknownHostException e) { + log.error(e.getMessage()); + } + } else { + ledStr.append("0"); + NetworkManager.stream(ledStr.toString()); + } + } + + /** + * Sends color to satellites using average or dominant algorithm + * + * @param leds array of colors to send + * @param sat satellite where to send colors + */ + private static void sendColorToSatellites(Color[] leds, Satellite sat) { + Color[] ledMatrix = Arrays.stream(leds).toArray(Color[]::new); + if (Enums.Orientation.CLOCKWISE.equals((LocalizedEnum.fromBaseStr(Enums.Orientation.class, MainSingleton.getInstance().config.getOrientation())))) { + Collections.reverse(Arrays.asList(ledMatrix)); + } + java.util.List clonedLeds = new LinkedList<>(); + LEDCoordinate.getStartEndLeds zoneDetail = LEDCoordinate.getGetStartEndLeds(sat); + int zoneStart = zoneDetail.start() - 1; + int zoneNumLed = (zoneDetail.end() - zoneDetail.start()) + 1; + int zoneEnd = zoneDetail.end() - 1; + int satNumLed = Integer.parseInt(sat.getLedNum()); + if (Enums.Algo.AVG_COLOR.getBaseI18n().equals(sat.getAlgo())) { + if (satNumLed <= zoneNumLed) { + clonedLeds = ImageProcessor.reduceColors(ledMatrix, sat, zoneDetail); + } else { + clonedLeds = ImageProcessor.padColors(ledMatrix, sat, zoneDetail); + } + } else { + Color avgColor = ImageProcessor.getAverageForAllZones(ledMatrix, zoneStart, zoneEnd); + for (int i = 0; i < satNumLed; i++) { + clonedLeds.add(new Color(avgColor.getRed(), avgColor.getGreen(), avgColor.getBlue())); + } + } + Color[] cToSend = clonedLeds.toArray(Color[]::new); + if (Enums.Direction.NORMAL.equals((LocalizedEnum.fromBaseStr(Enums.Direction.class, sat.getOrientation())))) { + Collections.reverse(Arrays.asList(cToSend)); + } + ManagerSingleton.getInstance().udpClient.get(sat.getDeviceIp()).manageStream(cToSend); + } + /** * Manage default MQTT topic * @@ -170,24 +301,24 @@ private static void manageDefaultTopic(MqttMessage message) throws IOException { if (mqttmsg.get(Constants.STATE) != null && mqttmsg.get(Constants.MQTT_TOPIC) != null) { if (mqttmsg.get(Constants.MQTT_TOPIC) != null) { if (mqttmsg.get(Constants.STATE).asText().equals(Constants.ON) && mqttmsg.get(Constants.EFFECT).asText().equals(Constants.SOLID)) { - FireflyLuciferin.config.setToggleLed(true); + MainSingleton.getInstance().config.setToggleLed(true); String brightnessToSet; if (mqttmsg.get(Constants.COLOR) != null) { - if (FireflyLuciferin.nightMode) { - brightnessToSet = String.valueOf(FireflyLuciferin.config.getBrightness()); + if (MainSingleton.getInstance().nightMode) { + brightnessToSet = String.valueOf(MainSingleton.getInstance().config.getBrightness()); } else { brightnessToSet = String.valueOf(mqttmsg.get(Constants.MQTT_BRIGHTNESS)); } - FireflyLuciferin.config.setColorChooser(mqttmsg.get(Constants.COLOR).get("r") + "," + mqttmsg.get(Constants.COLOR).get("g") + "," + MainSingleton.getInstance().config.setColorChooser(mqttmsg.get(Constants.COLOR).get("r") + "," + mqttmsg.get(Constants.COLOR).get("g") + "," + mqttmsg.get(Constants.COLOR).get("b") + "," + brightnessToSet); } } CommonUtility.updateFpsWithDeviceTopic(mqttmsg); } } else if (mqttmsg.get(Constants.START_STOP_INSTANCES) != null && mqttmsg.get(Constants.START_STOP_INSTANCES).asText().equals(Enums.PlayerStatus.STOP.name())) { - FireflyLuciferin.guiManager.stopCapturingThreads(false); + MainSingleton.getInstance().guiManager.stopCapturingThreads(false); } else if (mqttmsg.get(Constants.START_STOP_INSTANCES) != null && mqttmsg.get(Constants.START_STOP_INSTANCES).asText().equals(Enums.PlayerStatus.PLAY.name())) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else if (mqttmsg.get(Constants.STATE) != null) { manageFpsTopic(message); } @@ -207,14 +338,14 @@ private static void manageDefaultTopic(MqttMessage message) throws IOException { */ private static void manageMqttSetTopic(MqttMessage message) throws IOException { if (message.toString().contains(Constants.MQTT_START)) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else if (message.toString().contains(Constants.MQTT_STOP)) { ObjectMapper gammaMapper = new ObjectMapper(); JsonNode macObj = gammaMapper.readTree(message.getPayload()); if (macObj.get(Constants.MAC) != null) { String mac = macObj.get(Constants.MAC).asText(); if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac().equals(mac)) { - FireflyLuciferin.guiManager.pipelineManager.stopCapturePipeline(); + MainSingleton.getInstance().guiManager.pipelineManager.stopCapturePipeline(); } } } @@ -242,42 +373,42 @@ public static String getTopic(String command) { String topic = null; String gwBaseTopic = Constants.MQTT_BASE_TOPIC; String fireflyBaseTopic = Constants.MQTT_FIREFLY_BASE_TOPIC; - String defaultTopic = FireflyLuciferin.config.getMqttTopic(); - if (!FireflyLuciferin.config.isMqttEnable()) { + String defaultTopic = MainSingleton.getInstance().config.getMqttTopic(); + if (!MainSingleton.getInstance().config.isMqttEnable()) { defaultTopic = Constants.MQTT_BASE_TOPIC; } - String defaultFireflyTopic = fireflyBaseTopic + "_" + FireflyLuciferin.config.getMqttTopic(); - if (Constants.DEFAULT_MQTT_TOPIC.equals(FireflyLuciferin.config.getMqttTopic()) - || gwBaseTopic.equals(FireflyLuciferin.config.getMqttTopic())) { + String defaultFireflyTopic = fireflyBaseTopic + "_" + MainSingleton.getInstance().config.getMqttTopic(); + if (Constants.TOPIC_DEFAULT_MQTT.equals(MainSingleton.getInstance().config.getMqttTopic()) + || gwBaseTopic.equals(MainSingleton.getInstance().config.getMqttTopic())) { defaultTopic = gwBaseTopic; defaultFireflyTopic = fireflyBaseTopic; } switch (command) { - case Constants.DEFAULT_MQTT_TOPIC -> - topic = Constants.DEFAULT_MQTT_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.DEFAULT_MQTT_STATE_TOPIC -> - topic = Constants.DEFAULT_MQTT_STATE_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.UPDATE_MQTT_TOPIC -> topic = Constants.UPDATE_MQTT_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.UPDATE_RESULT_MQTT_TOPIC -> - topic = Constants.UPDATE_RESULT_MQTT_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.FIREFLY_LUCIFERIN_FRAMERATE -> - topic = Constants.FIREFLY_LUCIFERIN_FRAMERATE.replace(fireflyBaseTopic, defaultFireflyTopic); - case Constants.FIREFLY_LUCIFERIN_GAMMA -> - topic = Constants.FIREFLY_LUCIFERIN_GAMMA.replace(fireflyBaseTopic, defaultFireflyTopic); - case Constants.ASPECT_RATIO_TOPIC -> - topic = Constants.ASPECT_RATIO_TOPIC.replace(fireflyBaseTopic, defaultFireflyTopic); - case Constants.SET_ASPECT_RATIO_TOPIC -> - topic = Constants.SET_ASPECT_RATIO_TOPIC.replace(fireflyBaseTopic, defaultFireflyTopic); - case Constants.SET_SMOOTHING_TOPIC -> - topic = Constants.SET_SMOOTHING_TOPIC.replace(fireflyBaseTopic, defaultFireflyTopic); - case Constants.FIREFLY_LUCIFERIN_EFFECT_TOPIC -> - topic = Constants.FIREFLY_LUCIFERIN_EFFECT_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.GLOW_WORM_FIRM_CONFIG_TOPIC -> topic = Constants.GLOW_WORM_FIRM_CONFIG_TOPIC; - case Constants.UNSUBSCRIBE_STREAM_TOPIC -> - topic = Constants.UNSUBSCRIBE_STREAM_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.LDR_TOPIC -> topic = Constants.LDR_TOPIC.replace(gwBaseTopic, defaultTopic); - case Constants.FIREFLY_LUCIFERIN_PROFILE_SET -> - topic = Constants.FIREFLY_LUCIFERIN_PROFILE_SET.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_DEFAULT_MQTT -> + topic = Constants.TOPIC_DEFAULT_MQTT.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_DEFAULT_MQTT_STATE -> + topic = Constants.TOPIC_DEFAULT_MQTT_STATE.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_UPDATE_MQTT -> topic = Constants.TOPIC_UPDATE_MQTT.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_UPDATE_RESULT_MQTT -> + topic = Constants.TOPIC_UPDATE_RESULT_MQTT.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_FIREFLY_LUCIFERIN_FRAMERATE -> + topic = Constants.TOPIC_FIREFLY_LUCIFERIN_FRAMERATE.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_FIREFLY_LUCIFERIN_GAMMA -> + topic = Constants.TOPIC_FIREFLY_LUCIFERIN_GAMMA.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_ASPECT_RATIO -> + topic = Constants.TOPIC_ASPECT_RATIO.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_SET_ASPECT_RATIO -> + topic = Constants.TOPIC_SET_ASPECT_RATIO.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_SET_SMOOTHING -> + topic = Constants.TOPIC_SET_SMOOTHING.replace(fireflyBaseTopic, defaultFireflyTopic); + case Constants.TOPIC_FIREFLY_LUCIFERIN_EFFECT -> + topic = Constants.TOPIC_FIREFLY_LUCIFERIN_EFFECT.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_GLOW_WORM_FIRM_CONFIG -> topic = Constants.TOPIC_GLOW_WORM_FIRM_CONFIG; + case Constants.TOPIC_UNSUBSCRIBE_STREAM -> + topic = Constants.TOPIC_UNSUBSCRIBE_STREAM.replace(gwBaseTopic, defaultTopic); + case Constants.HTTP_SET_LDR -> topic = Constants.HTTP_SET_LDR.replace(gwBaseTopic, defaultTopic); + case Constants.TOPIC_FIREFLY_LUCIFERIN_PROFILE_SET -> + topic = Constants.TOPIC_FIREFLY_LUCIFERIN_PROFILE_SET.replace(fireflyBaseTopic, defaultFireflyTopic); } return topic; } @@ -288,21 +419,68 @@ public static String getTopic(String command) { * @return true if current topic is different from main topic */ public static boolean currentTopicDiffersFromMainTopic() { - if (JavaFXStarter.whoAmI != 1 && FireflyLuciferin.config.isMqttEnable()) { + if (MainSingleton.getInstance().whoAmI != 1 && MainSingleton.getInstance().config.isMqttEnable()) { StorageManager sm = new StorageManager(); Configuration mainConfig = sm.readMainConfig(); - return !FireflyLuciferin.config.getMqttTopic().equals(mainConfig.getMqttTopic()); + return !MainSingleton.getInstance().config.getMqttTopic().equals(mainConfig.getMqttTopic()); } return false; } + /** + * Get MQTT connection Options + * + * @return MQTT connection Options + */ + private static MqttConnectOptions getMqttConnectOptions() { + MqttConnectOptions connOpts = new MqttConnectOptions(); + connOpts.setAutomaticReconnect(true); + connOpts.setCleanSession(true); + connOpts.setConnectionTimeout(10); + connOpts.setMaxInflight(1000); // Default = 10 + if (MainSingleton.getInstance().config.getMqttUsername() != null && !MainSingleton.getInstance().config.getMqttUsername().isEmpty()) { + connOpts.setUserName(MainSingleton.getInstance().config.getMqttUsername()); + } + if (MainSingleton.getInstance().config.getMqttPwd() != null && !MainSingleton.getInstance().config.getMqttPwd().isEmpty()) { + connOpts.setPassword(MainSingleton.getInstance().config.getMqttPwd().toCharArray()); + } + return connOpts; + } + + /** + * Check is a String is a valid IPv4 address + * + * @param ip address as String + * @return true if the string is an IPv4 address + */ + public static boolean isValidIp(String ip) { + try { + if (ip == null || ip.isEmpty()) { + return false; + } + String[] parts = ip.split("\\."); + if (parts.length != 4) { + return false; + } + for (String s : parts) { + int i = Integer.parseInt(s); + if ((i < 0) || (i > 255)) { + return false; + } + } + return !ip.endsWith("."); + } catch (NumberFormatException nfe) { + return false; + } + } + /** * Manage aspect ratio topic * * @param message mqtt message */ private void manageAspectRatio(MqttMessage message) { - FireflyLuciferin.guiManager.trayIconManager.manageAspectRatioListener(message.toString(), false); + MainSingleton.getInstance().guiManager.trayIconManager.manageAspectRatioListener(message.toString(), false); } /** @@ -311,11 +489,11 @@ private void manageAspectRatio(MqttMessage message) { * @param message mqtt message */ private void manageSmoothing(MqttMessage message) { - if (FireflyLuciferin.RUNNING) { + if (MainSingleton.getInstance().RUNNING) { Platform.runLater(() -> { - FireflyLuciferin.config.setFrameInsertion(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, message.toString()).getBaseI18n()); - FireflyLuciferin.guiManager.stopCapturingThreads(FireflyLuciferin.RUNNING); - CommonUtility.delaySeconds(() -> FireflyLuciferin.guiManager.startCapturingThreads(), 4); + MainSingleton.getInstance().config.setFrameInsertion(LocalizedEnum.fromBaseStr(Enums.FrameInsertion.class, message.toString()).getBaseI18n()); + MainSingleton.getInstance().guiManager.stopCapturingThreads(MainSingleton.getInstance().RUNNING); + CommonUtility.delaySeconds(() -> MainSingleton.getInstance().guiManager.startCapturingThreads(), 4); }); } } @@ -326,7 +504,7 @@ private void manageSmoothing(MqttMessage message) { * @param message message */ private void manageEffect(String message) { - if (FireflyLuciferin.config != null) { + if (MainSingleton.getInstance().config != null) { CommonUtility.delayMilliseconds(() -> { log.info("Setting mode via MQTT - " + message); setEffect(message); @@ -340,8 +518,8 @@ private void manageEffect(String message) { * @param message message */ private void manageProfile(String message) { - if (FireflyLuciferin.config != null) { - CommonUtility.delayMilliseconds(() -> FireflyLuciferin.guiManager.trayIconManager.manageProfileListener(message), 200); + if (MainSingleton.getInstance().config != null) { + CommonUtility.delayMilliseconds(() -> MainSingleton.getInstance().guiManager.trayIconManager.manageProfileListener(message), 200); } } @@ -352,12 +530,12 @@ private void manageProfile(String message) { * @param message message */ private void manageFirmwareConfig(String message) throws JsonProcessingException { - if (FireflyLuciferin.config != null) { + if (MainSingleton.getInstance().config != null) { if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac() != null) { ObjectMapper mapper = new ObjectMapper(); JsonNode mqttmsg = mapper.readTree(message); if (CommonUtility.getDeviceToUse().getMac().equals(mqttmsg.get(Constants.MAC).asText())) { - FireflyLuciferin.config.setColorMode(mqttmsg.get(Constants.COLOR_MODE).asInt()); + MainSingleton.getInstance().config.setColorMode(mqttmsg.get(Constants.COLOR_MODE).asInt()); } } log.debug(message); @@ -368,27 +546,27 @@ private void manageFirmwareConfig(String message) throws JsonProcessingException * Set effect */ private void setEffect(String message) { - String previousEffect = FireflyLuciferin.config.getEffect(); - FireflyLuciferin.config.setEffect(message); + String previousEffect = MainSingleton.getInstance().config.getEffect(); + MainSingleton.getInstance().config.setEffect(message); CommonUtility.sleepMilliseconds(200); if ((Enums.Effect.BIAS_LIGHT.getBaseI18n().equals(message) || Enums.Effect.MUSIC_MODE_VU_METER.getBaseI18n().equals(message) || Enums.Effect.MUSIC_MODE_VU_METER_DUAL.getBaseI18n().equals(message) || Enums.Effect.MUSIC_MODE_BRIGHT.getBaseI18n().equals(message) || Enums.Effect.MUSIC_MODE_RAINBOW.getBaseI18n().equals(message))) { - if (!FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.startCapturingThreads(); + if (!MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else { if (!previousEffect.equals(message)) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); CommonUtility.sleepSeconds(1); - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } } } else { - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); - FireflyLuciferin.config.setToggleLed(!message.contains(Constants.OFF)); + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); + MainSingleton.getInstance().config.setToggleLed(!message.contains(Constants.OFF)); CommonUtility.turnOnLEDs(); } } @@ -404,7 +582,7 @@ private void manageGamma(MqttMessage message) throws IOException { ObjectMapper gammaMapper = new ObjectMapper(); JsonNode gammaObj = gammaMapper.readTree(message.getPayload()); if (gammaObj.get(Constants.MQTT_GAMMA) != null) { - FireflyLuciferin.config.setGamma(Double.parseDouble(gammaObj.get(Constants.MQTT_GAMMA).asText())); + MainSingleton.getInstance().config.setGamma(Double.parseDouble(gammaObj.get(Constants.MQTT_GAMMA).asText())); } } @@ -414,80 +592,31 @@ private void manageGamma(MqttMessage message) throws IOException { * @param message mqtt message */ private void showUpdateNotification(MqttMessage message) { - if (UpgradeManager.deviceNameForSerialDevice.equals(message.toString()) - || UpgradeManager.deviceNameForSerialDevice.equals(message + Constants.CDC_DEVICE)) { + if (ManagerSingleton.getInstance().deviceNameForSerialDevice.equals(message.toString()) + || ManagerSingleton.getInstance().deviceNameForSerialDevice.equals(message + Constants.CDC_DEVICE)) { log.info("Update successfull=" + message); if (!CommonUtility.isSingleDeviceMultiScreen() || CommonUtility.isSingleDeviceMainInstance()) { javafx.application.Platform.runLater(() -> { String notificationContext = message + " "; - if (UpgradeManager.deviceNameForSerialDevice.contains(Constants.CDC_DEVICE) && !FireflyLuciferin.config.isWirelessStream()) { + if (ManagerSingleton.getInstance().deviceNameForSerialDevice.contains(Constants.CDC_DEVICE) && !MainSingleton.getInstance().config.isWirelessStream()) { notificationContext += CommonUtility.getWord(Constants.DEVICEUPGRADE_SUCCESS_CDC); } else { notificationContext += CommonUtility.getWord(Constants.DEVICEUPGRADE_SUCCESS); } if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showNotification(CommonUtility.getWord(Constants.UPGRADE_SUCCESS), + MainSingleton.getInstance().guiManager.showNotification(CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.UPGRADE_SUCCESS), + MainSingleton.getInstance().guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, Alert.AlertType.INFORMATION); } }); } CommonUtility.sleepSeconds(60); - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } } - /** - * Reconnect to MQTT Broker - * - * @throws MqttException can't handle MQTT connection - */ - void attemptReconnect() throws MqttException { - boolean firstConnection = mqttDeviceName == null; - if (NativeExecutor.isWindows()) { - mqttDeviceName = Constants.MQTT_DEVICE_NAME_WIN; - } else if (NativeExecutor.isLinux()) { - mqttDeviceName = Constants.MQTT_DEVICE_NAME_LIN; - } else { - mqttDeviceName = Constants.MQTT_DEVICE_NAME_MAC; - } - mqttDeviceName += "_" + ThreadLocalRandom.current().nextInt(); - MemoryPersistence persistence = new MemoryPersistence(); - client = new MqttClient(FireflyLuciferin.config.getMqttServer(), mqttDeviceName, persistence); - MqttConnectOptions connOpts = new MqttConnectOptions(); - connOpts.setAutomaticReconnect(true); - connOpts.setCleanSession(true); - connOpts.setConnectionTimeout(10); - connOpts.setMaxInflight(1000); // Default = 10 - if (FireflyLuciferin.config.getMqttUsername() != null && !FireflyLuciferin.config.getMqttUsername().isEmpty()) { - connOpts.setUserName(FireflyLuciferin.config.getMqttUsername()); - } - if (FireflyLuciferin.config.getMqttPwd() != null && !FireflyLuciferin.config.getMqttPwd().isEmpty()) { - connOpts.setPassword(FireflyLuciferin.config.getMqttPwd().toCharArray()); - } - client.connect(connOpts); - client.setCallback(this); - if (firstConnection) { - CommonUtility.turnOnLEDs(); - // Wait that the device is engaged before updating MQTT discovery entities. - if (StorageManager.updateMqttDiscovery) { - ScheduledExecutorService es = Executors.newScheduledThreadPool(1); - es.scheduleAtFixedRate(() -> { - if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac() != null && !CommonUtility.getDeviceToUse().getMac().isEmpty()) { - MqttTabController.publishDiscoveryTopics(false); - MqttTabController.publishDiscoveryTopics(true); - es.shutdownNow(); - } - }, 0, 2, TimeUnit.SECONDS); - } - } - subscribeToTopics(); - log.info(Constants.MQTT_CONNECTED); - connected = true; - } - /** * Reconnect on connection lost * @@ -507,7 +636,7 @@ public void connectionLost(Throwable cause) { log.info("Long disconnection occurred"); NativeExecutor.restartNativeInstance(); } - client.setCallback(this); + ManagerSingleton.getInstance().client.setCallback(this); subscribeToTopics(); connected = true; log.info(Constants.MQTT_RECONNECTED); @@ -524,15 +653,15 @@ public void connectionLost(Throwable cause) { * @throws MqttException can't subscribe */ void subscribeToTopics() throws MqttException { - client.subscribe(getTopic(Constants.DEFAULT_MQTT_TOPIC)); - client.subscribe(getTopic(Constants.DEFAULT_MQTT_STATE_TOPIC)); - client.subscribe(getTopic(Constants.UPDATE_RESULT_MQTT_TOPIC)); - client.subscribe(getTopic(Constants.FIREFLY_LUCIFERIN_GAMMA)); - client.subscribe(getTopic(Constants.SET_SMOOTHING_TOPIC)); - client.subscribe(getTopic(Constants.SET_ASPECT_RATIO_TOPIC)); - client.subscribe(getTopic(Constants.FIREFLY_LUCIFERIN_EFFECT_TOPIC)); - client.subscribe(getTopic(Constants.FIREFLY_LUCIFERIN_PROFILE_SET)); - client.subscribe(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_DEFAULT_MQTT)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_DEFAULT_MQTT_STATE)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_UPDATE_RESULT_MQTT)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_GAMMA)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_SET_SMOOTHING)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_SET_ASPECT_RATIO)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_EFFECT)); + ManagerSingleton.getInstance().client.subscribe(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_PROFILE_SET)); + ManagerSingleton.getInstance().client.subscribe(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG); } /** @@ -545,24 +674,24 @@ void subscribeToTopics() throws MqttException { @SuppressWarnings("Duplicates") public void messageArrived(String topic, MqttMessage message) throws IOException { lastActivity = new Date(); - if (topic.equals(getTopic(Constants.DEFAULT_MQTT_STATE_TOPIC))) { + if (topic.equals(getTopic(Constants.TOPIC_DEFAULT_MQTT_STATE))) { manageDefaultTopic(message); - } else if (topic.equals(getTopic(Constants.UPDATE_RESULT_MQTT_TOPIC))) { + } else if (topic.equals(getTopic(Constants.TOPIC_UPDATE_RESULT_MQTT))) { // If a new firmware version is detected, restart the screen capture. showUpdateNotification(message); - } else if (topic.equals(getTopic(Constants.DEFAULT_MQTT_TOPIC))) { + } else if (topic.equals(getTopic(Constants.TOPIC_DEFAULT_MQTT))) { manageMqttSetTopic(message); - } else if (topic.equals(getTopic(Constants.FIREFLY_LUCIFERIN_GAMMA))) { + } else if (topic.equals(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_GAMMA))) { manageGamma(message); - } else if (topic.equals(getTopic(Constants.SET_ASPECT_RATIO_TOPIC))) { + } else if (topic.equals(getTopic(Constants.TOPIC_SET_ASPECT_RATIO))) { manageAspectRatio(message); - } else if (topic.equals(getTopic(Constants.SET_SMOOTHING_TOPIC))) { + } else if (topic.equals(getTopic(Constants.TOPIC_SET_SMOOTHING))) { manageSmoothing(message); - } else if (topic.equals(getTopic(Constants.FIREFLY_LUCIFERIN_EFFECT_TOPIC))) { + } else if (topic.equals(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_EFFECT))) { manageEffect(message.toString()); - } else if (topic.equals(getTopic(Constants.FIREFLY_LUCIFERIN_PROFILE_SET))) { + } else if (topic.equals(getTopic(Constants.TOPIC_FIREFLY_LUCIFERIN_PROFILE_SET))) { manageProfile(message.toString()); - } else if (topic.equals(Constants.GLOW_WORM_FIRM_CONFIG_TOPIC)) { + } else if (topic.equals(Constants.TOPIC_GLOW_WORM_FIRM_CONFIG)) { manageFirmwareConfig(message.toString()); } } @@ -577,4 +706,43 @@ public void deliveryComplete(IMqttDeliveryToken token) { //log.info("delivered"); } + /** + * Reconnect to MQTT Broker + * + * @throws MqttException can't handle MQTT connection + */ + void attemptReconnect() throws MqttException { + boolean firstConnection = mqttDeviceName == null; + if (NativeExecutor.isWindows()) { + mqttDeviceName = Constants.MQTT_DEVICE_NAME_WIN; + } else if (NativeExecutor.isLinux()) { + mqttDeviceName = Constants.MQTT_DEVICE_NAME_LIN; + } else { + mqttDeviceName = Constants.MQTT_DEVICE_NAME_MAC; + } + mqttDeviceName += "_" + ThreadLocalRandom.current().nextInt(); + MemoryPersistence persistence = new MemoryPersistence(); + ManagerSingleton.getInstance().client = new MqttClient(MainSingleton.getInstance().config.getMqttServer(), mqttDeviceName, persistence); + MqttConnectOptions connOpts = getMqttConnectOptions(); + ManagerSingleton.getInstance().client.connect(connOpts); + ManagerSingleton.getInstance().client.setCallback(this); + if (firstConnection) { + CommonUtility.turnOnLEDs(); + // Wait that the device is engaged before updating MQTT discovery entities. + if (ManagerSingleton.getInstance().updateMqttDiscovery) { + ScheduledExecutorService es = Executors.newScheduledThreadPool(1); + es.scheduleAtFixedRate(() -> { + if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac() != null && !CommonUtility.getDeviceToUse().getMac().isEmpty()) { + MqttTabController.publishDiscoveryTopics(false); + MqttTabController.publishDiscoveryTopics(true); + es.shutdownNow(); + } + }, 0, 2, TimeUnit.SECONDS); + } + } + subscribeToTopics(); + log.info(Constants.MQTT_CONNECTED); + connected = true; + } + } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/managers/PipelineManager.java b/src/main/java/org/dpsoftware/managers/PipelineManager.java index d58a605f1..a4a3b2180 100644 --- a/src/main/java/org/dpsoftware/managers/PipelineManager.java +++ b/src/main/java/org/dpsoftware/managers/PipelineManager.java @@ -21,32 +21,44 @@ */ package org.dpsoftware.managers; +import javafx.scene.control.Alert; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; -import org.dpsoftware.audio.AudioLoopback; -import org.dpsoftware.audio.AudioLoopbackNative; -import org.dpsoftware.audio.AudioLoopbackSoftware; -import org.dpsoftware.audio.AudioUtility; +import org.dpsoftware.MainSingleton; +import org.dpsoftware.NativeExecutor; +import org.dpsoftware.audio.*; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.grabber.GrabberManager; -import org.dpsoftware.gui.TrayIconManager; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.grabber.DbusScreenCast; +import org.dpsoftware.grabber.GrabberSingleton; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.DisplayInfo; import org.dpsoftware.gui.elements.GlowWormDevice; +import org.dpsoftware.gui.elements.Satellite; import org.dpsoftware.managers.dto.AudioDevice; import org.dpsoftware.managers.dto.ColorDto; import org.dpsoftware.managers.dto.StateDto; import org.dpsoftware.managers.dto.UnsubscribeInstanceDto; import org.dpsoftware.network.MessageClient; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.utilities.CommonUtility; +import org.freedesktop.dbus.DBusMap; +import org.freedesktop.dbus.DBusMatchRule; +import org.freedesktop.dbus.DBusPath; +import org.freedesktop.dbus.FileDescriptor; +import org.freedesktop.dbus.connections.impl.DBusConnection; +import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; +import org.freedesktop.dbus.exceptions.DBusException; +import org.freedesktop.dbus.types.UInt32; +import org.freedesktop.dbus.types.Variant; import java.awt.*; +import java.io.IOException; import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -58,27 +70,120 @@ @Slf4j public class PipelineManager { - public static boolean pipelineStarting = false; - public static boolean pipelineStopping = false; - public static String lastEffectInUse = ""; UpgradeManager upgradeManager = new UpgradeManager(); private ScheduledExecutorService scheduledExecutorService; + + record XdgStreamDetails(Integer streamId, FileDescriptor fileDescriptor) { + } + + /** + * Uses D-BUS to get the XDG ScreenCast stream ID & pipewire filedescriptor + * + * @return XDG ScreenCast stream details containing the ID from org.freedesktop.portal.ScreenCast:Start and + * FileDescriptor from org.freedesktop.portal.ScreenCast:OpenPipeWireRemote + * @throws RuntimeException on any concurrency or D-BUS issues + */ + @SneakyThrows + @SuppressWarnings("all") + public static XdgStreamDetails getXdgStreamDetails() { + CompletableFuture sessionHandleMaybe = new CompletableFuture<>(); + CompletableFuture streamIdMaybe = new CompletableFuture<>(); + DBusConnection dBusConnection = DBusConnectionBuilder.forSessionBus().build(); // cannot free/close this for the duration of the capture + DbusScreenCast screenCastIface = dBusConnection.getRemoteObject("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", DbusScreenCast.class); + String handleToken = UUID.randomUUID().toString().replaceAll("-", ""); + DBusMatchRule matchRule = new DBusMatchRule("signal", "org.freedesktop.portal.Request", "Response"); + dBusConnection.addGenericSigHandler(matchRule, signal -> { + try { + if (signal.getParameters().length == 2 // verify amount of arguments + && signal.getParameters()[0] instanceof UInt32 // verify argument types + && signal.getParameters()[1] instanceof DBusMap + && ((UInt32) signal.getParameters()[0]).intValue() == 0 // verify success-code + ) { + // parse signal & set appropriate Future as the result + if (((DBusMap) signal.getParameters()[1]).containsKey("session_handle")) { + sessionHandleMaybe.complete((String) (((Variant) ((DBusMap) signal.getParameters()[1]).get("session_handle")).getValue())); + } else if (((DBusMap) signal.getParameters()[1]).containsKey("streams")) { + if (((DBusMap) signal.getParameters()[1]).get("restore_token") != null) { + String restoreToken = (String) ((Variant) ((DBusMap) signal.getParameters()[1]).get("restore_token")).getValue(); + try { + if (!restoreToken.equals(MainSingleton.getInstance().config.getScreenCastRestoreToken())) { + MainSingleton.getInstance().config.setScreenCastRestoreToken((String) ((Variant) ((DBusMap) signal.getParameters()[1]).get("restore_token")).getValue()); + StorageManager storageManager = new StorageManager(); + storageManager.writeConfig(MainSingleton.getInstance().config, null); + } + } catch (IOException e) { + log.error("Can't write config file."); + } + } + streamIdMaybe.complete(((UInt32) ((Object[]) ((List) (((Variant) ((DBusMap) signal.getParameters()[1]).get("streams")).getValue())).get(0))[0]).intValue()); + } + } + } catch (DBusException e) { + throw new RuntimeException(e); // couldn't parse, fail early + } + }); + screenCastIface.CreateSession(Map.of("session_handle_token", new Variant<>(handleToken))); + DBusPath receivedSessionHandle = new DBusPath(sessionHandleMaybe.get()); + String restoreToken = MainSingleton.getInstance().config.getScreenCastRestoreToken(); + Map> selectSourcesMap = new HashMap<>() {{ + put("multiple", new Variant<>(false)); + put("types", new Variant<>(new UInt32(1 | 2))); // bitmask, 1 - screens, 2 - windows + put("persist_mode", new Variant<>(new UInt32(2))); + }}; + if (restoreToken != null && !restoreToken.isEmpty()) { + selectSourcesMap.put("restore_token", new Variant<>(restoreToken)); + } + screenCastIface.SelectSources(receivedSessionHandle, selectSourcesMap); + if (NativeExecutor.isWayland() && (MainSingleton.getInstance().config.getScreenCastRestoreToken() == null || MainSingleton.getInstance().config.getScreenCastRestoreToken().isEmpty())) { + DisplayManager displayManager = new DisplayManager(); + String displayName = displayManager.getDisplayName(MainSingleton.getInstance().whoAmI - 1); + MainSingleton.getInstance().guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.WAYLAND_SCREEN_REC_PERMISSION).replace("{0}", displayName), + CommonUtility.getWord(Constants.WAYLAND_SCREEN_REC_PERMISSION_CONTEXT).replace("{0}", displayName), Alert.AlertType.INFORMATION); + } + screenCastIface.Start(receivedSessionHandle, "", Collections.emptyMap()); + var c = streamIdMaybe.thenApply(streamId -> { + FileDescriptor fileDescriptor = screenCastIface.OpenPipeWireRemote(receivedSessionHandle, Collections.emptyMap()); // block until stream started before calling OpenPipeWireRemote + return new XdgStreamDetails(streamId, fileDescriptor); + }).get(); + return c; + } + /** * Calculate correct Pipeline for Linux * * @return params for Linux Pipeline */ public static String getLinuxPipelineParams() { - // startx{0}, endx{1}, starty{2}, endy{3} - DisplayManager displayManager = new DisplayManager(); - List displayList = displayManager.getDisplayList(); - DisplayInfo monitorInfo = displayList.get(FireflyLuciferin.config.getMonitorNumber()); - String gstreamerPipeline = Constants.GSTREAMER_PIPELINE_LINUX - .replace("{0}", String.valueOf((int) (monitorInfo.getMinX() + 1))) - .replace("{1}", String.valueOf((int) (monitorInfo.getMinX() + monitorInfo.getWidth() - 1))) - .replace("{2}", String.valueOf((int) (monitorInfo.getMinY()))) - .replace("{3}", String.valueOf((int) (monitorInfo.getMinY() + monitorInfo.getHeight() - 1))); + String gstreamerPipeline; + String pipeline; + if (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG.name()) + || MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG_NVIDIA.name())) { + if (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG.name())) { + pipeline = Constants.GSTREAMER_PIPELINE_PIPEWIREXDG; + } else { + pipeline = Constants.GSTREAMER_PIPELINE_PIPEWIREXDG_CUDA; + } + XdgStreamDetails xdgStreamDetails = getXdgStreamDetails(); + gstreamerPipeline = pipeline + .replace("{1}", String.valueOf(xdgStreamDetails.fileDescriptor.getIntFileDescriptor())) + .replace("{2}", xdgStreamDetails.streamId.toString()); + } else { + // startx{0}, endx{1}, starty{2}, endy{3} + if (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) { + pipeline = Constants.GSTREAMER_PIPELINE_XIMAGESRC; + } else { + pipeline = Constants.GSTREAMER_PIPELINE_XIMAGESRC_CUDA; + } + DisplayManager displayManager = new DisplayManager(); + List displayList = displayManager.getDisplayList(); + DisplayInfo monitorInfo = displayList.get(MainSingleton.getInstance().config.getMonitorNumber()); + gstreamerPipeline = pipeline + .replace("{0}", String.valueOf((int) (monitorInfo.getMinX() + 1))) + .replace("{1}", String.valueOf((int) (monitorInfo.getMinX() + monitorInfo.getWidth() - 1))) + .replace("{2}", String.valueOf((int) (monitorInfo.getMinY()))) + .replace("{3}", String.valueOf((int) (monitorInfo.getMinY() + monitorInfo.getHeight() - 1))); + } log.info(gstreamerPipeline); return gstreamerPipeline; } @@ -90,34 +195,48 @@ public static String getLinuxPipelineParams() { */ public static void offerToTheQueue(Color[] leds) { if (CommonUtility.isSingleDeviceMultiScreen()) { - if (MessageClient.msgClient == null || MessageClient.msgClient.clientSocket == null) { - MessageClient.msgClient = new MessageClient(); + if (NetworkSingleton.getInstance().msgClient == null || NetworkSingleton.getInstance().msgClient.clientSocket == null) { + NetworkSingleton.getInstance().msgClient = new MessageClient(); if (CommonUtility.isSingleDeviceMultiScreen()) { - MessageClient.msgClient.startConnection(Constants.MSG_SERVER_HOST, Constants.MSG_SERVER_PORT); + NetworkSingleton.getInstance().msgClient.startConnection(Constants.MSG_SERVER_HOST, Constants.MSG_SERVER_PORT); } } StringBuilder sb = new StringBuilder(); - sb.append(JavaFXStarter.whoAmI).append(","); + sb.append(MainSingleton.getInstance().whoAmI).append(","); for (Color color : leds) { sb.append(color.getRGB()).append(","); } - MessageClient.msgClient.sendMessage(sb.toString()); + NetworkSingleton.getInstance().msgClient.sendMessage(sb.toString()); } else { //noinspection ResultOfMethodCallIgnored - FireflyLuciferin.sharedQueue.offer(leds); + MainSingleton.getInstance().sharedQueue.offer(leds); } } + /** + * Search if all the configured satellites are engaged + * + * @return boolean if all satellites are engaged + */ + public static boolean isSatellitesEngaged() { + boolean result = true; + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + result = GuiSingleton.getInstance().deviceTableData.stream().anyMatch(e -> e.getDeviceIP().equals(sat.getKey())); + if (!result) break; + } + return result; + } + /** * Start high performance pipeline, MQTT or Serial managed (FULL or LIGHT firmware) */ public void startCapturePipeline() { - PipelineManager.pipelineStarting = true; - PipelineManager.pipelineStopping = false; + ManagerSingleton.getInstance().pipelineStarting = true; + ManagerSingleton.getInstance().pipelineStopping = false; if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { initAudioCapture(); } - if ((NetworkManager.client != null) || FireflyLuciferin.config.isFullFirmware()) { + if ((ManagerSingleton.getInstance().client != null) || MainSingleton.getInstance().config.isFullFirmware()) { startWiFiMqttManagedPipeline(); } else { startSerialManagedPipeline(); @@ -130,24 +249,14 @@ public void startCapturePipeline() { void initAudioCapture() { AudioUtility audioLoopback; audioLoopback = new AudioLoopbackNative(); - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); - Enums.Effect lastEffectInUseFromConfig = LocalizedEnum.fromBaseStr(Enums.Effect.class, lastEffectInUse); - boolean startAudioCapture = false; - switch (effectInUse) { - case MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> - startAudioCapture = true; - } - if (lastEffectInUseFromConfig != null) { - switch (lastEffectInUseFromConfig) { - case MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> - startAudioCapture = true; - } - } + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); + Enums.Effect lastEffectInUseFromConfig = LocalizedEnum.fromBaseStr(Enums.Effect.class, ManagerSingleton.getInstance().lastEffectInUse); + boolean startAudioCapture = isStartAudioCapture(effectInUse, lastEffectInUseFromConfig); if (startAudioCapture) { Map loopbackDevices = audioLoopback.getLoopbackDevices(); // if there is no native audio loopback (example stereo mix), fallback to software audio loopback using WASAPI if (loopbackDevices != null && !loopbackDevices.isEmpty() - && FireflyLuciferin.config.getAudioDevice().equals(Enums.Audio.DEFAULT_AUDIO_OUTPUT_NATIVE.getBaseI18n())) { + && MainSingleton.getInstance().config.getAudioDevice().equals(Enums.Audio.DEFAULT_AUDIO_OUTPUT_NATIVE.getBaseI18n())) { log.info("Starting native audio loopback."); audioLoopback.startVolumeLevelMeter(); } else { @@ -163,24 +272,44 @@ void initAudioCapture() { } } + /** + * Check is audio capturing is needed + * + * @param effectInUse name of the effect to use + * @param lastEffectInUseFromConfig previous effect in use + * @return true if audio capture is needed + */ + private boolean isStartAudioCapture(Enums.Effect effectInUse, Enums.Effect lastEffectInUseFromConfig) { + boolean startAudioCapture = false; + switch (effectInUse) { + case MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> + startAudioCapture = true; + } + if (lastEffectInUseFromConfig != null) { + switch (lastEffectInUseFromConfig) { + case MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> + startAudioCapture = true; + } + } + return startAudioCapture; + } + /** * Start high performance Serial pipeline, LIGHT firmware required */ private void startSerialManagedPipeline() { scheduledExecutorService = Executors.newScheduledThreadPool(1); Runnable framerateTask = () -> { - // Waiting Device to Use - GlowWormDevice glowWormDeviceSerial = CommonUtility.getDeviceToUse(); - // Check if the connected device match the minimum firmware version requirements for this Firefly Luciferin version + // Waiting Device to Use, check if the connected device match the minimum firmware version requirements for this Firefly Luciferin version Boolean firmwareMatchMinRequirements = upgradeManager.firmwareMatchMinimumRequirements(); if (CommonUtility.isSingleDeviceOtherInstance() || firmwareMatchMinRequirements != null) { if (CommonUtility.isSingleDeviceOtherInstance() || firmwareMatchMinRequirements) { setRunning(); - if (FireflyLuciferin.guiManager.trayIconManager.getTrayIcon() != null) { - FireflyLuciferin.guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.PLAY); + if (MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon() != null) { + MainSingleton.getInstance().guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.PLAY); } } else { - stopForFirmwareUpgrade(glowWormDeviceSerial); + stopForFirmwareUpgrade(); } } else { log.info("Waiting device for my instance..."); @@ -199,41 +328,43 @@ private void startWiFiMqttManagedPipeline() { // Waiting Device to Use GlowWormDevice glowWormDeviceToUse = CommonUtility.getDeviceToUse(); // Check if the connected device match the minimum firmware version requirements for this Firefly Luciferin version - Boolean firmwareMatchMinRequirements = (JavaFXStarter.whoAmI == 1 || !CommonUtility.isSingleDeviceMultiScreen()) ? upgradeManager.firmwareMatchMinimumRequirements() : null; - if (CommonUtility.isSingleDeviceOtherInstance() || firmwareMatchMinRequirements != null) { + Boolean firmwareMatchMinRequirements = (MainSingleton.getInstance().whoAmI == 1 || !CommonUtility.isSingleDeviceMultiScreen()) ? upgradeManager.firmwareMatchMinimumRequirements() : null; + if ((MainSingleton.getInstance().config.getSatellites() != null && GuiSingleton.getInstance().deviceTableData != null) + && (((MainSingleton.getInstance().config.getSatellites().isEmpty()) || isSatellitesEngaged()) + && (CommonUtility.isSingleDeviceOtherInstance() || firmwareMatchMinRequirements != null))) { if (CommonUtility.isSingleDeviceOtherInstance() || Boolean.TRUE.equals(firmwareMatchMinRequirements)) { setRunning(); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.ASPECT_RATIO_TOPIC), FireflyLuciferin.config.getDefaultLedMatrix()); - if (FireflyLuciferin.guiManager.trayIconManager.getTrayIcon() != null) { - FireflyLuciferin.guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.PLAY); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_ASPECT_RATIO), MainSingleton.getInstance().config.getDefaultLedMatrix()); + if (MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon() != null) { + MainSingleton.getInstance().guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.PLAY); } StateDto stateDto = new StateDto(); stateDto.setState(Constants.ON); stateDto.setBrightness(CommonUtility.getNightBrightness()); - stateDto.setWhitetemp(FireflyLuciferin.config.getWhiteTemperature()); + stateDto.setWhitetemp(MainSingleton.getInstance().config.getWhiteTemperature()); stateDto.setMAC(glowWormDeviceToUse.getMac()); turnOnLEDs(stateDto); - if ((FireflyLuciferin.config.isFullFirmware() && FireflyLuciferin.config.isWirelessStream())) { + if ((MainSingleton.getInstance().config.isFullFirmware() && MainSingleton.getInstance().config.isWirelessStream())) { // If multi display change stream topic - if (retryNumber.getAndIncrement() < 5 && FireflyLuciferin.config.getMultiMonitor() > 1 && !CommonUtility.isSingleDeviceMultiScreen()) { - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.UNSUBSCRIBE_STREAM_TOPIC), - CommonUtility.toJsonString(new UnsubscribeInstanceDto(String.valueOf(JavaFXStarter.whoAmI), FireflyLuciferin.config.getOutputDevice()))); + if (retryNumber.getAndIncrement() < 5 && MainSingleton.getInstance().config.getMultiMonitor() > 1 && !CommonUtility.isSingleDeviceMultiScreen()) { + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_UNSUBSCRIBE_STREAM), + CommonUtility.toJsonString(new UnsubscribeInstanceDto(String.valueOf(MainSingleton.getInstance().whoAmI), MainSingleton.getInstance().config.getOutputDevice()))); CommonUtility.sleepSeconds(1); } else { retryNumber.set(0); stateDto.setEffect(Constants.STATE_ON_GLOWWORMWIFI); - stateDto.setFfeffect(LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()).getBaseI18n()); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + stateDto.setFfeffect(LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()).getBaseI18n()); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } } else { stateDto.setEffect(Constants.STATE_ON_GLOWWORM); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } - if (FireflyLuciferin.FPS_GW_CONSUMER > 0 || !FireflyLuciferin.RUNNING) { + if (MainSingleton.getInstance().FPS_GW_CONSUMER > 0 || !MainSingleton.getInstance().RUNNING) { scheduledExecutorService.shutdown(); } } else { - stopForFirmwareUpgrade(glowWormDeviceToUse); + stopForFirmwareUpgrade(); } } else { log.info("Waiting device for my instance..."); @@ -263,32 +394,34 @@ private void turnOnLEDs(StateDto stateDto) { * Set running pipeline */ private void setRunning() { - FireflyLuciferin.RUNNING = true; - FireflyLuciferin.config.setToggleLed(true); - Enums.Effect effect = LocalizedEnum.fromBaseStr(Enums.Effect.class, lastEffectInUse); + MainSingleton.getInstance().RUNNING = true; + MainSingleton.getInstance().config.setToggleLed(true); + Enums.Effect effect = LocalizedEnum.fromBaseStr(Enums.Effect.class, ManagerSingleton.getInstance().lastEffectInUse); if (Enums.Effect.MUSIC_MODE_VU_METER.equals(effect) || Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(effect) || Enums.Effect.MUSIC_MODE_BRIGHT.equals(effect) || Enums.Effect.MUSIC_MODE_RAINBOW.equals(effect)) { - FireflyLuciferin.config.setEffect(lastEffectInUse); - } else if (!lastEffectInUse.isEmpty()) { - FireflyLuciferin.config.setEffect(Enums.Effect.BIAS_LIGHT.getBaseI18n()); + MainSingleton.getInstance().config.setEffect(ManagerSingleton.getInstance().lastEffectInUse); + } else if (!ManagerSingleton.getInstance().lastEffectInUse.isEmpty()) { + MainSingleton.getInstance().config.setEffect(Enums.Effect.BIAS_LIGHT.getBaseI18n()); } } /** * Stop capturing pipeline, firmware on the running device is too old - * - * @param glowWormDeviceToUse Glow Worm device selected in use on the current Firfly Luciferin instance */ - private void stopForFirmwareUpgrade(GlowWormDevice glowWormDeviceToUse) { - PipelineManager.pipelineStarting = false; - PipelineManager.pipelineStopping = false; - DevicesTabController.oldFirmwareDevice = true; - log.error(CommonUtility.getWord(Constants.MIN_FIRMWARE_NOT_MATCH), glowWormDeviceToUse.getDeviceName(), glowWormDeviceToUse.getDeviceVersion()); + private void stopForFirmwareUpgrade() { + ManagerSingleton.getInstance().pipelineStarting = false; + ManagerSingleton.getInstance().pipelineStopping = false; + GuiSingleton.getInstance().oldFirmwareDevice = true; + for (GlowWormDevice gwd : CommonUtility.getDeviceToUseWithSatellites()) { + if (Boolean.FALSE.equals(UpgradeManager.checkFirmwareVersion(gwd))) { + log.error(CommonUtility.getWord(Constants.MIN_FIRMWARE_NOT_MATCH), gwd.getDeviceName(), gwd.getDeviceVersion()); + } + } scheduledExecutorService.shutdown(); - if (FireflyLuciferin.guiManager.trayIconManager.getTrayIcon() != null) { - FireflyLuciferin.guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.GREY); + if (MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon() != null) { + MainSingleton.getInstance().guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.GREY); } } @@ -296,35 +429,36 @@ private void stopForFirmwareUpgrade(GlowWormDevice glowWormDeviceToUse) { * Stop high performance pipeline */ public void stopCapturePipeline() { - PipelineManager.pipelineStarting = false; - PipelineManager.pipelineStopping = true; + ManagerSingleton.getInstance().pipelineStarting = false; + ManagerSingleton.getInstance().pipelineStopping = true; if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) { scheduledExecutorService.shutdown(); } AudioLoopback audioLoopback = new AudioLoopback(); audioLoopback.stopVolumeLevelMeter(); - if (FireflyLuciferin.guiManager.trayIconManager.getTrayIcon() != null) { - FireflyLuciferin.guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.STOP); - TrayIconManager.popupMenu.remove(0); - TrayIconManager.popupMenu.add(FireflyLuciferin.guiManager.trayIconManager.createMenuItem(CommonUtility.getWord(Constants.START)), 0); + if (MainSingleton.getInstance().guiManager.trayIconManager.getTrayIcon() != null) { + MainSingleton.getInstance().guiManager.trayIconManager.setTrayIconImage(Enums.PlayerStatus.STOP); + GuiSingleton.getInstance().popupMenu.remove(0); + GuiSingleton.getInstance().popupMenu.add(MainSingleton.getInstance().guiManager.trayIconManager.createMenuItem(CommonUtility.getWord(Constants.START)), 0); } - if (GrabberManager.pipe != null && ((FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) - || (FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) - || (FireflyLuciferin.config.getCaptureMethod().equals(Configuration.CaptureMethod.AVFVIDEOSRC.name())))) { - GrabberManager.pipe.stop(); + if (GrabberSingleton.getInstance().pipe != null && ((MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.DDUPL.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.XIMAGESRC.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.PIPEWIREXDG.name())) + || (MainSingleton.getInstance().config.getCaptureMethod().equals(Configuration.CaptureMethod.AVFVIDEOSRC.name())))) { + GrabberSingleton.getInstance().pipe.stop(); } - FireflyLuciferin.FPS_PRODUCER_COUNTER = 0; - FireflyLuciferin.FPS_CONSUMER_COUNTER = 0; - FireflyLuciferin.FPS_CONSUMER = 0; - FireflyLuciferin.FPS_PRODUCER = 0; - FireflyLuciferin.RUNNING = false; - AudioLoopback.RUNNING_AUDIO = false; - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); + MainSingleton.getInstance().FPS_PRODUCER_COUNTER = 0; + MainSingleton.getInstance().FPS_CONSUMER_COUNTER = 0; + MainSingleton.getInstance().FPS_CONSUMER = 0; + MainSingleton.getInstance().FPS_PRODUCER = 0; + MainSingleton.getInstance().RUNNING = false; + AudioSingleton.getInstance().RUNNING_AUDIO = false; + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); switch (effectInUse) { case BIAS_LIGHT, MUSIC_MODE_VU_METER, MUSIC_MODE_VU_METER_DUAL, MUSIC_MODE_BRIGHT, MUSIC_MODE_RAINBOW -> - lastEffectInUse = FireflyLuciferin.config.getEffect(); + ManagerSingleton.getInstance().lastEffectInUse = MainSingleton.getInstance().config.getEffect(); } - AudioLoopback.AUDIO_BRIGHTNESS = 255; - FireflyLuciferin.config.setEffect(Enums.Effect.SOLID.getBaseI18n()); + AudioSingleton.getInstance().AUDIO_BRIGHTNESS = 255; + MainSingleton.getInstance().config.setEffect(Enums.Effect.SOLID.getBaseI18n()); } } diff --git a/src/main/java/org/dpsoftware/managers/PowerSavingManager.java b/src/main/java/org/dpsoftware/managers/PowerSavingManager.java index 3900998c2..6d7dcc044 100644 --- a/src/main/java/org/dpsoftware/managers/PowerSavingManager.java +++ b/src/main/java/org/dpsoftware/managers/PowerSavingManager.java @@ -25,12 +25,12 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; +import org.dpsoftware.grabber.GrabberSingleton; import org.dpsoftware.grabber.ImageProcessor; import org.dpsoftware.gui.elements.DisplayInfo; import org.dpsoftware.utilities.CommonUtility; @@ -81,7 +81,7 @@ public void addPowerSavingTask() { if (NativeExecutor.isWindows()) { screenSaverRunning = NativeExecutor.isScreensaverRunning(); } - if (!FireflyLuciferin.RUNNING && !CommonUtility.isSingleDeviceMultiScreen() && !screenSaverRunning) { + if (!MainSingleton.getInstance().RUNNING && !CommonUtility.isSingleDeviceMultiScreen() && !screenSaverRunning) { takeScreenshot(false); } managePowerSavingLeds(); @@ -102,7 +102,7 @@ private void mouseListenerThread() { mouseMoved = false; } else { mouseMoved = true; - if (!FireflyLuciferin.RUNNING && FireflyLuciferin.config.isToggleLed() && shutDownLedStrip) { + if (!MainSingleton.getInstance().RUNNING && MainSingleton.getInstance().config.isToggleLed() && shutDownLedStrip) { CommonUtility.turnOnLEDs(); } lastFrameTime = LocalDateTime.now(); @@ -121,12 +121,12 @@ private void managePowerSavingLeds() { if (!mouseMoved && ((screenSaverTaskNeeded && screenSaverRunning) || shutDownLedStrip)) { if (powerSavingScreenSaver != PowerSavingScreenSaver.TRIGGERED_NOT_RUNNING && powerSavingScreenSaver != PowerSavingScreenSaver.TRIGGERED_RUNNING) { - if (FireflyLuciferin.RUNNING) { + if (MainSingleton.getInstance().RUNNING) { powerSavingScreenSaver = PowerSavingScreenSaver.TRIGGERED_RUNNING; shutDownLedStrip = true; } else { powerSavingScreenSaver = PowerSavingScreenSaver.TRIGGERED_NOT_RUNNING; - CommonUtility.turnOffLEDs(FireflyLuciferin.config); + CommonUtility.turnOffLEDs(MainSingleton.getInstance().config); takeScreenshot(true); } log.info("Power saving on."); @@ -159,21 +159,21 @@ public void takeScreenshot(boolean overWriteLedArray) { try { robot = new Robot(); DisplayManager displayManager = new DisplayManager(); - DisplayInfo monitorInfo = displayManager.getDisplayInfo(FireflyLuciferin.config.getMonitorNumber()); + DisplayInfo monitorInfo = displayManager.getDisplayInfo(MainSingleton.getInstance().config.getMonitorNumber()); // We use the config file here because Linux thinks that the display width and height is the sum of the available screens - ImageProcessor.screen = robot.createScreenCapture(new Rectangle( + GrabberSingleton.getInstance().screen = robot.createScreenCapture(new Rectangle( (int) (monitorInfo.getDisplayInfoAwt().getMinX() / monitorInfo.getScaleX()), (int) (monitorInfo.getDisplayInfoAwt().getMinY() / monitorInfo.getScaleX()), - (int) (FireflyLuciferin.config.getScreenResX() / monitorInfo.getScaleX()), - (int) (FireflyLuciferin.config.getScreenResY() / monitorInfo.getScaleX()) + (int) (MainSingleton.getInstance().config.getScreenResX() / monitorInfo.getScaleX()), + (int) (MainSingleton.getInstance().config.getScreenResY() / monitorInfo.getScaleX()) )); - if (FireflyLuciferin.config.getRuntimeLogLevel().equals(Level.TRACE.levelStr)) { + if (MainSingleton.getInstance().config.getRuntimeLogLevel().equals(Level.TRACE.levelStr)) { log.info("Taking screenshot"); - ImageIO.write(ImageProcessor.screen, "png", new java.io.File("screenshot" + JavaFXStarter.whoAmI + ".png")); + ImageIO.write(GrabberSingleton.getInstance().screen, "png", new java.io.File("screenshot" + MainSingleton.getInstance().whoAmI + ".png")); } - int osScaling = FireflyLuciferin.config.getOsScaling(); - Color[] ledsScreenshotTmp = new Color[ImageProcessor.ledMatrix.size()]; - LinkedHashMap ledMatrixTmp = (LinkedHashMap) ImageProcessor.ledMatrix.clone(); + int osScaling = MainSingleton.getInstance().config.getOsScaling(); + Color[] ledsScreenshotTmp = new Color[GrabberSingleton.getInstance().ledMatrix.size()]; + LinkedHashMap ledMatrixTmp = (LinkedHashMap) GrabberSingleton.getInstance().ledMatrix.clone(); // We need an ordered collection so no parallelStream here ledMatrixTmp.forEach((key, value) -> { if (overWriteLedArray) { @@ -196,7 +196,7 @@ public void takeScreenshot(boolean overWriteLedArray) { */ public boolean isScreenSaverTaskNeeded() { return NativeExecutor.isWindows() && (!Enums.PowerSaving.DISABLED.equals(LocalizedEnum.fromBaseStr(Enums.PowerSaving.class, - FireflyLuciferin.config.getPowerSaving()))) && NativeExecutor.isScreenSaverEnabled(); + MainSingleton.getInstance().config.getPowerSaving()))) && NativeExecutor.isScreenSaverEnabled(); } /** @@ -209,7 +209,7 @@ public void checkForLedDuplication(Color[] leds) { lastFrameTime = LocalDateTime.now(); ledArray = Arrays.copyOf(leds, leds.length); } - int minutesToShutdown = Integer.parseInt(FireflyLuciferin.config.getPowerSaving().split(" ")[0]); + int minutesToShutdown = Integer.parseInt(MainSingleton.getInstance().config.getPowerSaving().split(" ")[0]); if (!screenSaverTaskNeeded || !screenSaverRunning) { shutDownLedStrip = lastFrameTime.isBefore(LocalDateTime.now().minusMinutes(minutesToShutdown)); } diff --git a/src/main/java/org/dpsoftware/managers/SerialManager.java b/src/main/java/org/dpsoftware/managers/SerialManager.java index 382f90503..1bc1bd1c4 100644 --- a/src/main/java/org/dpsoftware/managers/SerialManager.java +++ b/src/main/java/org/dpsoftware/managers/SerialManager.java @@ -25,13 +25,14 @@ import javafx.scene.control.Alert; import lombok.extern.slf4j.Slf4j; import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.gui.GUIManager; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.gui.GuiManager; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.GlowWormDevice; import org.dpsoftware.utilities.CommonUtility; @@ -47,9 +48,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import static org.dpsoftware.FireflyLuciferin.config; -import static org.dpsoftware.FireflyLuciferin.serial; - /** * Serial port utility */ @@ -63,32 +61,32 @@ public class SerialManager { */ public void initSerial(FireflyLuciferin fireflyLuciferin) { CommPortIdentifier serialPortId = null; - if (!config.isWirelessStream()) { + if (!MainSingleton.getInstance().config.isWirelessStream()) { int numberOfSerialDevices = 0; var enumComm = CommPortIdentifier.getPortIdentifiers(); while (enumComm.hasMoreElements()) { numberOfSerialDevices++; CommPortIdentifier serialPortAvailable = (CommPortIdentifier) enumComm.nextElement(); - if (config.getOutputDevice().equals(serialPortAvailable.getName()) || config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO)) { + if (MainSingleton.getInstance().config.getOutputDevice().equals(serialPortAvailable.getName()) || MainSingleton.getInstance().config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO)) { serialPortId = serialPortAvailable; } } try { if (serialPortId != null) { log.info(CommonUtility.getWord(Constants.SERIAL_PORT_IN_USE) + serialPortId.getName() + ", connecting..."); - serial = serialPortId.open(fireflyLuciferin.getClass().getName(), config.getTimeout()); - serial.setSerialPortParams(Integer.parseInt(config.getBaudRate()), SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - input = new BufferedReader(new InputStreamReader(serial.getInputStream())); + MainSingleton.getInstance().serial = serialPortId.open(fireflyLuciferin.getClass().getName(), MainSingleton.getInstance().config.getTimeout()); + MainSingleton.getInstance().serial.setSerialPortParams(Integer.parseInt(MainSingleton.getInstance().config.getBaudRate()), SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + input = new BufferedReader(new InputStreamReader(MainSingleton.getInstance().serial.getInputStream())); // add event listeners - serial.addEventListener(fireflyLuciferin); - serial.notifyOnDataAvailable(true); - DevicesTabController.deviceTableData.add(new GlowWormDevice(Constants.USB_DEVICE, serialPortId.getName(), false, + MainSingleton.getInstance().serial.addEventListener(fireflyLuciferin); + MainSingleton.getInstance().serial.notifyOnDataAvailable(true); + GuiSingleton.getInstance().deviceTableData.add(new GlowWormDevice(Constants.USB_DEVICE, serialPortId.getName(), false, Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH, - FireflyLuciferin.formatter.format(new Date()), Constants.DASH, Constants.DASH, Constants.DASH, Enums.ColorOrder.GRB.name(), + MainSingleton.getInstance().formatter.format(new Date()), Constants.DASH, Constants.DASH, Constants.DASH, Enums.ColorOrder.GRB.name(), Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH, Constants.DASH)); - GUIManager guiManager = new GUIManager(); - if (numberOfSerialDevices > 1 && config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO)) { - FireflyLuciferin.communicationError = true; + GuiManager guiManager = new GuiManager(); + if (numberOfSerialDevices > 1 && MainSingleton.getInstance().config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO)) { + MainSingleton.getInstance().communicationError = true; if (NativeExecutor.isWindows()) { guiManager.showLocalizedNotification(Constants.SERIAL_PORT_AMBIGUOUS, Constants.SERIAL_PORT_AMBIGUOUS_CONTEXT, TrayIcon.MessageType.ERROR); @@ -99,17 +97,17 @@ public void initSerial(FireflyLuciferin fireflyLuciferin) { log.error(Constants.SERIAL_ERROR_OPEN_HEADER); } log.info("Connected: Serial " + serialPortId.getName()); - if (FireflyLuciferin.guiManager != null) { - FireflyLuciferin.guiManager.trayIconManager.resetTray(); + if (MainSingleton.getInstance().guiManager != null) { + MainSingleton.getInstance().guiManager.trayIconManager.resetTray(); } - FireflyLuciferin.serialConnected = true; - FireflyLuciferin.communicationError = false; + MainSingleton.getInstance().serialConnected = true; + MainSingleton.getInstance().communicationError = false; initOutputStream(); } } catch (PortInUseException | UnsupportedCommOperationException | NullPointerException | IOException | TooManyListenersException e) { log.error(e.getMessage()); - FireflyLuciferin.communicationError = true; + MainSingleton.getInstance().communicationError = true; } } } @@ -122,48 +120,48 @@ public void initSerial(FireflyLuciferin fireflyLuciferin) { */ public void sendColorsViaUSB(Color[] leds) throws IOException { // Effect is set via MQTT when using Full Firmware - if (config.isFullFirmware()) { - FireflyLuciferin.fireflyEffect = 100; + if (MainSingleton.getInstance().config.isFullFirmware()) { + MainSingleton.getInstance().fireflyEffect = 100; } else { for (Enums.Effect ef : Enums.Effect.values()) { - if (ef.getBaseI18n().equals(config.getEffect())) { - FireflyLuciferin.fireflyEffect = ef.ordinal() + 1; + if (ef.getBaseI18n().equals(MainSingleton.getInstance().config.getEffect())) { + MainSingleton.getInstance().fireflyEffect = ef.ordinal() + 1; } } } - if (!UpgradeManager.serialVersionOk) { + if (!ManagerSingleton.getInstance().serialVersionOk) { UpgradeManager upgradeManager = new UpgradeManager(); // Check if the connected device match the minimum firmware version requirements for this Firefly Luciferin version Boolean firmwareMatchMinRequirements = upgradeManager.firmwareMatchMinimumRequirements(); if (firmwareMatchMinRequirements != null) { if (firmwareMatchMinRequirements) { - UpgradeManager.serialVersionOk = true; + ManagerSingleton.getInstance().serialVersionOk = true; } } } else { int i = 0, j = -1; - byte[] ledsArray = new byte[(FireflyLuciferin.ledNumber * 3) + 26]; + byte[] ledsArray = new byte[(MainSingleton.getInstance().ledNumber * 3) + 26]; // DPsoftware checksum - int ledsCountHi = ((FireflyLuciferin.ledNumHighLowCount) >> 8) & 0xff; - int ledsCountLo = (FireflyLuciferin.ledNumHighLowCount) & 0xff; - int loSecondPart = (FireflyLuciferin.ledNumHighLowCountSecondPart) & 0xff; - int brightnessToSend = (AudioLoopback.AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioLoopback.AUDIO_BRIGHTNESS) & 0xff; - int gpioToSend = (FireflyLuciferin.gpio) & 0xff; - int baudRateToSend = (FireflyLuciferin.baudRate) & 0xff; - int whiteTempToSend = (config.getWhiteTemperature()) & 0xff; - int fireflyEffectToSend = (FireflyLuciferin.fireflyEffect) & 0xff; - int enableLdr = (config.isEnableLDR() ? 1 : 2) & 0xff; - int ldrTurnOff = (config.isLdrTurnOff() ? 1 : 2) & 0xff; - int ldrInterval = (config.getLdrInterval()) & 0xff; - int ldrMin = (config.getLdrMin()) & 0xff; - int ldrActionToUse = (FireflyLuciferin.ldrAction) & 0xff; - int colorModeToSend = (config.getColorMode()) & 0xff; - int colorOrderToSend = (FireflyLuciferin.colorOrder) & 0xff; + int ledsCountHi = ((MainSingleton.getInstance().ledNumHighLowCount) >> 8) & 0xff; + int ledsCountLo = (MainSingleton.getInstance().ledNumHighLowCount) & 0xff; + int loSecondPart = (MainSingleton.getInstance().ledNumHighLowCountSecondPart) & 0xff; + int brightnessToSend = (AudioSingleton.getInstance().AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioSingleton.getInstance().AUDIO_BRIGHTNESS) & 0xff; + int gpioToSend = (MainSingleton.getInstance().gpio) & 0xff; + int baudRateToSend = (MainSingleton.getInstance().baudRate) & 0xff; + int whiteTempToSend = (MainSingleton.getInstance().config.getWhiteTemperature()) & 0xff; + int fireflyEffectToSend = (MainSingleton.getInstance().fireflyEffect) & 0xff; + int enableLdr = (MainSingleton.getInstance().config.isEnableLDR() ? 1 : 2) & 0xff; + int ldrTurnOff = (MainSingleton.getInstance().config.isLdrTurnOff() ? 1 : 2) & 0xff; + int ldrInterval = (MainSingleton.getInstance().config.getLdrInterval()) & 0xff; + int ldrMin = (MainSingleton.getInstance().config.getLdrMin()) & 0xff; + int ldrActionToUse = (MainSingleton.getInstance().ldrAction) & 0xff; + int colorModeToSend = (MainSingleton.getInstance().config.getColorMode()) & 0xff; + int colorOrderToSend = (MainSingleton.getInstance().colorOrder) & 0xff; // Pins is set to +10 because null values are zero, so GPIO 0 is 10, GPIO 1 is 11. - int relayPinToSend = (FireflyLuciferin.relayPin >= 0 ? FireflyLuciferin.relayPin + 10 : 0) & 0xff; - int sbPinToSend = (FireflyLuciferin.sbPin >= 0 ? FireflyLuciferin.sbPin + 10 : 0) & 0xff; - int ldrPinToSend = (FireflyLuciferin.ldrPin >= 0 ? FireflyLuciferin.ldrPin + 10 : 0) & 0xff; - int gpioClockToSend = (FireflyLuciferin.gpioClockPin) & 0xff; + int relayPinToSend = (MainSingleton.getInstance().relayPin >= 0 ? MainSingleton.getInstance().relayPin + 10 : 0) & 0xff; + int sbPinToSend = (MainSingleton.getInstance().sbPin >= 0 ? MainSingleton.getInstance().sbPin + 10 : 0) & 0xff; + int ldrPinToSend = (MainSingleton.getInstance().ldrPin >= 0 ? MainSingleton.getInstance().ldrPin + 10 : 0) & 0xff; + int gpioClockToSend = (MainSingleton.getInstance().gpioClockPin) & 0xff; ledsArray[++j] = (byte) ('D'); ledsArray[++j] = (byte) ('P'); ledsArray[++j] = (byte) ('s'); @@ -191,24 +189,24 @@ public void sendColorsViaUSB(Color[] leds) throws IOException { ledsArray[++j] = (byte) (gpioClockToSend); ledsArray[++j] = (byte) ((ledsCountHi ^ ledsCountLo ^ loSecondPart ^ brightnessToSend ^ gpioToSend ^ baudRateToSend ^ whiteTempToSend ^ fireflyEffectToSend ^ enableLdr ^ ldrTurnOff ^ ldrInterval ^ ldrMin ^ ldrActionToUse ^ colorModeToSend ^ colorOrderToSend ^ relayPinToSend ^ sbPinToSend ^ ldrPinToSend ^ gpioClockToSend ^ 0x55)); - FireflyLuciferin.ldrAction = 1; + MainSingleton.getInstance().ldrAction = 1; if (leds.length == 1) { - FireflyLuciferin.colorInUse = leds[0]; - while (i < FireflyLuciferin.ledNumber) { + MainSingleton.getInstance().colorInUse = leds[0]; + while (i < MainSingleton.getInstance().ledNumber) { ledsArray[++j] = (byte) leds[0].getRed(); ledsArray[++j] = (byte) leds[0].getGreen(); ledsArray[++j] = (byte) leds[0].getBlue(); i++; } } else { - while (i < FireflyLuciferin.ledNumber) { + while (i < MainSingleton.getInstance().ledNumber) { ledsArray[++j] = (byte) leds[i].getRed(); ledsArray[++j] = (byte) leds[i].getGreen(); ledsArray[++j] = (byte) leds[i].getBlue(); i++; } } - FireflyLuciferin.output.write(ledsArray); + MainSingleton.getInstance().output.write(ledsArray); } } @@ -219,18 +217,18 @@ public void sendColorsViaUSB(Color[] leds) throws IOException { public void manageSolidLed() { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); scheduledExecutorService.scheduleAtFixedRate(() -> { - if (!FireflyLuciferin.RUNNING) { - if (config.isToggleLed() && !config.isFullFirmware()) { + if (!MainSingleton.getInstance().RUNNING) { + if (MainSingleton.getInstance().config.isToggleLed() && !MainSingleton.getInstance().config.isFullFirmware()) { Color[] colorToUse = new Color[1]; - if (FireflyLuciferin.colorInUse == null) { - String[] color = config.getColorChooser().split(","); + if (MainSingleton.getInstance().colorInUse == null) { + String[] color = MainSingleton.getInstance().config.getColorChooser().split(","); colorToUse[0] = new Color(Integer.parseInt(color[0]), Integer.parseInt(color[1]), Integer.parseInt(color[2])); - config.setBrightness(Integer.parseInt(color[3])); + MainSingleton.getInstance().config.setBrightness(Integer.parseInt(color[3])); } else { - colorToUse[0] = FireflyLuciferin.colorInUse; + colorToUse[0] = MainSingleton.getInstance().colorInUse; } try { - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, config.getEffect()); + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); if (Enums.Effect.RAINBOW.equals(effectInUse) || Enums.Effect.FIRE.equals(effectInUse)) { for (int i = 0; i <= 10; i++) { sendColorsViaUSB(colorToUse); @@ -251,11 +249,11 @@ public void manageSolidLed() { * Initialize OutputStream */ public void initOutputStream() { - if (!config.isWirelessStream() && !FireflyLuciferin.communicationError) { + if (!MainSingleton.getInstance().config.isWirelessStream() && !MainSingleton.getInstance().communicationError) { try { - FireflyLuciferin.output = serial.getOutputStream(); + MainSingleton.getInstance().output = MainSingleton.getInstance().serial.getOutputStream(); } catch (IOException | NullPointerException e) { - FireflyLuciferin.communicationError = true; + MainSingleton.getInstance().communicationError = true; log.error(e.getMessage()); log.error(Constants.SERIAL_ERROR_HEADER); } @@ -273,21 +271,21 @@ public void handleSerialEvent(SerialPortEvent event) { if (input.ready()) { String inputLine = input.readLine(); log.debug(inputLine); - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) { - if (!config.isMqttEnable() && config.isFullFirmware()) { - DevicesTabController.deviceTableData.forEach(gwDevice -> { + if (!MainSingleton.getInstance().config.isMqttEnable() && MainSingleton.getInstance().config.isFullFirmware()) { + GuiSingleton.getInstance().deviceTableData.forEach(gwDevice -> { if (glowWormDevice.getMac().equals(gwDevice.getMac())) { - gwDevice.setLastSeen(FireflyLuciferin.formatter.format(new Date())); + gwDevice.setLastSeen(MainSingleton.getInstance().formatter.format(new Date())); } }); } - glowWormDevice.setLastSeen(FireflyLuciferin.formatter.format(new Date())); + glowWormDevice.setLastSeen(MainSingleton.getInstance().formatter.format(new Date())); // Skipping the Setting LED loop from Glow Worm Luciferin Serial communication if (!inputLine.contains(Constants.SETTING_LED_SERIAL)) { if (inputLine.contains(Constants.SERIAL_VERSION)) { String deviceVer = inputLine.replace(Constants.SERIAL_VERSION, ""); - if (config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard())) { + if (MainSingleton.getInstance().config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard())) { deviceVer = Constants.FORCE_FIRMWARE_AUTO_UPGRADE; } glowWormDevice.setDeviceVersion(deviceVer); @@ -314,10 +312,10 @@ public void handleSerialEvent(SerialPortEvent event) { validBaudrate = false; } glowWormDevice.setBaudRate(validBaudrate ? Enums.BaudRate.findByValue(receivedBaudrate).getBaudRate() : Constants.DASH); - } else if ((!config.isFullFirmware() || !config.isMqttEnable() || !config.isWirelessStream()) && inputLine.contains(Constants.SERIAL_FRAMERATE)) { - FireflyLuciferin.FPS_GW_CONSUMER = Float.parseFloat(inputLine.replace(Constants.SERIAL_FRAMERATE, "")); + } else if ((!MainSingleton.getInstance().config.isFullFirmware() || !MainSingleton.getInstance().config.isMqttEnable()) && inputLine.contains(Constants.SERIAL_FRAMERATE)) { + MainSingleton.getInstance().FPS_GW_CONSUMER = Float.parseFloat(inputLine.replace(Constants.SERIAL_FRAMERATE, "")); } else if (inputLine.contains(Constants.SERIAL_LDR)) { - CommonUtility.ldrStrength = Integer.parseInt(inputLine.replace(Constants.SERIAL_LDR, "")); + MainSingleton.getInstance().ldrStrength = Integer.parseInt(inputLine.replace(Constants.SERIAL_LDR, "")); glowWormDevice.setLdrValue(inputLine.replace(Constants.SERIAL_LDR, "") + Constants.PERCENT); } else if (inputLine.contains(Constants.SERIAL_LDR_LDRPIN)) { glowWormDevice.setLdrPin(inputLine.replace(Constants.SERIAL_LDR_LDRPIN, "")); @@ -351,9 +349,9 @@ public Map getAvailableDevices() { try { serialPortId = (CommPortIdentifier) enumComm.nextElement(); if (serialPortId != null) { - serial = serialPortId.open(FireflyLuciferin.class.getName(), config != null ? config.getTimeout() : 2000); + MainSingleton.getInstance().serial = serialPortId.open(FireflyLuciferin.class.getName(), MainSingleton.getInstance().config != null ? MainSingleton.getInstance().config.getTimeout() : 2000); availableDevice.put(serialPortId.getName(), true); - serial.close(); + MainSingleton.getInstance().serial.close(); } } catch (PortInUseException | NullPointerException e) { if (serialPortId != null) { diff --git a/src/main/java/org/dpsoftware/managers/StorageManager.java b/src/main/java/org/dpsoftware/managers/StorageManager.java index d98743f28..04521248a 100644 --- a/src/main/java/org/dpsoftware/managers/StorageManager.java +++ b/src/main/java/org/dpsoftware/managers/StorageManager.java @@ -29,14 +29,13 @@ import javafx.scene.Scene; import javafx.stage.Stage; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; import org.dpsoftware.LEDCoordinate; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; -import org.dpsoftware.gui.GUIManager; +import org.dpsoftware.gui.GuiManager; import org.dpsoftware.gui.controllers.ColorCorrectionDialogController; import org.dpsoftware.managers.dto.LedMatrixInfo; import org.dpsoftware.utilities.CommonUtility; @@ -56,7 +55,6 @@ @Slf4j public class StorageManager { - public static boolean updateMqttDiscovery = false; private final ObjectMapper mapper; public boolean restartNeeded = false; private String path; @@ -89,7 +87,7 @@ public StorageManager() { * @throws IOException can't write to file */ public void writeConfig(Configuration config, String forceFilename) throws IOException { - String filename = switch (JavaFXStarter.whoAmI) { + String filename = switch (MainSingleton.getInstance().whoAmI) { case 1 -> Constants.CONFIG_FILENAME; case 2 -> Constants.CONFIG_FILENAME_2; case 3 -> Constants.CONFIG_FILENAME_3; @@ -135,7 +133,7 @@ public Configuration readConfigFile(String filename) { */ public Configuration readProfileAndCheckDifference(String profileName, StorageManager sm) { Configuration config = readProfileConfig(profileName); - sm.checkProfileDifferences(config, FireflyLuciferin.config); + sm.checkProfileDifferences(config, MainSingleton.getInstance().config); return config; } @@ -155,7 +153,7 @@ public Configuration readProfileConfig(String profileName) { * @return current configuration file */ public Configuration readProfileInUseConfig() { - return readConfig(false, FireflyLuciferin.config != null ? FireflyLuciferin.profileArgs : Constants.DEFAULT); + return readConfig(false, MainSingleton.getInstance().config != null ? MainSingleton.getInstance().profileArgs : Constants.DEFAULT); } /** @@ -183,9 +181,9 @@ public Configuration readConfig(boolean readMainConfig, String profileName) { if (readMainConfig) { return mainConfig; } - if (JavaFXStarter.whoAmI == 2) { + if (MainSingleton.getInstance().whoAmI == 2) { currentConfig = readConfigFile(Constants.CONFIG_FILENAME_2); - } else if (JavaFXStarter.whoAmI == 3) { + } else if (MainSingleton.getInstance().whoAmI == 3) { currentConfig = readConfigFile(Constants.CONFIG_FILENAME_3); } else { currentConfig = mainConfig; @@ -239,7 +237,7 @@ public void checkProfileDifferences(Configuration defaultConfig, Configuration p restartReasons.add(Constants.TOOLTIP_MONITORNUMBER); if (defaultConfig.getMultiMonitor() != profileConfig.getMultiMonitor()) restartReasons.add(Constants.TOOLTIP_MULTIMONITOR); - if (restartReasons.size() > 0) { + if (!restartReasons.isEmpty()) { restartNeeded = true; log.info(String.join("\n", restartReasons)); } @@ -263,8 +261,8 @@ public boolean checkIfFileExist(String filename) { */ public Configuration loadConfigurationYaml() { Configuration config; - if (FireflyLuciferin.profileArgs != null && !FireflyLuciferin.profileArgs.isEmpty()) { - config = readProfileConfig(FireflyLuciferin.profileArgs); + if (MainSingleton.getInstance().profileArgs != null && !MainSingleton.getInstance().profileArgs.isEmpty()) { + config = readProfileConfig(MainSingleton.getInstance().profileArgs); } else { config = readProfileInUseConfig(); } @@ -272,14 +270,14 @@ public Configuration loadConfigurationYaml() { try { String fxml; fxml = Constants.FXML_SETTINGS; - Scene scene = new Scene(GUIManager.loadFXML(fxml)); + Scene scene = new Scene(GuiManager.loadFXML(fxml)); Stage stage = new Stage(); stage.setTitle(" " + CommonUtility.getWord(Constants.SETTINGS)); stage.setScene(scene); if (!NativeExecutor.isSystemTraySupported() || NativeExecutor.isLinux()) { stage.setOnCloseRequest(evt -> NativeExecutor.exit()); } - GUIManager.setStageIcon(stage); + GuiManager.setStageIcon(stage); stage.showAndWait(); config = readProfileInUseConfig(); } catch (IOException stageError) { @@ -328,7 +326,7 @@ public void updateConfigFile(Configuration config) throws IOException { } } if (writeToStorage) { - config.setConfigVersion(FireflyLuciferin.version); + config.setConfigVersion(MainSingleton.getInstance().version); writeConfig(config, null); } } @@ -440,7 +438,7 @@ private boolean updatePrevious2124(Configuration config, boolean writeToStorage) if (UpgradeManager.versionNumberToNumber(config.getConfigVersion()) < 21121004) { if (config.isMqttEnable()) { if (CommonUtility.isSingleDeviceMainInstance() || !CommonUtility.isSingleDeviceMultiScreen()) { - updateMqttDiscovery = true; + ManagerSingleton.getInstance().updateMqttDiscovery = true; writeToStorage = true; } } @@ -479,8 +477,8 @@ private void configureLedMatrix(Configuration config) { public Set listProfilesForThisInstance() { return Stream.of(Objects.requireNonNull(new File(path + File.separator).listFiles())) .filter(file -> !file.isDirectory()) - .filter(file -> file.getName().split("_")[0].equals(String.valueOf(JavaFXStarter.whoAmI))) - .map(file -> file.getName().replace(Constants.YAML_EXTENSION, "").replace(JavaFXStarter.whoAmI + "_", "")) + .filter(file -> file.getName().split("_")[0].equals(String.valueOf(MainSingleton.getInstance().whoAmI))) + .map(file -> file.getName().replace(Constants.YAML_EXTENSION, "").replace(MainSingleton.getInstance().whoAmI + "_", "")) .sorted() .collect(Collectors.toCollection(LinkedHashSet::new)); } @@ -503,7 +501,7 @@ public boolean deleteProfile(String profileName) { * @return file name */ public String getProfileFileName(String profileName) { - return JavaFXStarter.whoAmI + "_" + profileName + Constants.YAML_EXTENSION; + return MainSingleton.getInstance().whoAmI + "_" + profileName + Constants.YAML_EXTENSION; } /** diff --git a/src/main/java/org/dpsoftware/managers/UpgradeManager.java b/src/main/java/org/dpsoftware/managers/UpgradeManager.java index 97492806f..30dbbb601 100644 --- a/src/main/java/org/dpsoftware/managers/UpgradeManager.java +++ b/src/main/java/org/dpsoftware/managers/UpgradeManager.java @@ -36,13 +36,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; -import org.dpsoftware.gui.GUIManager; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.gui.GuiManager; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.GlowWormDevice; import org.dpsoftware.managers.dto.WebServerStarterDto; import org.dpsoftware.network.tcpUdp.TcpClient; @@ -62,10 +61,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import java.util.Random; +import java.util.*; import java.util.stream.Collectors; /** @@ -77,8 +74,6 @@ @NoArgsConstructor public class UpgradeManager { - public static boolean serialVersionOk = false; - public static String deviceNameForSerialDevice = ""; String latestReleaseStr = ""; /** @@ -95,6 +90,52 @@ public static long versionNumberToNumber(String latestReleaseStr) { + Long.parseLong((majorMinorHotfix[2])); } + /** + * Get buffered reader for the url connection + * + * @param useAlphaFirmware params that specify if we must use an alpha firm + * @return buffered reader + * @throws URISyntaxException invalid url + * @throws IOException can't open connecton + */ + private static BufferedReader getBufferedReader(boolean useAlphaFirmware) throws URISyntaxException, IOException { + URL url; + if (useAlphaFirmware) { + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { + url = new URI(Constants.GITHUB_GLOW_WORM_URL_FULL_BETA).toURL(); + } else { + url = new URI(Constants.GITHUB_GLOW_WORM_URL_LIGHT_BETA).toURL(); + } + } else { + if (MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isFullFirmware()) { + url = new URI(Constants.GITHUB_GLOW_WORM_URL_FULL).toURL(); + } else { + url = new URI(Constants.GITHUB_GLOW_WORM_URL_LIGHT).toURL(); + } + } + URLConnection urlConnection = url.openConnection(); + return new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + } + + /** + * Check if the device passed as input matches the minimum firmware version + * + * @param glowWormDeviceInUse device to check + * @return true or false if it matches, null if there is no device connected with that IP + */ + public static Boolean checkFirmwareVersion(GlowWormDevice glowWormDeviceInUse) { + PropertiesLoader propertiesLoader = new PropertiesLoader(); + if (glowWormDeviceInUse != null && glowWormDeviceInUse.getMac() != null && !Constants.DASH.equals(glowWormDeviceInUse.getDeviceVersion()) + && !glowWormDeviceInUse.getDeviceVersion().isEmpty() && !Constants.LIGHT_FIRMWARE_DUMMY_VERSION.equals(glowWormDeviceInUse.getDeviceVersion())) { + String minimumFirmwareVersionProp = propertiesLoader.retrieveProperties(Constants.PROP_MINIMUM_FIRMWARE_VERSION); + long minimumFirmwareVersion = versionNumberToNumber(minimumFirmwareVersionProp); + long deviceVersion = versionNumberToNumber(glowWormDeviceInUse.getDeviceVersion()); + return (deviceVersion >= minimumFirmwareVersion); + } else { + return null; + } + } + /** * Check for Firefly Luciferin update on GitHub * @@ -141,22 +182,7 @@ public boolean checkRemoteUpdateGW(boolean useAlphaFirmware, String currentVersi try { if (currentVersion != null && !currentVersion.equals(Constants.LIGHT_FIRMWARE_DUMMY_VERSION) && !currentVersion.equals(Constants.DASH)) { long numericVerion = versionNumberToNumber(currentVersion); - URL url; - if (useAlphaFirmware) { - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { - url = new URI(Constants.GITHUB_GLOW_WORM_URL_FULL_BETA).toURL(); - } else { - url = new URI(Constants.GITHUB_GLOW_WORM_URL_LIGHT_BETA).toURL(); - } - } else { - if (FireflyLuciferin.config != null && FireflyLuciferin.config.isFullFirmware()) { - url = new URI(Constants.GITHUB_GLOW_WORM_URL_FULL).toURL(); - } else { - url = new URI(Constants.GITHUB_GLOW_WORM_URL_LIGHT).toURL(); - } - } - URLConnection urlConnection = url.openConnection(); - BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + BufferedReader in = getBufferedReader(useAlphaFirmware); String inputLine; StringBuilder jsonStr = new StringBuilder(); while ((inputLine = in.readLine()) != null) { @@ -195,7 +221,7 @@ public void downloadNewVersion(Stage stage) { Scene scene = new Scene(root); stage.setScene(scene); stage.setTitle(CommonUtility.getWord(Constants.DOWNLOADING) + " " + Constants.FIREFLY_LUCIFERIN + " v" + latestReleaseStr); - GUIManager.setStageIcon(stage); + GuiManager.setStageIcon(stage); Label label = new Label(""); final ProgressBar progressBar = new ProgressBar(0); @@ -224,7 +250,7 @@ public void downloadNewVersion(Stage stage) { * * @return downloader task */ - @SuppressWarnings({"all"}) + @SuppressWarnings("all") private Task createWorker() { return new Task() { @Override @@ -237,13 +263,13 @@ protected Object call() throws Exception { filename = Constants.SETUP_FILENAME_MAC; } else { List commandOutput = NativeExecutor.runNative(Constants.DPKG_CHECK_CMD.split(" "), Constants.CMD_WAIT_DELAY); - if (commandOutput.size() > 0) { + if (!commandOutput.isEmpty()) { filename = Constants.SETUP_FILENAME_LINUX_DEB; } else { filename = Constants.SETUP_FILENAME_LINUX_RPM; } } - URL website = new URL(Constants.GITHUB_RELEASES + latestReleaseStr + "/" + filename); + URL website = new URI(Constants.GITHUB_RELEASES + latestReleaseStr + "/" + filename).toURL(); URLConnection connection = website.openConnection(); ReadableByteChannel rbc = Channels.newChannel(connection.getInputStream()); String downloadPath = System.getProperty(Constants.HOME_PATH) + File.separator + Constants.DOCUMENTS_FOLDER @@ -260,13 +286,13 @@ protected Object call() throws Exception { updateMessage(CommonUtility.getWord(Constants.DOWNLOAD_PROGRESS_BAR) + percentage + Constants.PERCENT); updateProgress(percentage, 100); } - if (transferedSize >= expectedSize) { - log.info(transferedSize + CommonUtility.getWord(Constants.DOWNLOAD_COMPLETE)); - } + log.info(transferedSize + CommonUtility.getWord(Constants.DOWNLOAD_COMPLETE)); fos.close(); Thread.sleep(1000); if (NativeExecutor.isWindows()) { - Runtime.getRuntime().exec(downloadPath); + List execCommand = new ArrayList<>(); + execCommand.add(downloadPath); + NativeExecutor.runNative(execCommand.toArray(String[]::new), 0); } NativeExecutor.exit(); } catch (IOException e) { @@ -285,9 +311,9 @@ protected Object call() throws Exception { */ public boolean checkFireflyUpdates(Stage stage) { boolean fireflyUpdate = false; - if (FireflyLuciferin.config.isCheckForUpdates()) { + if (MainSingleton.getInstance().config.isCheckForUpdates()) { log.info("Checking for Firefly Luciferin Update"); - fireflyUpdate = checkRemoteUpdateFF(FireflyLuciferin.version); + fireflyUpdate = checkRemoteUpdateFF(MainSingleton.getInstance().version); if (fireflyUpdate) { String upgradeContext; if (NativeExecutor.isWindows()) { @@ -297,7 +323,7 @@ public boolean checkFireflyUpdates(Stage stage) { } else { upgradeContext = CommonUtility.getWord(Constants.CLICK_OK_DOWNLOAD_LINUX) + CommonUtility.getWord(Constants.ONCE_DOWNLOAD_FINISHED); } - Optional result = FireflyLuciferin.guiManager.showWebAlert(Constants.FIREFLY_LUCIFERIN, + Optional result = MainSingleton.getInstance().guiManager.showWebAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.NEW_VERSION_AVAILABLE) + " " + upgradeContext, Constants.GITHUB_CHANGELOG, Alert.AlertType.CONFIRMATION); ButtonType button = result.orElse(ButtonType.OK); @@ -309,96 +335,6 @@ public boolean checkFireflyUpdates(Stage stage) { return fireflyUpdate; } - /** - * Check for Glow Worm Luciferin updates - * - * @param fireflyUpdate check is done if Firefly Luciferin is up to date - */ - public void checkGlowWormUpdates(boolean fireflyUpdate) { - if (FireflyLuciferin.config.isCheckForUpdates() && !FireflyLuciferin.communicationError && !fireflyUpdate) { - CommonUtility.delaySeconds(() -> { - PropertiesLoader propertiesLoader = new PropertiesLoader(); - boolean useAlphaFirmware = Boolean.parseBoolean(propertiesLoader.retrieveProperties(Constants.GW_ALPHA_DOWNLOAD)); - log.info("Checking for Glow Worm Luciferin Update" + (useAlphaFirmware ? " using Alpha channel." : "")); - if (!DevicesTabController.deviceTableData.isEmpty()) { - ArrayList devicesToUpdate = new ArrayList<>(); - // Updating MQTT devices for FULL firmware or Serial devices for LIGHT firmware - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { - if (!FireflyLuciferin.config.isFullFirmware() || !glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) { - // USB Serial device prior to 4.3.8 and there is no version information, needs the update so fake the version - if (glowWormDevice.getDeviceVersion().equals(Constants.DASH)) { - glowWormDevice.setDeviceVersion(Constants.LIGHT_FIRMWARE_DUMMY_VERSION); - } - if (checkRemoteUpdateGW(useAlphaFirmware, glowWormDevice.getDeviceVersion())) { - // If MQTT is enabled only first instance manage the update, if MQTT is disabled every instance, manage its notification - if (!FireflyLuciferin.config.isFullFirmware() || JavaFXStarter.whoAmI == 1 || NetworkManager.currentTopicDiffersFromMainTopic()) { - devicesToUpdate.add(glowWormDevice); - } - } - } - }); - if (!devicesToUpdate.isEmpty()) { - javafx.application.Platform.runLater(() -> { - String deviceToUpdateStr = devicesToUpdate - .stream() - .map(s -> Constants.DASH + " " + "(" + s.getDeviceIP() + ") " + s.getDeviceName() + "\n") - .collect(Collectors.joining()); - String deviceContent; - if (devicesToUpdate.size() == 1) { - deviceContent = FireflyLuciferin.config.isFullFirmware() ? CommonUtility.getWord(Constants.DEVICE_UPDATED) : CommonUtility.getWord(Constants.DEVICE_UPDATED_LIGHT); - } else { - deviceContent = CommonUtility.getWord(Constants.DEVICES_UPDATED); - } - String upgradeMessage; - if (NativeExecutor.isLinux()) { - upgradeMessage = CommonUtility.getWord(Constants.UPDATE_NEEDED_LINUX); - } else { - upgradeMessage = CommonUtility.getWord(Constants.UPDATE_NEEDED); - } - Optional result = FireflyLuciferin.guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, - CommonUtility.getWord(Constants.NEW_FIRMWARE_AVAILABLE), deviceContent + deviceToUpdateStr - + (FireflyLuciferin.config.isFullFirmware() ? CommonUtility.getWord(Constants.UPDATE_BACKGROUND) : upgradeMessage) - + "\n", Alert.AlertType.CONFIRMATION); - ButtonType button = result.orElse(ButtonType.OK); - if (FireflyLuciferin.config.isFullFirmware()) { - if (button == ButtonType.OK) { - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); - CommonUtility.sleepSeconds(15); - } - if (FireflyLuciferin.config.isMqttEnable()) { - log.info("Starting web server"); - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.UPDATE_MQTT_TOPIC), - CommonUtility.toJsonString(new WebServerStarterDto(true))); - devicesToUpdate.forEach(glowWormDevice -> executeUpdate(glowWormDevice, false)); - } else { - devicesToUpdate.forEach(glowWormDevice -> { - log.info("Starting web server: " + glowWormDevice.getDeviceIP()); - TcpClient.httpGet(CommonUtility.toJsonString(new WebServerStarterDto(true)), - NetworkManager.getTopic(Constants.UPDATE_MQTT_TOPIC), glowWormDevice.getDeviceIP()); - log.info("Updating: " + glowWormDevice.getDeviceIP()); - CommonUtility.sleepSeconds(5); - executeUpdate(glowWormDevice, false); - }); - FireflyLuciferin.guiManager.startCapturingThreads(); - } - } - } else { - if (button == ButtonType.OK) { - if (NativeExecutor.isLinux()) { - devicesToUpdate.forEach(glowWormDevice -> executeUpdate(glowWormDevice, true)); - } else { - FireflyLuciferin.guiManager.surfToURL(Constants.WEB_INSTALLER_URL); - } - } - } - }); - } - } - }, 20); - } - } - /** * Execute the firmware upgrade on the microcontroller * @@ -411,7 +347,7 @@ void executeUpdate(GlowWormDevice glowWormDevice, boolean downloadFirmwareOnly) if (versionNumberToNumber(glowWormDevice.getDeviceVersion()) > versionNumberToNumber(Constants.MINIMUM_FIRMWARE_FOR_AUTO_UPGRADE)) { CommonUtility.sleepSeconds(4); String filename; - if (FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config.isFullFirmware()) { filename = Constants.UPDATE_FILENAME; } else { filename = Constants.UPDATE_FILENAME_LIGHT; @@ -430,9 +366,9 @@ void executeUpdate(GlowWormDevice glowWormDevice, boolean downloadFirmwareOnly) } } else { if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showLocalizedNotification(Constants.CANT_UPGRADE_TOO_OLD, Constants.MANUAL_UPGRADE, TrayIcon.MessageType.INFO); + MainSingleton.getInstance().guiManager.showLocalizedNotification(Constants.CANT_UPGRADE_TOO_OLD, Constants.MANUAL_UPGRADE, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showLocalizedAlert(Constants.FIREFLY_LUCIFERIN, Constants.CANT_UPGRADE_TOO_OLD, + MainSingleton.getInstance().guiManager.showLocalizedAlert(Constants.FIREFLY_LUCIFERIN, Constants.CANT_UPGRADE_TOO_OLD, Constants.MANUAL_UPGRADE, Alert.AlertType.INFORMATION); } } @@ -485,17 +421,17 @@ private void postDataToMicrocontroller(GlowWormDevice glowWormDevice, Path path) } if (Constants.OK.contentEquals(response)) { log.info(CommonUtility.getWord(Constants.FIRMWARE_UPGRADE_RES), glowWormDevice.getDeviceName(), Constants.OK); - if (!FireflyLuciferin.config.isMqttEnable()) { + if (!MainSingleton.getInstance().config.isMqttEnable()) { String notificationContext = glowWormDevice.getDeviceName() + " "; - if (Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard()) && !FireflyLuciferin.config.isWirelessStream()) { + if (Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard()) && !MainSingleton.getInstance().config.isWirelessStream()) { notificationContext += CommonUtility.getWord(Constants.DEVICEUPGRADE_SUCCESS_CDC); } else { notificationContext += CommonUtility.getWord(Constants.DEVICEUPGRADE_SUCCESS); } if (NativeExecutor.isWindows()) { - FireflyLuciferin.guiManager.showNotification(CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, TrayIcon.MessageType.INFO); + MainSingleton.getInstance().guiManager.showNotification(CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, TrayIcon.MessageType.INFO); } else { - FireflyLuciferin.guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, Alert.AlertType.INFORMATION); + MainSingleton.getInstance().guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, CommonUtility.getWord(Constants.UPGRADE_SUCCESS), notificationContext, Alert.AlertType.INFORMATION); } } } else { @@ -509,13 +445,12 @@ private void postDataToMicrocontroller(GlowWormDevice glowWormDevice, Path path) * @param filename file to download * @throws IOException error during download */ - @SuppressWarnings({"all"}) - void downloadFile(String filename) throws IOException { + void downloadFile(String filename) throws IOException, URISyntaxException { PropertiesLoader propertiesLoader = new PropertiesLoader(); boolean useAlphaFirmware = Boolean.parseBoolean(propertiesLoader.retrieveProperties(Constants.GW_ALPHA_DOWNLOAD)); String downloadUrl = useAlphaFirmware ? Constants.GITHUB_RELEASES_FIRMWARE_BETA : Constants.GITHUB_RELEASES_FIRMWARE; downloadUrl += ("/" + filename); - URL website = new URL(downloadUrl); + URL website = new URI(downloadUrl).toURL(); URLConnection connection = website.openConnection(); ReadableByteChannel rbc = Channels.newChannel(connection.getInputStream()); String downloadPath = System.getProperty(Constants.HOME_PATH) + File.separator + Constants.DOCUMENTS_FOLDER @@ -528,9 +463,7 @@ void downloadFile(String filename) throws IOException { while (transferedSize < expectedSize) { transferedSize += fos.getChannel().transferFrom(rbc, transferedSize, 1 << 8); } - if (transferedSize >= expectedSize) { - log.info(transferedSize + " " + CommonUtility.getWord(Constants.DOWNLOAD_COMPLETE)); - } + log.info(transferedSize + " " + CommonUtility.getWord(Constants.DOWNLOAD_COMPLETE)); fos.close(); } @@ -543,30 +476,125 @@ public void checkForUpdates(Stage stage) { UpgradeManager vm = new UpgradeManager(); // Check Firefly updates boolean fireflyUpdate = false; - if (JavaFXStarter.whoAmI == 1) { + if (MainSingleton.getInstance().whoAmI == 1) { fireflyUpdate = vm.checkFireflyUpdates(stage); } // If Firefly Luciferin is up to date, check for the Glow Worm Luciferin firmware vm.checkGlowWormUpdates(fireflyUpdate); } + /** + * Check for Glow Worm Luciferin updates + * + * @param fireflyUpdate check is done if Firefly Luciferin is up to date + */ + public void checkGlowWormUpdates(boolean fireflyUpdate) { + if (MainSingleton.getInstance().config.isCheckForUpdates() && !MainSingleton.getInstance().communicationError && !fireflyUpdate) { + CommonUtility.delaySeconds(() -> { + PropertiesLoader propertiesLoader = new PropertiesLoader(); + boolean useAlphaFirmware = Boolean.parseBoolean(propertiesLoader.retrieveProperties(Constants.GW_ALPHA_DOWNLOAD)); + log.info("Checking for Glow Worm Luciferin Update" + (useAlphaFirmware ? " using Alpha channel." : "")); + if (!GuiSingleton.getInstance().deviceTableData.isEmpty()) { + ArrayList devicesToUpdate = new ArrayList<>(); + // Updating MQTT devices for FULL firmware or Serial devices for LIGHT firmware + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { + if (!MainSingleton.getInstance().config.isFullFirmware() || !glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) { + // USB Serial device prior to 4.3.8 and there is no version information, needs the update so fake the version + if (glowWormDevice.getDeviceVersion().equals(Constants.DASH)) { + glowWormDevice.setDeviceVersion(Constants.LIGHT_FIRMWARE_DUMMY_VERSION); + } + if (checkRemoteUpdateGW(useAlphaFirmware, glowWormDevice.getDeviceVersion())) { + // If MQTT is enabled only first instance manage the update, if MQTT is disabled every instance, manage its notification + if (!MainSingleton.getInstance().config.isFullFirmware() || MainSingleton.getInstance().whoAmI == 1 || NetworkManager.currentTopicDiffersFromMainTopic()) { + devicesToUpdate.add(glowWormDevice); + } + } + } + }); + if (!devicesToUpdate.isEmpty()) { + javafx.application.Platform.runLater(() -> { + String deviceToUpdateStr = devicesToUpdate + .stream() + .map(s -> Constants.DASH + " " + "(" + s.getDeviceIP() + ") " + s.getDeviceName() + "\n") + .collect(Collectors.joining()); + String deviceContent; + if (devicesToUpdate.size() == 1) { + deviceContent = MainSingleton.getInstance().config.isFullFirmware() ? CommonUtility.getWord(Constants.DEVICE_UPDATED) : CommonUtility.getWord(Constants.DEVICE_UPDATED_LIGHT); + } else { + deviceContent = CommonUtility.getWord(Constants.DEVICES_UPDATED); + } + String upgradeMessage; + if (NativeExecutor.isLinux()) { + upgradeMessage = CommonUtility.getWord(Constants.UPDATE_NEEDED_LINUX); + } else { + upgradeMessage = CommonUtility.getWord(Constants.UPDATE_NEEDED); + } + Optional result = MainSingleton.getInstance().guiManager.showAlert(Constants.FIREFLY_LUCIFERIN, + CommonUtility.getWord(Constants.NEW_FIRMWARE_AVAILABLE), deviceContent + deviceToUpdateStr + + (MainSingleton.getInstance().config.isFullFirmware() ? CommonUtility.getWord(Constants.UPDATE_BACKGROUND) : upgradeMessage) + + "\n", Alert.AlertType.CONFIRMATION); + ButtonType button = result.orElse(ButtonType.OK); + if (MainSingleton.getInstance().config.isFullFirmware()) { + if (button == ButtonType.OK) { + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); + CommonUtility.sleepSeconds(15); + } + if (MainSingleton.getInstance().config.isMqttEnable()) { + log.info("Starting web server"); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_UPDATE_MQTT), + CommonUtility.toJsonString(new WebServerStarterDto(true))); + devicesToUpdate.forEach(glowWormDevice -> executeUpdate(glowWormDevice, false)); + } else { + devicesToUpdate.forEach(glowWormDevice -> { + log.info("Starting web server: " + glowWormDevice.getDeviceIP()); + TcpClient.httpGet(CommonUtility.toJsonString(new WebServerStarterDto(true)), + NetworkManager.getTopic(Constants.TOPIC_UPDATE_MQTT), glowWormDevice.getDeviceIP()); + log.info("Updating: " + glowWormDevice.getDeviceIP()); + CommonUtility.sleepSeconds(5); + executeUpdate(glowWormDevice, false); + }); + CommonUtility.delaySeconds(() -> MainSingleton.getInstance().guiManager.startCapturingThreads(), 60); + } + } + } else { + if (button == ButtonType.OK) { + if (NativeExecutor.isLinux()) { + devicesToUpdate.forEach(glowWormDevice -> executeUpdate(glowWormDevice, true)); + } else { + MainSingleton.getInstance().guiManager.surfToURL(Constants.WEB_INSTALLER_URL); + } + } + } + }); + } + } + }, 20); + } + } + /** * Check if the connected device match the minimum firmware version requirements for this Firefly Luciferin version - * Returns true if the connected device have a compatible firmware version + * Returns true if the connected device have a compatible firmware version, if satellites are configured, check for + * satellites too * - * @return true or false + * @return true or false, null if there is no device or if not all satellites has been engaged */ public Boolean firmwareMatchMinimumRequirements() { - PropertiesLoader propertiesLoader = new PropertiesLoader(); - GlowWormDevice glowWormDeviceInUse = CommonUtility.getDeviceToUse(); - if (glowWormDeviceInUse != null && glowWormDeviceInUse.getMac() != null && !Constants.DASH.equals(glowWormDeviceInUse.getDeviceVersion()) - && !glowWormDeviceInUse.getDeviceVersion().isEmpty() && !Constants.LIGHT_FIRMWARE_DUMMY_VERSION.equals(glowWormDeviceInUse.getDeviceVersion())) { - String minimumFirmwareVersionProp = propertiesLoader.retrieveProperties(Constants.PROP_MINIMUM_FIRMWARE_VERSION); - long minimumFirmwareVersion = versionNumberToNumber(minimumFirmwareVersionProp); - long deviceVersion = versionNumberToNumber(glowWormDeviceInUse.getDeviceVersion()); - return (deviceVersion >= minimumFirmwareVersion); + List devices = CommonUtility.getDeviceToUseWithSatellites(); + List results = new ArrayList<>(); + // if all satellites are engaged along with the main instance + if (!devices.isEmpty() && devices.size() == MainSingleton.getInstance().config.getSatellites().size() + 1) { + for (GlowWormDevice gwd : devices) { + results.add(checkFirmwareVersion(gwd)); + } + boolean isThereNull = results.stream().anyMatch(Objects::isNull); + boolean isThereFalse = results.stream().anyMatch(res -> (res != null && !res)); + if (isThereNull) return null; + else return !isThereFalse; } else { return null; } } + } diff --git a/src/main/java/org/dpsoftware/managers/dto/StateStatusDto.java b/src/main/java/org/dpsoftware/managers/dto/StateStatusDto.java index c0d93a280..cf2904dbf 100644 --- a/src/main/java/org/dpsoftware/managers/dto/StateStatusDto.java +++ b/src/main/java/org/dpsoftware/managers/dto/StateStatusDto.java @@ -39,7 +39,6 @@ @Setter public class StateStatusDto extends StateDto { - public static boolean closeOtherInstaces = false; private boolean running; private List deviceTableData; private float fpsgwconsumer; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/DiscoveryObject.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/DiscoveryObject.java index 5167711c0..3939ca913 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/DiscoveryObject.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/DiscoveryObject.java @@ -22,7 +22,7 @@ package org.dpsoftware.managers.dto.mqttdiscovery; import com.fasterxml.jackson.annotation.JsonIgnore; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; /** @@ -47,8 +47,8 @@ public interface DiscoveryObject { @JsonIgnore default String getBaseGWDiscoveryTopic() { String discoveryTopicBasePath = Constants.MQTT_DISCOVERY_TOPIC_BASE_PATH; - if (!FireflyLuciferin.config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { - discoveryTopicBasePath += "_" + FireflyLuciferin.config.getMqttTopic(); + if (!MainSingleton.getInstance().config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { + discoveryTopicBasePath += "_" + MainSingleton.getInstance().config.getMqttTopic(); } return discoveryTopicBasePath; } @@ -62,8 +62,8 @@ default String getBaseGWDiscoveryTopic() { @JsonIgnore default String getBaseFireflyDiscoveryTopic() { String discoveryTopicBasePath = Constants.MQTT_FIREFLY_BASE_TOPIC; - if (!FireflyLuciferin.config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { - discoveryTopicBasePath += "_" + FireflyLuciferin.config.getMqttTopic(); + if (!MainSingleton.getInstance().config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { + discoveryTopicBasePath += "_" + MainSingleton.getInstance().config.getMqttTopic(); } return discoveryTopicBasePath; } @@ -77,8 +77,8 @@ default String getBaseFireflyDiscoveryTopic() { */ @JsonIgnore default String generateUniqueName(String nameBaseStr) { - if (!FireflyLuciferin.config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { - nameBaseStr += "_" + FireflyLuciferin.config.getMqttTopic(); + if (!MainSingleton.getInstance().config.getMqttTopic().equals(Constants.MQTT_BASE_TOPIC)) { + nameBaseStr += "_" + MainSingleton.getInstance().config.getMqttTopic(); } return nameBaseStr; } diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/LightDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/LightDiscovery.java index 535b56437..f1d3fbb00 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/LightDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/LightDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -52,7 +52,7 @@ public class LightDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/light/" + getBaseGWDiscoveryTopic() + "/GlowWorm/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/light/" + getBaseGWDiscoveryTopic() + "/GlowWorm/config"; } @Override @@ -60,10 +60,10 @@ public String getCreateEntityStr() { this.name = generateUniqueName("Glow Worm Luciferin"); this.uniqueId = this.name.replaceAll(" ", "_"); this.schema = "json"; - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); - this.brightness_state_topic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); + this.brightness_state_topic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.brightness_value_template = "{{ value_json.brightness }}"; - this.commandTopic = "lights/" + FireflyLuciferin.config.getMqttTopic() + "/set"; + this.commandTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic() + "/set"; this.effect = true; this.brightness = true; this.rgb = true; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/NumberWhiteTempDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/NumberWhiteTempDiscovery.java index 9b2a6f8ea..128ab36d6 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/NumberWhiteTempDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/NumberWhiteTempDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -52,16 +52,16 @@ public class NumberWhiteTempDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/number/" + getBaseGWDiscoveryTopic() + "/whitetemp/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/number/" + getBaseGWDiscoveryTopic() + "/whitetemp/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin White Temp"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic() + "/set"; + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic() + "/set"; this.valueTemplate = "{{ value_json.whitetemp * 100 }}"; - this.commandTopic = "lights/" + FireflyLuciferin.config.getMqttTopic() + "/set"; + this.commandTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic() + "/set"; this.commandTemplate = "{\"state\":\"ON\",\"whitetemp\":{{ (value / 100 ) | int }},\"allInstances\":\"1\"}"; this.icon = "mdi:temperature-kelvin"; this.initial = 6500; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectAspectRatioDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectAspectRatioDiscovery.java index 55fbb3e74..df97e6c4b 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectAspectRatioDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectAspectRatioDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.utilities.CommonUtility; @@ -56,7 +56,7 @@ public class SelectAspectRatioDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/setaspectratio/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/setaspectratio/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectColorModeDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectColorModeDiscovery.java index 274b813d6..d336f7297 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectColorModeDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectColorModeDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.utilities.CommonUtility; @@ -54,7 +54,7 @@ public class SelectColorModeDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/device" + CommonUtility.getDeviceToUse().getMac().replace(":", "") + "/colormode/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/device" + CommonUtility.getDeviceToUse().getMac().replace(":", "") + "/colormode/config"; } @Override @@ -73,7 +73,7 @@ public String getCreateEntityStr() { cntOutput++; } colorModeIndex.append("{% endif %}"); - this.commandTopic = Constants.GLOW_WORM_FIRM_CONFIG_TOPIC; + this.commandTopic = Constants.TOPIC_GLOW_WORM_FIRM_CONFIG; this.commandTemplate = "{\"colorMode\":\"" + colorModeIndex + "\",\"MAC\":\"" + CommonUtility.getDeviceToUse().getMac() + "\"}"; this.icon = "mdi:palette"; return CommonUtility.toJsonString(this); diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectEffectDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectEffectDiscovery.java index da2ecf0e6..66c0e6e96 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectEffectDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectEffectDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Enums; import org.dpsoftware.utilities.CommonUtility; @@ -53,7 +53,7 @@ public class SelectEffectDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/" + getBaseFireflyDiscoveryTopic() + "/effect/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/" + getBaseFireflyDiscoveryTopic() + "/effect/config"; } @Override @@ -62,7 +62,7 @@ public String getCreateEntityStr() { this.uniqueId = this.name.replaceAll(" ", "_"); this.stateTopic = "lights/" + getBaseFireflyDiscoveryTopic() + "/framerate"; this.valueTemplate = "{{ value_json.effect }}"; - this.commandTopic = "lights/" + FireflyLuciferin.config.getMqttTopic() + "/effectToGw"; + this.commandTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic() + "/effectToGw"; this.commandTemplate = "{\"state\":\"ON\",\"effect\":\"{{value}}\"}"; this.options = new ArrayList<>(); for (Enums.Effect effect : Enums.Effect.values()) { diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectGammaDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectGammaDiscovery.java index 00f1415dd..1d4d46351 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectGammaDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectGammaDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Enums; import org.dpsoftware.utilities.CommonUtility; @@ -54,7 +54,7 @@ public class SelectGammaDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/gamma/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/gamma/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectProfileDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectProfileDiscovery.java index 524d045fb..1fa5d2265 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectProfileDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectProfileDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.managers.StorageManager; import org.dpsoftware.utilities.CommonUtility; @@ -54,7 +54,7 @@ public class SelectProfileDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/" + getBaseFireflyDiscoveryTopic() + "/profile/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/" + getBaseFireflyDiscoveryTopic() + "/profile/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectSmoothingDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectSmoothingDiscovery.java index 5686fc99f..e34b4abb0 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectSmoothingDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SelectSmoothingDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Enums; import org.dpsoftware.utilities.CommonUtility; @@ -54,7 +54,7 @@ public class SelectSmoothingDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/setsmoothing/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/select/" + getBaseGWDiscoveryTopic() + "/setsmoothing/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorAspectRatioDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorAspectRatioDiscovery.java index ce3c2d85f..0fda13ccd 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorAspectRatioDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorAspectRatioDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -44,7 +44,7 @@ public class SensorAspectRatioDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/aspectratio/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/aspectratio/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorConsumingDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorConsumingDiscovery.java index 4088c3e5e..4d87b9790 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorConsumingDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorConsumingDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -46,7 +46,7 @@ public class SensorConsumingDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Firefly_Luciferin_Consuming/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Firefly_Luciferin_Consuming/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGWConsumingDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGWConsumingDiscovery.java index 187b144d7..25a45b51e 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGWConsumingDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGWConsumingDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -48,14 +48,14 @@ public class SensorGWConsumingDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Glow_Worm_Luciferin_FPS_running/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Glow_Worm_Luciferin_FPS_running/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Glow Worm Luciferin Consuming"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.framerate }}"; this.unitOfMeasurement = "FPS"; this.forceUpdate = true; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGpioDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGpioDiscovery.java index 01b0717fe..944fd403f 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGpioDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorGpioDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -46,14 +46,14 @@ public class SensorGpioDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/gpio/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/gpio/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin GPIO"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.gpio if value_json.gpio > 0 else states('sensor." + this.uniqueId.toLowerCase() + "') }}"; this.unitOfMeasurement = ""; this.icon = "mdi:chip"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLastUpdateDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLastUpdateDiscovery.java index 2cdeb50c0..8919a2bc6 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLastUpdateDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLastUpdateDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -44,14 +44,14 @@ public class SensorLastUpdateDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Last_Update_GlowWorm/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Last_Update_GlowWorm/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Last Update Glow Worm Luciferin"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ as_timestamp(now()) | timestamp_custom(\"%Y-%m-%d ~ %H:%M:%S\") }}"; this.icon = "mdi:update"; return CommonUtility.toJsonString(this); diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLdrDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLdrDiscovery.java index ebfc0d457..ef499e421 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLdrDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLdrDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -46,14 +46,14 @@ public class SensorLdrDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/ldr/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/ldr/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin LDR"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.ldr if value_json.ldr is defined else '0' }}"; this.unitOfMeasurement = "%"; this.icon = "mdi:theme-light-dark"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLedsDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLedsDiscovery.java index 196ccee4f..5b222294f 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLedsDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorLedsDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -46,14 +46,14 @@ public class SensorLedsDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/number_of_leds/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/number_of_leds/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin number of leds"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.lednum }}"; this.unitOfMeasurement = ""; this.icon = "mdi:led-strip-variant"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorProducingDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorProducingDiscovery.java index af84a46f1..d5826bbca 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorProducingDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorProducingDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.utilities.CommonUtility; @@ -48,7 +48,7 @@ public class SensorProducingDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Firefly_Luciferin_Producing/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/Firefly_Luciferin_Producing/config"; } @Override diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorVersionDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorVersionDiscovery.java index fb4186e3c..eb8c66c7e 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorVersionDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorVersionDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -48,14 +48,14 @@ public class SensorVersionDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/GlowWorm_Version/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/GlowWorm_Version/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Glow Worm Luciferin Version"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.ver if value_json.ver is defined else states('sensor." + this.uniqueId.toLowerCase() + "') }}"; this.forceUpdate = true; this.icon = "mdi:numeric"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorWiFiDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorWiFiDiscovery.java index 8360b9d25..e16c742bb 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorWiFiDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SensorWiFiDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -46,14 +46,14 @@ public class SensorWiFiDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/wifi/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/sensor/" + getBaseGWDiscoveryTopic() + "/wifi/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin WiFi"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.stateTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.valueTemplate = "{{ value_json.wifi }}"; this.unitOfMeasurement = "%"; this.icon = "mdi:wifi"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchBiasLightDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchBiasLightDiscovery.java index bb97bc2a2..cc65b2e60 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchBiasLightDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchBiasLightDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -54,7 +54,7 @@ public class SwitchBiasLightDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/switch/" + getBaseGWDiscoveryTopic() + "/biaslight/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/switch/" + getBaseGWDiscoveryTopic() + "/biaslight/config"; } @Override @@ -62,7 +62,7 @@ public String getCreateEntityStr() { this.name = generateUniqueName("Luciferin Bias Light"); this.uniqueId = this.name.replaceAll(" ", "_"); this.stateTopic = "lights/" + getBaseFireflyDiscoveryTopic() + "/framerate"; - this.commandTopic = "lights/" + FireflyLuciferin.config.getMqttTopic(); + this.commandTopic = "lights/" + MainSingleton.getInstance().config.getMqttTopic(); this.payloadOn = "{\"state\":\"ON\",\"startStopInstances\":\"PLAY\"}"; this.payloadOff = "{\"state\":\"ON\",\"startStopInstances\":\"STOP\"}"; this.valueTemplate = "{{ value_json.producing | int > 0 }}"; diff --git a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchRebootDiscovery.java b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchRebootDiscovery.java index 5f9a06aa3..a0de71aae 100644 --- a/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchRebootDiscovery.java +++ b/src/main/java/org/dpsoftware/managers/dto/mqttdiscovery/SwitchRebootDiscovery.java @@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.utilities.CommonUtility; @JsonIgnoreProperties(ignoreUnknown = true) @@ -48,15 +48,15 @@ public class SwitchRebootDiscovery implements DiscoveryObject { @Override public String getDiscoveryTopic() { - return FireflyLuciferin.config.getMqttDiscoveryTopic() + "/button/" + getBaseGWDiscoveryTopic() + "/rebootglowworm/config"; + return MainSingleton.getInstance().config.getMqttDiscoveryTopic() + "/button/" + getBaseGWDiscoveryTopic() + "/rebootglowworm/config"; } @Override public String getCreateEntityStr() { this.name = generateUniqueName("Reboot Glow Worm Luciferin"); this.uniqueId = this.name.replaceAll(" ", "_"); - this.stateTopic = "stat/" + FireflyLuciferin.config.getMqttTopic() + "/reboot"; - this.commandTopic = "cmnd/" + FireflyLuciferin.config.getMqttTopic() + "/reboot"; + this.stateTopic = "stat/" + MainSingleton.getInstance().config.getMqttTopic() + "/reboot"; + this.commandTopic = "cmnd/" + MainSingleton.getInstance().config.getMqttTopic() + "/reboot"; this.qos = 1; this.retain = false; this.payloadPress = "OFF"; diff --git a/src/main/java/org/dpsoftware/network/MessageClient.java b/src/main/java/org/dpsoftware/network/MessageClient.java index 8f61bbb53..4a51c47d9 100644 --- a/src/main/java/org/dpsoftware/network/MessageClient.java +++ b/src/main/java/org/dpsoftware/network/MessageClient.java @@ -26,10 +26,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Constants; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.GlowWormDevice; import org.dpsoftware.utilities.CommonUtility; @@ -49,7 +49,6 @@ @Slf4j public class MessageClient { - public static MessageClient msgClient; public Socket clientSocket; private PrintWriter out; private BufferedReader in; @@ -62,37 +61,37 @@ public static void getSingleInstanceMultiScreenStatus() { // Create a task that runs every 2 seconds Runnable framerateTask = () -> { try { - if (msgClient == null || msgClient.clientSocket == null) { - msgClient = new MessageClient(); - msgClient.startConnection(Constants.MSG_SERVER_HOST, Constants.MSG_SERVER_PORT); + if (NetworkSingleton.getInstance().msgClient == null || NetworkSingleton.getInstance().msgClient.clientSocket == null) { + NetworkSingleton.getInstance().msgClient = new MessageClient(); + NetworkSingleton.getInstance().msgClient.startConnection(Constants.MSG_SERVER_HOST, Constants.MSG_SERVER_PORT); } - String response = msgClient.sendMessage(Constants.MSG_SERVER_STATUS); + String response = NetworkSingleton.getInstance().msgClient.sendMessage(Constants.MSG_SERVER_STATUS); JsonNode stateStatusDto = CommonUtility.fromJsonToObject(response); assert stateStatusDto != null; - FireflyLuciferin.config.setEffect(stateStatusDto.get(Constants.EFFECT).asText()); + MainSingleton.getInstance().config.setEffect(stateStatusDto.get(Constants.EFFECT).asText()); boolean mainInstanceRunning = stateStatusDto.get(Constants.RUNNING).asText().equals(Constants.TRUE); // Close instance if server is closed. boolean exit = stateStatusDto.get(Constants.EXIT.toLowerCase()).asBoolean(); if (!CommonUtility.isSingleDeviceMainInstance() && exit) { NativeExecutor.exit(); } - FireflyLuciferin.FPS_GW_CONSUMER = Float.parseFloat(stateStatusDto.get(Constants.FPS_GW_CONSUMER).asText()); + MainSingleton.getInstance().FPS_GW_CONSUMER = Float.parseFloat(stateStatusDto.get(Constants.FPS_GW_CONSUMER).asText()); // Update device table data - DevicesTabController.deviceTableData.remove(0, DevicesTabController.deviceTableData.size()); + GuiSingleton.getInstance().deviceTableData.remove(0, GuiSingleton.getInstance().deviceTableData.size()); ObjectMapper mapper = new ObjectMapper(); JsonNode arrayNode = stateStatusDto.get(Constants.DEVICE_TABLE_DATA); if (arrayNode.isArray()) { ObjectReader reader = mapper.readerFor(new TypeReference>() { }); List list = reader.readValue(arrayNode); - DevicesTabController.deviceTableData.addAll(list); + GuiSingleton.getInstance().deviceTableData.addAll(list); } // Set other instances Running - if (FireflyLuciferin.RUNNING != mainInstanceRunning) { + if (MainSingleton.getInstance().RUNNING != mainInstanceRunning) { if (mainInstanceRunning) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else { - FireflyLuciferin.guiManager.stopCapturingThreads(false); + MainSingleton.getInstance().guiManager.stopCapturingThreads(false); } } } catch (Exception e) { @@ -131,7 +130,7 @@ public String sendMessage(String msg) { return in.readLine(); } } catch (IOException e) { - MessageClient.msgClient = null; + NetworkSingleton.getInstance().msgClient = null; log.error(e.getMessage()); } return ""; diff --git a/src/main/java/org/dpsoftware/network/MessageServer.java b/src/main/java/org/dpsoftware/network/MessageServer.java index 7ffcf2c29..7d426b6ef 100644 --- a/src/main/java/org/dpsoftware/network/MessageServer.java +++ b/src/main/java/org/dpsoftware/network/MessageServer.java @@ -22,14 +22,13 @@ package org.dpsoftware.network; import com.fasterxml.jackson.databind.JsonNode; -import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.NativeExecutor; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.managers.StorageManager; import org.dpsoftware.managers.dto.StateStatusDto; import org.dpsoftware.utilities.CommonUtility; @@ -41,7 +40,6 @@ import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; -import java.net.SocketException; /** * Message server using Java Sockets, used for single instance multi monitor @@ -49,24 +47,31 @@ @Slf4j public class MessageServer { - public static boolean closeServer = false; - public static int totalLedNum = FireflyLuciferin.ledNumber; - public static MessageServer messageServer; - private static Color[] leds; - private static boolean firstDisplayReceived = false; - private static boolean secondDisplayReceived = false; - private static boolean thirdDisplayReceived = false; - private static int firstDisplayLedNum = 0; - private static int secondDisplayLedNum = 0; + private Color[] leds; + private boolean firstDisplayReceived = false; + private boolean secondDisplayReceived = false; + private boolean thirdDisplayReceived = false; + private int firstDisplayLedNum = 0; + private int secondDisplayLedNum = 0; private ServerSocket serverSocket; + private static StateStatusDto getStateStatusDto() { + StateStatusDto stateStatusDto = new StateStatusDto(); + stateStatusDto.setEffect(MainSingleton.getInstance().config.getEffect()); + stateStatusDto.setRunning(MainSingleton.getInstance().RUNNING); + stateStatusDto.setDeviceTableData(GuiSingleton.getInstance().deviceTableData); + stateStatusDto.setFpsgwconsumer(MainSingleton.getInstance().FPS_GW_CONSUMER); + stateStatusDto.setExit(MainSingleton.getInstance().closeOtherInstaces); + return stateStatusDto; + } + /** * Start message server for multi screen, single instance */ - public static void startMessageServer() { + public void startMessageServer() { CommonUtility.delaySeconds(() -> { try { - messageServer.start(Constants.MSG_SERVER_PORT); + NetworkSingleton.getInstance().messageServer.start(Constants.MSG_SERVER_PORT); } catch (IOException e) { log.error(e.getMessage()); } @@ -76,19 +81,19 @@ public static void startMessageServer() { /** * Init totalNumLed based on all instances */ - public static void initNumLed() { + public void initNumLed() { StorageManager sm = new StorageManager(); // Server starts if there are 2 or more monitors Configuration otherConfig1 = sm.readConfigFile(Constants.CONFIG_FILENAME); firstDisplayLedNum = otherConfig1.getLedMatrix().get(Enums.AspectRatio.FULLSCREEN.getBaseI18n()).size(); Configuration otherConfig2 = sm.readConfigFile(Constants.CONFIG_FILENAME_2); secondDisplayLedNum = otherConfig2.getLedMatrix().get(Enums.AspectRatio.FULLSCREEN.getBaseI18n()).size(); - if (FireflyLuciferin.config.getMultiMonitor() == 3) { + if (MainSingleton.getInstance().config.getMultiMonitor() == 3) { Configuration otherConfig3 = sm.readConfigFile(Constants.CONFIG_FILENAME_3); int thirdDisplayLedNum = otherConfig3.getLedMatrix().get(Enums.AspectRatio.FULLSCREEN.getBaseI18n()).size(); - totalLedNum = firstDisplayLedNum + secondDisplayLedNum + thirdDisplayLedNum; + NetworkSingleton.getInstance().totalLedNum = firstDisplayLedNum + secondDisplayLedNum + thirdDisplayLedNum; } else { - totalLedNum = firstDisplayLedNum + secondDisplayLedNum; + NetworkSingleton.getInstance().totalLedNum = firstDisplayLedNum + secondDisplayLedNum; } } @@ -100,9 +105,9 @@ public static void initNumLed() { */ public void start(int port) throws IOException { log.info("Starting message server"); - leds = new Color[totalLedNum]; + leds = new Color[NetworkSingleton.getInstance().totalLedNum]; serverSocket = new ServerSocket(port); - while (!closeServer) { + while (!NetworkSingleton.getInstance().closeServer) { if (!serverSocket.isClosed()) { new ClientHandler(serverSocket.accept()).start(); } @@ -130,11 +135,11 @@ void startStopCapture(String msg) { JsonNode stateStatusDto = CommonUtility.fromJsonToObject(msg); assert stateStatusDto != null; boolean otherInstanceRunning = stateStatusDto.get(Constants.RUNNING).asBoolean(); - if (FireflyLuciferin.RUNNING != otherInstanceRunning) { + if (MainSingleton.getInstance().RUNNING != otherInstanceRunning) { if (otherInstanceRunning) { - FireflyLuciferin.guiManager.startCapturingThreads(); + MainSingleton.getInstance().guiManager.startCapturingThreads(); } else { - FireflyLuciferin.guiManager.stopCapturingThreads(false); + MainSingleton.getInstance().guiManager.stopCapturingThreads(false); } } } @@ -163,15 +168,15 @@ private void collectAndSendData(String inputLine, PrintWriter out) { for (int i = 1; i <= ledsString.length - 1; i++) { leds[startIndex + i] = new Color(Integer.parseInt(ledsString[i])); } - if (FireflyLuciferin.config.getMultiMonitor() == 2 && firstDisplayReceived && secondDisplayReceived) { + if (MainSingleton.getInstance().config.getMultiMonitor() == 2 && firstDisplayReceived && secondDisplayReceived) { firstDisplayReceived = false; secondDisplayReceived = false; - FireflyLuciferin.sharedQueue.offer(leds); - } else if (FireflyLuciferin.config.getMultiMonitor() == 3 && firstDisplayReceived && secondDisplayReceived && thirdDisplayReceived) { + MainSingleton.getInstance().sharedQueue.offer(leds); + } else if (MainSingleton.getInstance().config.getMultiMonitor() == 3 && firstDisplayReceived && secondDisplayReceived && thirdDisplayReceived) { firstDisplayReceived = false; secondDisplayReceived = false; thirdDisplayReceived = false; - FireflyLuciferin.sharedQueue.offer(leds); + MainSingleton.getInstance().sharedQueue.offer(leds); } out.println(inputLine); } @@ -186,21 +191,15 @@ public ClientHandler(Socket socket) { this.clientSocket = socket; } - @SneakyThrows public void run() { - PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); - BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - String inputLine; try { + PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); + BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + String inputLine; while ((inputLine = in.readLine()) != null) { // Send status to clients if (inputLine.equals(Constants.MSG_SERVER_STATUS)) { - StateStatusDto stateStatusDto = new StateStatusDto(); - stateStatusDto.setEffect(FireflyLuciferin.config.getEffect()); - stateStatusDto.setRunning(FireflyLuciferin.RUNNING); - stateStatusDto.setDeviceTableData(DevicesTabController.deviceTableData); - stateStatusDto.setFpsgwconsumer(FireflyLuciferin.FPS_GW_CONSUMER); - stateStatusDto.setExit(StateStatusDto.closeOtherInstaces); + StateStatusDto stateStatusDto = getStateStatusDto(); out.println(CommonUtility.toJsonString(stateStatusDto)); } else if (inputLine.contains(Constants.CLIENT_ACTION)) { startStopCapture(inputLine); @@ -216,7 +215,7 @@ public void run() { in.close(); out.close(); clientSocket.close(); - } catch (SocketException e) { + } catch (IOException e) { log.error(e.getMessage()); } } diff --git a/src/main/java/org/dpsoftware/network/NetworkSingleton.java b/src/main/java/org/dpsoftware/network/NetworkSingleton.java new file mode 100644 index 000000000..5bb511d97 --- /dev/null +++ b/src/main/java/org/dpsoftware/network/NetworkSingleton.java @@ -0,0 +1,51 @@ +/* + NetworkSingleton.java + + Firefly Luciferin, very fast Java Screen Capture software designed + for Glow Worm Luciferin firmware. + + Copyright © 2020 - 2023 Davide Perini (https://github.com/sblantipodi) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +package org.dpsoftware.network; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dpsoftware.MainSingleton; + +/** + * Network singleton used to share common data + */ +@Getter +@Setter +@NoArgsConstructor +public class NetworkSingleton { + + @Getter + private final static NetworkSingleton instance; + + static { + instance = new NetworkSingleton(); + } + + public boolean udpBroadcastReceiverRunning = false; + public MessageClient msgClient; + public boolean closeServer = false; + public int totalLedNum = MainSingleton.getInstance().ledNumber; + public MessageServer messageServer; + +} + diff --git a/src/main/java/org/dpsoftware/network/tcpUdp/TcpClient.java b/src/main/java/org/dpsoftware/network/tcpUdp/TcpClient.java index 6c801bafb..ed0e6d9d0 100644 --- a/src/main/java/org/dpsoftware/network/tcpUdp/TcpClient.java +++ b/src/main/java/org/dpsoftware/network/tcpUdp/TcpClient.java @@ -22,17 +22,19 @@ package org.dpsoftware.network.tcpUdp; import lombok.extern.slf4j.Slf4j; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; +import org.dpsoftware.gui.elements.Satellite; +import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.dto.TcpResponse; import org.dpsoftware.utilities.CommonUtility; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; +import java.net.*; import java.nio.charset.StandardCharsets; +import java.util.Map; /** * Utility class for TCP communication @@ -41,7 +43,7 @@ public class TcpClient { /** - * Send an HTTP GET to a specifi IP address + * Send an HTTP GET to a specific IP address * * @param msg msg to use in the payload param * @param topic http get path @@ -57,7 +59,7 @@ public static TcpResponse httpGet(String msg, String topic, String destinationIP .replace("{1}", topic) .replace("{2}", URLEncoder.encode(msg, StandardCharsets.UTF_8)); log.trace("HTTP GET=" + request); - URL url = new URL(request); + URL url = new URI(request).toURL(); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); con.setDoOutput(true); @@ -77,7 +79,7 @@ public static TcpResponse httpGet(String msg, String topic, String destinationIP tcpResponse.setErrorCode(status); log.trace(CommonUtility.toJsonStringPrettyPrinted(tcpResponse)); return tcpResponse; - } catch (IOException e) { + } catch (IOException | URISyntaxException e) { log.error(e.getMessage()); } return tcpResponse; @@ -94,6 +96,16 @@ public static TcpResponse httpGet(String msg, String topic) { TcpResponse tcpResponse = new TcpResponse(); if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getDeviceIP() != null) { tcpResponse = httpGet(msg, topic, CommonUtility.getDeviceToUse().getDeviceIP()); + if (MainSingleton.getInstance().config.getSatellites() != null) { + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getDeviceIP() != null) { + String swappedMsg = NetworkManager.swapMac(msg, sat.getValue()); + if (!Constants.HTTP_TOPIC_TO_SKIP_FOR_SATELLITES.contains(topic)) { + httpGet(swappedMsg, topic, sat.getValue().getDeviceIp()); + } + } + } + } } return tcpResponse; } diff --git a/src/main/java/org/dpsoftware/network/tcpUdp/UdpClient.java b/src/main/java/org/dpsoftware/network/tcpUdp/UdpClient.java index b93f7fdc0..f57b5ac59 100644 --- a/src/main/java/org/dpsoftware/network/tcpUdp/UdpClient.java +++ b/src/main/java/org/dpsoftware/network/tcpUdp/UdpClient.java @@ -22,7 +22,7 @@ package org.dpsoftware.network.tcpUdp; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.audio.AudioLoopback; +import org.dpsoftware.audio.AudioSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.utilities.CommonUtility; @@ -80,7 +80,7 @@ public void manageStream(Color[] leds) { StringBuilder sb = new StringBuilder(); sb.append("DPsoftware").append(","); sb.append(leds.length).append(","); - sb.append((AudioLoopback.AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioLoopback.AUDIO_BRIGHTNESS)).append(","); + sb.append((AudioSingleton.getInstance().AUDIO_BRIGHTNESS == 255 ? CommonUtility.getNightBrightness() : AudioSingleton.getInstance().AUDIO_BRIGHTNESS)).append(","); sb.append(chunkTotal).append(","); sb.append(chunkNum).append(","); int chunkSizeInteger = (int) Constants.UDP_CHUNK_SIZE * chunkNum; diff --git a/src/main/java/org/dpsoftware/network/tcpUdp/UdpServer.java b/src/main/java/org/dpsoftware/network/tcpUdp/UdpServer.java index a816a4a25..6e4c9429d 100644 --- a/src/main/java/org/dpsoftware/network/tcpUdp/UdpServer.java +++ b/src/main/java/org/dpsoftware/network/tcpUdp/UdpServer.java @@ -23,18 +23,21 @@ import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.gui.controllers.DevicesTabController; -import org.dpsoftware.managers.UpgradeManager; +import org.dpsoftware.gui.GuiSingleton; +import org.dpsoftware.gui.elements.Satellite; +import org.dpsoftware.managers.ManagerSingleton; +import org.dpsoftware.managers.NetworkManager; +import org.dpsoftware.network.NetworkSingleton; import org.dpsoftware.utilities.CommonUtility; import java.io.IOException; import java.net.*; import java.util.Enumeration; +import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; @@ -47,7 +50,6 @@ @Slf4j public class UdpServer { - public static boolean udpBroadcastReceiverRunning = false; DatagramSocket socket; InetAddress localIP; InetAddress broadcastAddress; @@ -60,11 +62,11 @@ public class UdpServer { */ public UdpServer() { try { - if (JavaFXStarter.whoAmI == 1) { + if (MainSingleton.getInstance().whoAmI == 1) { socket = new DatagramSocket(Constants.UDP_BROADCAST_PORT); - } else if (JavaFXStarter.whoAmI == 2) { + } else if (MainSingleton.getInstance().whoAmI == 2) { socket = new DatagramSocket(Constants.UDP_BROADCAST_PORT_2); - } else if (JavaFXStarter.whoAmI == 3) { + } else if (MainSingleton.getInstance().whoAmI == 3) { socket = new DatagramSocket(Constants.UDP_BROADCAST_PORT_3); } assert socket != null; @@ -90,53 +92,57 @@ public void receiveBroadcastUDPPacket() { System.out.println("UDP broadcast listen on " + socket.getLocalAddress()); byte[] buf = new byte[512]; DatagramPacket packet = new DatagramPacket(buf, buf.length); - while (udpBroadcastReceiverRunning) { - socket.receive(packet); - String received = new String(packet.getData(), 0, packet.getLength()); - if (!received.startsWith(Constants.UDP_DEVICE_NAME)) { - if (!received.contains(Constants.UDP_PING)) { - log.trace("Received UDP broadcast=" + received); - // Share received broadcast with other Firefly Luciferin instances - shareBroadCastToOtherInstances(received); - } - if (LocalizedEnum.fromBaseStr(Enums.Effect.class, received) != null) { - FireflyLuciferin.config.setEffect(received); - if (!FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.startCapturingThreads(); + while (NetworkSingleton.getInstance().udpBroadcastReceiverRunning) { + try { + socket.receive(packet); + String received = new String(packet.getData(), 0, packet.getLength()); + if (!received.startsWith(Constants.UDP_DEVICE_NAME) && !received.startsWith(Constants.UDP_DEVICE_NAME_STATIC)) { + if (!received.contains(Constants.UDP_PING)) { + log.trace("Received UDP broadcast=" + received); + // Share received broadcast with other Firefly Luciferin instances + shareBroadCastToOtherInstances(received); } - } - if (received.contains(Constants.STOP_STR)) { - if (FireflyLuciferin.RUNNING) { - FireflyLuciferin.guiManager.stopCapturingThreads(false); - CommonUtility.turnOnLEDs(); + if (LocalizedEnum.fromBaseStr(Enums.Effect.class, received) != null) { + MainSingleton.getInstance().config.setEffect(received); + if (!MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.startCapturingThreads(); + } } - } - if (!Constants.UDP_PONG.equals(received) && !Constants.UDP_PING.equals(received)) { - JsonNode responseJson = CommonUtility.fromJsonToObject(received); - if (responseJson != null && responseJson.get(Constants.STATE) != null && responseJson.get(Constants.MQTT_DEVICE_NAME) != null) { - turnOnLightFirstTime(responseJson); - CommonUtility.updateDeviceTable(Objects.requireNonNull(responseJson)); - CommonUtility.updateFpsWithDeviceTopic(Objects.requireNonNull(responseJson)); - } else if (responseJson != null && responseJson.get(Constants.MQTT_FRAMERATE) != null) { - CommonUtility.updateFpsWithFpsTopic(Objects.requireNonNull(responseJson)); - } else if (UpgradeManager.deviceNameForSerialDevice.equals(received)) { - log.info("Update successful=" + received); - CommonUtility.sleepSeconds(60); - FireflyLuciferin.guiManager.startCapturingThreads(); - } else { - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { - if (glowWormDevice.getDeviceName().equals(received)) { - log.info("Update successful=" + received); - shareBroadCastToOtherInstances(received); - } - }); + if (received.contains(Constants.STOP_STR)) { + if (MainSingleton.getInstance().RUNNING) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(false); + CommonUtility.turnOnLEDs(); + } + } + if (!Constants.UDP_PONG.equals(received) && !Constants.UDP_PING.equals(received)) { + JsonNode responseJson = CommonUtility.fromJsonToObject(received); + if (responseJson != null && responseJson.get(Constants.STATE) != null && responseJson.get(Constants.MQTT_DEVICE_NAME) != null) { + turnOnLightFirstTime(responseJson); + CommonUtility.updateDeviceTable(Objects.requireNonNull(responseJson)); + CommonUtility.updateFpsWithDeviceTopic(Objects.requireNonNull(responseJson)); + } else if (responseJson != null && responseJson.get(Constants.MQTT_FRAMERATE) != null) { + CommonUtility.updateFpsWithFpsTopic(Objects.requireNonNull(responseJson)); + } else if (ManagerSingleton.getInstance().deviceNameForSerialDevice.equals(received)) { + log.info("Update successful=" + received); + CommonUtility.sleepSeconds(60); + MainSingleton.getInstance().guiManager.startCapturingThreads(); + } else { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { + if (glowWormDevice.getDeviceName().equals(received)) { + log.info("Update successful=" + received); + shareBroadCastToOtherInstances(received); + } + }); + } } } + } catch (Exception e) { + log.error(e.getMessage()); + log.error("UDP msg contains errors"); } } } catch (Exception e) { log.error(e.getMessage()); - e.printStackTrace(); } return null; }); @@ -169,11 +175,16 @@ void broadcastToCorrectNetworkAdapter() { // Do not want to use the loopback interface. if (!networkInterface.isLoopback()) { for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { + boolean useBroadcast = !NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp()); if (localIP != null && localIP.getHostAddress() != null && interfaceAddress != null && interfaceAddress.getAddress() != null - && interfaceAddress.getAddress().getHostAddress() != null && interfaceAddress.getBroadcast() != null + && interfaceAddress.getAddress().getHostAddress() != null && ((interfaceAddress.getBroadcast() != null) || useBroadcast) && localIP.getHostAddress().equals(interfaceAddress.getAddress().getHostAddress())) { log.info("Network adapter in use=" + networkInterface.getDisplayName()); - log.info("Broadcast address found=" + interfaceAddress.getBroadcast()); + if (useBroadcast) { + log.info("Broadcast address found=" + interfaceAddress.getBroadcast()); + } else { + log.info("Use static IP address=" + MainSingleton.getInstance().config.getOutputDevice()); + } pingTask(interfaceAddress); setIpTask(interfaceAddress); } @@ -196,19 +207,24 @@ private void setIpTask(InterfaceAddress interfaceAddress) { ScheduledExecutorService udpIpExecutorService = Executors.newScheduledThreadPool(1); Runnable setIpTask = () -> { try { - byte[] bufferBroadcastPing; DatagramPacket broadCastPing; // Send the name of the device where Firefly wants to connect - if (!Constants.SERIAL_PORT_AUTO.equals(FireflyLuciferin.config.getOutputDevice())) { - String udpMsg = (Constants.UDP_DEVICE_NAME + FireflyLuciferin.config.getOutputDevice()); - bufferBroadcastPing = udpMsg.getBytes(); - broadcastAddress = interfaceAddress.getBroadcast(); - broadCastPing = new DatagramPacket(bufferBroadcastPing, bufferBroadcastPing.length, - interfaceAddress.getBroadcast(), Constants.UDP_BROADCAST_PORT); - log.trace(udpMsg); - socket.send(broadCastPing); + if (!Constants.SERIAL_PORT_AUTO.equals(MainSingleton.getInstance().config.getOutputDevice())) { + if (MainSingleton.getInstance().config.getSatellites() != null) { + boolean useBroadcast = !NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp()); + if (useBroadcast) { + broadCastPing = getDatagramPacket(Constants.UDP_DEVICE_NAME, MainSingleton.getInstance().config.getOutputDevice(), interfaceAddress.getBroadcast(), interfaceAddress.getBroadcast()); + } else { + broadCastPing = getDatagramPacket(Constants.UDP_DEVICE_NAME_STATIC, MainSingleton.getInstance().config.getOutputDevice(), interfaceAddress.getAddress(), InetAddress.getByName(MainSingleton.getInstance().config.getStaticGlowWormIp())); + } + socket.send(broadCastPing); + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + broadCastPing = getDatagramPacket(Constants.UDP_DEVICE_NAME_STATIC, sat.getValue().getDeviceIp(), interfaceAddress.getAddress(), InetAddress.getByName(sat.getValue().getDeviceIp())); + socket.send(broadCastPing); + } + } } - } catch (IOException e) { + } catch (Exception e) { log.error(e.getMessage()); } }; @@ -227,32 +243,59 @@ private void pingTask(InterfaceAddress interfaceAddress) { ScheduledExecutorService udpBrExecutorService = Executors.newScheduledThreadPool(1); Runnable pingTask = () -> { try { - String udpMsg = (Constants.UDP_PING + interfaceAddress.getBroadcast().toString().substring(1)); - byte[] bufferBroadcastPing = udpMsg.getBytes(); DatagramPacket broadCastPing; - broadcastAddress = interfaceAddress.getBroadcast(); - broadCastPing = new DatagramPacket(bufferBroadcastPing, bufferBroadcastPing.length, - interfaceAddress.getBroadcast(), Constants.UDP_BROADCAST_PORT); - socket.send(broadCastPing); - log.trace(udpMsg); - } catch (IOException e) { + if (MainSingleton.getInstance().config.getSatellites() != null) { + boolean useBroadcast = !NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp()); + if (useBroadcast) { + broadCastPing = getDatagramPacket(Constants.UDP_PING, interfaceAddress.getBroadcast().toString().substring(1), interfaceAddress.getBroadcast(), interfaceAddress.getBroadcast()); + } else { + broadCastPing = getDatagramPacket(Constants.UDP_PING, interfaceAddress.getAddress().toString().substring(1), interfaceAddress.getAddress(), InetAddress.getByName(MainSingleton.getInstance().config.getStaticGlowWormIp())); + } + socket.send(broadCastPing); + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + broadCastPing = getDatagramPacket(Constants.UDP_PING, interfaceAddress.getAddress().toString().substring(1), interfaceAddress.getAddress(), InetAddress.getByName(sat.getValue().getDeviceIp())); + socket.send(broadCastPing); + } + } + } catch (Exception e) { log.error(e.getMessage()); } }; udpBrExecutorService.scheduleAtFixedRate(pingTask, 0, 1, TimeUnit.SECONDS); } + /** + * Set Ip datagram packet + * + * @param outputDevice device name + * @param broadcastIp IP to use for broadcast + * @param deviceIp device IP for communication + * @return datagram packet to use for sending the msg + */ + private DatagramPacket getDatagramPacket(String prefix, String outputDevice, InetAddress broadcastIp, InetAddress deviceIp) { + byte[] bufferBroadcastPing; + DatagramPacket broadCastPing; + String udpMsg; + udpMsg = (prefix + outputDevice); + bufferBroadcastPing = udpMsg.getBytes(); + log.trace(udpMsg); + broadcastAddress = broadcastIp; + broadCastPing = new DatagramPacket(bufferBroadcastPing, bufferBroadcastPing.length, + deviceIp, Constants.UDP_BROADCAST_PORT); + return broadCastPing; + } + /** * Share received broadcast with other Firefly Luciferin instances * * @param received received brodcast */ private void shareBroadCastToOtherInstances(String received) { - if (!FireflyLuciferin.config.isMultiScreenSingleDevice() && JavaFXStarter.whoAmI == 1 && FireflyLuciferin.config.getMultiMonitor() >= 2) { + if (!MainSingleton.getInstance().config.isMultiScreenSingleDevice() && MainSingleton.getInstance().whoAmI == 1 && MainSingleton.getInstance().config.getMultiMonitor() >= 2) { shareBroadCastToOtherInstance(received.getBytes(), Constants.UDP_BROADCAST_PORT_2); log.trace("Sharing to instance 2 =" + received); } - if (!FireflyLuciferin.config.isMultiScreenSingleDevice() && JavaFXStarter.whoAmI == 1 && FireflyLuciferin.config.getMultiMonitor() == 3) { + if (!MainSingleton.getInstance().config.isMultiScreenSingleDevice() && MainSingleton.getInstance().whoAmI == 1 && MainSingleton.getInstance().config.getMultiMonitor() == 3) { shareBroadCastToOtherInstance(received.getBytes(), Constants.UDP_BROADCAST_PORT_3); log.trace("Sharing to instance 3 =" + received); } diff --git a/src/main/java/org/dpsoftware/utilities/ColorUtilities.java b/src/main/java/org/dpsoftware/utilities/ColorUtilities.java index db3f3c058..40e526b0b 100644 --- a/src/main/java/org/dpsoftware/utilities/ColorUtilities.java +++ b/src/main/java/org/dpsoftware/utilities/ColorUtilities.java @@ -22,7 +22,7 @@ package org.dpsoftware.utilities; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Constants; import org.dpsoftware.managers.dto.ColorRGBW; @@ -199,15 +199,15 @@ private static float hue2RGB(float v1, float v2, float vH) { */ public static ColorRGBW calculateRgbMode(int r, int g, int b) { int[] colorCorrectionRGB = {0, 0, 0}; - int whiteTempInUse = FireflyLuciferin.config.getWhiteTemperature(); + int whiteTempInUse = MainSingleton.getInstance().config.getWhiteTemperature(); int w; w = r < g ? (Math.min(r, b)) : (Math.min(g, b)); - if (FireflyLuciferin.config.getColorMode() == 2) { + if (MainSingleton.getInstance().config.getColorMode() == 2) { // subtract white in accurate mode r -= w; g -= w; b -= w; - } else if (FireflyLuciferin.config.getColorMode() == 4) { + } else if (MainSingleton.getInstance().config.getColorMode() == 4) { // RGB only, turn off white led w = 0; } @@ -258,7 +258,7 @@ public static void colorKtoRGB(int[] rgb, int whiteTempInUse) { * @return corrected color */ public static int applyBrightnessCorrection(int c) { - return c > 0 ? (c * ((FireflyLuciferin.config.getBrightness() * 100) / 255)) / 100 : c; + return c > 0 ? (c * ((MainSingleton.getInstance().config.getBrightness() * 100) / 255)) / 100 : c; } } \ No newline at end of file diff --git a/src/main/java/org/dpsoftware/utilities/CommonUtility.java b/src/main/java/org/dpsoftware/utilities/CommonUtility.java index 5788fb143..5093d6708 100644 --- a/src/main/java/org/dpsoftware/utilities/CommonUtility.java +++ b/src/main/java/org/dpsoftware/utilities/CommonUtility.java @@ -29,18 +29,17 @@ import javafx.stage.Stage; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.dpsoftware.FireflyLuciferin; -import org.dpsoftware.JavaFXStarter; -import org.dpsoftware.NativeExecutor; +import org.dpsoftware.MainSingleton; import org.dpsoftware.config.Configuration; import org.dpsoftware.config.Constants; import org.dpsoftware.config.Enums; import org.dpsoftware.config.LocalizedEnum; -import org.dpsoftware.gui.controllers.DevicesTabController; +import org.dpsoftware.gui.GuiSingleton; import org.dpsoftware.gui.elements.GlowWormDevice; +import org.dpsoftware.gui.elements.Satellite; +import org.dpsoftware.managers.ManagerSingleton; import org.dpsoftware.managers.NetworkManager; import org.dpsoftware.managers.SerialManager; -import org.dpsoftware.managers.UpgradeManager; import org.dpsoftware.managers.dto.ColorDto; import org.dpsoftware.managers.dto.LedMatrixInfo; import org.dpsoftware.managers.dto.StateDto; @@ -53,7 +52,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import static org.dpsoftware.FireflyLuciferin.config; /** * CommonUtility class for useful methods @@ -61,9 +59,6 @@ @Slf4j public class CommonUtility { - public static int wifiStrength = 0; - public static int ldrStrength = 0; - /** * From Java Object to JSON String, useful to handle checked exceptions in lambdas * @@ -119,40 +114,56 @@ public static JsonNode fromJsonToObject(String jsonString) { public static GlowWormDevice getDeviceToUse() { GlowWormDevice glowWormDeviceToUse = new GlowWormDevice(); // MQTT Stream - if (FireflyLuciferin.config.isWirelessStream()) { - if (!FireflyLuciferin.config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO) || FireflyLuciferin.config.getMultiMonitor() > 1) { - glowWormDeviceToUse = DevicesTabController.deviceTableData.stream() - .filter(glowWormDevice -> glowWormDevice.getDeviceName().equals(FireflyLuciferin.config.getOutputDevice())) + if (MainSingleton.getInstance().config.isWirelessStream()) { + if (!MainSingleton.getInstance().config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO) || MainSingleton.getInstance().config.getMultiMonitor() > 1) { + glowWormDeviceToUse = GuiSingleton.getInstance().deviceTableData.stream() + .filter(glowWormDevice -> glowWormDevice.getDeviceName().equals(MainSingleton.getInstance().config.getOutputDevice())) .findAny().orElse(null); - } else if (DevicesTabController.deviceTableData != null && DevicesTabController.deviceTableData.size() > 0) { - glowWormDeviceToUse = DevicesTabController.deviceTableData.get(0); + } else if (GuiSingleton.getInstance().deviceTableData != null && !GuiSingleton.getInstance().deviceTableData.isEmpty()) { + glowWormDeviceToUse = GuiSingleton.getInstance().deviceTableData.get(0); } - } else if (FireflyLuciferin.config.isFullFirmware()) { // MQTT Enabled + } else if (MainSingleton.getInstance().config.isFullFirmware()) { // MQTT Enabled // Waiting both MQTT and serial device - GlowWormDevice glowWormDeviceSerial = DevicesTabController.deviceTableData.stream() + GlowWormDevice glowWormDeviceSerial = GuiSingleton.getInstance().deviceTableData.stream() .filter(glowWormDevice -> glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) .findAny().orElse(null); if (glowWormDeviceSerial != null && glowWormDeviceSerial.getMac() != null) { - glowWormDeviceToUse = DevicesTabController.deviceTableData.stream() + glowWormDeviceToUse = GuiSingleton.getInstance().deviceTableData.stream() .filter(glowWormDevice -> glowWormDevice.getMac().equals(glowWormDeviceSerial.getMac())) .filter(glowWormDevice -> !glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) .findAny().orElse(null); } } else { // Serial only - glowWormDeviceToUse = DevicesTabController.deviceTableData.stream() + glowWormDeviceToUse = GuiSingleton.getInstance().deviceTableData.stream() .filter(glowWormDevice -> glowWormDevice.getDeviceName().equals(Constants.USB_DEVICE)) .findAny().orElse(null); } return glowWormDeviceToUse; } + /** + * Return current device infos, Serial or Wireless with satellites + * + * @return device infos if all satellites are engaged + */ + public static List getDeviceToUseWithSatellites() { + List devices = new ArrayList<>(); + devices.add(getDeviceToUse()); + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + GuiSingleton.getInstance().deviceTableData.stream() + .filter(device -> device.getDeviceIP().equals(sat.getKey())) + .findAny().ifPresent(devices::add); + } + return devices; + } + /** * Check if is single device main instance * * @return true or false */ public static boolean isSingleDeviceMainInstance() { - return FireflyLuciferin.config != null && FireflyLuciferin.config.isMultiScreenSingleDevice() && FireflyLuciferin.config.getMultiMonitor() > 1 && JavaFXStarter.whoAmI == 1; + return MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isMultiScreenSingleDevice() && MainSingleton.getInstance().config.getMultiMonitor() > 1 && MainSingleton.getInstance().whoAmI == 1; } /** @@ -161,7 +172,7 @@ public static boolean isSingleDeviceMainInstance() { * @return true or false */ public static boolean isSingleDeviceOtherInstance() { - return FireflyLuciferin.config != null && FireflyLuciferin.config.isMultiScreenSingleDevice() && FireflyLuciferin.config.getMultiMonitor() > 1 && JavaFXStarter.whoAmI > 1; + return MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isMultiScreenSingleDevice() && MainSingleton.getInstance().config.getMultiMonitor() > 1 && MainSingleton.getInstance().whoAmI > 1; } /** @@ -170,7 +181,7 @@ public static boolean isSingleDeviceOtherInstance() { * @return true or false */ public static boolean isSingleDeviceMultiScreen() { - return FireflyLuciferin.config != null && FireflyLuciferin.config.isMultiScreenSingleDevice() && FireflyLuciferin.config.getMultiMonitor() > 1; + return MainSingleton.getInstance().config != null && MainSingleton.getInstance().config.isMultiScreenSingleDevice() && MainSingleton.getInstance().config.getMultiMonitor() > 1; } /** @@ -183,7 +194,7 @@ public static void sleepSeconds(int numberOfSeconds) { try { TimeUnit.SECONDS.sleep(numberOfSeconds); } catch (InterruptedException e) { - e.printStackTrace(); + log.error(e.getMessage()); } } @@ -196,7 +207,7 @@ public static void sleepMilliseconds(int numberOfMilliseconds) { try { TimeUnit.MILLISECONDS.sleep(numberOfMilliseconds); } catch (InterruptedException e) { - e.printStackTrace(); + log.error(e.getMessage()); } } @@ -274,11 +285,11 @@ public static ScheduledFuture delayMilliseconds(Runnable command, long delay) * @return conditioned brightness */ public static int getNightBrightness() { - float nightBrightness = Float.parseFloat(FireflyLuciferin.config.getNightModeBrightness().replace("%", "")); - if (FireflyLuciferin.nightMode && nightBrightness > 0) { - nightBrightness = (int) (FireflyLuciferin.config.getBrightness() * (1 - (nightBrightness / 100))); + float nightBrightness = Float.parseFloat(MainSingleton.getInstance().config.getNightModeBrightness().replace("%", "")); + if (MainSingleton.getInstance().nightMode && nightBrightness > 0) { + nightBrightness = (int) (MainSingleton.getInstance().config.getBrightness() * (1 - (nightBrightness / 100))); } else { - nightBrightness = FireflyLuciferin.config.getBrightness(); + nightBrightness = MainSingleton.getInstance().config.getBrightness(); } return (int) nightBrightness; } @@ -305,27 +316,36 @@ public static void addDevice(JsonNode actualObj) { log.debug(CommonUtility.toJsonStringPrettyPrinted(actualObj)); boolean validBaudRate = Integer.parseInt(actualObj.get(Constants.BAUD_RATE).toString()) >= 1 && Integer.parseInt(actualObj.get(Constants.BAUD_RATE).toString()) <= 8; - if (FireflyLuciferin.config.getMultiMonitor() == 1 && (FireflyLuciferin.config.getOutputDevice() == null - || FireflyLuciferin.config.getOutputDevice().isEmpty() - || FireflyLuciferin.config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO))) { - if (FireflyLuciferin.config.isWirelessStream()) { - FireflyLuciferin.config.setOutputDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue()); + boolean useBroadcast = !NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp()); + boolean isMyStaticDevice = !useBroadcast && MainSingleton.getInstance().config.getStaticGlowWormIp().equals(actualObj.get(Constants.STATE_IP).textValue()); + // Set current output device if it was AUTO or empty + if (isMyStaticDevice || (MainSingleton.getInstance().config.getMultiMonitor() == 1 && (MainSingleton.getInstance().config.getOutputDevice() == null + || MainSingleton.getInstance().config.getOutputDevice().isEmpty() + || MainSingleton.getInstance().config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO)))) { + if (MainSingleton.getInstance().config.isWirelessStream()) { + if (NetworkManager.isValidIp(MainSingleton.getInstance().config.getStaticGlowWormIp())) { + if (isMyStaticDevice) { + MainSingleton.getInstance().config.setOutputDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue()); + } + } else { + MainSingleton.getInstance().config.setOutputDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue()); + } } else { - if (DevicesTabController.deviceTableData != null && DevicesTabController.deviceTableData.size() > 0) { - FireflyLuciferin.config.setOutputDevice(DevicesTabController.deviceTableData.get(0).getDeviceIP()); + if (GuiSingleton.getInstance().deviceTableData != null && !GuiSingleton.getInstance().deviceTableData.isEmpty()) { + MainSingleton.getInstance().config.setOutputDevice(GuiSingleton.getInstance().deviceTableData.get(0).getDeviceIP()); } } } - if (CommonUtility.isSingleDeviceMultiScreen() && (FireflyLuciferin.config.getOutputDevice().isEmpty() - || FireflyLuciferin.config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO))) { - FireflyLuciferin.config.setOutputDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue()); + if (CommonUtility.isSingleDeviceMultiScreen() && (MainSingleton.getInstance().config.getOutputDevice().isEmpty() + || MainSingleton.getInstance().config.getOutputDevice().equals(Constants.SERIAL_PORT_AUTO))) { + MainSingleton.getInstance().config.setOutputDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue()); } - if (DevicesTabController.deviceTableData != null) { + if (GuiSingleton.getInstance().deviceTableData != null) { if (actualObj.get(Constants.WIFI) == null) { - wifiStrength = actualObj.get(Constants.WIFI) != null ? actualObj.get(Constants.WIFI).asInt() : 0; + MainSingleton.getInstance().wifiStrength = actualObj.get(Constants.WIFI) != null ? actualObj.get(Constants.WIFI).asInt() : 0; } if (actualObj.get(Constants.MQTT_LDR_VALUE) == null) { - wifiStrength = actualObj.get(Constants.MQTT_LDR_VALUE) != null ? actualObj.get(Constants.MQTT_LDR_VALUE).asInt() : 0; + MainSingleton.getInstance().wifiStrength = actualObj.get(Constants.MQTT_LDR_VALUE) != null ? actualObj.get(Constants.MQTT_LDR_VALUE).asInt() : 0; } String deviceColorMode = Constants.DASH; int deviceColorModeInt = 0; @@ -339,10 +359,10 @@ public static void addDevice(JsonNode actualObj) { } String deviceVer = (actualObj.get(Constants.DEVICE_VER).textValue()); String deviceBoard = actualObj.get(Constants.DEVICE_BOARD) == null ? Constants.DASH : actualObj.get(Constants.DEVICE_BOARD).textValue(); - if (config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(deviceBoard)) { + if (MainSingleton.getInstance().config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(deviceBoard)) { deviceVer = Constants.FORCE_FIRMWARE_AUTO_UPGRADE; } - DevicesTabController.deviceTableData.add(new GlowWormDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue(), + GlowWormDevice deviceToAdd = new GlowWormDevice(actualObj.get(Constants.MQTT_DEVICE_NAME).textValue(), actualObj.get(Constants.STATE_IP).textValue(), actualObj.get(Constants.STATE_DHCP) != null && actualObj.get(Constants.STATE_DHCP).asBoolean(), (actualObj.get(Constants.WIFI) == null ? Constants.DASH : actualObj.get(Constants.WIFI) + Constants.PERCENT), @@ -351,24 +371,26 @@ public static void addDevice(JsonNode actualObj) { (actualObj.get(Constants.MAC) == null ? Constants.DASH : actualObj.get(Constants.MAC).textValue()), (actualObj.get(Constants.GPIO) == null ? Constants.DASH : actualObj.get(Constants.GPIO).toString()), (actualObj.get(Constants.NUMBER_OF_LEDS) == null ? Constants.DASH : actualObj.get(Constants.NUMBER_OF_LEDS).textValue()), - (FireflyLuciferin.formatter.format(new Date())), + (MainSingleton.getInstance().formatter.format(new Date())), Enums.FirmwareType.FULL.name(), (((actualObj.get(Constants.BAUD_RATE) == null) || !validBaudRate) ? Constants.DASH : Enums.BaudRate.findByValue(Integer.parseInt(actualObj.get(Constants.BAUD_RATE).toString())).getBaudRate()), - (actualObj.get(Constants.MQTT_TOPIC) == null ? FireflyLuciferin.config.isFullFirmware() ? Constants.MQTT_BASE_TOPIC : Constants.DASH + (actualObj.get(Constants.MQTT_TOPIC) == null ? MainSingleton.getInstance().config.isFullFirmware() ? Constants.MQTT_BASE_TOPIC : Constants.DASH : actualObj.get(Constants.MQTT_TOPIC).textValue()), deviceColorMode, Enums.ColorOrder.findByValue(deviceColorOrderInt).name(), (actualObj.get(Constants.MQTT_LDR_VALUE) == null ? Constants.DASH : actualObj.get(Constants.MQTT_LDR_VALUE).asInt() + Constants.PERCENT), (actualObj.get(Constants.HTTP_LDR_RELAYPIN) == null ? Constants.DASH : actualObj.get(Constants.HTTP_LDR_RELAYPIN).toString()), (actualObj.get(Constants.HTTP_LDR_SBPIN) == null ? Constants.DASH : actualObj.get(Constants.HTTP_LDR_SBPIN).toString()), (actualObj.get(Constants.HTTP_LDR_LDRPIN) == null ? Constants.DASH : actualObj.get(Constants.HTTP_LDR_LDRPIN).toString()), - (actualObj.get(Constants.GPIO_CLOCK) == null ? Constants.DASH : actualObj.get(Constants.GPIO_CLOCK).toString()))); + (actualObj.get(Constants.GPIO_CLOCK) == null ? Constants.DASH : actualObj.get(Constants.GPIO_CLOCK).toString())); + GuiSingleton.getInstance().deviceTableData.add(deviceToAdd); + updateSatelliteIp(deviceToAdd); if (CommonUtility.getDeviceToUse() != null && actualObj.get(Constants.MAC) != null) { if (CommonUtility.getDeviceToUse().getMac().equals(actualObj.get(Constants.MAC).textValue())) { if (actualObj.get(Constants.WHITE_TEMP) != null) { - FireflyLuciferin.config.setWhiteTemperature(actualObj.get(Constants.WHITE_TEMP).asInt()); + MainSingleton.getInstance().config.setWhiteTemperature(actualObj.get(Constants.WHITE_TEMP).asInt()); } - FireflyLuciferin.config.setColorMode(deviceColorModeInt); + MainSingleton.getInstance().config.setColorMode(deviceColorModeInt); } } } @@ -386,14 +408,14 @@ public static void addDevice(JsonNode actualObj) { */ public static void updateDeviceTable(JsonNode mqttmsg) { String freshDeviceName = mqttmsg.get(Constants.MQTT_DEVICE_NAME).textValue(); - if (DevicesTabController.deviceTableData.isEmpty()) { + if (GuiSingleton.getInstance().deviceTableData.isEmpty()) { CommonUtility.addDevice(mqttmsg); } else { AtomicBoolean isDevicePresent = new AtomicBoolean(false); - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (glowWormDevice.getDeviceName().equals(freshDeviceName)) { isDevicePresent.set(true); - glowWormDevice.setLastSeen(FireflyLuciferin.formatter.format(new Date())); + glowWormDevice.setLastSeen(MainSingleton.getInstance().formatter.format(new Date())); if (mqttmsg.get(Constants.GPIO) != null) { glowWormDevice.setGpio(mqttmsg.get(Constants.GPIO).toString()); } @@ -401,19 +423,20 @@ public static void updateDeviceTable(JsonNode mqttmsg) { glowWormDevice.setGpioClock(mqttmsg.get(Constants.GPIO_CLOCK).toString()); } if (mqttmsg.get(Constants.WIFI) != null) { - CommonUtility.wifiStrength = mqttmsg.get(Constants.WIFI) != null ? mqttmsg.get(Constants.WIFI).asInt() : 0; + MainSingleton.getInstance().wifiStrength = mqttmsg.get(Constants.WIFI) != null ? mqttmsg.get(Constants.WIFI).asInt() : 0; glowWormDevice.setWifi(mqttmsg.get(Constants.WIFI).asInt() + Constants.PERCENT); } if (mqttmsg.get(Constants.STATE_IP) != null) { glowWormDevice.setDeviceIP(mqttmsg.get(Constants.STATE_IP).textValue()); + updateSatelliteIp(glowWormDevice); } if (mqttmsg.get(Constants.WHITE_TEMP) != null) { if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac().equals(glowWormDevice.getMac())) { - FireflyLuciferin.config.setWhiteTemperature(mqttmsg.get(Constants.WHITE_TEMP).asInt()); + MainSingleton.getInstance().config.setWhiteTemperature(mqttmsg.get(Constants.WHITE_TEMP).asInt()); } } if (mqttmsg.get(Constants.MQTT_LDR_VALUE) != null) { - CommonUtility.ldrStrength = mqttmsg.get(Constants.MQTT_LDR_VALUE) != null ? mqttmsg.get(Constants.MQTT_LDR_VALUE).asInt() : 0; + MainSingleton.getInstance().ldrStrength = mqttmsg.get(Constants.MQTT_LDR_VALUE) != null ? mqttmsg.get(Constants.MQTT_LDR_VALUE).asInt() : 0; glowWormDevice.setLdrValue(mqttmsg.get(Constants.MQTT_LDR_VALUE).asInt() + Constants.PERCENT); } if (mqttmsg.get(Constants.BAUD_RATE) != null) { @@ -423,12 +446,12 @@ public static void updateDeviceTable(JsonNode mqttmsg) { int tempColorMode = mqttmsg.get(Constants.COLOR).get(Constants.COLOR_MODE).asInt(); glowWormDevice.setColorMode(Enums.ColorMode.values()[tempColorMode - 1].getI18n()); if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac().equals(glowWormDevice.getMac())) { - FireflyLuciferin.config.setColorMode(tempColorMode); + MainSingleton.getInstance().config.setColorMode(tempColorMode); } int tempColorOrder = mqttmsg.get(Constants.COLOR).get(Constants.COLOR_ORDER).asInt(); glowWormDevice.setColorOrder(Enums.ColorOrder.findByValue(tempColorOrder).name()); if (CommonUtility.getDeviceToUse() != null && CommonUtility.getDeviceToUse().getMac().equals(glowWormDevice.getMac())) { - FireflyLuciferin.colorOrder = tempColorOrder; + MainSingleton.getInstance().colorOrder = tempColorOrder; } } if (mqttmsg.get(Constants.NUMBER_OF_LEDS) != null) { @@ -451,7 +474,7 @@ public static void updateDeviceTable(JsonNode mqttmsg) { } if (mqttmsg.get(Constants.DEVICE_VER) != null) { String deviceVer = (mqttmsg.get(Constants.DEVICE_VER).textValue()); - if (config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard())) { + if (MainSingleton.getInstance().config.isCheckForUpdates() && Enums.SupportedDevice.ESP32_S3_CDC.name().equals(glowWormDevice.getDeviceBoard())) { deviceVer = Constants.FORCE_FIRMWARE_AUTO_UPGRADE; } glowWormDevice.setDeviceVersion(deviceVer); @@ -462,14 +485,36 @@ public static void updateDeviceTable(JsonNode mqttmsg) { CommonUtility.addDevice(mqttmsg); } } - if (UpgradeManager.deviceNameForSerialDevice.isEmpty()) { + if (ManagerSingleton.getInstance().deviceNameForSerialDevice.isEmpty()) { GlowWormDevice mqttDeviceInUse = CommonUtility.getDeviceToUse(); if (mqttDeviceInUse != null) { - UpgradeManager.deviceNameForSerialDevice = mqttDeviceInUse.getDeviceName(); + ManagerSingleton.getInstance().deviceNameForSerialDevice = mqttDeviceInUse.getDeviceName(); if (Enums.SupportedDevice.ESP32_S3_CDC.name().equals(mqttDeviceInUse.getDeviceBoard())) { - UpgradeManager.deviceNameForSerialDevice += Constants.CDC_DEVICE; + ManagerSingleton.getInstance().deviceNameForSerialDevice += Constants.CDC_DEVICE; + } + } + } + } + + /** + * Satellites uses IP to be engaged. Their IP can be dynamic, if Firefly detect an instance that has the same device name, + * swap the IP of the satellite with that device. + * + * @param deviceToAdd new devices detected by Firefly Luciferin + */ + private static void updateSatelliteIp(GlowWormDevice deviceToAdd) { + if (MainSingleton.getInstance().config.getSatellites() != null && !MainSingleton.getInstance().config.getSatellites().isEmpty()) { + Map tempSatellites = new LinkedHashMap<>(MainSingleton.getInstance().config.getSatellites()); + for (Map.Entry sat : MainSingleton.getInstance().config.getSatellites().entrySet()) { + if (sat.getValue().getDeviceName().equals(deviceToAdd.getDeviceName()) && !sat.getValue().getDeviceIp().equals(deviceToAdd.getDeviceIP())) { + log.info("{} Satellite's IP is changed, updating it.", deviceToAdd.getDeviceName()); + tempSatellites.remove(sat.getKey()); + sat.getValue().setDeviceIp(deviceToAdd.getDeviceIP()); + tempSatellites.put(deviceToAdd.getDeviceIP(), sat.getValue()); } } + MainSingleton.getInstance().config.getSatellites().clear(); + MainSingleton.getInstance().config.getSatellites().putAll(tempSatellites); } } @@ -483,30 +528,28 @@ public static void updateDeviceTable(JsonNode mqttmsg) { public static void updateFpsWithFpsTopic(JsonNode fpsTopicMsg) { if (fpsTopicMsg.get(Constants.MAC) != null) { String macToUpdate = fpsTopicMsg.get(Constants.MAC).textValue(); - List matchingDevice = DevicesTabController.deviceTableData.stream() + List matchingDevice = GuiSingleton.getInstance().deviceTableData.stream() .filter(p -> p.getMac().equals(macToUpdate)).toList(); if (matchingDevice.isEmpty()) { - List matchingDeviceTemp = DevicesTabController.deviceTableDataTemp.stream() + List matchingDeviceTemp = GuiSingleton.getInstance().deviceTableDataTemp.stream() .filter(p -> p.getMac().equals(macToUpdate)).toList(); if (!matchingDeviceTemp.isEmpty()) { log.info("Known device, adding to the device table."); - DevicesTabController.deviceTableData.addAll(matchingDeviceTemp); - DevicesTabController.deviceTableDataTemp.removeIf(e -> e.getMac().equals(macToUpdate)); + GuiSingleton.getInstance().deviceTableData.addAll(matchingDeviceTemp); + GuiSingleton.getInstance().deviceTableDataTemp.removeIf(e -> e.getMac().equals(macToUpdate)); } } - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (glowWormDevice.getMac().equals(macToUpdate)) { - glowWormDevice.setLastSeen(FireflyLuciferin.formatter.format(new Date())); + glowWormDevice.setLastSeen(MainSingleton.getInstance().formatter.format(new Date())); glowWormDevice.setNumberOfLEDSconnected(fpsTopicMsg.get(Constants.NUMBER_OF_LEDS).textValue()); if (fpsTopicMsg.get(Constants.MQTT_LDR_VALUE) != null) { glowWormDevice.setLdrValue(fpsTopicMsg.get(Constants.MQTT_LDR_VALUE).asInt() + Constants.PERCENT); - CommonUtility.ldrStrength = fpsTopicMsg.get(Constants.MQTT_LDR_VALUE) != null ? fpsTopicMsg.get(Constants.MQTT_LDR_VALUE).asInt() : 0; + MainSingleton.getInstance().ldrStrength = fpsTopicMsg.get(Constants.MQTT_LDR_VALUE) != null ? fpsTopicMsg.get(Constants.MQTT_LDR_VALUE).asInt() : 0; } - if (glowWormDevice.getDeviceName().equals(FireflyLuciferin.config.getOutputDevice()) || glowWormDevice.getDeviceIP().equals(FireflyLuciferin.config.getOutputDevice())) { - if (FireflyLuciferin.config.isWirelessStream()) { - FireflyLuciferin.FPS_GW_CONSUMER = Float.parseFloat(fpsTopicMsg.get(Constants.MQTT_TOPIC_FRAMERATE).asText()); - } - CommonUtility.wifiStrength = fpsTopicMsg.get(Constants.WIFI) != null ? fpsTopicMsg.get(Constants.WIFI).asInt() : 0; + if (glowWormDevice.getDeviceName().equals(MainSingleton.getInstance().config.getOutputDevice()) || glowWormDevice.getDeviceIP().equals(MainSingleton.getInstance().config.getOutputDevice())) { + MainSingleton.getInstance().FPS_GW_CONSUMER = Float.parseFloat(fpsTopicMsg.get(Constants.MQTT_TOPIC_FRAMERATE).asText()); + MainSingleton.getInstance().wifiStrength = fpsTopicMsg.get(Constants.WIFI) != null ? fpsTopicMsg.get(Constants.WIFI).asInt() : 0; } } }); @@ -521,10 +564,10 @@ public static void updateFpsWithFpsTopic(JsonNode fpsTopicMsg) { public static void updateFpsWithDeviceTopic(JsonNode mqttmsg) { if (mqttmsg.get(Constants.MQTT_TOPIC_FRAMERATE) != null) { String macToUpdate = mqttmsg.get(Constants.MAC).asText(); - DevicesTabController.deviceTableData.forEach(glowWormDevice -> { + GuiSingleton.getInstance().deviceTableData.forEach(glowWormDevice -> { if (glowWormDevice.getMac().equals(macToUpdate)) { - if (glowWormDevice.getDeviceName().equals(FireflyLuciferin.config.getOutputDevice()) || glowWormDevice.getDeviceIP().equals(FireflyLuciferin.config.getOutputDevice())) { - FireflyLuciferin.FPS_GW_CONSUMER = Float.parseFloat(mqttmsg.get(Constants.MQTT_TOPIC_FRAMERATE).asText()); + if (glowWormDevice.getDeviceName().equals(MainSingleton.getInstance().config.getOutputDevice()) || glowWormDevice.getDeviceIP().equals(MainSingleton.getInstance().config.getOutputDevice())) { + MainSingleton.getInstance().FPS_GW_CONSUMER = Float.parseFloat(mqttmsg.get(Constants.MQTT_TOPIC_FRAMERATE).asText()); } } }); @@ -535,18 +578,18 @@ public static void updateFpsWithDeviceTopic(JsonNode mqttmsg) { * Turn ON LEDs when Luciferin starts or on profile switch */ public static void turnOnLEDs() { - Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, FireflyLuciferin.config.getEffect()); + Enums.Effect effectInUse = LocalizedEnum.fromBaseStr(Enums.Effect.class, MainSingleton.getInstance().config.getEffect()); if (!Enums.Effect.BIAS_LIGHT.equals(effectInUse) && !Enums.Effect.MUSIC_MODE_VU_METER.equals(effectInUse) && !Enums.Effect.MUSIC_MODE_VU_METER_DUAL.equals(effectInUse) && !Enums.Effect.MUSIC_MODE_BRIGHT.equals(effectInUse) && !Enums.Effect.MUSIC_MODE_RAINBOW.equals(effectInUse)) { - if (FireflyLuciferin.config.isToggleLed()) { - String[] color = FireflyLuciferin.config.getColorChooser().split(","); - if (FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config.isToggleLed()) { + String[] color = MainSingleton.getInstance().config.getColorChooser().split(","); + if (MainSingleton.getInstance().config.isFullFirmware()) { StateDto stateDto = new StateDto(); stateDto.setState(Constants.ON); - stateDto.setEffect(FireflyLuciferin.config.getEffect()); + stateDto.setEffect(MainSingleton.getInstance().config.getEffect()); ColorDto colorDto = new ColorDto(); colorDto.setR(Integer.parseInt(color[0])); colorDto.setG(Integer.parseInt(color[1])); @@ -556,13 +599,13 @@ public static void turnOnLEDs() { if (CommonUtility.getDeviceToUse() != null) { stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); } - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } else { SerialManager serialManager = new SerialManager(); serialManager.sendSerialParams(Integer.parseInt(color[0]), Integer.parseInt(color[1]), Integer.parseInt(color[2])); } } else { - if (FireflyLuciferin.config.isFullFirmware()) { + if (MainSingleton.getInstance().config.isFullFirmware()) { StateDto stateDto = new StateDto(); stateDto.setState(Constants.OFF); stateDto.setEffect(Constants.SOLID); @@ -570,7 +613,7 @@ public static void turnOnLEDs() { if (CommonUtility.getDeviceToUse() != null) { stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); } - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto)); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto)); } else { SerialManager serialManager = new SerialManager(); serialManager.sendSerialParams(0, 0, 0); @@ -596,10 +639,10 @@ public static void turnOffLEDs(Configuration currentConfig) { */ public static void turnOffLEDs(Configuration currentConfig, int qos) { if (currentConfig != null) { - if (FireflyLuciferin.RUNNING && !NativeExecutor.exitTriggered) { - FireflyLuciferin.guiManager.stopCapturingThreads(true); + if (MainSingleton.getInstance().RUNNING && !MainSingleton.getInstance().exitTriggered) { + MainSingleton.getInstance().guiManager.stopCapturingThreads(true); } - if (!NativeExecutor.exitTriggered) { + if (!MainSingleton.getInstance().exitTriggered) { CommonUtility.sleepMilliseconds(100); } if (currentConfig.isFullFirmware()) { @@ -607,16 +650,16 @@ public static void turnOffLEDs(Configuration currentConfig, int qos) { stateDto.setState(Constants.OFF); stateDto.setEffect(Constants.SOLID); stateDto.setBrightness(CommonUtility.getNightBrightness()); - stateDto.setWhitetemp(FireflyLuciferin.config.getWhiteTemperature()); + stateDto.setWhitetemp(MainSingleton.getInstance().config.getWhiteTemperature()); if (CommonUtility.getDeviceToUse() != null) { stateDto.setMAC(CommonUtility.getDeviceToUse().getMac()); } - NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.DEFAULT_MQTT_TOPIC), CommonUtility.toJsonString(stateDto), false, false, qos); + NetworkManager.publishToTopic(NetworkManager.getTopic(Constants.TOPIC_DEFAULT_MQTT), CommonUtility.toJsonString(stateDto), false, false, qos); } else { java.awt.Color[] leds = new java.awt.Color[1]; try { leds[0] = new java.awt.Color(0, 0, 0); - FireflyLuciferin.config.setBrightness(CommonUtility.getNightBrightness()); + MainSingleton.getInstance().config.setBrightness(CommonUtility.getNightBrightness()); SerialManager serialManager = new SerialManager(); serialManager.sendColorsViaUSB(leds); } catch (IOException e) { @@ -653,7 +696,7 @@ public static boolean isInteger(String strNum) { */ public static String getWord(String key) { try { - return FireflyLuciferin.bundle.getString(key); + return MainSingleton.getInstance().bundle.getString(key); } catch (MissingResourceException e) { return key; } @@ -724,7 +767,7 @@ public static void groupByCalc(LedMatrixInfo ledMatrixInfo) { * @return capitalized string */ public static String capitalize(String str) { - if (str == null || str.length() == 0) return str; + if (str == null || str.isEmpty()) return str; return str.substring(0, 1).toUpperCase() + str.substring(1); } diff --git a/src/main/resources/gstreamer b/src/main/resources/gstreamer index f2704e9da..b6979aead 160000 --- a/src/main/resources/gstreamer +++ b/src/main/resources/gstreamer @@ -1 +1 @@ -Subproject commit f2704e9daba22861d0f40acda69abe354707c1a1 +Subproject commit b6979aead7d525c166d1ef5aba636b33e65b134f diff --git a/src/main/resources/messagebundle_de.properties b/src/main/resources/messagebundle_de.properties index 68cf102a5..adcc3e207 100644 --- a/src/main/resources/messagebundle_de.properties +++ b/src/main/resources/messagebundle_de.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Speichern und schließen fxml.save=Speichern +fxml.reset=Képernyő visszaállítása fxml.setting.controls=Steuerung fxml.setting.ledsconfig=LED Konfiguration fxml.setting.mode=Modus @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Bildfrequenz (FPS) fxml.devicestab.software.version=Softwareversion fxml.devicestab.connected.devices=Verbunde Geräte fxml.devicestab.power.saving=Ausschalten nach +fxml.devicestab.surround.lighting=Surround-Beleuchtung fxml.devicestab.multi.monitor=Bildschirmanzahl fxml.devicestab.sync.check=Synch. Überprüfung fxml.devicestab.check.updates=Nach Updates suchen @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=Im Uhrzeigersinn enum.orientation.anticlockwise=Gegen den Uhrzeigersinn +enum.direction.normal=Normal +enum.direction.inverse=Invers enum.led.offset.bottom.left=Unten links enum.led.offset.bottom.center=Unten mitte @@ -259,6 +263,11 @@ serial.port.ambiguos.context=Mehr als ein Gerät sind mit deinen seriellen Ports mqtt.error.title=MQTT Verbindungsfehler mqtt.error.header=Es kann keine Verbindung zum MQTT-Server hergestellt werden. mqtt.error.context=Luciferin kann keine Verbindung zum MQTT-Server herstellen, bitte überprüfe deine Einstellungen und versuche es erneut. +cuda.error.title=Plugin-Fehler +cuda.error.header=GStreamer-Plugins nicht gefunden. +cuda.error.context=Ihr System verfügt nicht über alle erforderlichen Plugins zum Ausführen von NVIDIA CUDA.\nBitte überprüfen Sie das WIKI des Projekts, um zu erfahren, wie Sie alle erforderlichen Abhängigkeiten installieren. +wayland.screen.rec.permission=Luciferin benötigt die Erlaubnis, Ihre\n{0} +wayland.screen.rec.permission.context=In einem Popup werden Sie um Erlaubnis zum Aufzeichnen Ihres Bildschirms gebeten.\nBitte wählen Sie „{0}“\nund klicken Sie dann auf die Schaltfläche „Teilen“. click.ok.download=\nKlicke auf “OK”, um die neue Version herunterzuladen und zu installieren. click.ok.download.linux=\nKlicke auf “OK”, um die neue Version in \n~/Documents/FireflyLuciferin herunterzuladen.\n once.download.finished=Sobald der Download abgeschlossen ist,\nwechsle bitte zu diesem Ordner und installiere das Programm manuell. @@ -302,7 +311,32 @@ tc.after.text=RGB nach der Korrektur ({0}, {1}, {2}) tc.after.text.rgwb=RGBW nach der Korrektur ({0}, {1}, {2}, {3}) tc.full.saturation=Volle Sättigung tc.half.saturation=Halbe Sättigung +enum.color.algo.avg=Durchschnittliche Farbe +enum.color.algo.avg.all=Durchschnittlich bei allen LEDs +enum.satellite.zone.entire.screen=Gesamter Bildschirm +enum.satellite.zone.top=Hoch +enum.satellite.zone.top.right=Oben rechts +enum.satellite.zone.right=Nach rechts +enum.satellite.zone.bottom.right=Unten rechts +enum.satellite.zone.bottom=Runter +enum.satellite.zone.bottom.left=Unten links +enum.satellite.zone.left=Nach links +enum.satellite.zone.top.left=Oben links +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algorithmus +fxml.satellite.zone=Zone +fxml.satellite.orientation=Richtung +fxml.satellite.manage.sat=Satelliten verwalten +fxml.satellite.manager.sat.ip=Satelliten-IP +fxml.satellite.manager.zone=Zonen (Start/Ende) +fxml.satellite.manager.orient=Richtung/LED # +fxml.satellite.manager.algo=Capture-Algorithmus +satellite.ip.error.title=Satellit +satellite.ip.error.header=Der Satellit kann nicht hinzugefügt werden +satellite.ip.error.content=Bitte geben Sie eine gültige IP-Adresse ein +tooltip.reset.wayland=Berechtigung zur Bildschirmaufzeichnung zurücksetzen tooltip.topled=Anzahl der LEDs in der oberen Reihe tooltip.leftled=Anzahl der LEDs in der linken Spalte tooltip.rightled=Anzahl der LEDs in der rechten Spalte @@ -318,15 +352,16 @@ tooltip.white.temp=Die Markierung in der Mitte deaktiviert den Weißabgleich. tooltip.color.mode=Verwenden Sie RGB für WS2812B oder ähnliches und RGBW für SK6812B oder ähnliches. tooltip.gamma=Kleinere Werte resultieren in helleren LEDs, aber weniger akkuraten Farben. 2.2 ist üblicherweise gut geeignet für SDR-Inhalte, 6.0 für HDR-Inhalte. tooltip.capturemethod=Wenn du eine Grafikkarte hast, ist die Desktop Duplication API (DDUPL) schneller als andere Methoden. -tooltip.linuxcapturemethod=Aufnahmemethode +tooltip.linuxcapturemethod=Wenn Sie Wayland verwenden, müssen Sie die PIPEWIRE-Erfassungsmethode verwenden. tooltip.maccapturemethod=Aufnahmemethode tooltip.numberofthreads=1 Thread ist bei Verwendung von DDUPL ausreichend, 3 oder mehr Threads sind für andere Aufnahmemethoden empfohlen. -tooltip.serialport=Für diese Anzeige zu verwendendes Ausgabegerät +tooltip.serialport=Für diese Anzeige zu verwendendes Ausgabegerät. Wenn Sie sich hinter einem VLAN/Subnetz befinden oder lieber eine statische IP-Adresse verwenden möchten, geben Sie die IP-Adresse Ihres Glow Worm-Geräts ein. tooltip.aspectratio=Wähle “Balken oben/unten”, falls deine Videoinhalte schwarze, horizontale Balken beinhalten oder “Balken rechts/links” bei vertikalen Rändern. tooltip.language=Auswahl der Sprache tooltip.framerate=30 FPS ist die empfohlene Bildwiederholrate. Diese Einstellung ist spezifisch für die Standard-Funktion tooltip.mqtthost=OPTIONAL: MQTT protocol://host tooltip.power.saving=Schaltet die LEDs bei Inaktivität nach der eingestellten Zeit aus +tooltip.sat.btn=Das Hinzufügen oder Entfernen von Satelliten für die Surround-Beleuchtung erfordert eine vollständige Firmware. tooltip.multimonitor=Pro Monitor ist ein Mikrocontroller erforderlich tooltip.monitornumber=Wählen Sie einen Monitor für die Bildschirmaufnahme aus tooltip.mqttport=OPTIONAL: MQTT-Port @@ -408,4 +443,10 @@ tooltip.ldr.ldrlabel=Aktuelle Helligkeit des Raumes tooltip.brightness.limiter=Limit peak brightness without affecting lower brightness scenes. tooltip.frame.insertion=Auf höherem Level werden die Übergänge von einer Farbe zur anderen weicher, aber die LEDs werden auf schnelle Änderungen langsamer reagieren. tooltip.colorcorrection.latency.test=Dieser Test zeigt Farben in schneller Folge an und hilft Ihnen zu überprüfen, ob die Latenz zwischen dem auf Ihrem Monitor angezeigten Bild und der auf dem LED-Streifen angezeigten Farbe für Sie akzeptabel ist. -tooltip.colorcorrection.latency.test.speed=Sie können den Latenztest mit 10 verschiedenen Geschwindigkeiten ausführen \ No newline at end of file +tooltip.colorcorrection.latency.test.speed=Sie können den Latenztest mit 10 verschiedenen Geschwindigkeiten ausführen +tooltip.sat.manager.ip=Bitte wählen Sie aus der Liste aus, welchen Satelliten Sie hinzufügen möchten, oder geben Sie seine IP-Adresse ein +tooltip.sat.manager.zone=Bildschirmaufnahmebereich zum Senden an den Satelliten +tooltip.sat.manager.orientation=LED-Richtung +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Capture-Algorithmus +tooltip.sat.manager.add=Drücken Sie diese Taste, um einen Satelliten hinzuzufügen \ No newline at end of file diff --git a/src/main/resources/messagebundle_en.properties b/src/main/resources/messagebundle_en.properties index 46d55e863..b25a144a3 100644 --- a/src/main/resources/messagebundle_en.properties +++ b/src/main/resources/messagebundle_en.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Save and close fxml.save=Save +fxml.reset=Reset screen fxml.setting.controls=Controls fxml.setting.ledsconfig=LEDs config fxml.setting.mode=Mode @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Software version fxml.devicestab.connected.devices=Connected devices fxml.devicestab.power.saving=Power saving +fxml.devicestab.surround.lighting=Surround lighting fxml.devicestab.multi.monitor=Multi monitor fxml.devicestab.sync.check=Sync check fxml.devicestab.check.updates=Check for updates @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=Clockwise enum.orientation.anticlockwise=Anticlockwise +enum.direction.normal=Normal +enum.direction.inverse=Inverse enum.led.offset.bottom.left=Bottom Left enum.led.offset.bottom.center=Bottom Center @@ -259,6 +263,11 @@ serial.port.ambiguos.context=There is more than one device connected to your ser mqtt.error.title=MQTT Connection Error mqtt.error.header=Unable to connect to the MQTT server mqtt.error.context=Luciferin is unable to connect to the MQTT server, please correct your settings and retry. +cuda.error.title=Plugins error +cuda.error.header=GStreamer plugins not found. +cuda.error.context=Your system does not have all the required plugins to run NVIDIA CUDA.\nPlease check the project's WIKI to learn how to install all the required dependencies. +wayland.screen.rec.permission=Luciferin needs the permission to record your\n{0} +wayland.screen.rec.permission.context=A popup will ask you for the permission to record your screen,\nplease select the "{0}"\nand then click the "Share" button. click.ok.download=\nClick Ok to download and install the new version. click.ok.download.linux=\nClick Ok to download new version in your\n~/Documents/FireflyLuciferin folder.\n once.download.finished=Once the download is finished,\nplease go to that folder and install it manually. @@ -302,7 +311,32 @@ tc.after.text=RGB after correction ({0}, {1}, {2}) tc.after.text.rgwb=RGBW after correction ({0}, {1}, {2}, {3}) tc.full.saturation=Full saturation tc.half.saturation=Half saturation +enum.color.algo.avg=Average color +enum.color.algo.avg.all=Average on all LEDs +enum.satellite.zone.entire.screen=Entire screen +enum.satellite.zone.top=Top +enum.satellite.zone.top.right=Top right +enum.satellite.zone.right=Right +enum.satellite.zone.bottom.right=Bottom right +enum.satellite.zone.bottom=Bottom +enum.satellite.zone.bottom.left=Bottom left +enum.satellite.zone.left=Left +enum.satellite.zone.top.left=Top left +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algorithm +fxml.satellite.zone=Zone +fxml.satellite.orientation=Direction +fxml.satellite.manage.sat=Manage satellites +fxml.satellite.manager.sat.ip=Satellite IP +fxml.satellite.manager.zone=Zones (Start/End) +fxml.satellite.manager.orient=Direction / Led # +fxml.satellite.manager.algo=Capture algorithm +satellite.ip.error.title=Satellite +satellite.ip.error.header=Can't add the satellite +satellite.ip.error.content=Please enter a valid IP address +tooltip.reset.wayland=Reset screen recording permission tooltip.topled=# of LEDs in the top row tooltip.leftled=# of LEDs in the left column tooltip.rightled=# of LEDs in the right column @@ -318,15 +352,16 @@ tooltip.white.temp=The marker in the center disables white balance. tooltip.color.mode=Use RGB for WS2812B or similar and RGBW for SK6812B or similar. tooltip.gamma=Smaller values results in brighter LEDs but less accurate colors. 2.2 is generally good for SDR contents, 6.0 is generally good for HDR contents. tooltip.capturemethod=If you have a GPU, Desktop Duplication API (DDUPL) is faster than other methods -tooltip.linuxcapturemethod=Capture method +tooltip.linuxcapturemethod=If you use Wayland you must use the PIPEWIRE acquisition method. tooltip.maccapturemethod=Capture method tooltip.numberofthreads=1 thread is enough when using DDUPL, 3 or more threads are recommended for other capture methods -tooltip.serialport=Output device to use for this display +tooltip.serialport=Output device to use for this display. If you are behind a VLAN/Subnet or prefer to use a static IP address, enter the IP address of your Glow Worm device. tooltip.aspectratio=Select letterbox if your video content presents horizontal black bars or pillarbox if you see vertical black bars tooltip.language=Choose language tooltip.framerate=30 FPS is the recommended framerate. This setting is specific to the bias light function. tooltip.mqtthost=OPTIONAL: MQTT protocol://host tooltip.power.saving=Turn off LEDs if there is no activity for the configured number of minutes +tooltip.sat.btn=Add or remove satellites for surround lighting, requires full firmware. tooltip.multimonitor=One microcontroller per monitor is required tooltip.monitornumber=Choose a monitor for the screen capture tooltip.mqttport=OPTIONAL: MQTT port @@ -409,3 +444,9 @@ tooltip.brightness.limiter=Limit peak brightness without affecting lower brightn tooltip.frame.insertion=Higher levels will smooth transitions from one color to another but LEDs will be less responsive to quick changes. tooltip.colorcorrection.latency.test=This test displays colors in rapid succession and helps you check if the latency between the image shown on your monitor and the color displayed on the led strip is acceptable to you. tooltip.colorcorrection.latency.test.speed=You can run the latency test at 10 different speed +tooltip.sat.manager.ip=Please choose which satellite to add from the list or enter its IP address +tooltip.sat.manager.zone=Screen capture zone to send to the satellite +tooltip.sat.manager.orientation=LED direction +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Capture algorithm +tooltip.sat.manager.add=Press this button to add a satellite \ No newline at end of file diff --git a/src/main/resources/messagebundle_es.properties b/src/main/resources/messagebundle_es.properties index 7799cd0e1..79baa410c 100644 --- a/src/main/resources/messagebundle_es.properties +++ b/src/main/resources/messagebundle_es.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Guardar y cerrar fxml.save=Guardar +fxml.reset=Reiniciar pantalla fxml.setting.controls=Controles fxml.setting.ledsconfig=Configuración de LEDs fxml.setting.mode=Modo @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Versión de programa fxml.devicestab.connected.devices=Dispositivos conectados fxml.devicestab.power.saving=Ahorro de energía +fxml.devicestab.surround.lighting=Iluminación envolvente fxml.devicestab.multi.monitor=Pantalla múltiple fxml.devicestab.sync.check=Comprobación de sincronismo fxml.devicestab.check.updates=Comprobar actualizaciones @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=Horario enum.orientation.anticlockwise=Antihorario +enum.direction.normal=Normal +enum.direction.inverse=Inverso enum.led.offset.bottom.left=Abajo izquierda enum.led.offset.bottom.center=Abajo centro @@ -189,14 +193,13 @@ enum.framerate.90.fps=90 enum.framerate.120.fps=120 enum.framerate.144.fps=144 enum.framerate.unlocked=DESBLOQUEADO - -enum.frame.insertion.no.smoothing=Sin matices -enum.frame.insertion.smoothing.lvl.1=Sombras Lvl 1 -enum.frame.insertion.smoothing.lvl.2=Sombras Lvl 2 -enum.frame.insertion.smoothing.lvl.3=Sombras Lvl 3 -enum.frame.insertion.smoothing.lvl.4=Sombras Lvl 4 -enum.frame.insertion.smoothing.lvl.5=Sombras Lvl 5 -enum.frame.insertion.smoothing.lvl.6=Sombras Lvl 6 +enum.frame.insertion.no.smoothing=Sin suavizado +enum.frame.insertion.smoothing.lvl.1=Sombras Nivel 1 +enum.frame.insertion.smoothing.lvl.2=Sombras Nivel 2 +enum.frame.insertion.smoothing.lvl.3=Sombras Nivel 3 +enum.frame.insertion.smoothing.lvl.4=Sombras Nivel 4 +enum.frame.insertion.smoothing.lvl.5=Sombras Nivel 5 +enum.frame.insertion.smoothing.lvl.6=Sombras Nivel 6 enum.effect.bias.light=Luz ambiente enum.effect.mm.vumeter=Modo musical (VU Meter) @@ -259,6 +262,11 @@ serial.port.ambiguos.context=Hay más de un dispositivo conectado a los puertos mqtt.error.title=Error de conexión MQTT mqtt.error.header=No se pudo conectar al servidor MQTT mqtt.error.context=Luciferin no puede conectarse al servidor MQTT, por favor, corrija sus ajustes y reinténtelo. +cuda.error.title=Error de plugins +cuda.error.header=Complementos de GStreamer no encontrados. +cuda.error.context=Su sistema no tiene todos los complementos necesarios para ejecutar NVIDIA CUDA.\nConsulte el WIKI del proyecto para saber cómo instalar todas las dependencias necesarias. +wayland.screen.rec.permission=Luciferin necesita permiso para grabar tu\n{0} +wayland.screen.rec.permission.context=Una ventana emergente le pedirá permiso para grabar su pantalla.\nSeleccione "{0}"\ny luego haga clic en el botón "Compartir". click.ok.download=\nPulse OK para descatgar e instalar la nueva versión. click.ok.download.linux=\nPulse OK para descargar la nueva versión en su carpeta\n~/Documents/FireflyLuciferin.\n once.download.finished=Cuando haya terminado la descarga,\npor favor, vaya a dicha carpeta e instálelo manualmente. @@ -302,7 +310,32 @@ tc.after.text=RGB después de la corrección ({0}, {1}, {2}) tc.after.text.rgwb=RGBW después de la corrección ({0}, {1}, {2}, {3}) tc.full.saturation=Saturación completa tc.half.saturation=Media saturación +enum.color.algo.avg=Color promedio +enum.color.algo.avg.all=Promedio en todos los LED +enum.satellite.zone.entire.screen=Pantalla completa +enum.satellite.zone.top=Arriba +enum.satellite.zone.top.right=Parte superior derecha +enum.satellite.zone.right=Derecha +enum.satellite.zone.bottom.right=Abajo a la derecha +enum.satellite.zone.bottom=Abajo +enum.satellite.zone.bottom.left=Abajo a la izquierda +enum.satellite.zone.left=Izquierda +enum.satellite.zone.top.left=Arriba a la izquierda +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algoritmo +fxml.satellite.zone=Zona +fxml.satellite.orientation=Dirección +fxml.satellite.manage.sat=Administrar satélites +fxml.satellite.manager.sat.ip=IP satelital +fxml.satellite.manager.zone=Zones (Start/End) +fxml.satellite.manager.orient=Dirección / Led # +fxml.satellite.manager.algo=Algoritmo de captura +satellite.ip.error.title=Satélite +satellite.ip.error.header=No se puede agregar el satélite +satellite.ip.error.content=Por favor ingrese una dirección IP válida +tooltip.reset.wayland=Restablecer el permiso de grabación de pantalla tooltip.topled=nº de LEDs en la fila superior tooltip.leftled=nº de LEDs en la columna izquierda tooltip.rightled=nº de LEDs en la columna derecha @@ -318,15 +351,16 @@ tooltip.white.temp=El marcador en el centro desactiva el balance de blancos. tooltip.color.mode=Utilice RGB para WS2812B o similar y RGBW para SK6812B o similar. tooltip.gamma=Los valores más pequeños se traducen en LEDs más brillantes pero con colores más inexactos. 2.2 es un valor bueno para contenidos SDR, 6.0 es un valor bueno para contenidos HDR. tooltip.capturemethod=Si tiene una GPU, la Desktop Duplication API (DDUPL) es más rápida que otros métodos -tooltip.linuxcapturemethod=Método de captura +tooltip.linuxcapturemethod=Si utilizas Wayland deberás utilizar el método de adquisición PIPEWIRE. tooltip.maccapturemethod=Método de captura tooltip.numberofthreads=Cuando use DDUPL es suficiente con un hilo, se recomiendan 3 o más hilos para los otros métodos de captura -tooltip.serialport=Dispositivo de salida a usar con esta pantalla +tooltip.serialport=Dispositivo de salida a usar con esta pantalla. Si está detrás de una VLAN/Subred o prefiere usar una dirección IP estática, ingrese la dirección IP de su dispositivo Glow Worm. tooltip.aspectratio=Seleccione letterbox si su contenido de vídeo tiene franjas negras horizontales o pillarbox si ve barras negras verticales. tooltip.language=Escoger idioma tooltip.framerate=30 FPS es la tasa de refresco recomenddada. Este ajuste es específico para la función de iluminación ambiental. tooltip.mqtthost=OPCIONAL: protocolo MQTT://host tooltip.power.saving=Apagar los LEDs si no hay actividad durante el número de minutos configurado +tooltip.sat.btn=Agregue o elimine satélites para iluminación envolvente, requiere firmware completo. tooltip.multimonitor=Se requiere un microcontrolador por pantalla tooltip.monitornumber=Escoger la pantalla a capturar tooltip.mqttport=OPCIONAL: puerto MQTT @@ -406,6 +440,12 @@ tooltip.ldr.calibrateldr=El nivel de brillo actual de la habitación se usará c tooltip.ldr.resetldr=Restablecer calibración LDR tooltip.ldr.ldrlabel=Nivel de brillo actual en la habitación tooltip.brightness.limiter=Limit peak brightness without affecting lower brightness scenes. -tooltip.frame.insertion=Los niveles más altos suavizarán las transiciones de un color a otro, pero los LED serán menos responder a cambios rápidos. +tooltip.frame.insertion=Los niveles más altos harán menos bruscas las transiciones de un color a otro, pero los LED responderán peor a los cambios rápidos. tooltip.colorcorrection.latency.test=Esta prueba muestra colores en rápida sucesión y lo ayuda a verificar si la latencia entre la imagen que se muestra en su monitor y el color que se muestra en la tira de LED es aceptable para usted. -tooltip.colorcorrection.latency.test.speed=Puede ejecutar la prueba de latencia a 10 velocidades diferentes \ No newline at end of file +tooltip.colorcorrection.latency.test.speed=Puede ejecutar la prueba de latencia a 10 velocidades diferentes +tooltip.sat.manager.ip=Elija qué satélite agregar de la lista o ingrese su dirección IP +tooltip.sat.manager.zone=Zona de captura de pantalla para enviar al satélite +tooltip.sat.manager.orientation=Dirección de LED +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Algoritmo de captura +tooltip.sat.manager.add=Presione este botón para agregar un satélite \ No newline at end of file diff --git a/src/main/resources/messagebundle_fr.properties b/src/main/resources/messagebundle_fr.properties index 9941925c1..ca483f441 100644 --- a/src/main/resources/messagebundle_fr.properties +++ b/src/main/resources/messagebundle_fr.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Sauvegarder et fermer fxml.save=Sauvegarder +fxml.reset=Écran de réinitialisation fxml.setting.controls=Contrôles fxml.setting.ledsconfig=Config LED fxml.setting.mode=Mode @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Version logiciel fxml.devicestab.connected.devices=Appareils connectés fxml.devicestab.power.saving=Economie d'énergie +fxml.devicestab.surround.lighting=Éclairage d'ambiance fxml.devicestab.multi.monitor=Multi-Écrans fxml.devicestab.sync.check=Vérif. Syncro fxml.devicestab.check.updates=Vérif. M.A.J @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=Sens Horaire enum.orientation.anticlockwise=Sens Anti-Horaire +enum.direction.normal=Normale +enum.direction.inverse=Inverse enum.led.offset.bottom.left=Bas Gauche enum.led.offset.bottom.center=Bas Milieu @@ -259,6 +263,11 @@ serial.port.ambiguos.context=Il y a plus d'un appareil connecté a vos ports sé mqtt.error.title=Érreur de connexion MQTT mqtt.error.header=Impossible de se connecter au serveur MQTT mqtt.error.context=Luciferin n'arrive pas à se connecter au serveur MQTT, merci de vérifier vos réglages et de réessayer. +cuda.error.title=Erreur de plugin +cuda.error.header=Plugins GStreamer introuvables. +cuda.error.context=Votre système ne dispose pas de tous les plugins requis pour exécuter NVIDIA CUDA.\nVeuillez consulter le WIKI du projet pour savoir comment installer toutes les dépendances requises. +wayland.screen.rec.permission=Luciferin a besoin de l'autorisation pour enregistrer votre\n{0} +wayland.screen.rec.permission.context=Une fenêtre contextuelle vous demandera l'autorisation d'enregistrer votre écran.\nVeuillez sélectionner "{0}"\npuis cliquez sur le bouton "Partager". click.ok.download=\nCliquer sur Ok pour télécharger et installer la nouvelle version. click.ok.download.linux=\nCliquez sur OK pour télécharger la nouvelle version dans votre répertoire\n~/Documents/FireflyLuciferin\n once.download.finished=Une fois le téléchargement terminé,\nveuillez accéder à ce dossier et l'installer manuellement. @@ -302,7 +311,32 @@ tc.after.text=RGB après correction ({0}, {1}, {2}) tc.after.text.rgwb=RGBW après correction ({0}, {1}, {2}, {3}) tc.full.saturation=Pleine saturation tc.half.saturation=Demi-saturation +enum.color.algo.avg=Couleur moyenne +enum.color.algo.avg.all=Moyenne sur toutes les LED +enum.satellite.zone.entire.screen=Écran entier +enum.satellite.zone.top=En haut +enum.satellite.zone.top.right=En haut à droite +enum.satellite.zone.right=Droite +enum.satellite.zone.bottom.right=En bas à droite +enum.satellite.zone.bottom=Bas +enum.satellite.zone.bottom.left=En bas à gauche +enum.satellite.zone.left=Gauche +enum.satellite.zone.top.left=En haut à gauche +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algorithme +fxml.satellite.zone=Zone +fxml.satellite.orientation=Direction +fxml.satellite.manage.sat=Gérer les satellites +fxml.satellite.manager.sat.ip=IP satellitaire +fxml.satellite.manager.zone=Zones (Début/Fin) +fxml.satellite.manager.orient=Direction / LED # +fxml.satellite.manager.algo=Algorithme de capture +satellite.ip.error.title=Satellite +satellite.ip.error.header=Can't add the satellite +satellite.ip.error.content=Please enter a valid IP address +tooltip.reset.wayland=Réinitialiser l'autorisation d'enregistrement d'écran tooltip.topled=# de LED dans la rangée supérieure tooltip.leftled=# de LED dans la colonne de gauche tooltip.rightled=# de LED dans la colonne de droite @@ -318,15 +352,16 @@ tooltip.white.temp=La correction des couleurs peut être effectuée en ajustant tooltip.color.mode=Utilisez RGB pour WS2812B ou similaire et RGBW pour SK6812B ou similaire. tooltip.gamma=Des valeurs plus petites donnent des LED plus lumineuses mais des couleurs moins précises. 2.2 est généralement bon pour les contenus SDR, 6.0 est généralement bon pour les contenus HDR. tooltip.capturemethod=Si vous avez un GPU, l'API DDUPL est plus rapide que les autres méthodes -tooltip.linuxcapturemethod=Méthode de capture +tooltip.linuxcapturemethod=Si vous utilisez Wayland, vous devez utiliser la méthode d'acquisition PIPEWIRE. tooltip.maccapturemethod=Méthode de capture tooltip.numberofthreads=1 thread suffit lors de l'utilisation de DDUPL, 3 threads ou plus sont recommandés pour les autres méthodes de capture -tooltip.serialport=Périphérique de sortie à utiliser pour cet affichage +tooltip.serialport=Périphérique de sortie à utiliser pour cet affichage. Si vous êtes derrière un VLAN/sous-réseau ou si vous préférez utiliser une adresse IP statique, entrez l'adresse IP de votre appareil Glow Worm. tooltip.aspectratio=Sélectionnez letterbox si votre contenu vidéo présente des barres noires horizontales ou pillarbox si vous voyez des barres noires verticales. tooltip.language=Choisissez la langue tooltip.framerate=30 FPS est la fréquence recommandée. Ce réglage est spécifique à la fonction bias light. tooltip.mqtthost=OPTIONNEL: MQTT protocol://host tooltip.power.saving=Éteignez les LED s'il n'y a pas d'activité pendant le nombre de minutes configuré +tooltip.sat.btn=Ajouter ou supprimer des satellites pour l'éclairage surround, nécessite un micrologiciel complet. tooltip.multimonitor=Un microcontrôleur par moniteur est requis tooltip.monitornumber=Choisissez un moniteur pour la capture d'écran tooltip.mqttport=OPTIONNEL: Port MQTT @@ -408,4 +443,10 @@ tooltip.ldr.ldrlabel=Niveau de luminosité actuel dans la pièce tooltip.brightness.limiter=Limit peak brightness without affecting lower brightness scenes. tooltip.frame.insertion=Des niveaux plus élevés lisseront les transitions d'une couleur à une autre, mais les LED seront moins sensibles aux changements rapides. tooltip.colorcorrection.latency.test=Ce test affiche les couleurs en succession rapide et vous aide à vérifier si la latence entre l'image affichée sur votre moniteur et la couleur affichée sur la bande led vous convient. -tooltip.colorcorrection.latency.test.speed=Vous pouvez exécuter le test de latence à 10 vitesses différentes \ No newline at end of file +tooltip.colorcorrection.latency.test.speed=Vous pouvez exécuter le test de latence à 10 vitesses différentes +tooltip.sat.manager.ip=Veuillez choisir le satellite à ajouter dans la liste ou entrez son adresse IP +tooltip.sat.manager.zone=Zone de capture d'écran à envoyer au satellite +tooltip.sat.manager.orientation=Orientation des DEL +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Algorithme de capture +tooltip.sat.manager.add=Appuyez sur ce bouton pour ajouter un satellite \ No newline at end of file diff --git a/src/main/resources/messagebundle_hu.properties b/src/main/resources/messagebundle_hu.properties index 14ab2e71e..8a7db5393 100644 --- a/src/main/resources/messagebundle_hu.properties +++ b/src/main/resources/messagebundle_hu.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Mentés és bezár fxml.save=Mentés +fxml.reset=Képernyő visszaállítása fxml.setting.controls=Vezérlés fxml.setting.ledsconfig=LED konfiguráció fxml.setting.mode=Mód @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Szoftververzió fxml.devicestab.connected.devices=Csatlakoztatott eszközök fxml.devicestab.power.saving=Energiagazdálkodás +fxml.devicestab.surround.lighting=Térhatású világítás fxml.devicestab.multi.monitor=Több monitor fxml.devicestab.sync.check=Szinkornizáció ell. fxml.devicestab.check.updates=Frissítések keresése @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Négyzetes enum.orientation.clockwise=Óramutatóval megegyező enum.orientation.anticlockwise=Óramutatóval ellentétes +enum.direction.normal=Normál +enum.direction.inverse=Inverz enum.led.offset.bottom.left=Bal alul enum.led.offset.bottom.center=Középen alul @@ -259,6 +263,11 @@ serial.port.ambiguos.context=Több mint két eszköz kapcsolódik a soros portho mqtt.error.title=MQTT kapcsolódási hiba mqtt.error.header=Nem lehet csatlakozni az MQTT szerverhez mqtt.error.context=Luciferin nem tud csatlakozni az MQTT szerverhez, ellenőrizd a beállításokat és próbáld újra. +cuda.error.title=Plugin hiba +cuda.error.header=A GStreamer bővítmények nem találhatók. +cuda.error.context=Rendszere nem rendelkezik az NVIDIA CUDA futtatásához szükséges összes beépülő modullal.\nKérjük, ellenőrizze a projekt WIKI-jét, hogy megtudja, hogyan telepítheti az összes szükséges függőséget. +wayland.screen.rec.permission=A Luciferinnek engedélyre van szüksége az Ön\n{0} +wayland.screen.rec.permission.context=Egy felugró ablak engedélyt kér a képernyő rögzítésére,\nkérjük, válassza ki a(z) "{0}" lehetőséget\n, majd kattintson a "Megosztás" gombra. click.ok.download=\nAz új verzió telepítéséhez klikkelj az OK-ra. click.ok.download.linux=\nAz új verziójú \n~/Documents/FireflyLuciferin mappában taláható firmware telepítéséhez klikkelj az OK-ra.\n once.download.finished=A letöltés végeztével,\n kérlek telepítsed manuálisan a letöltési mappából. @@ -302,7 +311,32 @@ tc.after.text=RGB korrekció után ({0}, {1}, {2}) tc.after.text.rgwb=RGBW korrekció után ({0}, {1}, {2}, {3}) tc.full.saturation=Teljes telítettség tc.half.saturation=Félig telítettség +enum.color.algo.avg=Átlagos szín +enum.color.algo.avg.all=Átlag minden LED-en +enum.satellite.zone.entire.screen=A teljes képernyő +enum.satellite.zone.top=Fel +enum.satellite.zone.top.right=Jobb felső +enum.satellite.zone.right=Jobb +enum.satellite.zone.bottom.right=Jobb alsó +enum.satellite.zone.bottom=Le +enum.satellite.zone.bottom.left=Bal alsó +enum.satellite.zone.left=Bal +enum.satellite.zone.top.left=Bal felső +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algoritmus +fxml.satellite.zone=Zóna +fxml.satellite.orientation=Irány +fxml.satellite.manage.sat=Műholdak kezelése +fxml.satellite.manager.sat.ip=Műholdas IP +fxml.satellite.manager.zone=Zónák (kezdet/vége) +fxml.satellite.manager.orient=Irány / Led # +fxml.satellite.manager.algo=Rögzítési algoritmus +satellite.ip.error.title=Műhold +satellite.ip.error.header=Nem sikerült hozzáadni a műholdat +satellite.ip.error.content=Kérjük, adjon meg egy érvényes IP-címet +tooltip.reset.wayland=Képernyőfelvételi engedély visszaállítása tooltip.topled=LED-ek száma a felső sorban tooltip.leftled=LED-ek száma a bal oldalon tooltip.rightled=LED-ek száma a jobb oldalon @@ -318,15 +352,16 @@ tooltip.white.temp=A középen lévő marker letiltja a fehéregyensúlyt. tooltip.color.mode=Használjon RGB-t a WS2812B vagy hasonlóhoz és RGBW-t az SK6812 vagy hasonlóhoz. tooltip.gamma=Alacsony értékek magasabb fényerőt, de pontatlanabb színvisszadást eredméyneznek. 2.2-es érték általában megfelelő az SDR forrásokhoz. 6.0 általában megfelelő a HDR forrásokhoz. tooltip.capturemethod=Ha van GPU a gépben, akkor a Desktop Duplication API (DDUPL) gyorsabb mint a többi módszer. -tooltip.linuxcapturemethod=Vételezési mód +tooltip.linuxcapturemethod=Ha Wayland-et használ, akkor a PIPEWIRE adatgyűjtési módszert kell használnia. tooltip.maccapturemethod=Vételezési mód tooltip.numberofthreads=1 szál elegendő DDUPL használata esetén. 3 vagy több szál szükséges más módokhoz. -tooltip.serialport=Kimeneti eszköz ehhez a kijelzőhöz +tooltip.serialport=Kimeneti eszköz ehhez a kijelzőhöz. Ha Ön VLAN/alhálózat mögött van, vagy statikus IP-címet szeretne használni, adja meg Glow Worm eszköze IP-címét. tooltip.aspectratio=Válaszd ki a "szélesvászon"-t, ha a videó alatt és felett fekete sáv van, vagy "négyzetes"-t, ha a videó mellett két oldalt fekete sáv van. tooltip.language=Válassz nyelvet tooltip.framerate=30 FPS az ajánlott képkockasebesség. Ez a beállítás csak az alap funkcióra van hatással. tooltip.mqtthost=OPCIONÁLIS: MQTT protocol://host tooltip.power.saving=Kikapcsolja a LED-eket ha egy meghatározott ideig nincs aktivitás +tooltip.sat.btn=Műholdak hozzáadása vagy eltávolítása térhatású világításhoz, teljes firmware szükséges. tooltip.multimonitor=Monitoronként egy mikrokontroller szükséges tooltip.monitornumber=Válaszd ki melyik monitoron legyen a képernyő vételezés tooltip.mqttport=OPCIONÁLIS: MQTT port @@ -408,4 +443,10 @@ tooltip.ldr.ldrlabel=A helyiség jelenlegi fényereje tooltip.brightness.limiter=Limit peak brightness without affecting lower brightness scenes. tooltip.frame.insertion=A magasabb szintek simábbá teszik az átmenetet egyik színről a másikra, de a LED-ek kevésbé reagálnak a gyors változásokra. tooltip.colorcorrection.latency.test=Ez a teszt gyors egymásutánban jeleníti meg a színeket, és segít ellenőrizni, hogy a monitoron megjelenő kép és a led csíkon megjelenő szín közötti késleltetés elfogadható-e az Ön számára. -tooltip.colorcorrection.latency.test.speed=A késleltetési tesztet 10 különböző sebességgel futtathatja \ No newline at end of file +tooltip.colorcorrection.latency.test.speed=A késleltetési tesztet 10 különböző sebességgel futtathatja +tooltip.sat.manager.ip=Kérjük, válassza ki a listából a hozzáadni kívánt műholdat, vagy adja meg annak IP-címét +tooltip.sat.manager.zone=Képernyőfelvételi zóna a műholdra küldendő +tooltip.sat.manager.orientation=LED irány +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Rögzítési algoritmus +tooltip.sat.manager.add=Nyomja meg ezt a gombot műhold hozzáadásához \ No newline at end of file diff --git a/src/main/resources/messagebundle_it.properties b/src/main/resources/messagebundle_it.properties index eb15b7e89..ec178d22a 100644 --- a/src/main/resources/messagebundle_it.properties +++ b/src/main/resources/messagebundle_it.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Salva e chiudi fxml.save=Salva +fxml.reset=Resetta lo schermo fxml.setting.controls=Controlli fxml.setting.ledsconfig=Configurazione LED fxml.setting.mode=Modalità @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Versione software fxml.devicestab.connected.devices=Device connessi fxml.devicestab.power.saving=Risparmio energia +fxml.devicestab.surround.lighting=Illuminazione surround fxml.devicestab.multi.monitor=Multi monitor fxml.devicestab.sync.check=Sync check fxml.devicestab.check.updates=Verifica aggiornamenti @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=Orario enum.orientation.anticlockwise=Antiorario +enum.direction.normal=Normale +enum.direction.inverse=Inverso enum.led.offset.bottom.left=In basso a sinistra enum.led.offset.bottom.center=In basso al centro @@ -259,6 +263,11 @@ serial.port.ambiguos.context=C'è più di un dispositivo connesso sulle porte se mqtt.error.title=MQTT errore di connessione mqtt.error.header=Impossibile connettersi al server MQTT mqtt.error.context=Luciferin non riesce a connettersi al server MQTT. Per favore correggi le impostazioni e riprova. +cuda.error.title=Errore dei plugin +cuda.error.header=Plugin GStreamer non trovati. +cuda.error.context=Il tuo sistema non dispone di tutti i plugin necessari per eseguire NVIDIA CUDA.\nControlla il WIKI del progetto per sapere come installare tutte le dipendenze richieste. +wayland.screen.rec.permission=Luciferin ha bisogno del permesso per registrare il tuo\n{0} +wayland.screen.rec.permission.context=Un popup ti chiederà l'autorizzazione per registrare il tuo schermo,\nseleziona "{0}"\n quindi fai clic sul pulsante "Condividi". click.ok.download=\nClicca Ok per scaricare e installare la nuova versione. click.ok.download.linux=\nClicca Ok per scaricare la nuova versione nella seguente\n~/Documents/FireflyLuciferin cartella.\n once.download.finished=Quando il download sarà terminato,\nvai in quella cartella e installa manualmente. @@ -302,7 +311,32 @@ tc.after.text=RGB dopo la correzione ({0}, {1}, {2}) tc.after.text.rgwb=RGBW dopo la correzione ({0}, {1}, {2}, {3}) tc.full.saturation=Saturazione piena tc.half.saturation=Mezza saturazione +enum.color.algo.avg=Colore medio +enum.color.algo.avg.all=Colore medio su tutti i LED +enum.satellite.zone.entire.screen=Schermo intero +enum.satellite.zone.top=In alto +enum.satellite.zone.top.right=In alto a destra +enum.satellite.zone.right=Destra +enum.satellite.zone.bottom.right=In basso a destra +enum.satellite.zone.bottom=In basso +enum.satellite.zone.bottom.left=In basso a sinistra +enum.satellite.zone.left=Sinistra +enum.satellite.zone.top.left=In alto a sinistra +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Algoritmo +fxml.satellite.zone=Zona +fxml.satellite.orientation=Direzione +fxml.satellite.manage.sat=Gestisci i satelliti +fxml.satellite.manager.sat.ip=IP del satellite +fxml.satellite.manager.zone=Zona (Inizio/Fine) +fxml.satellite.manager.orient=Direzione / Led # +fxml.satellite.manager.algo=Algoritmo +satellite.ip.error.title=Satellite +satellite.ip.error.header=Impossibile aggiungere il satellite +satellite.ip.error.content=Inserisci un indirizzo IP valido +tooltip.reset.wayland=Reimposta l'autorizzazione alla registrazione dello schermo tooltip.topled=# di LED in alto tooltip.leftled=# di LED a sinistra tooltip.rightled=# di LED a destra @@ -318,15 +352,16 @@ tooltip.white.temp=L'indicatore al centro disabilita il bilanciamento del bianco tooltip.color.mode=Utilizzare RGB per WS2812B o simili e RGBW per SK6812B o simili. tooltip.gamma=Valori più piccoli producono LED più luminosi ma con colori meno accurati. 2.2 è generalmente consigliato per i contenuti SDR, 6.0 può funzionare bene sui contenuti HDR. tooltip.capturemethod=Desktop Duplication API (DDUPL) è il metodo consigliato se hai una GPU -tooltip.linuxcapturemethod=Metodo di cattura +tooltip.linuxcapturemethod=Se usi Wayland devi usare il metodo di acquisizione PIPEWIRE. tooltip.maccapturemethod=Metodo di cattura tooltip.numberofthreads=1 thread è sufficiente quando si usa DDUPL, 3 o più thread sono consigliati con gli altri metodi di cattura -tooltip.serialport=Dispositivo di output da utilizzare per questo schermo +tooltip.serialport=Dispositivo di output da utilizzare per questo schermo. Se sei dietro una VLAN/Subnet o preferisci usare l'indirizzo IP statico, immetti l'indirizzo IP del tuo dispositivo Glow Worm. tooltip.aspectratio=Seleziona letterbox se il tuo video presenta delle barre nere orizzontali, pillarbox se presenta barre nere verticali tooltip.language=Scegli la lingua tooltip.framerate=30 FPS è il framerate raccomandato. Questa impostazione è specifica per la funzione "Illuminazione Bias" tooltip.mqtthost=OPZIONALE: MQTT protocol://host tooltip.power.saving=Spegni i LED se non c'è attività per il numero di minuti configurato +tooltip.sat.btn=Aggiungi o rimuovi i satelliti per l'illuminazione surround, richiede il firmware FULL. tooltip.multimonitor=E' necessario un microcontrollore per monitor tooltip.monitornumber=Seleziona un monitor per la cattura dello schermo tooltip.mqttport=OPZIONALE: Porta MQTT @@ -409,3 +444,9 @@ tooltip.brightness.limiter=Limit peak brightness without affecting lower brightn tooltip.frame.insertion=Livelli più alti migliorano la fluidità nelle transizioni tra un colore ed un altro ma i LED risulteranno meno responsivi ai cambiamenti veloci. tooltip.colorcorrection.latency.test=Questo test visualizza i colori in rapida successione e ti aiuta a verificare se la latenza tra l'immagine mostrata sul tuo monitor e il colore visualizzato sulla striscia led è per te accettabile. tooltip.colorcorrection.latency.test.speed=Puoi eseguire il test di latenza a 10 diverse velocità +tooltip.sat.manager.ip=Scegli quale satellite aggiungere dall'elenco o inserisci il suo indirizzo IP +tooltip.sat.manager.zone=Zona di cattura dello schermo da inviare al satellite +tooltip.sat.manager.orientation=Direzione dei LED +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Algoritmo di cattura +tooltip.sat.manager.add=Premi questo pulsante per aggiungere un satellite \ No newline at end of file diff --git a/src/main/resources/messagebundle_ru.properties b/src/main/resources/messagebundle_ru.properties index 9ca80e0a1..8c49d1afa 100644 --- a/src/main/resources/messagebundle_ru.properties +++ b/src/main/resources/messagebundle_ru.properties @@ -1,5 +1,6 @@ fxml.save.and.close=Сохранить и закрыть fxml.save=Сохранить +fxml.reset=Сбросить экран fxml.setting.controls=Управление fxml.setting.ledsconfig=Настройки LED fxml.setting.mode=Захват экрана @@ -73,6 +74,7 @@ fxml.info.signal.framerate=Framerate (FPS) fxml.devicestab.software.version=Версия программы fxml.devicestab.connected.devices=Подключённые устройства fxml.devicestab.power.saving=Энергосбережение +fxml.devicestab.surround.lighting=Объемное освещение fxml.devicestab.multi.monitor=Несколько экранов fxml.devicestab.sync.check=Синхронизация FPS fxml.devicestab.check.updates=Проверка обновлений @@ -137,6 +139,8 @@ enum.aspect.ratio.pillarbox=Pillarbox enum.orientation.clockwise=По часовой enum.orientation.anticlockwise=Против часовой +enum.direction.normal=Нормальный +enum.direction.inverse=Обратный enum.led.offset.bottom.left=Внизу слева enum.led.offset.bottom.center=Внизу посередине @@ -259,6 +263,11 @@ serial.port.ambiguos.context=К последовательному порту п mqtt.error.title=MQTT Ошибка подключения mqtt.error.header=Не удается подключиться к серверу MQTT. mqtt.error.context=Luciferin не удается подключиться к серверу MQTT, исправьте настройки и повторите попытку. +cuda.error.title=Ошибка плагинов +cuda.error.header=Плагины GStreamer не найдены. +cuda.error.context=В вашей системе нет всех необходимых плагинов для запуска NVIDIA CUDA.\nПожалуйста, проверьте WIKI проекта, чтобы узнать, как установить все необходимые зависимости. +wayland.screen.rec.permission=Люциферину необходимо разрешение на запись вашего\n{0} +wayland.screen.rec.permission.context=Всплывающее окно запросит разрешение на запись вашего экрана.\nвыберите «{0}»\nи нажмите кнопку «Поделиться». click.ok.download=\nНажмите «ОК», чтобы загрузить и установить новую версию. click.ok.download.linux=\nНажмите «ОК», чтобы загрузить новую версию в папку \n~/Documents/FireflyLuciferin.\n once.download.finished=Когда загрузка будет завершена,\nперейдите в эту папку и установите программу вручную. @@ -302,12 +311,37 @@ tc.after.text=RGB после коррекции ({0}, {1}, {2}) tc.after.text.rgwb=RGBW после коррекции ({0}, {1}, {2}, {3}) tc.full.saturation=Полное насыщение tc.half.saturation=Половина насыщения +enum.color.algo.avg=Средний цвет +enum.color.algo.avg.all=В среднем по всем светодиодам +enum.satellite.zone.entire.screen=Весь экран +enum.satellite.zone.top=Вверх +enum.satellite.zone.top.right=В правом верхнем углу +enum.satellite.zone.right=Верно +enum.satellite.zone.bottom.right=Внизу справа +enum.satellite.zone.bottom=Вниз +enum.satellite.zone.bottom.left=Внизу слева +enum.satellite.zone.left=Левый +enum.satellite.zone.top.left=Верхний левый +fxml.satellite.deviceip=IP +fxml.satellite.lednum=Led # +fxml.satellite.algo=Алгоритм +fxml.satellite.zone=Зона +fxml.satellite.orientation=Направление +fxml.satellite.manage.sat=Управление спутниками +fxml.satellite.manager.sat.ip=Спутниковый IP +fxml.satellite.manager.zone=Зоны (Начало/Конец) +fxml.satellite.manager.orient=Направление/светодиод # +fxml.satellite.manager.algo=Алгоритм захвата +satellite.ip.error.title=спутник +satellite.ip.error.header=Не могу добавить спутник +satellite.ip.error.content=Пожалуйста, введите действительный IP-адрес +tooltip.reset.wayland=Сбросить разрешение на запись экрана tooltip.topled=# светодиодов верху tooltip.leftled=# светодиодов слева tooltip.rightled=# светодиодов справа tooltip.bottomleftled=# светодиодов снизу слева -tooltip.bottomrightled=# светодиодов снизу справа +tooltip.bottomrightled=# светодиодов снизу справа\ tooltip.bottomrowled=# светодиодов внизу tooltip.orientation=Направление светодиодной ленты tooltip.screenwidth=Ширина монитора в пикселях @@ -318,15 +352,16 @@ tooltip.white.temp=Маркер в центре отключает баланс tooltip.color.mode=Используйте RGB для WS2812B или аналогичного и RGBW для SK6812B или аналогичного. tooltip.gamma=Меньшие значения приводят к более ярким светодиодам, но менее точным цветам. 2.2 обычно подходит для контента SDR, 6.0 — для контента HDR. tooltip.capturemethod=Если у вас есть видеокарта, Desktop Duplication API (DDUPL) работает быстрее, чем другие методы. -tooltip.linuxcapturemethod=Метод захвата +tooltip.linuxcapturemethod=Если вы используете Wayland, вы должны использовать метод сбора данных PIPEWIRE. tooltip.maccapturemethod=Метод захвата tooltip.numberofthreads=При использовании DDUPL достаточно 1 потока, для других методов захвата рекомендуется 3 и более потоков. -tooltip.serialport=Устройство вывода, используемое для этого дисплея +tooltip.serialport=Устройство вывода, используемое для этого дисплея. Если вы находитесь за VLAN/подсетью или предпочитаете использовать статический IP-адрес, введите IP-адрес вашего устройства Glow Worm. tooltip.aspectratio=Выберите «letterbox», если на экране сверху и снизу горизонтальные черные полосы, или «pillarbox» - если вертикальные по бокам. tooltip.language=Выберите язык tooltip.framerate=30 FPS является рекомендуемой частотой кадров. Эта настройка специфична для режима "Захват экрана" tooltip.mqtthost=ОПЦИОНАЛЬНО: MQTT protocol://host tooltip.power.saving=Выключить подсветку, если нет активности в течение заданного времени +tooltip.sat.btn=Добавить или удалить спутники для объемного освещения, требуется полная прошивка. tooltip.multimonitor=Требуется один контроллер на монитор tooltip.monitornumber=Выберите монитор для захвата экрана tooltip.mqttport=ОПЦИОНАЛЬНО: MQTT порт @@ -408,4 +443,10 @@ tooltip.ldr.ldrlabel=Текущий уровень яркости в комна tooltip.brightness.limiter=Limit peak brightness without affecting lower brightness scenes. tooltip.frame.insertion=Более высокие уровни будут сглаживать переход от одного цвета к другому, но светодиоды будут менее отзывчивы к быстрым изменениям. tooltip.colorcorrection.latency.test=Этот тест отображает цвета в быстрой последовательности и помогает вам проверить, приемлема ли для вас задержка между изображением, отображаемым на вашем мониторе, и цветом, отображаемым на светодиодной ленте. -tooltip.colorcorrection.latency.test.speed=Вы можете запустить тест задержки на 10 разных скоростях \ No newline at end of file +tooltip.colorcorrection.latency.test.speed=Вы можете запустить тест задержки на 10 разных скоростях +tooltip.sat.manager.ip=Пожалуйста, выберите спутник для добавления из списка или введите его IP-адрес +tooltip.sat.manager.zone=Зона захвата экрана для отправки на спутник +tooltip.sat.manager.orientation=направление светодиода +tooltip.sat.manager.num.led=Led # +tooltip.sat.manager.algo=Алгоритм захвата +tooltip.sat.manager.add=Нажмите эту кнопку, чтобы добавить спутник \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/colorCorrectionDialog.fxml b/src/main/resources/org/dpsoftware/gui/colorCorrectionDialog.fxml index 93e55e13a..98253e41f 100644 --- a/src/main/resources/org/dpsoftware/gui/colorCorrectionDialog.fxml +++ b/src/main/resources/org/dpsoftware/gui/colorCorrectionDialog.fxml @@ -3,8 +3,9 @@ - - + diff --git a/src/main/resources/org/dpsoftware/gui/controlTab.fxml b/src/main/resources/org/dpsoftware/gui/controlTab.fxml index aee98e10c..38eb44990 100644 --- a/src/main/resources/org/dpsoftware/gui/controlTab.fxml +++ b/src/main/resources/org/dpsoftware/gui/controlTab.fxml @@ -3,10 +3,9 @@ - - + diff --git a/src/main/resources/org/dpsoftware/gui/css/main.css b/src/main/resources/org/dpsoftware/gui/css/main.css index 8d0465094..be8181884 100644 --- a/src/main/resources/org/dpsoftware/gui/css/main.css +++ b/src/main/resources/org/dpsoftware/gui/css/main.css @@ -80,6 +80,7 @@ .redHueTestImage .track { -fx-background-color: linear-gradient(to left, #FF8000, red, #ff007b); } + .redHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #FF8000, red, #ff007b); } @@ -95,6 +96,7 @@ .yellowHueTestImage .track { -fx-background-color: linear-gradient(to left, #80ff00, yellow, #ff8400); } + .yellowHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #80ff00, yellow, #ff8400); } @@ -110,6 +112,7 @@ .greenHueTestImage .track { -fx-background-color: linear-gradient(to left, #00ff80, #00ff00, #7bff00); } + .greenHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #00ff80, #00ff00, #7bff00); } @@ -125,6 +128,7 @@ .cyanHueTestImage .track { -fx-background-color: linear-gradient(to left, #007fff, #00ffff, #00ff84); } + .cyanHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #007fff, #00ffff, #00ff84); } @@ -140,6 +144,7 @@ .blueHueTestImage .track { -fx-background-color: linear-gradient(to left, #7f00ff, blue, #007bff); } + .blueHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #7f00ff, blue, #007bff); } @@ -155,6 +160,7 @@ .magentaHueTestImage .track { -fx-background-color: linear-gradient(to left, #ff0080, magenta, #8400ff); } + .magentaHueTestImageVertical .track { -fx-background-color: linear-gradient(to bottom, #ff0080, magenta, #8400ff); } @@ -213,3 +219,34 @@ -fx-padding: 0 0 0 0; } +.table-view .table-cell { + -fx-alignment: center-left; +} + +.windowCloseBtn, .windowMinimizeBtn { + -fx-background-insets: 0; + -fx-border-color: black; + -fx-border-width: 0 0 0 0; + -fx-text-fill: white; + -fx-font-weight: bold; +} + +.windowCloseBtn { + -fx-border-radius: 0 10 0 0; + -fx-background-radius: 0 10 0 0; +} + +.windowMinimizeBtn { + -fx-border-radius: 0 0 0 0; + -fx-background-radius: 0 0 0 0; +} + +.windowCloseBtn:hover { + -fx-background-color: #c42b1c; +} + +#rootPane { + -fx-background-radius: 10px; + -fx-alignment: center; + -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, .75), 10, 0.19, 0, 0); +} diff --git a/src/main/resources/org/dpsoftware/gui/css/theme-dark-blue.css b/src/main/resources/org/dpsoftware/gui/css/theme-dark-blue.css index faf85c55a..92e855604 100644 --- a/src/main/resources/org/dpsoftware/gui/css/theme-dark-blue.css +++ b/src/main/resources/org/dpsoftware/gui/css/theme-dark-blue.css @@ -7,7 +7,7 @@ .root { -fx-accent: #1da8ff; -fx-focus-color: -fx-accent; - -fx-base: #192439; + -fx-base: #1c2940; -fx-control-inner-background: derive(-fx-base, 35%); -fx-control-inner-background-alt: -fx-control-inner-background; } @@ -31,3 +31,19 @@ .roundedBordersDialog { -fx-border-color: #172236 !important; } + +#rootPane { + -fx-background-color: #283b5c; +} + +.windowCloseBtn { + -fx-background-color: #283b5c; +} + +.windowMinimizeBtn { + -fx-background-color: #283b5c; +} + +.windowMinimizeBtn:hover { + -fx-background-color: #385180; +} \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/css/theme-dark-cyan.css b/src/main/resources/org/dpsoftware/gui/css/theme-dark-cyan.css index 0845ff3d2..ac4a3a896 100644 --- a/src/main/resources/org/dpsoftware/gui/css/theme-dark-cyan.css +++ b/src/main/resources/org/dpsoftware/gui/css/theme-dark-cyan.css @@ -7,11 +7,27 @@ .root { -fx-accent: #0099ff; -fx-focus-color: -fx-accent; - -fx-base: #373e43; + -fx-base: #40494f; -fx-control-inner-background: derive(-fx-base, 35%); -fx-control-inner-background-alt: -fx-control-inner-background; } .roundedBordersDialog { -fx-border-color: #32393d !important; +} + +#rootPane { + -fx-background-color: #555c61; +} + +.windowCloseBtn { + -fx-background-color: #555c61; +} + +.windowMinimizeBtn { + -fx-background-color: #555c61; +} + +.windowMinimizeBtn:hover { + -fx-background-color: #878e93; } \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/css/theme-dark-orange.css b/src/main/resources/org/dpsoftware/gui/css/theme-dark-orange.css index 054e0c5fd..104856878 100644 --- a/src/main/resources/org/dpsoftware/gui/css/theme-dark-orange.css +++ b/src/main/resources/org/dpsoftware/gui/css/theme-dark-orange.css @@ -14,4 +14,20 @@ .roundedBordersDialog { -fx-border-color: #424242 !important; +} + +#rootPane { + -fx-background-color: #646464; +} + +.windowCloseBtn { + -fx-background-color: #646464; +} + +.windowMinimizeBtn { + -fx-background-color: #646464; +} + +.windowMinimizeBtn:hover { + -fx-background-color: #969696; } \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/css/theme-dark-purple.css b/src/main/resources/org/dpsoftware/gui/css/theme-dark-purple.css index dc6b0d79b..140e9955c 100644 --- a/src/main/resources/org/dpsoftware/gui/css/theme-dark-purple.css +++ b/src/main/resources/org/dpsoftware/gui/css/theme-dark-purple.css @@ -22,4 +22,20 @@ .roundedBordersDialog { -fx-border-color: #47475d !important; +} + +#rootPane { + -fx-background-color: #5d5d79; +} + +.windowCloseBtn { + -fx-background-color: #5d5d79; +} + +.windowMinimizeBtn { + -fx-background-color: #5d5d79; +} + +.windowMinimizeBtn:hover { + -fx-background-color: #385180; } \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/css/theme-dark.css b/src/main/resources/org/dpsoftware/gui/css/theme-dark.css index ce0903606..56ed56844 100644 --- a/src/main/resources/org/dpsoftware/gui/css/theme-dark.css +++ b/src/main/resources/org/dpsoftware/gui/css/theme-dark.css @@ -9,7 +9,7 @@ } .text-field { - -fx-prompt-text-fill: gray; + -fx-prompt-text-fill: grey; } .titulo { @@ -70,5 +70,4 @@ .hyperlink { -fx-text-fill: lightgray !important; -} - +} \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/devicesTab.fxml b/src/main/resources/org/dpsoftware/gui/devicesTab.fxml index dc9f4857e..93c8b52cd 100644 --- a/src/main/resources/org/dpsoftware/gui/devicesTab.fxml +++ b/src/main/resources/org/dpsoftware/gui/devicesTab.fxml @@ -17,21 +17,21 @@ prefWidth="220.66666666666669"/> - + + + + + + + - - - - - - - + + diff --git a/src/main/resources/org/dpsoftware/gui/ledsConfigTab.fxml b/src/main/resources/org/dpsoftware/gui/ledsConfigTab.fxml index d558d4572..ffd2aae53 100644 --- a/src/main/resources/org/dpsoftware/gui/ledsConfigTab.fxml +++ b/src/main/resources/org/dpsoftware/gui/ledsConfigTab.fxml @@ -2,12 +2,12 @@ - + + - - + diff --git a/src/main/resources/org/dpsoftware/gui/miscTab.fxml b/src/main/resources/org/dpsoftware/gui/miscTab.fxml index 95926c44c..d46ca3cc2 100644 --- a/src/main/resources/org/dpsoftware/gui/miscTab.fxml +++ b/src/main/resources/org/dpsoftware/gui/miscTab.fxml @@ -1,12 +1,12 @@ - + - - - + + diff --git a/src/main/resources/org/dpsoftware/gui/modeTab.fxml b/src/main/resources/org/dpsoftware/gui/modeTab.fxml index 05a84ee40..0fe0032f7 100644 --- a/src/main/resources/org/dpsoftware/gui/modeTab.fxml +++ b/src/main/resources/org/dpsoftware/gui/modeTab.fxml @@ -4,64 +4,51 @@ - + - + - - + + - - - - - - - - - - + + + + + + + + + + - + - + diff --git a/src/main/resources/org/dpsoftware/gui/settings.fxml b/src/main/resources/org/dpsoftware/gui/settings.fxml index 80d4e50ed..d72ccb10d 100644 --- a/src/main/resources/org/dpsoftware/gui/settings.fxml +++ b/src/main/resources/org/dpsoftware/gui/settings.fxml @@ -1,26 +1,36 @@ + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + \ No newline at end of file diff --git a/src/main/resources/org/dpsoftware/gui/settingsCustomBar.fxml b/src/main/resources/org/dpsoftware/gui/settingsCustomBar.fxml new file mode 100644 index 000000000..8c47abb33 --- /dev/null +++ b/src/main/resources/org/dpsoftware/gui/settingsCustomBar.fxml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/project.properties b/src/main/resources/project.properties index 8f1a7a8f9..102280025 100644 --- a/src/main/resources/project.properties +++ b/src/main/resources/project.properties @@ -1,4 +1,4 @@ version=${project.version} -minimum.firmware.version=5.11.8 +minimum.firmware.version=5.12.9 # This feature is not exposed to end users. Used for testing purpose only. Set false before the release. gw.alpha.download=false \ No newline at end of file