diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..7129df25 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "vscjava.vscode-lombok" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 5ccb46ed..18b39892 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ configure Maven to use Logback: ch.qos.logback logback-classic - 1.1.7 + 1.5.34 ``` @@ -156,7 +156,7 @@ Or with Gradle: ```groovy dependencies { implementation('io.obs-websocket.community:client:2.0.0') - implementation 'ch.qos.logback:logback-classic:1.1.7' + implementation 'ch.qos.logback:logback-classic:1.5.34' } ``` diff --git a/client/build.gradle b/client/build.gradle index 1ffd5f63..40eb3c06 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -1,6 +1,6 @@ plugins { id 'java-library' - id 'org.unbroken-dome.test-sets' version '4.0.0' + id 'org.unbroken-dome.test-sets' version '4.1.0' id 'jacoco' id 'signing' id 'maven-publish' @@ -16,12 +16,10 @@ group = 'io.obs-websocket.community' version = rootProject.file('VERSION').text.trim() + (isRelease ? '' : '-SNAPSHOT') def localArchiveBaseName = 'client' -java.sourceCompatibility = JavaVersion.VERSION_1_8 - dependencies { api libs.websocket api libs.gson - implementation libs.sl4j.api + implementation libs.slf4j.api compileOnly libs.lombok annotationProcessor libs.lombok @@ -32,14 +30,21 @@ dependencies { testCompileOnly libs.lombok testAnnotationProcessor libs.lombok testImplementation libs.mockito.core - testImplementation libs.sl4j.simple + testRuntimeOnly libs.junit.platform.launcher + testImplementation libs.slf4j.simple } java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 withSourcesJar() withJavadocJar() } +tasks.withType(JavaCompile).configureEach { + options.release = 8 +} + testSets { // Covers cases where OBS instance is not required integrationTest { diff --git a/client/src/endToEndManualTest/java/io/obswebsocket/community/client/test/ObsRemoteE2eObservationIT.java b/client/src/endToEndManualTest/java/io/obswebsocket/community/client/test/ObsRemoteE2eObservationIT.java index c24240b1..3d5c4086 100644 --- a/client/src/endToEndManualTest/java/io/obswebsocket/community/client/test/ObsRemoteE2eObservationIT.java +++ b/client/src/endToEndManualTest/java/io/obswebsocket/community/client/test/ObsRemoteE2eObservationIT.java @@ -1,18 +1,21 @@ package io.obswebsocket.community.client.test; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.google.gson.JsonObject; -import io.obswebsocket.community.client.message.response.inputs.GetInputMuteResponse; import java.io.File; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.google.gson.JsonObject; + +import io.obswebsocket.community.client.message.response.inputs.GetInputMuteResponse; +import io.obswebsocket.community.client.model.MediaInputAction; + /** * This test should be run manually, following the prompts in the command-line and observing OBS for * the desired behavior. Authentication should be disabled. See the README in the obs-resources @@ -21,6 +24,7 @@ public class ObsRemoteE2eObservationIT extends AbstractObsE2ETest { @BeforeAll + @SuppressWarnings("unused") static void beforeAll() { connectToObs(); } @@ -34,6 +38,7 @@ public void beforeEach() { } @AfterAll + @SuppressWarnings("unused") static void afterAll() { remote.disconnect(); // System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "Debug"); @@ -44,7 +49,8 @@ public void afterEach() { try { Thread.sleep(1000); } catch (InterruptedException e) { - e.printStackTrace(); + Thread.currentThread().interrupt(); + throw new IllegalStateException("Interrupted while waiting after manual test", e); } System.out.println("<< Test Complete"); @@ -201,24 +207,24 @@ void playPauseVlcMedia() { remote.setSceneItemEnabled(SCENE1, vlcId, true, loggingCallback()); obsShould("Pause video 1"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.PAUSE, loggingCallback()); // BUG: Toggle Play/Pause does not work in Palakis OBS plugin! // see https://github.com/obsproject/obs-websocket/issues/725 // I've noted we can also replicate the problem obsShould("Toggle Play Video 1"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.PLAY, loggingCallback()); obsShould("Toggle Pause Video 1"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.PAUSE, loggingCallback()); obsShould("Switch to video 2"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.NEXT, loggingCallback()); obsShould("Restart, back at video 1 (should auto play)"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.RESTART, loggingCallback()); obsShould("Stop video 1 (going back to beginning)"); - remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP", loggingCallback()); + remote.triggerMediaInputAction(SOURCE_VLC_MEDIA, MediaInputAction.STOP, loggingCallback()); } @Test diff --git a/example/build.gradle b/example/build.gradle index 9d832dad..d9bbe5ee 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -7,5 +7,5 @@ version = rootProject.file('VERSION').text.trim() dependencies { implementation project(':client') - implementation libs.sl4j.simple + implementation libs.slf4j.simple } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e5832..b1b8ef56 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661e..df6a6ad7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb6..b9bb139f 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +82,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -133,22 +132,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -165,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -193,16 +198,19 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 53a6b238..88192db3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,91 +1,82 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +exit /b 1 + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +"%COMSPEC%" /c exit 1 + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel + +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/messagegenerator/build.gradle b/messagegenerator/build.gradle index 27e27981..b3873939 100644 --- a/messagegenerator/build.gradle +++ b/messagegenerator/build.gradle @@ -8,8 +8,8 @@ version = rootProject.file('VERSION').text.trim() dependencies { implementation project(':client') implementation libs.javapoet - implementation libs.sl4j.api - implementation libs.sl4j.simple + implementation libs.slf4j.api + implementation libs.slf4j.simple implementation libs.lombok // Needed in implementation, lombok annotations will be generated too implementation libs.commons.io @@ -19,6 +19,7 @@ dependencies { testImplementation libs.junit.jupiter.engine testImplementation libs.assertj.core testImplementation libs.mockito.core + testRuntimeOnly libs.junit.platform.launcher testCompileOnly libs.lombok testAnnotationProcessor libs.lombok } diff --git a/messagegenerator/src/test/java/io/obswebsocket/community/generator/AbstractTestBase.java b/messagegenerator/src/test/java/io/obswebsocket/community/generator/AbstractTestBase.java index 925fc1a7..0482bad5 100644 --- a/messagegenerator/src/test/java/io/obswebsocket/community/generator/AbstractTestBase.java +++ b/messagegenerator/src/test/java/io/obswebsocket/community/generator/AbstractTestBase.java @@ -1,9 +1,5 @@ package io.obswebsocket.community.generator; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - -import io.obswebsocket.community.generator.model.generated.RequestField; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -11,7 +7,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; + import org.apache.commons.io.IOUtils; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import io.obswebsocket.community.generator.model.generated.RequestField; abstract class AbstractTestBase { @@ -58,11 +58,6 @@ protected List buildDataFields() { protected String readExpected(String path) { InputStream stream = AbstractTestBase.class.getResourceAsStream(path); Objects.requireNonNull(stream, path + " can't be read"); - try { - return String.join("\n", IOUtils.readLines(stream, StandardCharsets.UTF_8)).trim(); - } catch (IOException e) { - fail(e); - return null; - } + return String.join("\n", IOUtils.readLines(stream, StandardCharsets.UTF_8)).trim(); } } diff --git a/settings.gradle b/settings.gradle index 1c2351c7..729f510b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,18 +6,19 @@ include 'messagegenerator' dependencyResolutionManagement { versionCatalogs { libs { - library('lombok', 'org.projectlombok:lombok:1.18.24') - library('websocket', 'org.eclipse.jetty.websocket:websocket-client:9.4.49.v20220914') - library('gson', 'com.google.code.gson:gson:2.9.0') - library('sl4j-api', 'org.slf4j:slf4j-api:2.0.3') - library('sl4j-simple', 'org.slf4j:slf4j-simple:2.0.3') + library('lombok', 'org.projectlombok:lombok:1.18.46') + library('websocket', 'org.eclipse.jetty.websocket:websocket-client:9.4.58.v20250814') + library('gson', 'com.google.code.gson:gson:2.14.0') + library('slf4j-api', 'org.slf4j:slf4j-api:2.0.18') + library('slf4j-simple', 'org.slf4j:slf4j-simple:2.0.18') library('javapoet', 'com.squareup:javapoet:1.13.0') - library('commons-io', 'commons-io:commons-io:2.11.0') - library('junit-jupiter-api', 'org.junit.jupiter:junit-jupiter-api:5.9.0') - library('junit-jupiter-engine', 'org.junit.jupiter:junit-jupiter-engine:5.9.0') - library('assertj-core', 'org.assertj:assertj-core:3.23.1') - library('jsonassert', 'org.skyscreamer:jsonassert:1.5.1') - library('mockito-core', 'org.mockito:mockito-core:4.8.0') + library('commons-io', 'commons-io:commons-io:2.22.0') + library('junit-jupiter-api', 'org.junit.jupiter:junit-jupiter-api:5.14.4') + library('junit-jupiter-engine', 'org.junit.jupiter:junit-jupiter-engine:5.14.4') + library('junit-platform-launcher', 'org.junit.platform:junit-platform-launcher:1.14.4') + library('assertj-core', 'org.assertj:assertj-core:3.27.7') + library('jsonassert', 'org.skyscreamer:jsonassert:1.5.3') + library('mockito-core', 'org.mockito:mockito-core:5.23.0') } } } \ No newline at end of file