mirror of
https://github.com/ppy/osu
synced 2025-02-17 10:57:03 +00:00
Rework preview tracks to reduce usage complexities
This commit is contained in:
parent
ab2889da1f
commit
b2066c5d73
16
osu.Game/Audio/IPreviewTrackOwner.cs
Normal file
16
osu.Game/Audio/IPreviewTrackOwner.cs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for objects that can own <see cref="IPreviewTrack"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IPreviewTrackOwner"/>s can cancel the currently playing <see cref="PreviewTrack"/> through the
|
||||
/// global <see cref="PreviewTrackManager"/> if they're the owner of the playing <see cref="PreviewTrack"/>.
|
||||
/// </remarks>
|
||||
public interface IPreviewTrackOwner
|
||||
{
|
||||
}
|
||||
}
|
@ -5,49 +5,87 @@ using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Framework.Threading;
|
||||
|
||||
namespace osu.Game.Audio
|
||||
{
|
||||
public class PreviewTrack : Component
|
||||
public abstract class PreviewTrack : Component
|
||||
{
|
||||
public Track Track { get; private set; }
|
||||
private readonly OverlayContainer owner;
|
||||
|
||||
private readonly BeatmapSetInfo beatmapSetInfo;
|
||||
|
||||
public event Action Stopped;
|
||||
public event Action Started;
|
||||
|
||||
public PreviewTrack(BeatmapSetInfo beatmapSetInfo, OverlayContainer owner)
|
||||
{
|
||||
this.beatmapSetInfo = beatmapSetInfo;
|
||||
this.owner = owner;
|
||||
}
|
||||
private Track track;
|
||||
private bool wasPlaying;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(PreviewTrackManager previewTrackManager)
|
||||
private void load()
|
||||
{
|
||||
Track = previewTrackManager.Get(this, beatmapSetInfo);
|
||||
}
|
||||
track = GetTrack();
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Track.Restart();
|
||||
Started?.Invoke();
|
||||
if (track != null)
|
||||
track.Looping = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop preview playback
|
||||
/// Length of the track.
|
||||
/// </summary>
|
||||
/// <param name="source">An <see cref="OverlayContainer"/> which is probably the owner of this <see cref="PreviewTrack"/></param>
|
||||
public void Stop(OverlayContainer source = null)
|
||||
public double Length => track?.Length ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// The current track time.
|
||||
/// </summary>
|
||||
public double CurrentTime => track?.CurrentTime ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the track is loaded.
|
||||
/// </summary>
|
||||
public bool TrackLoaded => track?.IsLoaded ?? false;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (source != null && owner != source)
|
||||
base.Update();
|
||||
|
||||
// Todo: Track currently doesn't signal its completion, so we have to handle it manually
|
||||
if (track != null && wasPlaying && track.HasCompleted)
|
||||
Stop();
|
||||
}
|
||||
|
||||
private ScheduledDelegate startDelegate;
|
||||
|
||||
public void Start() => startDelegate = Schedule(() =>
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
Track.Stop();
|
||||
|
||||
if (track == null)
|
||||
return;
|
||||
|
||||
if (wasPlaying)
|
||||
return;
|
||||
wasPlaying = true;
|
||||
|
||||
track.Restart();
|
||||
Started?.Invoke();
|
||||
});
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
startDelegate?.Cancel();
|
||||
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
if (track == null)
|
||||
return;
|
||||
|
||||
if (!wasPlaying)
|
||||
return;
|
||||
wasPlaying = false;
|
||||
|
||||
track.Stop();
|
||||
Stopped?.Invoke();
|
||||
}
|
||||
|
||||
protected abstract Track GetTrack();
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,17 @@ namespace osu.Game.Audio
|
||||
{
|
||||
public class PreviewTrackManager : Component
|
||||
{
|
||||
private readonly BindableDouble muteBindable = new BindableDouble();
|
||||
|
||||
private AudioManager audio;
|
||||
private TrackManager trackManager;
|
||||
private BindableDouble muteBindable;
|
||||
|
||||
public PreviewTrack CurrentTrack { get; private set; }
|
||||
private TrackManagerPreviewTrack current;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, FrameworkConfigManager config)
|
||||
{
|
||||
trackManager = new TrackManager(new OnlineStore());
|
||||
muteBindable = new BindableDouble();
|
||||
|
||||
this.audio = audio;
|
||||
audio.AddItem(trackManager);
|
||||
@ -31,30 +31,55 @@ namespace osu.Game.Audio
|
||||
config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo)
|
||||
{
|
||||
if (CurrentTrack?.Track.HasCompleted ?? false)
|
||||
CurrentTrack.Stop();
|
||||
var track = new TrackManagerPreviewTrack(beatmapSetInfo, trackManager);
|
||||
|
||||
base.Update();
|
||||
}
|
||||
|
||||
public Track Get(PreviewTrack previewTrack, BeatmapSetInfo beatmapSetInfo)
|
||||
{
|
||||
previewTrack.Started += () =>
|
||||
track.Started += () =>
|
||||
{
|
||||
CurrentTrack?.Stop();
|
||||
CurrentTrack = previewTrack;
|
||||
current?.Stop();
|
||||
current = track;
|
||||
audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
};
|
||||
|
||||
previewTrack.Stopped += () =>
|
||||
track.Stopped += () =>
|
||||
{
|
||||
CurrentTrack = null;
|
||||
current = null;
|
||||
audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
};
|
||||
|
||||
return trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3");
|
||||
return track;
|
||||
}
|
||||
|
||||
public void Stop(IPreviewTrackOwner source)
|
||||
{
|
||||
if (current?.Owner != source)
|
||||
return;
|
||||
|
||||
current?.Stop();
|
||||
current = null;
|
||||
}
|
||||
|
||||
private class TrackManagerPreviewTrack : PreviewTrack
|
||||
{
|
||||
public IPreviewTrackOwner Owner { get; private set; }
|
||||
|
||||
private readonly BeatmapSetInfo beatmapSetInfo;
|
||||
private readonly TrackManager trackManager;
|
||||
|
||||
public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager)
|
||||
{
|
||||
this.beatmapSetInfo = beatmapSetInfo;
|
||||
this.trackManager = trackManager;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IPreviewTrackOwner owner)
|
||||
{
|
||||
Owner = owner;
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,20 +8,32 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using OpenTK;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
public class OsuFocusedOverlayContainer : FocusedOverlayContainer
|
||||
public class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner
|
||||
{
|
||||
private SampleChannel samplePopIn;
|
||||
private SampleChannel samplePopOut;
|
||||
|
||||
private PreviewTrackManager previewTrackManager;
|
||||
|
||||
protected readonly Bindable<OverlayActivation> OverlayActivationMode = new Bindable<OverlayActivation>(OverlayActivation.All);
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame osuGame, AudioManager audio)
|
||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
|
||||
dependencies.CacheAs<IPreviewTrackOwner>(this);
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager)
|
||||
{
|
||||
this.previewTrackManager = previewTrackManager;
|
||||
|
||||
if (osuGame != null)
|
||||
OverlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||
|
||||
@ -66,5 +78,11 @@ namespace osu.Game.Graphics.Containers
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
previewTrackManager.Stop(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
if (Playing.Value && preview != null)
|
||||
{
|
||||
// prevent negative (potential infinite) width if a track without length was loaded
|
||||
progress.Width = preview.Track.Length > 0 ? (float)(preview.Track.CurrentTime / preview.Track.Length) : 0f;
|
||||
progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f;
|
||||
}
|
||||
else
|
||||
progress.Width = 0;
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -38,7 +37,6 @@ namespace osu.Game.Overlays
|
||||
private readonly ScrollContainer scroll;
|
||||
|
||||
private BeatmapSetInfo beatmapSet;
|
||||
private PreviewTrackManager previewTrackManager;
|
||||
|
||||
public BeatmapSetInfo BeatmapSet
|
||||
{
|
||||
@ -111,11 +109,10 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(APIAccess api, RulesetStore rulesets, PreviewTrackManager previewTrackManager)
|
||||
private void load(APIAccess api, RulesetStore rulesets)
|
||||
{
|
||||
this.api = api;
|
||||
this.rulesets = rulesets;
|
||||
this.previewTrackManager = previewTrackManager;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
@ -127,8 +124,6 @@ namespace osu.Game.Overlays
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
previewTrackManager.CurrentTrack?.Stop(this);
|
||||
|
||||
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null);
|
||||
}
|
||||
|
||||
|
@ -113,9 +113,9 @@ namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (PreviewPlaying && Preview != null && Preview.Track.IsLoaded)
|
||||
if (PreviewPlaying && Preview != null && Preview.TrackLoaded)
|
||||
{
|
||||
PreviewBar.Width = (float)(Preview.Track.CurrentTime / Preview.Track.Length);
|
||||
PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,21 +29,14 @@ namespace osu.Game.Overlays.Direct
|
||||
if (value == beatmapSet) return;
|
||||
beatmapSet = value;
|
||||
|
||||
Preview?.Stop(parentOverlayContainer);
|
||||
if (Preview != null)
|
||||
{
|
||||
Preview.Stop();
|
||||
RemoveInternal(Preview);
|
||||
Preview = null;
|
||||
}
|
||||
|
||||
Playing.Value = false;
|
||||
Preview = null;
|
||||
}
|
||||
}
|
||||
|
||||
private OverlayContainer parentOverlayContainer
|
||||
{
|
||||
get
|
||||
{
|
||||
var d = Parent;
|
||||
while (!(d is OverlayContainer))
|
||||
d = d.Parent;
|
||||
|
||||
return (OverlayContainer)d;
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,9 +82,13 @@ namespace osu.Game.Overlays.Direct
|
||||
Playing.ValueChanged += playingStateChanged;
|
||||
}
|
||||
|
||||
private PreviewTrackManager previewTrackManager;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colour)
|
||||
private void load(OsuColour colour, PreviewTrackManager previewTrackManager)
|
||||
{
|
||||
this.previewTrackManager = previewTrackManager;
|
||||
|
||||
hoverColour = colour.Yellow;
|
||||
}
|
||||
|
||||
@ -103,15 +100,18 @@ namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
loading = true;
|
||||
|
||||
LoadComponentAsync(
|
||||
Preview = new PreviewTrack(beatmapSet, parentOverlayContainer),
|
||||
t =>
|
||||
{
|
||||
Preview.Started += () => Playing.Value = true;
|
||||
Preview.Stopped += () => Playing.Value = false;
|
||||
Preview.Start();
|
||||
loading = false;
|
||||
});
|
||||
Preview = previewTrackManager.Get(beatmapSet);
|
||||
Preview.Started += () => Playing.Value = true;
|
||||
Preview.Stopped += () => Playing.Value = false;
|
||||
|
||||
LoadComponentAsync(Preview, t =>
|
||||
{
|
||||
AddInternal(t);
|
||||
|
||||
Preview.Start();
|
||||
|
||||
loading = false;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ namespace osu.Game.Overlays
|
||||
|
||||
if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return;
|
||||
|
||||
previewTrackManager.CurrentTrack?.Stop(this);
|
||||
previewTrackManager.Stop(this);
|
||||
|
||||
getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty,
|
||||
((FilterControl)Filter).Ruleset.Value,
|
||||
@ -289,12 +289,6 @@ namespace osu.Game.Overlays
|
||||
|
||||
private int distinctCount(List<string> list) => list.Distinct().ToArray().Length;
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
previewTrackManager.CurrentTrack?.Stop(this);
|
||||
base.PopOut();
|
||||
}
|
||||
|
||||
public class ResultCounts
|
||||
{
|
||||
public readonly int Artists;
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -31,7 +30,6 @@ namespace osu.Game.Overlays
|
||||
protected ProfileHeader Header;
|
||||
private SectionsContainer<ProfileSection> sectionsContainer;
|
||||
private ProfileTabControl tabs;
|
||||
private PreviewTrackManager previewTrackManager;
|
||||
|
||||
public const float CONTENT_X_MARGIN = 50;
|
||||
|
||||
@ -58,10 +56,9 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(APIAccess api, PreviewTrackManager previewTrackManager)
|
||||
private void load(APIAccess api)
|
||||
{
|
||||
this.api = api;
|
||||
this.previewTrackManager = previewTrackManager;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
@ -73,7 +70,6 @@ namespace osu.Game.Overlays
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
previewTrackManager.CurrentTrack?.Stop(this);
|
||||
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user