using Content.Shared.Audio.Jukebox; using Robust.Client.Audio; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Audio.Components; using Robust.Shared.Prototypes; using Robust.Shared.Timing; using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow; namespace Content.Client.Audio.Jukebox; [GenerateTypedNameReferences] public sealed partial class JukeboxMenu : FancyWindow { [Dependency] private readonly IEntityManager _entManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; private AudioSystem _audioSystem; /// /// True if playing, false if paused. /// public event Action? OnPlayPressed; public event Action? OnStopPressed; public event Action>? OnSongSelected; public event Action? SetTime; public event Action>? OnSongQueueAdd; public event Action? OnQueueRemove; private EntityUid? _audio; private float _lockTimer; public JukeboxMenu() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _audioSystem = _entManager.System(); CurrentSong.SetOnPressedStop(args => { OnStopPressed?.Invoke(); }); CurrentSong.SetOnPressedPlay((song, playPauseState, args) => { OnPlayPressed?.Invoke(playPauseState); }); PlaybackSlider.OnReleased += PlaybackSliderKeyUp; } public JukeboxMenu(AudioSystem audioSystem) { _audioSystem = audioSystem; } public void SetAudioStream(EntityUid? audio) { _audio = audio; } private void PlaybackSliderKeyUp(Slider args) { SetTime?.Invoke(PlaybackSlider.Value); _lockTimer = 0.5f; } /// /// Re-populates the list of jukebox prototypes available. /// public void Populate(IEnumerable jukeboxProtos) { MusicList.RemoveAllChildren(); foreach (var entry in jukeboxProtos) { // MusicList.AddItem(entry.Name, metadata: entry.ID); var songControl = new JukeboxEntry(entry) {EntryType = JukeboxEntry.JukeboxEntryType.List}; songControl.SetOnPressedPlay((song, _, args) => { if (song == null) return; OnSongSelected?.Invoke(song.ID); OnPlayPressed?.Invoke(true); }); songControl.SetOnPressedQueue((song, args) => { if (song == null) return; OnSongQueueAdd?.Invoke(song.ID); }); MusicList.AddChild(songControl); } } public void SetSelectedSong(ProtoId? song, float length) { if (song == null) return; if (!_prototype.TryIndex(song, out var songProto)) return; SongSelected.Text = Loc.GetString("jukebox-menu-selectedsong"); PlaybackSlider.Visible = true; CurrentSong.Visible = true; CurrentSong.SetSong(songProto); PlaybackSlider.MaxValue = length; PlaybackSlider.SetValueWithoutEvent(0); } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); if (_lockTimer > 0f) { _lockTimer -= args.DeltaSeconds; } if (_entManager.TryGetComponent(_audio, out AudioComponent? audio)) { DurationLabel.Text = $@"{TimeSpan.FromSeconds(audio.PlaybackPosition):mm\:ss} / {_audioSystem.GetAudioLength(audio.FileName):mm\:ss}"; } else { DurationLabel.Text = $"00:00 / 00:00"; } if (PlaybackSlider.Grabbed) return; if (audio != null || _entManager.TryGetComponent(_audio, out audio)) { PlaybackSlider.SetValueWithoutEvent(audio.PlaybackPosition); } else { PlaybackSlider.SetValueWithoutEvent(0f); } } /// /// Re-populates the queue with avaiable jukebox prototypes. /// public void PopulateQueue(IEnumerable> queue) { MusicListQueue.RemoveAllChildren(); int i = 0; foreach (var song in queue) { if (!_prototype.TryIndex(song, out var songProto)) continue; i += 1; var songControl = new JukeboxEntry(songProto) {EntryType = JukeboxEntry.JukeboxEntryType.Queue}; MusicListQueue.AddChild(songControl); songControl.SetOnPressedRemove((source, args) => { int index = source.GetPositionInParent(); OnQueueRemove?.Invoke(index); }); } } public void SetIsPlaying(bool isPlaying) { CurrentSong.PlayPauseState = isPlaying; } }