// Copyright (c) Arlo Godfrey. All Rights Reserved. // Licensed under the GNU Lesser General Public License, Version 3.0 with additional terms. // See the LICENSE, LICENSE.LESSER and LICENSE.ADDITIONAL files in the project root for more information. using System; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Diagnostics; using StrixMusic.Sdk.AppModels; using StrixMusic.Sdk.BaseModels; using StrixMusic.Sdk.CoreModels; namespace StrixMusic.Sdk.MediaPlayback.LocalDevice { /// /// The default playback device for the app. /// public sealed class StrixDevice : IDevice { private readonly IPlaybackHandlerService _playbackHandler; /// /// Creates a new instance of . /// public StrixDevice(IPlaybackHandlerService playbackHandler) { _playbackHandler = playbackHandler; PlaybackContext = null; // TODO: Implement StrixPlaybackQueueCollection //PlaybackQueue = new StrixPlaybackQueueCollection(); AttachEvents(); } private void AttachEvents() { _playbackHandler.RepeatStateChanged += PlaybackHandler_RepeatStateChanged; _playbackHandler.ShuffleStateChanged += PlaybackHandler_ShuffleStateChanged; _playbackHandler.PlaybackSpeedChanged += PlaybackHandler_PlaybackSpeedChanged; _playbackHandler.PlaybackStateChanged += PlaybackHandler_PlaybackStateChanged; _playbackHandler.PositionChanged += PlaybackHandler_PositionChanged; _playbackHandler.VolumeChanged += PlaybackHandler_VolumeChanged; _playbackHandler.CurrentItemChanged += PlaybackHandler_CurrentItemChanged; } private void DetachEvents() { _playbackHandler.RepeatStateChanged -= PlaybackHandler_RepeatStateChanged; _playbackHandler.ShuffleStateChanged -= PlaybackHandler_ShuffleStateChanged; _playbackHandler.PlaybackSpeedChanged -= PlaybackHandler_PlaybackSpeedChanged; _playbackHandler.PlaybackStateChanged -= PlaybackHandler_PlaybackStateChanged; _playbackHandler.PositionChanged -= PlaybackHandler_PositionChanged; _playbackHandler.VolumeChanged -= PlaybackHandler_VolumeChanged; _playbackHandler.CurrentItemChanged -= PlaybackHandler_CurrentItemChanged; } private void PlaybackHandler_CurrentItemChanged(object sender, PlaybackItem? e) { Guard.IsNotNull(e, nameof(e)); SetPlaybackData(PlaybackContext, e); } private void PlaybackHandler_PlaybackStateChanged(object sender, PlaybackState e) => PlaybackStateChanged?.Invoke(sender, e); private void PlaybackHandler_PositionChanged(object sender, TimeSpan e) => PositionChanged?.Invoke(sender, e); private void PlaybackHandler_VolumeChanged(object sender, double e) => VolumeChanged?.Invoke(this, e); private void PlaybackHandler_PlaybackSpeedChanged(object sender, double e) => PlaybackSpeedChanged?.Invoke(sender, e); private void PlaybackHandler_RepeatStateChanged(object sender, RepeatState e) => RepeatStateChanged?.Invoke(sender, e); private void PlaybackHandler_ShuffleStateChanged(object sender, bool e) => ShuffleStateChanged?.Invoke(sender, e); /// public event EventHandler? IsActiveChanged; /// public event EventHandler? PlaybackContextChanged; /// public event EventHandler? NowPlayingChanged; /// public event EventHandler? ShuffleStateChanged; /// public event EventHandler? PositionChanged; /// public event EventHandler? RepeatStateChanged; /// public event EventHandler? PlaybackStateChanged; /// public event EventHandler? VolumeChanged; /// public event EventHandler? PlaybackSpeedChanged; /// public TimeSpan Position => _playbackHandler.Position; /// public PlaybackState PlaybackState => _playbackHandler.PlaybackState; /// public double Volume => _playbackHandler.Volume; /// public double PlaybackSpeed => _playbackHandler.PlaybackSpeed; /// public Task ResumeAsync(CancellationToken cancellationToken = default) => _playbackHandler.ResumeAsync(cancellationToken); /// public Task PauseAsync(CancellationToken cancellationToken = default) => _playbackHandler.PauseAsync(cancellationToken); /// public Task SeekAsync(TimeSpan position, CancellationToken cancellationToken = default) => _playbackHandler.SeekAsync(position, cancellationToken); /// public Task ChangePlaybackSpeedAsync(double speed, CancellationToken cancellationToken = default) => _playbackHandler.ChangePlaybackSpeedAsync(speed, cancellationToken); /// public Task ChangeVolumeAsync(double volume, CancellationToken cancellationToken = default) => _playbackHandler.ChangeVolumeAsync(volume, cancellationToken); /// public string Id => "609EBD5A-EBA1-4DDE-9828-C72B096D35DF"; /// public string Name => "This Device"; /// public bool IsActive { get; private set; } /// public ICore? SourceCore { get; } /// public ICoreDevice? Source { get; } /// public ITrackCollection? PlaybackQueue { get; } /// public IPlayableBase? PlaybackContext { get; private set; } /// public PlaybackItem? NowPlaying { get; private set; } /// public DeviceType Type => DeviceType.Local; /// public bool ShuffleState => _playbackHandler.ShuffleState; /// public RepeatState RepeatState => _playbackHandler.RepeatState; /// public bool IsSeekAsyncAvailable => true; /// public bool IsResumeAsyncAvailable => true; /// public bool IsPauseAsyncAvailable => true; /// public bool IsChangeVolumeAsyncAvailable => true; /// public bool IsChangePlaybackSpeedAvailable => true; /// public bool IsNextAsyncAvailable => true; /// public bool IsPreviousAsyncAvailable => true; /// public bool IsToggleShuffleAsyncAvailable => true; /// public bool IsToggleRepeatAsyncAvailable => true; /// public Task NextAsync(CancellationToken cancellationToken = default) => _playbackHandler.NextAsync(cancellationToken); /// public Task PreviousAsync(CancellationToken cancellationToken = default) => _playbackHandler.PreviousAsync(cancellationToken); /// public Task SwitchToAsync(CancellationToken cancellationToken = default) { IsActive = true; IsActiveChanged?.Invoke(this, IsActive); // Maybe preload some things? return Task.CompletedTask; } /// /// Sets playback data for this device. /// /// The playback context. /// The track that is playing. internal void SetPlaybackData(IPlayableBase? playbackContext, PlaybackItem nowPlaying) { PlaybackContext = playbackContext; PlaybackContextChanged?.Invoke(this, playbackContext); NowPlaying = nowPlaying; NowPlayingChanged?.Invoke(this, nowPlaying); } /// public Task ToggleShuffleAsync(CancellationToken cancellationToken = default) => _playbackHandler.ToggleShuffleAsync(cancellationToken); /// public Task ToggleRepeatAsync(CancellationToken cancellationToken = default) => _playbackHandler.ToggleRepeatAsync(cancellationToken); /// public ValueTask DisposeAsync() { DetachEvents(); return default; } } }