diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs
index 39b3c23ddd..367f612dc8 100644
--- a/osu.Game/Beatmaps/BeatmapMetadata.cs
+++ b/osu.Game/Beatmaps/BeatmapMetadata.cs
@@ -51,7 +51,12 @@ namespace osu.Game.Beatmaps
[JsonProperty(@"tags")]
public string Tags { get; set; }
+ ///
+ /// The time in milliseconds to begin playing the track for preview purposes.
+ /// If -1, the track should begin playing at 40% of its length.
+ ///
public int PreviewTime { get; set; }
+
public string AudioFile { get; set; }
public string BackgroundFile { get; set; }
diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
index 30382c444f..aab8ff6bd6 100644
--- a/osu.Game/Beatmaps/WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -266,6 +266,26 @@ namespace osu.Game.Beatmaps
[NotNull]
public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000);
+ ///
+ /// Reads the correct track restart point from beatmap metadata and sets looping to enabled.
+ ///
+ public void PrepareTrackForPreviewLooping()
+ {
+ Track.Looping = true;
+ Track.RestartPoint = Metadata.PreviewTime;
+
+ if (Track.RestartPoint == -1)
+ {
+ if (!Track.IsLoaded)
+ {
+ // force length to be populated (https://github.com/ppy/osu-framework/issues/4202)
+ Track.Seek(Track.CurrentTime);
+ }
+
+ Track.RestartPoint = 0.4f * Track.Length;
+ }
+ }
+
///
/// Transfer a valid audio track into this working beatmap. Used as an optimisation to avoid reload / track swap
/// across difficulties in the same beatmap set.
diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs
index 71b83d4aab..71f3b60026 100644
--- a/osu.Game/Screens/Menu/IntroScreen.cs
+++ b/osu.Game/Screens/Menu/IntroScreen.cs
@@ -168,7 +168,7 @@ namespace osu.Game.Screens.Menu
{
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Menu.
if (UsingThemedIntro)
- Track.Restart();
+ Track.Start();
}
protected override void LogoArriving(OsuLogo logo, bool resuming)
diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs
index 97fd58318b..424e6d2cd5 100644
--- a/osu.Game/Screens/Menu/MainMenu.cs
+++ b/osu.Game/Screens/Menu/MainMenu.cs
@@ -179,14 +179,15 @@ namespace osu.Game.Screens.Menu
base.OnEntering(last);
buttons.FadeInFromZero(500);
- var metadata = Beatmap.Value.Metadata;
-
if (last is IntroScreen && musicController.TrackLoaded)
{
- if (!musicController.CurrentTrack.IsRunning)
+ var track = musicController.CurrentTrack;
+
+ // presume the track is the current beatmap's track. not sure how correct this assumption is but it has worked until now.
+ if (!track.IsRunning)
{
- musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length);
- musicController.CurrentTrack.Start();
+ Beatmap.Value.PrepareTrackForPreviewLooping();
+ track.Restart();
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
index e755f8c405..86422085a1 100644
--- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
@@ -173,9 +173,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
if (track != null)
{
- track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
- track.Looping = true;
-
+ Beatmap.Value.PrepareTrackForPreviewLooping();
music?.EnsurePlayingSomething();
}
}
@@ -185,10 +183,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
var track = Beatmap?.Value?.Track;
if (track != null)
- {
track.Looping = false;
- track.RestartPoint = 0;
- }
}
}
}
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index edbab083cd..b7f7c40539 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -648,8 +648,9 @@ namespace osu.Game.Screens.Select
{
Debug.Assert(!isHandlingLooping);
- music.CurrentTrack.Looping = isHandlingLooping = true;
+ isHandlingLooping = true;
+ ensureTrackLooping(Beatmap.Value, TrackChangeDirection.None);
music.TrackChanged += ensureTrackLooping;
}
@@ -665,7 +666,7 @@ namespace osu.Game.Screens.Select
}
private void ensureTrackLooping(WorkingBeatmap beatmap, TrackChangeDirection changeDirection)
- => music.CurrentTrack.Looping = true;
+ => beatmap.PrepareTrackForPreviewLooping();
public override bool OnBackButton()
{
@@ -719,8 +720,6 @@ namespace osu.Game.Screens.Select
bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track;
- track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
-
if (!track.IsRunning && (music.UserPauseRequested != true || isNewTrack))
music.Play(true);