From 016743e1986ff07a88159219ddf8078b4151e704 Mon Sep 17 00:00:00 2001 From: Pixirora Date: Mon, 11 Nov 2024 19:16:03 -0500 Subject: [PATCH] Fix potential threading crashes --- .../music/metadata/MusicMetadataImpl.java | 14 ++++---- .../impl/music/progress/PlayingSong.java | 3 +- .../kitten_sounds/impl/MusicControlsImpl.java | 36 ++++++++----------- .../kitten_sounds/impl/MusicPolling.java | 5 ++- .../kitten_sounds/impl/MusicControlsImpl.java | 35 +++++++----------- .../kitten_sounds/impl/MusicPolling.java | 5 ++- 6 files changed, 44 insertions(+), 54 deletions(-) diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/metadata/MusicMetadataImpl.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/metadata/MusicMetadataImpl.java index d8ae5a5..0a2b179 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/metadata/MusicMetadataImpl.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/metadata/MusicMetadataImpl.java @@ -3,10 +3,10 @@ import java.nio.file.Path; import java.time.Duration; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import net.pixaurora.kit_tunes.api.music.Album; import net.pixaurora.kit_tunes.api.music.Artist; @@ -15,14 +15,14 @@ import net.pixaurora.kitten_heart.impl.service.MusicMetadataService; public class MusicMetadataImpl implements MusicMetadataService, MutableMusicMetadata { - private final Map albums = new HashMap<>(); - private final Map artists = new HashMap<>(); - private final Map tracks = new HashMap<>(); + private final Map albums = new ConcurrentHashMap<>(); + private final Map artists = new ConcurrentHashMap<>(); + private final Map tracks = new ConcurrentHashMap<>(); - private final HashMap trackMatches = new HashMap<>(); - private final HashMap> trackToAlbums = new HashMap<>(); + private final Map trackMatches = new ConcurrentHashMap<>(); + private final Map> trackToAlbums = new ConcurrentHashMap<>(); - private final HashMap trackDurations = new HashMap<>(); + private final Map trackDurations = new ConcurrentHashMap<>(); @Override public void add(Album album) { diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java index 9f2ba00..ce25ab6 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java @@ -21,7 +21,7 @@ public class PlayingSong implements ProgressProvider { private final ListeningProgress progress; private final MusicControls controls; - private boolean hasSentMiddleEvent; + private volatile boolean hasSentMiddleEvent; private final long middleEventMillis; public PlayingSong(ResourcePath path, Optional track, ListeningProgress progress, MusicControls controls) { @@ -31,6 +31,7 @@ public PlayingSong(ResourcePath path, Optional track, ListeningProgress p this.controls = controls; this.middleEventMillis = track.map(Track::duration).map(duration -> duration.toMillis() * 6 / 10) .orElse(Constants.MINIMUM_TIME_TO_SCROBBLE.toMillis()); + this.hasSentMiddleEvent = false; if (this.track.isPresent()) { Track track0 = track.get(); diff --git a/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java b/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java index da6817c..8210aff 100644 --- a/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java +++ b/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java @@ -1,9 +1,7 @@ package net.pixaurora.kitten_sounds.impl; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import com.mojang.blaze3d.audio.Channel; @@ -13,11 +11,13 @@ public class MusicControlsImpl implements MusicControls { private Optional channel = Optional.empty(); + private final AtomicReference playbackState = new AtomicReference<>(PlaybackState.STOPPED); public void channel(ChannelHandle channel) { this.channel = Optional.of(channel); } + @Override public void pause() { if (this.channel.isPresent()) { this.channel.get().execute(Channel::pause); @@ -33,26 +33,18 @@ public void unpause() { @Override public PlaybackState playbackState() { - if (this.channel.isEmpty() || this.channel.get().isStopped()) { - return PlaybackState.STOPPED; - } + return this.playbackState.get(); + } - CompletableFuture playbackState = new CompletableFuture().orTimeout(1, - TimeUnit.MINUTES); - - this.channel.get().execute(channel -> { - if (channel.playing()) { - playbackState.complete(PlaybackState.PLAYING); - } else { - playbackState.complete(PlaybackState.PAUSED); - } - }); - - try { - return playbackState.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException("Couldn't get playback state!", e); - } + public void updatePlaybackState(Channel channel) { + this.playbackState.set(computePlaybackState(channel)); } + public PlaybackState computePlaybackState(Channel channel) { + if (channel.playing()) { + return PlaybackState.PLAYING; + } else { + return PlaybackState.PAUSED; + } + } } diff --git a/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java b/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java index 646ac70..6e8a94e 100644 --- a/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java +++ b/projects/kitten-sounds/r1.17.0/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java @@ -55,7 +55,10 @@ public static void pollTrackProgress(Map polledSong.progress().measureProgress((SongProgressTracker) (Object) channel)); + channel -> { + polledSong.progress().measureProgress((SongProgressTracker) (Object) channel); + polledSong.controls().updatePlaybackState(channel); + }); return false; } diff --git a/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java b/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java index 0275dcc..8210aff 100644 --- a/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java +++ b/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicControlsImpl.java @@ -1,9 +1,7 @@ package net.pixaurora.kitten_sounds.impl; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import com.mojang.blaze3d.audio.Channel; @@ -13,6 +11,7 @@ public class MusicControlsImpl implements MusicControls { private Optional channel = Optional.empty(); + private final AtomicReference playbackState = new AtomicReference<>(PlaybackState.STOPPED); public void channel(ChannelHandle channel) { this.channel = Optional.of(channel); @@ -34,26 +33,18 @@ public void unpause() { @Override public PlaybackState playbackState() { - if (this.channel.isEmpty() || this.channel.get().isStopped()) { - return PlaybackState.STOPPED; - } + return this.playbackState.get(); + } - CompletableFuture playbackState = new CompletableFuture().orTimeout(1, - TimeUnit.MINUTES); - - this.channel.get().execute(channel -> { - if (channel.playing()) { - playbackState.complete(PlaybackState.PLAYING); - } else { - playbackState.complete(PlaybackState.PAUSED); - } - }); - - try { - return playbackState.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException("Couldn't get playback state!", e); - } + public void updatePlaybackState(Channel channel) { + this.playbackState.set(computePlaybackState(channel)); } + public PlaybackState computePlaybackState(Channel channel) { + if (channel.playing()) { + return PlaybackState.PLAYING; + } else { + return PlaybackState.PAUSED; + } + } } diff --git a/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java b/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java index c6a0c48..8896cf4 100644 --- a/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java +++ b/projects/kitten-sounds/r1.20.3/src/main/java/net/pixaurora/kitten_sounds/impl/MusicPolling.java @@ -55,7 +55,10 @@ public static void pollTrackProgress(Map polledSong.progress().measureProgress((SongProgressTracker) (Object) channel)); + channel -> { + polledSong.progress().measureProgress((SongProgressTracker) (Object) channel); + polledSong.controls().updatePlaybackState(channel); + }); return false; }