From afaed25555c6e795349c6aab72d55124c39cfca5 Mon Sep 17 00:00:00 2001 From: Kris Date: Sun, 22 Mar 2026 10:20:25 +0200 Subject: [PATCH] a --- .gitignore | 2 + LICENSE | 121 +++++++++ build.gradle | 92 +++++++ gradle.properties | 20 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 46175 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 248 ++++++++++++++++++ gradlew.bat | 93 +++++++ settings.gradle | 10 + .../darkworld/MinecraftMprisClient.java | 241 +++++++++++++++++ .../java/download/darkworld/MprisClient.java | 10 + .../darkworld/MprisNowPlayingToast.java | 110 ++++++++ src/main/resources/assets/modid/icon.png | Bin 0 -> 3138 bytes src/main/resources/fabric.mod.json | 28 ++ 14 files changed, 982 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/client/java/download/darkworld/MinecraftMprisClient.java create mode 100644 src/client/java/download/darkworld/MprisClient.java create mode 100644 src/client/java/download/darkworld/MprisNowPlayingToast.java create mode 100644 src/main/resources/assets/modid/icon.png create mode 100644 src/main/resources/fabric.mod.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..151fdd4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.gradle \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1625c17 --- /dev/null +++ b/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..0df7db6 --- /dev/null +++ b/build.gradle @@ -0,0 +1,92 @@ +plugins { + id 'net.fabricmc.fabric-loom-remap' version "${loom_version}" + id 'maven-publish' +} + +version = project.mod_version +group = project.maven_group + +base { + archivesName = project.archives_base_name +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. +} + +loom { + splitEnvironmentSourceSets() + + mods { + "modid" { + sourceSet sourceSets.main + sourceSet sourceSets.client + } + } + +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings loom.officialMojangMappings() + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + include(implementation("com.github.hypfvieh:dbus-java-core:5.2.0")) + include(implementation("com.github.hypfvieh:dbus-java-transport-native-unixsocket:5.2.0")) + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": inputs.properties.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 21 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +jar { + inputs.property "archivesName", project.base.archivesName + + from("LICENSE") { + rename { "${it}_${inputs.properties.archivesName}"} + } +} + +// configure the maven publication +publishing { + publications { + create("mavenJava", MavenPublication) { + artifactId = project.archives_base_name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3d34d96 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 +org.gradle.configuration-cache=false + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=1.21.11 +loader_version=0.18.4 +loom_version=1.15-SNAPSHOT + +# Mod Properties +mod_version=1.0.0 +maven_group=download.darkworld +archives_base_name=mpris + +# Dependencies +fabric_api_version=0.141.3+1.21.11 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..61285a659d17295f1de7c53e24fdf13ad755c379 GIT binary patch literal 46175 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..19a6bde --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..adff685 --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# 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. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/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/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# 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 + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + 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 +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e509b2d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +@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 with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +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 + +goto fail + +: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 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +: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 diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..75c4d72 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + mavenCentral() + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/src/client/java/download/darkworld/MinecraftMprisClient.java b/src/client/java/download/darkworld/MinecraftMprisClient.java new file mode 100644 index 0000000..ab8b3a7 --- /dev/null +++ b/src/client/java/download/darkworld/MinecraftMprisClient.java @@ -0,0 +1,241 @@ +package download.darkworld; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import com.mojang.logging.LogUtils; +import org.freedesktop.dbus.connections.impl.DBusConnection; +import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; +import org.freedesktop.dbus.exceptions.DBusException; +import org.freedesktop.dbus.interfaces.DBus; +import org.freedesktop.dbus.interfaces.DBusSigHandler; +import org.freedesktop.dbus.interfaces.Properties; +import org.freedesktop.dbus.matchrules.DBusMatchRule; +import org.freedesktop.dbus.matchrules.DBusMatchRuleBuilder; +import org.freedesktop.dbus.types.Variant; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.toasts.ToastManager; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +public final class MinecraftMprisClient { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final long CACHE_TTL_MS = 1000L; + private static final String DBUS_SERVICE = "org.freedesktop.DBus"; + private static final String DBUS_PATH = "/org/freedesktop/DBus"; + private static final String MPRIS_PATH = "/org/mpris/MediaPlayer2"; + private static final String MPRIS_PREFIX = "org.mpris.MediaPlayer2."; + private static final String PLAYER_INTERFACE = "org.mpris.MediaPlayer2.Player"; + + @Nullable + private static DBusConnection connection; + @Nullable + private static AutoCloseable propertiesChangedHandler; + private static final Map lastAnnouncedTrackIds = new ConcurrentHashMap<>(); + + private MinecraftMprisClient() { + } + + public static void initialize() { + synchronized (MinecraftMprisClient.class) { + try { + LOGGER.info("[mpris] initializing DBus MPRIS bridge"); + DBusConnection dbusConnection = getConnection(); + if (dbusConnection == null) { + LOGGER.warn("[mpris] DBus connection was null during initialization"); + return; + } + + if (propertiesChangedHandler == null) { + LOGGER.info("[mpris] registering global PropertiesChanged handler"); + DBusMatchRule matchRule = DBusMatchRuleBuilder.create() + .withType(Properties.PropertiesChanged.class) + .withPath(MPRIS_PATH) + .withArg0123(0, PLAYER_INTERFACE) + .build(); + propertiesChangedHandler = dbusConnection.addSigHandler(matchRule, new PlayerPropertiesChangedHandler()); + } + LOGGER.info("[mpris] initialization complete"); + } catch (DBusException | RuntimeException exception) { + LOGGER.error("[mpris] initialization failed", exception); + resetConnectionState(); + } + } + } + + @Nullable + private static SongInfo refreshCurrentSong(String serviceName) { + try { + DBusConnection dbusConnection = getConnection(); + if (dbusConnection == null) { + LOGGER.warn("[mpris] refreshCurrentSong({}): connection was null", serviceName); + return null; + } + LOGGER.info("[mpris] checking player {}", serviceName); + Properties properties = dbusConnection.getRemoteObject(serviceName, MPRIS_PATH, Properties.class); + String playbackStatus = properties.Get(PLAYER_INTERFACE, "PlaybackStatus"); + LOGGER.info("[mpris] player {} playbackStatus={}", serviceName, playbackStatus); + if (!"Playing".equals(playbackStatus)) { + return null; + } + + Map metadata = properties.Get(PLAYER_INTERFACE, "Metadata"); + if (metadata == null) { + LOGGER.info("[mpris] player {} returned null metadata", serviceName); + return null; + } + + String title = stringValue(metadata.get("xesam:title")); + String artist = artistsValue(metadata.get("xesam:artist")); + String trackId = stringValue(metadata.get("mpris:trackid")); + String displayText = formatDisplayText(artist, title); + LOGGER.info("[mpris] player {} metadata artist='{}' title='{}' trackId='{}'", serviceName, artist, title, trackId); + if (displayText != null && trackId != null && !trackId.isBlank()) { + return new SongInfo(serviceName, trackId, displayText); + } + } catch (DBusException | RuntimeException exception) { + LOGGER.error("[mpris] refreshCurrentSong failed for {}", serviceName, exception); + return null; + } + + return null; + } + + @Nullable + private static DBusConnection getConnection() throws DBusException { + if (connection == null) { + LOGGER.info("[mpris] opening session bus connection"); + connection = DBusConnectionBuilder.forSessionBus() + .withShared(true) + .build(); + } + + return connection; + } + + private static synchronized void handleSongStateChange(String serviceName) { + LOGGER.info("[mpris] handleSongStateChange triggered for {}", serviceName); + SongInfo song = refreshCurrentSong(serviceName); + String currentTrackId = song != null ? song.trackId() : null; + String lastAnnouncedTrackId = lastAnnouncedTrackIds.get(serviceName); + LOGGER.info("[mpris] player={} currentTrackId={}, lastAnnouncedTrackId={}", serviceName, currentTrackId, lastAnnouncedTrackId); + if (currentTrackId == null || currentTrackId.equals(lastAnnouncedTrackId)) { + LOGGER.info("[mpris] not showing toast because track id is null or unchanged"); + return; + } + + lastAnnouncedTrackIds.put(serviceName, currentTrackId); + Minecraft minecraft = Minecraft.getInstance(); + String title = song.displayText(); + LOGGER.info("[mpris] scheduling toast for player={} trackId={} title='{}'", serviceName, currentTrackId, title); + minecraft.execute(() -> showToast(minecraft, serviceName, currentTrackId, title)); + } + + private static void showToast(Minecraft minecraft, String playerId, String trackId, String title) { + LOGGER.info("[mpris] showToast executing on client thread for player={} trackId={} title='{}'", playerId, trackId, title); + ToastManager toastManager = minecraft.getToastManager(); + MprisNowPlayingToast toast = toastManager.getToast(MprisNowPlayingToast.class, playerId); + if (toast == null) { + LOGGER.info("[mpris] creating new toast instance"); + toast = new MprisNowPlayingToast(playerId, trackId, title); + toast.showToast(trackId, title, minecraft.options); + toastManager.addToast(toast); + return; + } + + LOGGER.info("[mpris] reusing existing toast instance"); + toast.showToast(trackId, title, minecraft.options); + } + + private static synchronized void resetConnectionState() { + LOGGER.warn("[mpris] resetting DBus connection state"); + lastAnnouncedTrackIds.clear(); + if (propertiesChangedHandler != null) { + try { + propertiesChangedHandler.close(); + } catch (Exception ignored) { + } + propertiesChangedHandler = null; + } + + if (connection != null) { + connection.disconnect(); + connection = null; + } + } + + @Nullable + private static String stringValue(@Nullable Object value) { + if (value == null) { + return null; + } + + if (value instanceof Variant variant) { + return stringValue(variant.getValue()); + } + + return value.toString(); + } + + @Nullable + private static String artistsValue(@Nullable Object value) { + if (value == null) { + return null; + } + + if (value instanceof Variant variant) { + return artistsValue(variant.getValue()); + } + if (value instanceof String string) { + return string; + } + if (value instanceof String[] strings) { + return String.join(", ", strings); + } + if (value instanceof List list) { + return list.stream() + .map(MinecraftMprisClient::stringValue) + .filter(part -> part != null && !part.isBlank()) + .reduce((left, right) -> left + ", " + right) + .orElse(null); + } + + return value.toString(); + } + + @Nullable + private static String formatDisplayText(@Nullable String artist, @Nullable String title) { + String cleanArtist = artist != null ? artist.trim() : null; + String cleanTitle = title != null ? title.trim() : null; + if (cleanArtist != null && !cleanArtist.isBlank() && cleanTitle != null && !cleanTitle.isBlank()) { + return cleanArtist + " - " + cleanTitle; + } + if (cleanTitle != null && !cleanTitle.isBlank()) { + return cleanTitle; + } + if (cleanArtist != null && !cleanArtist.isBlank()) { + return cleanArtist; + } + return null; + } + + private record SongInfo(String playerId, String trackId, String displayText) { + } + + private static final class PlayerPropertiesChangedHandler implements DBusSigHandler { + @Override + public void handle(Properties.PropertiesChanged signal) { + LOGGER.info("[mpris] PropertiesChanged interface={} changedKeys={} removedKeys={}", signal.getInterfaceName(), signal.getPropertiesChanged().keySet(), signal.getPropertiesRemoved()); + if (!PLAYER_INTERFACE.equals(signal.getInterfaceName())) { + return; + } + + Map> changedProperties = signal.getPropertiesChanged(); + if (!changedProperties.containsKey("Metadata") && !changedProperties.containsKey("PlaybackStatus")) { + return; + } + + handleSongStateChange(signal.getSource()); + } + } +} diff --git a/src/client/java/download/darkworld/MprisClient.java b/src/client/java/download/darkworld/MprisClient.java new file mode 100644 index 0000000..bd85536 --- /dev/null +++ b/src/client/java/download/darkworld/MprisClient.java @@ -0,0 +1,10 @@ +package download.darkworld; + +import net.fabricmc.api.ClientModInitializer; + +public class MprisClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + MinecraftMprisClient.initialize(); + } +} diff --git a/src/client/java/download/darkworld/MprisNowPlayingToast.java b/src/client/java/download/darkworld/MprisNowPlayingToast.java new file mode 100644 index 0000000..32f4302 --- /dev/null +++ b/src/client/java/download/darkworld/MprisNowPlayingToast.java @@ -0,0 +1,110 @@ +package download.darkworld; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.Options; +import net.minecraft.client.color.ColorLerper; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.components.toasts.ToastManager; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import net.minecraft.world.item.DyeColor; + +public final class MprisNowPlayingToast implements Toast { + private static final Identifier BACKGROUND_SPRITE = Identifier.withDefaultNamespace("toast/now_playing"); + private static final Identifier MUSIC_NOTES_SPRITE = Identifier.parse("icon/music_notes"); + private static final int PADDING = 7; + private static final int MUSIC_NOTES_SIZE = 16; + private static final int HEIGHT = 30; + private static final int MUSIC_NOTES_SPACE = 30; + private static final int VISIBILITY_DURATION = 5000; + private static final int TEXT_COLOR = DyeColor.LIGHT_GRAY.getTextColor(); + private static final long MUSIC_COLOR_CHANGE_FREQUENCY_MS = 25L; + private static int musicNoteColorTick; + private static long lastMusicNoteColorChange; + private static int musicNoteColor = -1; + + private final Minecraft minecraft; + private final String playerId; + private String trackId; + private Component title; + private boolean updateToast; + private double notificationDisplayTimeMultiplier; + private Visibility wantedVisibility = Visibility.HIDE; + + public MprisNowPlayingToast(String playerId, String trackId, String title) { + this.minecraft = Minecraft.getInstance(); + this.playerId = playerId; + this.trackId = trackId; + this.title = Component.literal(title); + } + + public void showToast(String trackId, String title, Options options) { + this.trackId = trackId; + this.title = Component.literal(title); + this.updateToast = true; + this.notificationDisplayTimeMultiplier = options.notificationDisplayTime().get(); + this.wantedVisibility = Visibility.SHOW; + } + + @Override + public Object getToken() { + return this.playerId; + } + + @Override + public Visibility getWantedVisibility() { + return this.wantedVisibility; + } + + @Override + public void update(ToastManager manager, long fullyVisibleForMs) { + if (this.updateToast) { + this.wantedVisibility = fullyVisibleForMs < VISIBILITY_DURATION * this.notificationDisplayTimeMultiplier ? Visibility.SHOW : Visibility.HIDE; + tickMusicNotes(); + } + } + + @Override + public void render(GuiGraphics graphics, Font font, long fullyVisibleForMs) { + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, BACKGROUND_SPRITE, 0, 0, this.width(), HEIGHT); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, MUSIC_NOTES_SPRITE, PADDING, PADDING, MUSIC_NOTES_SIZE, MUSIC_NOTES_SIZE, musicNoteColor); + graphics.drawString(font, this.title, MUSIC_NOTES_SPACE, 15 - 9 / 2, TEXT_COLOR); + } + + @Override + public void onFinishedRendering() { + this.updateToast = false; + } + + @Override + public int width() { + return MUSIC_NOTES_SPACE + this.minecraft.font.width(this.title) + PADDING; + } + + @Override + public int height() { + return HEIGHT; + } + + @Override + public float xPos(int screenWidth, float visiblePortion) { + return this.width() * visiblePortion - this.width(); + } + + @Override + public float yPos(int firstSlotIndex) { + return 0.0F; + } + + private static void tickMusicNotes() { + long now = System.currentTimeMillis(); + if (now > lastMusicNoteColorChange + MUSIC_COLOR_CHANGE_FREQUENCY_MS) { + musicNoteColorTick++; + lastMusicNoteColorChange = now; + musicNoteColor = ColorLerper.getLerpedColor(ColorLerper.Type.MUSIC_NOTE, musicNoteColorTick); + } + } +} diff --git a/src/main/resources/assets/modid/icon.png b/src/main/resources/assets/modid/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0dbf8ab10f692b41b2723de5dcdfeb9efcb38488 GIT binary patch literal 3138 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.18.4", + "minecraft": "~1.21.11", + "java": ">=21", + "fabric-api": "*" + } +}