Skip to content

Apply different workaround to fix ranked play single thread audio issues#37477

Merged
peppy merged 4 commits intoppy:masterfrom
peppy:audio-silly
Apr 22, 2026
Merged

Apply different workaround to fix ranked play single thread audio issues#37477
peppy merged 4 commits intoppy:masterfrom
peppy:audio-silly

Conversation

@peppy
Copy link
Copy Markdown
Member

@peppy peppy commented Apr 22, 2026

Thing to make release happen.

Reverts #37453
Reverts #37463
Alternative to #37473

Not that I disagree with any of these but I'm just looking to return to what works so we can do a release because we're on a clock here for other reasons.

Test which should work but doesn't, so I'm not adding:

diff --git a/osu.Game.Tests/Visual/RankedPlay/TestSceneOpponentPickScreen.cs b/osu.Game.Tests/Visual/RankedPlay/TestSceneOpponentPickScreen.cs
index f747004bbd..eb8e360d1e 100644
--- a/osu.Game.Tests/Visual/RankedPlay/TestSceneOpponentPickScreen.cs
+++ b/osu.Game.Tests/Visual/RankedPlay/TestSceneOpponentPickScreen.cs
@@ -1,12 +1,17 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.
 
+using System.Linq;
+using NUnit.Framework;
 using osu.Framework.Extensions;
+using osu.Framework.Testing;
 using osu.Game.Online.API;
 using osu.Game.Online.Multiplayer;
 using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
 using osu.Game.Online.Rooms;
 using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
+using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Card;
+using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
 
 namespace osu.Game.Tests.Visual.RankedPlay
 {
@@ -14,6 +19,8 @@ public partial class TestSceneOpponentPickScreen : RankedPlayTestScene
     {
         private RankedPlayScreen screen = null!;
 
+        private readonly BeatmapRequestHandler requestHandler = new BeatmapRequestHandler();
+
         public override void SetUpSteps()
         {
             base.SetUpSteps();
@@ -26,8 +33,6 @@ public override void SetUpSteps()
             AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
             AddUntilStep("screen loaded", () => screen.IsLoaded);
 
-            var requestHandler = new BeatmapRequestHandler();
-
             AddStep("setup request handler", () => ((DummyAPIAccess)API).HandleRequest = requestHandler.HandleRequest);
 
             AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
@@ -44,7 +49,11 @@ public override void SetUpSteps()
                     }).WaitSafely();
                 }
             });
+        }
 
+        [Test]
+        public void TestBasic()
+        {
             AddWaitStep("wait", 15);
 
             AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(2, hand => hand[0]).WaitSafely());
@@ -54,5 +63,29 @@ public override void SetUpSteps()
                 BeatmapID = requestHandler.Beatmaps[0].OnlineID
             }).WaitSafely());
         }
+
+        [Test]
+        public void TestPickPreviewPlayedOnOpponentPick()
+        {
+            RankedPlayCard.SongPreviewContainer? originalPreview = null;
+
+            AddStep("hover first card",
+                () => InputManager.MoveMouseTo(this.ChildrenOfType<PlayerHandOfCards>().Single().Cards
+                                                   .First(c => c.Item.PlaylistItem.Value != null && c.Item.PlaylistItem.Value.BeatmapID != requestHandler.Beatmaps[0].OnlineID)));
+            AddUntilStep("preview playing", () => originalPreview = this.ChildrenOfType<RankedPlayCard.SongPreviewContainer>().FirstOrDefault(p => p.IsRunning), () => Is.Not.Null);
+
+            AddStep("play beatmap", () => MultiplayerClient.PlayUserCard(2, hand => hand[0]).WaitSafely());
+            AddStep("reveal card", () => MultiplayerClient.RankedPlayRevealUserCard(2, hand => hand[0], new MultiplayerPlaylistItem
+            {
+                ID = 0,
+                BeatmapID = requestHandler.Beatmaps[0].OnlineID
+            }).WaitSafely());
+
+            AddUntilStep("wait for original preview stopped", () => originalPreview?.IsRunning, () => Is.False);
+
+            AddUntilStep("preview playing is opponent's pick",
+                () => ((RankedPlayCard)this.ChildrenOfType<RankedPlayCard.SongPreviewContainer>().SingleOrDefault(p => p.IsRunning)?.Parent!).Item.PlaylistItem.Value?.BeatmapID,
+                () => Is.EqualTo(requestHandler.Beatmaps[0].OnlineID));
+        }
     }
 }

peppy and others added 4 commits April 22, 2026 22:05
@peppy peppy changed the title Audio silly Apply different workaround to fix ranked play single thread audio issues Apr 22, 2026

if (!previewTrack.TrackLoaded)
{
trackStartStopAction = Schedule(startPreviewIfAvailable);
Copy link
Copy Markdown
Collaborator

@bdach bdach Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one worry i would have is the possibility that this gets scheduled after RankedPlayScreen.On{Suspending,Exiting}() fire. those overrides call PreviewTrackManager.StopAnyPlaying(), and that method operates directly on the preview track and not this wrapper.

it's probably a smaller chance that this happens than current master's "every time" because the start only gets scheduled if the track isn't loaded yet but it is still a possibility as far as i can tell.

you could institute a current screen check like i had on my proposal to prevent this. either that or ignore the possibility and fix framework properly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid but gonna chance it for now.

@peppy peppy merged commit a4f79f7 into ppy:master Apr 22, 2026
6 of 10 checks passed
Copilot AI pushed a commit to winnerspiros/osu that referenced this pull request Apr 22, 2026
…37477)

- Merge upstream ppy/osu master through commit a4f79f7 (PR ppy#37477:
  ranked play single-thread audio fix, supersedes/reverts ppy#37463).
- Resolve conflict in RankedPlayCard.SongPreview.cs in favour of our
  fork's existing late-bind approach (Enabled/CardHovered subscribed
  inside LoadComponentAsync callback so they never fire pre-load).
- Pick up the new TestPreviewStopsOnEnteringGameplay regression test.

Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants