From 73470e7dc40bca141df89446149d46cb3c98392e Mon Sep 17 00:00:00 2001 From: Denys Mostovsky Date: Fri, 11 Feb 2022 08:29:01 +0200 Subject: [PATCH 1/2] LDSW-3014: Spotify plugin logic separation between Spotify API and Plugin. Added Wrapper layer and business logic moved from Plugin to Wrapper. --- .../Playback/PlayAndNavigateAdjustment.cs | 21 +- .../Volume/SpotifyVolumeAdjustment.cs | 98 +---- .../DeviceSelectorCommandFolder.cs | 24 +- src/Win/Commands/LoginToSpotifyCommand.cs | 8 +- .../Playback/ChangeRepeatStateCommand.cs | 53 +-- src/Win/Commands/Playback/NextTrackCommand.cs | 18 +- .../Commands/Playback/PreviousTrackCommand.cs | 18 +- .../Commands/Playback/ShufflePlayCommand.cs | 31 +- .../Playback/TogglePlaybackCommand.cs | 32 +- src/Win/Commands/ToggleLikeCommand.cs | 51 +-- src/Win/Commands/Volume/MuteCommand.cs | 29 +- src/Win/Commands/Volume/ToggleMuteCommand.cs | 52 +-- src/Win/Commands/Volume/UnmuteCommand.cs | 24 +- .../DirectVolumeCommand.cs | 35 +- .../SaveToPlaylistCommand.cs | 30 +- .../StartPlaylistCommand.cs | 22 +- src/Win/SpotifyPremiumPlugin.Installer.cs | 10 +- src/Win/SpotifyPremiumPlugin.Statuses.cs | 39 ++ src/Win/SpotifyPremiumPlugin.cs | 10 +- src/Win/SpotifyPremiumPlugin.csproj | 9 +- .../SpotifyWrapper.Authentification.cs} | 137 ++---- .../SpotifyWrapper.Cache.cs} | 26 +- src/Win/Wrapper/SpotifyWrapper.Events.cs | 39 ++ .../SpotifyWrapper.Responses.cs} | 29 +- src/Win/Wrapper/SpotifyWrapper.cs | 400 ++++++++++++++++++ 25 files changed, 603 insertions(+), 642 deletions(-) create mode 100644 src/Win/SpotifyPremiumPlugin.Statuses.cs rename src/Win/{SpotifyPremiumPlugin.Api.cs => Wrapper/SpotifyWrapper.Authentification.cs} (61%) rename src/Win/{SpotifyPremiumPlugin.DevicesSelector.cs => Wrapper/SpotifyWrapper.Cache.cs} (71%) create mode 100644 src/Win/Wrapper/SpotifyWrapper.Events.cs rename src/Win/{SpotifyPremiumPlugin.ApiResponse.cs => Wrapper/SpotifyWrapper.Responses.cs} (64%) create mode 100644 src/Win/Wrapper/SpotifyWrapper.cs diff --git a/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs b/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs index cea2c85..99d1027 100644 --- a/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs +++ b/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs @@ -3,8 +3,7 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; - + internal class PlayAndNavigateAdjustment : PluginDynamicAdjustment { public PlayAndNavigateAdjustment() @@ -24,11 +23,11 @@ protected override void ApplyAdjustment(String actionParameter, Int32 ticks) { if (ticks > 0) { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SkipPlaybackToNext); + this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToNext(); } else { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SkipPlaybackToPrevious); + this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToPrevious(); } } catch (Exception e) @@ -42,7 +41,7 @@ protected override void RunCommand(String actionParameter) { try { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.TogglePlayback); + this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); } catch (Exception e) { @@ -56,17 +55,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width50.PlayAndNavigateTracks.png"); return bitmapImage; } - - public ErrorResponse SkipPlaybackToNext() => this.SpotifyPremiumPlugin.Api.SkipPlaybackToNext(this.SpotifyPremiumPlugin.CurrentDeviceId); - - public ErrorResponse SkipPlaybackToPrevious() => this.SpotifyPremiumPlugin.Api.SkipPlaybackToPrevious(this.SpotifyPremiumPlugin.CurrentDeviceId); - - public ErrorResponse TogglePlayback() - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - return playback.IsPlaying - ? this.SpotifyPremiumPlugin.Api.PausePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId) - : this.SpotifyPremiumPlugin.Api.ResumePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId, String.Empty, null, String.Empty, 0); - } } } diff --git a/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs b/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs index 25cabdb..22bbc5f 100644 --- a/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs +++ b/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs @@ -3,71 +3,24 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using System.Timers; - using SpotifyAPI.Web.Models; internal class SpotifyVolumeAdjustment : PluginDynamicAdjustment { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - - private Boolean _volumeBlocked; - - private Timer _volumeBlockedTimer; - - public SpotifyVolumeAdjustment() - : base( - "Spotify Volume", - "Spotify Volume description", - "Spotify Volume", - true) + + public SpotifyVolumeAdjustment() : base("Spotify Volume", "Spotify Volume description", "Spotify Volume", true) { } protected override void ApplyAdjustment(String actionParameter, Int32 ticks) { - try - { - var modifiedVolume = 0; - if (this._volumeBlocked) - { - modifiedVolume = this.SpotifyPremiumPlugin.PreviousVolume + ticks; - } - else - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - if (playback?.Device == null) - { - // Set plugin status and message - this.SpotifyPremiumPlugin.CheckStatusCode(System.Net.HttpStatusCode.NotFound, "Cannot adjust volume, no device"); - return; - } - else - { - this.InitVolumeBlockedTimer(); - modifiedVolume = playback.Device.VolumePercent + ticks; - } - } - - this.SpotifyPremiumPlugin.PreviousVolume = modifiedVolume; - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SetVolume, modifiedVolume); - } - catch (Exception e) - { - Tracer.Trace($"Spotify SpotifyVolumeAdjustment action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.SetVolume(ticks); } // Overwrite the RunCommand method that is called every time the user presses the encoder to which this command is assigned protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.TogglePlayback); - } - catch (Exception e) - { - Tracer.Trace($"Spotify SpotifyVolumeAdjustment action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) @@ -76,48 +29,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width50.Volume.png"); return bitmapImage; } - - public ErrorResponse TogglePlayback() - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - return playback.IsPlaying - ? this.SpotifyPremiumPlugin.Api.PausePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId) - : this.SpotifyPremiumPlugin.Api.ResumePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId, String.Empty, null, String.Empty, 0); - } - - private void InitVolumeBlockedTimer() - { - if (this._volumeBlockedTimer == null) - { - this._volumeBlockedTimer = new Timer(2000); - this._volumeBlockedTimer.Elapsed += this.VolumeBlockExpired; - } - - this._volumeBlocked = true; - if (this._volumeBlockedTimer.Enabled) - { - this._volumeBlockedTimer.Stop(); - } - - this._volumeBlockedTimer.Start(); - } - - public ErrorResponse SetVolume(Int32 percents) - { - if (percents > 100) - { - percents = 100; - } - - if (percents < 0) - { - percents = 0; - } - - var response = this.SpotifyPremiumPlugin.Api.SetVolume(percents, this.SpotifyPremiumPlugin.CurrentDeviceId); - return response; - } - - private void VolumeBlockExpired(Object o, ElapsedEventArgs e) => this._volumeBlocked = false; } } diff --git a/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs b/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs index bdd7a50..f15b6f0 100644 --- a/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs +++ b/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs @@ -32,7 +32,7 @@ public override BitmapImage GetButtonImage(PluginImageSize imageSize) public override IEnumerable GetButtonPressActionNames() { - this._devices = this.SpotifyPremiumPlugin?.Api?.GetDevices()?.Devices; + this._devices = this.SpotifyPremiumPlugin.Wrapper.GetDevices(); if (this._devices != null && this._devices.Any()) { this._devices.Add(new Device { Id = "activedevice", Name = "Active Device" }); @@ -56,27 +56,7 @@ public override String GetCommandDisplayName(String commandParameter, PluginImag public override void RunCommand(String commandParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.TransferPlayback, commandParameter); - } - catch (Exception e) - { - Tracer.Trace($"Spotify DeviceSelectorCommandFolder action obtain an error: ", e); - } - } - - public ErrorResponse TransferPlayback(String commandParameter) - { - if (commandParameter == "activedevice") - { - commandParameter = String.Empty; - } - - this.SpotifyPremiumPlugin.CurrentDeviceId = commandParameter; - this.SpotifyPremiumPlugin.SaveDeviceToCache(commandParameter); - - return this.SpotifyPremiumPlugin.Api.TransferPlayback(this.SpotifyPremiumPlugin.CurrentDeviceId, true); + this.SpotifyPremiumPlugin.Wrapper.TransferPlayback(commandParameter); } } } \ No newline at end of file diff --git a/src/Win/Commands/LoginToSpotifyCommand.cs b/src/Win/Commands/LoginToSpotifyCommand.cs index c172429..baf77ba 100644 --- a/src/Win/Commands/LoginToSpotifyCommand.cs +++ b/src/Win/Commands/LoginToSpotifyCommand.cs @@ -7,14 +7,10 @@ namespace Loupedeck.SpotifyPremiumPlugin internal class LoginToSpotifyCommand : PluginDynamicCommand { - public LoginToSpotifyCommand() - : base( - "Login to Spotify", - "Premium user login to Spotify API", - "Login") + public LoginToSpotifyCommand() : base("Login to Spotify", "Premium user login to Spotify API", "Login") { } - protected override void RunCommand(String actionParameter) => (this.Plugin as SpotifyPremiumPlugin).LoginToSpotify(); + protected override void RunCommand(String actionParameter) => (this.Plugin as SpotifyPremiumPlugin).Wrapper.LoginToSpotify(); } } diff --git a/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs b/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs index fbda683..289abd0 100644 --- a/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs +++ b/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs @@ -4,60 +4,24 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; using SpotifyAPI.Web.Enums; - using SpotifyAPI.Web.Models; - + internal class ChangeRepeatStateCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - private RepeatState _repeatState; - - public ChangeRepeatStateCommand() - : base( - "Change Repeat State", - "Change Repeat State description", - "Playback") + public ChangeRepeatStateCommand() : base("Change Repeat State", "Change Repeat State description", "Playback") { } protected override void RunCommand(String actionParameter) { - try - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - switch (playback.RepeatState) - { - case RepeatState.Off: - this._repeatState = RepeatState.Context; - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.ChangeRepeatState, this._repeatState); - break; - - case RepeatState.Context: - this._repeatState = RepeatState.Track; - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.ChangeRepeatState, this._repeatState); - break; - - case RepeatState.Track: - this._repeatState = RepeatState.Off; - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.ChangeRepeatState, this._repeatState); - break; - - default: - // Set plugin status and message - this.SpotifyPremiumPlugin.CheckStatusCode(System.Net.HttpStatusCode.NotFound, "Not able to change repeat state (check device etc.)"); - break; - } - } - catch (Exception e) - { - Tracer.Trace($"Spotify ChangeRepeatStateCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.ChangeRepeatState(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { String icon; - switch (this._repeatState) + switch (this.SpotifyPremiumPlugin.Wrapper.CachedRepeatState) { case RepeatState.Off: icon = "Loupedeck.SpotifyPremiumPlugin.Icons.Width80.RepeatOff.png"; @@ -80,14 +44,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage(icon); return bitmapImage; } - - public ErrorResponse ChangeRepeatState(RepeatState repeatState) - { - var response = this.SpotifyPremiumPlugin.Api.SetRepeatMode(repeatState, this.SpotifyPremiumPlugin.CurrentDeviceId); - - this.ActionImageChanged(); - - return response; - } } } diff --git a/src/Win/Commands/Playback/NextTrackCommand.cs b/src/Win/Commands/Playback/NextTrackCommand.cs index 9dd1bbd..a47f796 100644 --- a/src/Win/Commands/Playback/NextTrackCommand.cs +++ b/src/Win/Commands/Playback/NextTrackCommand.cs @@ -3,30 +3,18 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class NextTrackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public NextTrackCommand() - : base( - "Next Track", - "Next Track description", - "Playback") + public NextTrackCommand() : base("Next Track", "Next Track description", "Playback") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SkipPlaybackToNext); - } - catch (Exception e) - { - Tracer.Trace($"Spotify NextTrackCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToNext(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) @@ -34,7 +22,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.NextTrack.png"); return bitmapImage; } - - public ErrorResponse SkipPlaybackToNext() => this.SpotifyPremiumPlugin.Api.SkipPlaybackToNext(this.SpotifyPremiumPlugin.CurrentDeviceId); } } diff --git a/src/Win/Commands/Playback/PreviousTrackCommand.cs b/src/Win/Commands/Playback/PreviousTrackCommand.cs index 370516d..445dedf 100644 --- a/src/Win/Commands/Playback/PreviousTrackCommand.cs +++ b/src/Win/Commands/Playback/PreviousTrackCommand.cs @@ -3,30 +3,18 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class PreviousTrackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public PreviousTrackCommand() - : base( - "Previous Track", - "Previous Track description", - "Playback") + public PreviousTrackCommand() : base("Previous Track", "Previous Track description", "Playback") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SkipPlaybackToPrevious); - } - catch (Exception e) - { - Tracer.Trace($"Spotify PreviousTrackCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToPrevious(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) @@ -34,7 +22,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.PreviousTrack.png"); return bitmapImage; } - - public ErrorResponse SkipPlaybackToPrevious() => this.SpotifyPremiumPlugin.Api.SkipPlaybackToPrevious(this.SpotifyPremiumPlugin.CurrentDeviceId); } } diff --git a/src/Win/Commands/Playback/ShufflePlayCommand.cs b/src/Win/Commands/Playback/ShufflePlayCommand.cs index 137e173..9b21c1c 100644 --- a/src/Win/Commands/Playback/ShufflePlayCommand.cs +++ b/src/Win/Commands/Playback/ShufflePlayCommand.cs @@ -3,50 +3,25 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class ShufflePlayCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - private Boolean _shuffleState; - - public ShufflePlayCommand() - : base( - "Shuffle Play", - "Shuffle Play description", - "Playback") + public ShufflePlayCommand() : base( "Shuffle Play", "Shuffle Play description", "Playback") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.ShufflePlay); - } - catch (Exception e) - { - Tracer.Trace($"Spotify ShufflePlayCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.ShufflePlay(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { - return this._shuffleState ? + return this.SpotifyPremiumPlugin.Wrapper.CachedShuffleState ? EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.Shuffle.png") : EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.ShuffleOff.png"); } - - public ErrorResponse ShufflePlay() - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - this._shuffleState = !playback.ShuffleState; - var response = this.SpotifyPremiumPlugin.Api.SetShuffle(this._shuffleState, this.SpotifyPremiumPlugin.CurrentDeviceId); - - this.ActionImageChanged(); - - return response; - } } } diff --git a/src/Win/Commands/Playback/TogglePlaybackCommand.cs b/src/Win/Commands/Playback/TogglePlaybackCommand.cs index faa4b7d..a7b77f0 100644 --- a/src/Win/Commands/Playback/TogglePlaybackCommand.cs +++ b/src/Win/Commands/Playback/TogglePlaybackCommand.cs @@ -3,51 +3,25 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class TogglePlaybackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - private Boolean _isPlaying = true; - - public TogglePlaybackCommand() - : base( - "Toggle Playback", - "Toggles audio playback", - "Playback") + public TogglePlaybackCommand() : base("Toggle Playback", "Toggles audio playback", "Playback") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.TogglePlayback); - } - catch (Exception e) - { - Tracer.Trace($"Spotify TogglePlayback action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { - return this._isPlaying ? + return this.SpotifyPremiumPlugin.Wrapper.CachedPlayingState ? EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.Play.png") : EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.Pause.png"); } - - public ErrorResponse TogglePlayback() - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - this._isPlaying = playback.IsPlaying; - - this.ActionImageChanged(); - - return playback.IsPlaying - ? this.SpotifyPremiumPlugin.Api.PausePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId) - : this.SpotifyPremiumPlugin.Api.ResumePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId, String.Empty, null, String.Empty, 0); - } } } diff --git a/src/Win/Commands/ToggleLikeCommand.cs b/src/Win/Commands/ToggleLikeCommand.cs index b049b59..777877c 100644 --- a/src/Win/Commands/ToggleLikeCommand.cs +++ b/src/Win/Commands/ToggleLikeCommand.cs @@ -3,68 +3,23 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using System.Collections.Generic; - using System.Linq; internal class ToggleLikeCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - private Boolean _isLiked = true; - - public ToggleLikeCommand() - : base( - "Toggle Like", - "Toggle Like", - "Others") + public ToggleLikeCommand() : base("Toggle Like", "Toggle Like", "Others") { } protected override void RunCommand(String actionParameter) { - try - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - var trackId = playback.Item?.Id; - if (String.IsNullOrEmpty(trackId)) - { - // Set plugin status and message - this.SpotifyPremiumPlugin.CheckStatusCode(System.Net.HttpStatusCode.NotFound, "No track"); - return; - } - - var trackItemId = new List { trackId }; - var tracksExist = this.SpotifyPremiumPlugin.Api.CheckSavedTracks(trackItemId); - if (tracksExist.List == null && tracksExist.Error != null) - { - // Set plugin status and message - this.SpotifyPremiumPlugin.CheckStatusCode(System.Net.HttpStatusCode.NotFound, "No track list"); - return; - } - - if (tracksExist.List.Any() && tracksExist.List.FirstOrDefault() == false) - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SpotifyPremiumPlugin.Api.SaveTrack, trackId); - this._isLiked = true; - this.ActionImageChanged(); - } - else - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SpotifyPremiumPlugin.Api.RemoveSavedTracks, trackItemId); - this._isLiked = false; - - this.ActionImageChanged(); - } - } - catch (Exception e) - { - Tracer.Trace($"Spotify Toggle Like action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.ToggleLike(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { - return this._isLiked ? + return this.SpotifyPremiumPlugin.Wrapper.CachedLikeState ? EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.SongLike.png") : EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.SongDislike.png"); } diff --git a/src/Win/Commands/Volume/MuteCommand.cs b/src/Win/Commands/Volume/MuteCommand.cs index bd7ad26..dcfc4d3 100644 --- a/src/Win/Commands/Volume/MuteCommand.cs +++ b/src/Win/Commands/Volume/MuteCommand.cs @@ -3,30 +3,18 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class MuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public MuteCommand() - : base( - "Mute", - "Mute description", - "Spotify Volume") + public MuteCommand() : base("Mute", "Mute description", "Spotify Volume") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.Mute); - } - catch (Exception e) - { - Tracer.Trace($"Spotify MuteCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.Mute(); } protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) @@ -34,18 +22,5 @@ protected override BitmapImage GetCommandImage(String actionParameter, PluginIma var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.MuteVolume.png"); return bitmapImage; } - - public ErrorResponse Mute() - { - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - if (playback?.Device != null) - { - this.SpotifyPremiumPlugin.PreviousVolume = playback.Device.VolumePercent; - } - - var result = this.SpotifyPremiumPlugin.Api.SetVolume(0, this.SpotifyPremiumPlugin.CurrentDeviceId); - - return result; - } } } diff --git a/src/Win/Commands/Volume/ToggleMuteCommand.cs b/src/Win/Commands/Volume/ToggleMuteCommand.cs index 8345673..fae433f 100644 --- a/src/Win/Commands/Volume/ToggleMuteCommand.cs +++ b/src/Win/Commands/Volume/ToggleMuteCommand.cs @@ -3,70 +3,26 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class ToggleMuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - private Boolean _mute; - - public ToggleMuteCommand() - : base( - "Toggle Mute", - "Toggles audio mute state", - "Spotify Volume") + public ToggleMuteCommand() : base("Toggle Mute", "Toggles audio mute state", "Spotify Volume") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.ToggleMute); - } - catch (Exception e) - { - Tracer.Trace($"Spotify ToggleMuteCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.ToggleMute(); + this.ActionImageChanged(); } - protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { - return this._mute ? + return this.SpotifyPremiumPlugin.Wrapper.CachedMuteState ? EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.Volume.png") : EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.MuteVolume.png"); } - - public ErrorResponse ToggleMute() - { - this.ActionImageChanged(); - - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - return playback?.Device.VolumePercent != 0 ? this.Mute() : this.Unmute(); - } - - public ErrorResponse Unmute() - { - this._mute = false; - var unmuteVolume = this.SpotifyPremiumPlugin.PreviousVolume != 0 ? this.SpotifyPremiumPlugin.PreviousVolume : 50; - var result = this.SpotifyPremiumPlugin.Api.SetVolume(unmuteVolume, this.SpotifyPremiumPlugin.CurrentDeviceId); - return result; - } - - public ErrorResponse Mute() - { - this._mute = true; - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - if (playback?.Device != null) - { - this.SpotifyPremiumPlugin.PreviousVolume = playback.Device.VolumePercent; - } - - var result = this.SpotifyPremiumPlugin.Api.SetVolume(0, this.SpotifyPremiumPlugin.CurrentDeviceId); - - return result; - } } } diff --git a/src/Win/Commands/Volume/UnmuteCommand.cs b/src/Win/Commands/Volume/UnmuteCommand.cs index d3e9d32..360af96 100644 --- a/src/Win/Commands/Volume/UnmuteCommand.cs +++ b/src/Win/Commands/Volume/UnmuteCommand.cs @@ -3,44 +3,24 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using SpotifyAPI.Web.Models; internal class UnmuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public UnmuteCommand() - : base( - "Unmute", - "Unmute description", - "Spotify Volume") + public UnmuteCommand() : base("Unmute", "Unmute description", "Spotify Volume") { } protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.Unmute); - } - catch (Exception e) - { - Tracer.Trace($"Spotify UnmuteCommand action obtain an error: ", e); - } + this.SpotifyPremiumPlugin.Wrapper.Unmute(); } - protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { var bitmapImage = EmbeddedResources.ReadImage("Loupedeck.SpotifyPremiumPlugin.Icons.Width80.Volume.png"); return bitmapImage; } - - public ErrorResponse Unmute() - { - var unmuteVolume = this.SpotifyPremiumPlugin.PreviousVolume != 0 ? this.SpotifyPremiumPlugin.PreviousVolume : 50; - var result = this.SpotifyPremiumPlugin.Api.SetVolume(unmuteVolume, this.SpotifyPremiumPlugin.CurrentDeviceId); - return result; - } } } diff --git a/src/Win/ParameterizedCommands/DirectVolumeCommand.cs b/src/Win/ParameterizedCommands/DirectVolumeCommand.cs index c4dab53..3e968ab 100644 --- a/src/Win/ParameterizedCommands/DirectVolumeCommand.cs +++ b/src/Win/ParameterizedCommands/DirectVolumeCommand.cs @@ -3,14 +3,12 @@ namespace Loupedeck.SpotifyPremiumPlugin.ParameterizedCommands { using System; - using SpotifyAPI.Web.Models; internal class DirectVolumeCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public DirectVolumeCommand() - : base() + public DirectVolumeCommand() : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Direct Volume"; // so this will be shown as "group name" for parameterized commands @@ -21,36 +19,7 @@ public DirectVolumeCommand() protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SetVolume, actionParameter); - } - catch (Exception e) - { - Tracer.Trace($"Spotify DirectVolumeCommand action obtain an error: ", e); - } - } - - public ErrorResponse SetVolume(String percents) - { - var isConverted = Int32.TryParse(percents, out var volume); - return isConverted ? this.SetVolume(volume) : null; - } - - public ErrorResponse SetVolume(Int32 percents) - { - if (percents > 100) - { - percents = 100; - } - - if (percents < 0) - { - percents = 0; - } - - var response = this.SpotifyPremiumPlugin.Api.SetVolume(percents, this.SpotifyPremiumPlugin.CurrentDeviceId); - return response; + this.SpotifyPremiumPlugin.Wrapper.SetVolume(actionParameter); } } } diff --git a/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs b/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs index 3198823..3d421be 100644 --- a/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs +++ b/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs @@ -4,14 +4,12 @@ namespace Loupedeck.SpotifyPremiumPlugin.ParameterizedCommands { using System; using System.Linq; - using SpotifyAPI.Web.Models; internal class SaveToPlaylistCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public SaveToPlaylistCommand() - : base() + public SaveToPlaylistCommand() : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Save To Playlist"; // so this will be shown as "group name" for parameterized commands @@ -22,33 +20,13 @@ public SaveToPlaylistCommand() protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.SaveToPlaylist, actionParameter); - } - catch (Exception e) - { - Tracer.Trace($"Spotify SaveToPlaylistCommand action obtain an error: ", e); - } - } - - public ErrorResponse SaveToPlaylist(String playlistId) - { - var idWithUri = true; - if (idWithUri) - { - playlistId = playlistId.Replace("spotify:playlist:", String.Empty); - } - - var playback = this.SpotifyPremiumPlugin.Api.GetPlayback(); - var currentTrackUri = playback.Item.Uri; - return this.SpotifyPremiumPlugin.Api.AddPlaylistTrack(playlistId, currentTrackUri); + this.SpotifyPremiumPlugin.Wrapper.SaveToPlaylist(actionParameter); } protected override PluginActionParameter[] GetParameters() { - var playlists = this.SpotifyPremiumPlugin.GetAllPlaylists(); - return playlists?.Items + var playlists = this.SpotifyPremiumPlugin.Wrapper.GetAllPlaylists(); + return playlists? .Select(x => new PluginActionParameter(x.Uri, x.Name, String.Empty)) .ToArray(); } diff --git a/src/Win/ParameterizedCommands/StartPlaylistCommand.cs b/src/Win/ParameterizedCommands/StartPlaylistCommand.cs index 88e6598..328149e 100644 --- a/src/Win/ParameterizedCommands/StartPlaylistCommand.cs +++ b/src/Win/ParameterizedCommands/StartPlaylistCommand.cs @@ -4,14 +4,12 @@ namespace Loupedeck.SpotifyPremiumPlugin.ParameterizedCommands { using System; using System.Linq; - using SpotifyAPI.Web.Models; internal class StartPlaylistCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public StartPlaylistCommand() - : base() + public StartPlaylistCommand() : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Start Playlist"; // so this will be shown as "group name" for parameterized commands @@ -22,25 +20,13 @@ public StartPlaylistCommand() protected override void RunCommand(String actionParameter) { - try - { - this.SpotifyPremiumPlugin.CheckSpotifyResponse(this.StartPlaylist, actionParameter); - } - catch (Exception e) - { - Tracer.Trace($"Spotify StartPlaylistCommand action obtain an error: ", e); - } - } - - public ErrorResponse StartPlaylist(String contextUri) - { - return this.SpotifyPremiumPlugin.Api.ResumePlayback(this.SpotifyPremiumPlugin.CurrentDeviceId, contextUri, null, String.Empty); + this.SpotifyPremiumPlugin.Wrapper.StartPlaylist(actionParameter); } protected override PluginActionParameter[] GetParameters() { - var playlists = this.SpotifyPremiumPlugin.GetAllPlaylists(); - return playlists?.Items + var playlists = this.SpotifyPremiumPlugin.Wrapper.GetAllPlaylists(); + return playlists? .Select(x => new PluginActionParameter(x.Uri, x.Name, String.Empty)) .ToArray(); } diff --git a/src/Win/SpotifyPremiumPlugin.Installer.cs b/src/Win/SpotifyPremiumPlugin.Installer.cs index d4db094..e14d85d 100644 --- a/src/Win/SpotifyPremiumPlugin.Installer.cs +++ b/src/Win/SpotifyPremiumPlugin.Installer.cs @@ -3,11 +3,10 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; + using System.IO; public partial class SpotifyPremiumPlugin : Plugin { - public String ClientConfigurationFilePath => System.IO.Path.Combine(this.GetPluginDataDirectory(), "spotify-client.txt"); - public override Boolean Install() { // Here we ensure the plugin data directory is there. @@ -20,12 +19,11 @@ public override Boolean Install() } // Now we put a template configuration file from resources - var filePath = System.IO.Path.Combine(pluginDataDirectory, this.ClientConfigurationFilePath); - - using (var streamWriter = new System.IO.StreamWriter(filePath)) + var filePath = SpotifyWrapper.GetClientConfigurationFilePath(pluginDataDirectory); + using (var streamWriter = new StreamWriter(filePath)) { // Write data - this.Assembly.ExtractFile("spotify-client-template.txt", this.ClientConfigurationFilePath); + this.Assembly.ExtractFile("spotify-client-template.txt", filePath); } return true; diff --git a/src/Win/SpotifyPremiumPlugin.Statuses.cs b/src/Win/SpotifyPremiumPlugin.Statuses.cs new file mode 100644 index 0000000..8e5d81b --- /dev/null +++ b/src/Win/SpotifyPremiumPlugin.Statuses.cs @@ -0,0 +1,39 @@ +// Copyright (c) Loupedeck. All rights reserved. + +namespace Loupedeck.SpotifyPremiumPlugin +{ + using System; + using Loupedeck; + + /// + /// Plugin: handle wrapper status and switch plugin status + /// + public partial class SpotifyPremiumPlugin : Plugin + { + internal void WrapperStatusParser(Object o, WrapperChangedEventArgs e) + { + this.OnPluginStatusChanged(this.GetPluginStatus(e.WrapperStatus), e.Message, e.SupportUrl); + } + + private PluginStatus GetPluginStatus(WrapperStatus wrapperStatus) + { + switch (wrapperStatus) + { + case WrapperStatus.Unknown: + return Loupedeck.PluginStatus.Unknown; + + case WrapperStatus.Normal: + return Loupedeck.PluginStatus.Normal; + + case WrapperStatus.Warning: + return Loupedeck.PluginStatus.Warning; + + case WrapperStatus.Error: + return Loupedeck.PluginStatus.Error; + + default: + return Loupedeck.PluginStatus.Unknown; + } + } + } +} diff --git a/src/Win/SpotifyPremiumPlugin.cs b/src/Win/SpotifyPremiumPlugin.cs index 4de6905..294bb7b 100644 --- a/src/Win/SpotifyPremiumPlugin.cs +++ b/src/Win/SpotifyPremiumPlugin.cs @@ -16,19 +16,19 @@ public partial class SpotifyPremiumPlugin : Plugin // This plugin does not require an application (i.e. Spotify application installed on pc). public override Boolean HasNoApplication => true; + internal SpotifyWrapper Wrapper { get; private set; } + public override void Load() { this.LoadPluginIcons(); - // Set everything ready and connect to Spotify API - this.SpotifyConfiguration(); - - // Get current (active) device id from internal cache - this.CurrentDeviceId = this.GetCachedDeviceID(); + this.Wrapper = new SpotifyWrapper(this.GetPluginDataDirectory()); + this.Wrapper.WrapperStatusChanged += this.WrapperStatusParser; } public override void Unload() { + this.Wrapper.WrapperStatusChanged -= this.WrapperStatusParser; } public override void RunCommand(String commandName, String parameter) diff --git a/src/Win/SpotifyPremiumPlugin.csproj b/src/Win/SpotifyPremiumPlugin.csproj index eaf7ed4..ef43047 100644 --- a/src/Win/SpotifyPremiumPlugin.csproj +++ b/src/Win/SpotifyPremiumPlugin.csproj @@ -75,9 +75,7 @@ - - - + @@ -90,6 +88,11 @@ + + + + + diff --git a/src/Win/SpotifyPremiumPlugin.Api.cs b/src/Win/Wrapper/SpotifyWrapper.Authentification.cs similarity index 61% rename from src/Win/SpotifyPremiumPlugin.Api.cs rename to src/Win/Wrapper/SpotifyWrapper.Authentification.cs index e73ce4d..41ca001 100644 --- a/src/Win/SpotifyPremiumPlugin.Api.cs +++ b/src/Win/Wrapper/SpotifyWrapper.Authentification.cs @@ -1,6 +1,4 @@ -// Copyright (c) Loupedeck. All rights reserved. - -namespace Loupedeck.SpotifyPremiumPlugin +namespace Loupedeck.SpotifyPremiumPlugin { using System; using System.Collections.Generic; @@ -8,21 +6,16 @@ namespace Loupedeck.SpotifyPremiumPlugin using System.Linq; using System.Security.Cryptography; using System.Text; - using Loupedeck; + using Newtonsoft.Json; + using SpotifyAPI.Web; using SpotifyAPI.Web.Auth; + using SpotifyAPI.Web.Enums; using SpotifyAPI.Web.Models; - /// - /// Plugin Spotify API configuration and authorization - /// - public partial class SpotifyPremiumPlugin : Plugin + public partial class SpotifyWrapper { - private const String _clientId = "ClientId"; - private const String _clientSecret = "ClientSecret"; - private const String _tcpPorts = "TcpPorts"; - private static Token token = new Token(); private static AuthorizationCodeAuth auth; private static String spotifyTokenFilePath; @@ -31,13 +24,7 @@ public partial class SpotifyPremiumPlugin : Plugin private List tcpPorts = new List(); - internal SpotifyWebAPI Api { get; set; } - - internal String CurrentDeviceId { get; set; } - - internal Int32 PreviousVolume { get; set; } - - public Boolean SpotifyApiConnectionOk() + public Boolean SpotifyApiConnected() { if (this.Api == null) { @@ -66,15 +53,15 @@ private Boolean ReadConfigurationFile() Directory.CreateDirectory(Path.GetDirectoryName(spotifyClientConfigurationFile)); // Create the file - using (FileStream fs = File.Create(spotifyClientConfigurationFile)) + using (FileStream fileStream = File.Create(spotifyClientConfigurationFile)) { var info = new UTF8Encoding(true).GetBytes($"{_clientId}{Environment.NewLine}{_clientSecret}{Environment.NewLine}{_tcpPorts}"); // Add parameter titles to file. - fs.Write(info, 0, info.Length); + fileStream.Write(info, 0, info.Length); } - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, $"Spotify configuration is missing. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); + this.OnWrapperStatusChanged(WrapperStatus.Error, $"Spotify configuration is missing. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); return false; } @@ -88,7 +75,7 @@ private Boolean ReadConfigurationFile() _spotifyConfiguration.ContainsKey(_clientSecret) && _spotifyConfiguration.ContainsKey(_tcpPorts))) { - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, $"Check Spotify API app 'ClientId' / 'ClientSecret' and 'TcpPorts' in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); + this.OnWrapperStatusChanged(WrapperStatus.Error, $"Check Spotify API app 'ClientId' / 'ClientSecret' and 'TcpPorts' in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); return false; } @@ -102,14 +89,14 @@ private Boolean ReadConfigurationFile() if (this.tcpPorts.Count == 0) { - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, $"Check 'TcpPorts' values in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); + this.OnWrapperStatusChanged(WrapperStatus.Error, $"Check 'TcpPorts' values in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); return false; } return true; } - private void SpotifyConfiguration() + public void ReadSpotifyConfiguration() { if (!this.ReadConfigurationFile()) { @@ -118,7 +105,7 @@ private void SpotifyConfiguration() // Is there a token available token = null; - spotifyTokenFilePath = System.IO.Path.Combine(this.GetPluginDataDirectory(), "spotify.json"); + spotifyTokenFilePath = Path.Combine(this._cacheDirectory, "spotify.json"); if (File.Exists(spotifyTokenFilePath)) { token = this.ReadTokenFromLocalFile(); @@ -133,9 +120,9 @@ private void SpotifyConfiguration() AccessToken = token.AccessToken, TokenType = "Bearer", }; - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Normal, "Connected", null); + this.OnWrapperStatusChanged(WrapperStatus.Normal, "Connected", null); } - else if (token != null && !String.IsNullOrEmpty(token.RefreshToken)) + else if (!String.IsNullOrEmpty(token?.RefreshToken)) { // Get a new access token based on the Refresh Token this.RefreshToken(token.RefreshToken); @@ -143,8 +130,8 @@ private void SpotifyConfiguration() else { // User has to login from Loupedeck application Plugin UI: Login - Login to Spotify. See LoginToSpotifyCommand.cs - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, "Login to Spotify as Premium user", null); - } + this.OnWrapperStatusChanged(WrapperStatus.Error, "Login to Spotify as Premium user", null); + } } private Token ReadTokenFromLocalFile() @@ -153,7 +140,7 @@ private Token ReadTokenFromLocalFile() var localToken = JsonConvert.DeserializeObject(json); // Decrypt refresh token - if (localToken != null && !String.IsNullOrEmpty(localToken.RefreshToken)) + if (!String.IsNullOrEmpty(localToken?.RefreshToken)) { var secret = Convert.FromBase64String(localToken.RefreshToken); var plain = ProtectedData.Unprotect(secret, null, DataProtectionScope.CurrentUser); @@ -184,7 +171,7 @@ public void RefreshToken(String refreshToken) if (!String.IsNullOrWhiteSpace(newToken.Error)) { Tracer.Error($"Error happened during refreshing Spotify account token: {newToken.Error}: {newToken.ErrorDescription}"); - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, "Failed getting access to Spotify. Login as Premium user", null); + this.OnWrapperStatusChanged(WrapperStatus.Error, "Failed getting access to Spotify. Login as Premium user", null); } if (this.Api == null) @@ -196,64 +183,12 @@ public void RefreshToken(String refreshToken) }; } - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Normal, "Connected", null); + this.OnWrapperStatusChanged(WrapperStatus.Normal, "Connected", null); this.Api.AccessToken = newToken.AccessToken; this.SaveTokenToLocalFile(newToken, refreshToken); } - private PrivateProfile _privateProfile; - - private Paging GetUserPlaylists(Int32 offset = 0) - { - if (this.Api != null) - { - try - { - if (this._privateProfile == null) - { - this._privateProfile = this.Api.GetPrivateProfile(); - } - - var profileId = this._privateProfile?.Id; - if (!String.IsNullOrEmpty(profileId)) - { - var playlists = this.Api.GetUserPlaylists(profileId, 50, offset); - if (playlists?.Items != null && playlists.Items.Any()) - { - return playlists; - } - } - } - catch (Exception e) - { - Tracer.Trace(e, "Spotify playlists obtaining error"); - } - } - - return new Paging - { - Items = new List(), - }; - } - - public Paging GetAllPlaylists() - { - Paging playlists = this.GetUserPlaylists(); - if (playlists != null) - { - var totalPlaylistsCount = playlists.Total; - while (playlists.Items.Count < totalPlaylistsCount) - { - playlists.Items.AddRange(this.GetUserPlaylists(playlists.Items.Count).Items); - } - - return playlists; - } - - return null; - } - public void LoginToSpotify() { auth = this.GetAuthorizationCodeAuth(out var timeout); @@ -283,7 +218,7 @@ private async void Auth_AuthReceived(Object sender, AuthorizationCode payload) TokenType = previousToken.TokenType, }; - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Normal, null, null); + this.OnWrapperStatusChanged(WrapperStatus.Normal, null, null); this.SaveTokenToLocalFile(previousToken, previousToken.RefreshToken); } @@ -304,26 +239,26 @@ public AuthorizationCodeAuth GetAuthorizationCodeAuth(out Int32 timeout) } var scopes = - SpotifyAPI.Web.Enums.Scope.PlaylistReadPrivate | - SpotifyAPI.Web.Enums.Scope.Streaming | - SpotifyAPI.Web.Enums.Scope.UserReadCurrentlyPlaying | - SpotifyAPI.Web.Enums.Scope.UserReadPlaybackState | - SpotifyAPI.Web.Enums.Scope.UserLibraryRead | - SpotifyAPI.Web.Enums.Scope.UserLibraryModify | - SpotifyAPI.Web.Enums.Scope.UserReadPrivate | - SpotifyAPI.Web.Enums.Scope.UserModifyPlaybackState | - SpotifyAPI.Web.Enums.Scope.PlaylistReadCollaborative | - SpotifyAPI.Web.Enums.Scope.PlaylistModifyPublic | - SpotifyAPI.Web.Enums.Scope.PlaylistModifyPrivate | - SpotifyAPI.Web.Enums.Scope.PlaylistReadPrivate | - SpotifyAPI.Web.Enums.Scope.UserReadEmail; + Scope.PlaylistReadPrivate | + Scope.Streaming | + Scope.UserReadCurrentlyPlaying | + Scope.UserReadPlaybackState | + Scope.UserLibraryRead | + Scope.UserLibraryModify | + Scope.UserReadPrivate | + Scope.UserModifyPlaybackState | + Scope.PlaylistReadCollaborative | + Scope.PlaylistModifyPublic | + Scope.PlaylistModifyPrivate | + Scope.PlaylistReadPrivate | + Scope.UserReadEmail; return !this.ReadConfigurationFile() ? null : new AuthorizationCodeAuth( - _spotifyConfiguration[_clientId], // Spotify API Client Id + _spotifyConfiguration[_clientId], // Spotify API Client Id _spotifyConfiguration[_clientSecret], // Spotify API Client Secret - $"http://localhost:{selectedPort}", // selectedPort must correspond to that on the Spotify developers's configuration! + $"http://localhost:{selectedPort}", // selectedPort must correspond to that on the Spotify developers's configuration! $"http://localhost:{selectedPort}", scopes); } diff --git a/src/Win/SpotifyPremiumPlugin.DevicesSelector.cs b/src/Win/Wrapper/SpotifyWrapper.Cache.cs similarity index 71% rename from src/Win/SpotifyPremiumPlugin.DevicesSelector.cs rename to src/Win/Wrapper/SpotifyWrapper.Cache.cs index 91f0348..34962e3 100644 --- a/src/Win/SpotifyPremiumPlugin.DevicesSelector.cs +++ b/src/Win/Wrapper/SpotifyWrapper.Cache.cs @@ -1,25 +1,27 @@ -// Copyright (c) Loupedeck. All rights reserved. - -namespace Loupedeck.SpotifyPremiumPlugin +namespace Loupedeck.SpotifyPremiumPlugin { using System; using System.IO; - - /// - /// Plugin: Store Spotify devices locally - /// - public partial class SpotifyPremiumPlugin : Plugin + + public partial class SpotifyWrapper { - private readonly String _deviceCacheFileName = "CachedDevice.txt"; + private readonly String _cacheDirectory; + + private readonly String _deviceCacheFileName = "CachedDevice"; private readonly Object _locker = new Object(); - private String GetCacheFilePath(String fileName) => Path.Combine(this.GetPluginDataDirectory(), "Cache", fileName); + public static String GetClientConfigurationFilePath(String cacheDirectory) => Path.Combine(cacheDirectory, ClientConfigurationFileName); + + public static String ClientConfigurationFileName => "spotify-client.txt"; + + public String ClientConfigurationFilePath => Path.Combine(this._cacheDirectory, ClientConfigurationFileName); + + private String GetCacheFilePath(String fileName) => Path.Combine(this._cacheDirectory, fileName); public void SaveDeviceToCache(String deviceId) { - var cacheDirectory = Path.Combine(this.GetPluginDataDirectory(), "Cache"); - + var cacheDirectory = this._cacheDirectory; if (!Directory.Exists(cacheDirectory)) { try diff --git a/src/Win/Wrapper/SpotifyWrapper.Events.cs b/src/Win/Wrapper/SpotifyWrapper.Events.cs new file mode 100644 index 0000000..706ec8e --- /dev/null +++ b/src/Win/Wrapper/SpotifyWrapper.Events.cs @@ -0,0 +1,39 @@ +namespace Loupedeck.SpotifyPremiumPlugin +{ + using System; + + public partial class SpotifyWrapper + { + public event EventHandler WrapperStatusChanged; + + public void OnWrapperStatusChanged(WrapperStatus wrapperStatus, String message, String supportUrl) + { + var status = new WrapperChangedEventArgs(wrapperStatus, message, supportUrl); + this.WrapperStatusChanged?.Invoke(this, status); + } + } + + public class WrapperChangedEventArgs : EventArgs + { + public WrapperStatus WrapperStatus { get; set; } + + public String Message { get; set; } + + public String SupportUrl { get; set; } + + public WrapperChangedEventArgs(WrapperStatus wrapperStatus, String message, String supportUrl) + { + this.WrapperStatus = wrapperStatus; + this.Message = message; + this.SupportUrl = supportUrl; + } + } + + public enum WrapperStatus + { + Unknown = 0, + Normal = 1, + Warning = 2, + Error = 3, + } +} diff --git a/src/Win/SpotifyPremiumPlugin.ApiResponse.cs b/src/Win/Wrapper/SpotifyWrapper.Responses.cs similarity index 64% rename from src/Win/SpotifyPremiumPlugin.ApiResponse.cs rename to src/Win/Wrapper/SpotifyWrapper.Responses.cs index 9d1ff9f..24e66b4 100644 --- a/src/Win/SpotifyPremiumPlugin.ApiResponse.cs +++ b/src/Win/Wrapper/SpotifyWrapper.Responses.cs @@ -1,20 +1,17 @@ -// Copyright (c) Loupedeck. All rights reserved. - -namespace Loupedeck.SpotifyPremiumPlugin +namespace Loupedeck.SpotifyPremiumPlugin { using System; using System.Net; - using Loupedeck; + using SpotifyAPI.Web.Models; - /// - /// Plugin: Check Spotify API responses - /// - public partial class SpotifyPremiumPlugin : Plugin + public partial class SpotifyWrapper { + public WrapperStatus Status { get; set; } + public void CheckSpotifyResponse(Func apiCall, T param) { - if (!this.SpotifyApiConnectionOk()) + if (!this.SpotifyApiConnected()) { return; } @@ -26,7 +23,7 @@ public void CheckSpotifyResponse(Func apiCall, T param) public void CheckSpotifyResponse(Func apiCall) { - if (!this.SpotifyApiConnectionOk()) + if (!this.SpotifyApiConnected()) { return; } @@ -50,27 +47,27 @@ internal void CheckStatusCode(HttpStatusCode statusCode, String spotifyApiMessag case HttpStatusCode.ResetContent: case HttpStatusCode.PartialContent: - if (this.PluginStatus.Status != Loupedeck.PluginStatus.Normal) + if (this.Status != WrapperStatus.Normal) { - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Normal, null, null); + this.OnWrapperStatusChanged(WrapperStatus.Normal, null, null); } break; case HttpStatusCode.Unauthorized: // This should never happen? - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, "Login to Spotify", null); + this.OnWrapperStatusChanged(WrapperStatus.Error, "Login to Spotify", null); break; case HttpStatusCode.NotFound: // User doesn't have device set or some other Spotify related thing. User action needed. - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Warning, $"Spotify message: {spotifyApiMessage}", null); + this.OnWrapperStatusChanged(WrapperStatus.Warning, $"Spotify message: {spotifyApiMessage}", null); break; default: - if (this.PluginStatus.Status != Loupedeck.PluginStatus.Error) + if (this.Status != WrapperStatus.Error) { - this.OnPluginStatusChanged(Loupedeck.PluginStatus.Error, spotifyApiMessage, null); + this.OnWrapperStatusChanged(WrapperStatus.Error, spotifyApiMessage, null); } break; diff --git a/src/Win/Wrapper/SpotifyWrapper.cs b/src/Win/Wrapper/SpotifyWrapper.cs new file mode 100644 index 0000000..75a7a0d --- /dev/null +++ b/src/Win/Wrapper/SpotifyWrapper.cs @@ -0,0 +1,400 @@ +namespace Loupedeck.SpotifyPremiumPlugin +{ + using System; + using System.Net; + using System.Linq; + using System.Timers; + using System.Collections.Generic; + + using SpotifyAPI.Web; + using SpotifyAPI.Web.Enums; + using SpotifyAPI.Web.Models; + + public partial class SpotifyWrapper : IDisposable + { + private const String _clientId = "ClientId"; + private const String _clientSecret = "ClientSecret"; + private const String _tcpPorts = "TcpPorts"; + + private PrivateProfile _privateProfile; + + //private SpotifyPremiumPlugin Plugin { get; } + + internal SpotifyWebAPI Api { get; set; } + + public RepeatState CachedRepeatState { get; private set; } + + public Boolean CachedShuffleState { get; private set; } + + public Boolean CachedPlayingState { get; private set; } + + public Boolean CachedMuteState { get; private set; } + + public Boolean CachedLikeState { get; private set; } + + internal String CurrentDeviceId + { + get => this._currentDeviceId; + set + { + this._currentDeviceId = value; + this.SaveDeviceToCache(value); + } + } + + public SpotifyWrapper(String cacheDirectory) + { + this._cacheDirectory = cacheDirectory; + this.ReadSpotifyConfiguration(); + this.CurrentDeviceId = this.GetCachedDeviceID(); + } + + public void Dispose() + { + this.Api?.Dispose(); + } + + #region Volume + + /// + /// This is our most recently known Volume. Used when muting to remember the previous volume. Used for dials when + /// incrementing rapidly. + /// + internal Int32 PreviousVolume { get; set; } + + public void SetVolume(String volumeString) + { + if (Int32.TryParse(volumeString, out var volume)) + { + this.SetVolume(volume); + } + } + + public void SetVolume(Int32 percents) + { + if (percents > 100) + { + percents = 100; + } + + if (percents < 0) + { + percents = 0; + } + + this.InitVolumeBlockedTimer(); + + this.PreviousVolume = percents; + + ErrorResponse Func() => this.Api.SetVolume(percents, this.CurrentDeviceId); + this.CheckSpotifyResponse(Func); + } + + private Boolean _volumeCallsBlocked; + private Timer _volumeBlockedTimer; + private String _currentDeviceId; + + public void AdjustVolume(Int32 ticks) + { + var modifiedVolume = 0; + + // Because this can be called in rapid succession with a dial turn, and it take Spotify a bit of time to register + // volume changes round trip to the api, we don't want to Get the current Volume from Spotify if we've very recently set it + // a few times. Thus, we have a 2 second buffer after the last volume set, before we try to get the actual current volume + // from Spotify. + if (this._volumeCallsBlocked) + { + modifiedVolume = this.PreviousVolume + ticks; + } + else + { + var playback = this.Api.GetPlayback(); + if (playback?.Device == null) + { + // Set plugin status and message + this.CheckStatusCode(HttpStatusCode.NotFound, "Cannot adjust volume, no device"); + return; + } + else + { + modifiedVolume = playback.Device.VolumePercent + ticks; + } + } + + this.SetVolume(modifiedVolume); + } + + private void InitVolumeBlockedTimer() + { + if (this._volumeBlockedTimer == null) + { + this._volumeBlockedTimer = new Timer(2000); + this._volumeBlockedTimer.Elapsed += this.VolumeBlockExpired; + } + + this._volumeCallsBlocked = true; + if (this._volumeBlockedTimer.Enabled) + { + this._volumeBlockedTimer.Stop(); + } + + this._volumeBlockedTimer.Start(); + } + + private void VolumeBlockExpired(Object o, ElapsedEventArgs e) => this._volumeCallsBlocked = false; + + public void Mute() + { + var playback = this.Api.GetPlayback(); + + if (playback?.Device?.VolumePercent > 0) + { + this.PreviousVolume = playback.Device.VolumePercent; + } + + ErrorResponse Func() => this.Api.SetVolume(0, this.CurrentDeviceId); + this.CheckSpotifyResponse(Func); + } + + public void Unmute() + { + var unmuteVolume = this.PreviousVolume != 0 ? this.PreviousVolume : 50; + + ErrorResponse Func() => this.Api.SetVolume(unmuteVolume, this.CurrentDeviceId); + this.CheckSpotifyResponse(Func); + } + + /// + /// Toggle current Mute setting + /// + /// true if muted after this call + public Boolean ToggleMute() + { + var playback = this.Api.GetPlayback(); + + if (playback?.Device.VolumePercent != 0) + { + this.Mute(); + return this.CachedMuteState = true; + } + else + { + this.Unmute(); + return this.CachedMuteState = false; + } + } + + #endregion Volume + + #region Playback + + public const String _activeDevice = "activedevice"; + + public void TransferPlayback(String commandParameter) + { + if (commandParameter == _activeDevice) + { + commandParameter = String.Empty; + } + + this.CurrentDeviceId = commandParameter; + + ErrorResponse Func() => this.Api.TransferPlayback(this.CurrentDeviceId, true); + this.CheckSpotifyResponse(Func); + } + + public Boolean TogglePlayback() + { + var playback = this.Api.GetPlayback(); + + if (playback.IsPlaying) + { + this.CheckSpotifyResponse(this.Api.PausePlayback, this.CurrentDeviceId); + } + else + { + ErrorResponse Func() => this.Api.ResumePlayback(this.CurrentDeviceId, String.Empty, null, String.Empty, 0); + this.CheckSpotifyResponse(Func); + } + + return this.CachedPlayingState = !playback.IsPlaying; // presume we switched it at this point. + } + + public void SkipPlaybackToNext() => this.CheckSpotifyResponse(this.Api.SkipPlaybackToNext, this.CurrentDeviceId); + + public void SkipPlaybackToPrevious() => this.CheckSpotifyResponse(this.Api.SkipPlaybackToPrevious, this.CurrentDeviceId); + + public RepeatState ChangeRepeatState() + { + var playback = this.Api.GetPlayback(); + + RepeatState newRepeatState = RepeatState.Off; + + switch (playback.RepeatState) + { + case RepeatState.Off: + newRepeatState = RepeatState.Context; + break; + + case RepeatState.Context: + newRepeatState = RepeatState.Track; + break; + + case RepeatState.Track: + newRepeatState = RepeatState.Off; + break; + + default: + // Set plugin status and message + this.CheckStatusCode(HttpStatusCode.NotFound, "Not able to change repeat state (check device etc.)"); + break; + } + + this.CachedRepeatState = newRepeatState; + + ErrorResponse Func() => this.Api.SetRepeatMode(newRepeatState, this.CurrentDeviceId); + this.CheckSpotifyResponse(Func); + + return newRepeatState; + } + + public Boolean ShufflePlay() + { + var playback = this.Api.GetPlayback(); + var shuffleState = !playback.ShuffleState; + + ErrorResponse Func() => this.Api.SetShuffle(shuffleState, this.CurrentDeviceId); + this.CheckSpotifyResponse(Func); + + this.CachedShuffleState = shuffleState; + + return shuffleState; + } + + #endregion Playback + + #region Playlists + + public void StartPlaylist(String contextUri) + { + ErrorResponse Func() => this.Api.ResumePlayback(this.CurrentDeviceId, contextUri, null, String.Empty); + this.CheckSpotifyResponse(Func); + } + + public void SaveToPlaylist(String playlistId) + { + playlistId = playlistId.Replace("spotify:playlist:", String.Empty); + + var playback = this.Api.GetPlayback(); + var currentTrackUri = playback.Item.Uri; + + ErrorResponse Func() => this.Api.AddPlaylistTrack(playlistId, currentTrackUri); + this.CheckSpotifyResponse(Func); + } + + public List GetAllPlaylists() + { + Paging playlists = this.GetUserPlaylists(); + if (playlists != null) + { + var totalPlaylistsCount = playlists.Total; + while (playlists.Items.Count < totalPlaylistsCount) + { + playlists.Items.AddRange(this.GetUserPlaylists(playlists.Items.Count).Items); + } + + return playlists.Items; + } + + return null; + } + + private Paging GetUserPlaylists(Int32 offset = 0) + { + if (this.Api != null) + { + try + { + if (this._privateProfile == null) + { + this._privateProfile = this.Api.GetPrivateProfile(); + } + + var profileId = this._privateProfile?.Id; + if (!String.IsNullOrEmpty(profileId)) + { + var playlists = this.Api.GetUserPlaylists(profileId, 50, offset); + if (playlists?.Items?.Any() == true) + { + return playlists; + } + } + } + catch (Exception e) + { + Tracer.Trace(e, "Error obtaining Spotify playlists"); + } + } + + return new Paging + { + Items = new List(), + }; + } + + #endregion Playlists + + #region Devices + + public List GetDevices() + { + var devices = this.Api?.GetDevices()?.Devices; + + if (devices?.Any() == true) + { + devices.Add(new Device { Id = _activeDevice, Name = "Active Device" }); + } + + return devices; + } + + #endregion Devices + + #region Likes + + public Boolean ToggleLike() + { + var playback = this.Api.GetPlayback(); + var trackId = playback.Item?.Id; + if (String.IsNullOrEmpty(trackId)) + { + // Set plugin status and message + this.CheckStatusCode(HttpStatusCode.NotFound, "No track"); + return this.CachedMuteState = false; + } + + var trackItemId = new List { trackId }; + var tracksExist = this.Api.CheckSavedTracks(trackItemId); + if (tracksExist.List == null && tracksExist.Error != null) + { + // Set plugin status and message + this.CheckStatusCode(HttpStatusCode.NotFound, "No track list"); + return this.CachedMuteState = false; + } + + if (tracksExist.List.Any() && tracksExist.List.FirstOrDefault() == false) + { + this.CheckSpotifyResponse(this.Api.SaveTrack, trackId); + return this.CachedMuteState = true; + } + else + { + this.CheckSpotifyResponse(this.Api.RemoveSavedTracks, trackItemId); + return this.CachedMuteState = false; + } + } + + #endregion Likes + + } +} \ No newline at end of file From 3b4b097d31f0723f6132f183b395359018d4ddec Mon Sep 17 00:00:00 2001 From: Denys Mostovsky Date: Wed, 16 Feb 2022 22:25:27 +0200 Subject: [PATCH 2/2] LDSW-3014: Added .edictorconfig and fixed styleguide --- .editorconfig => src/.editorconfig | 15 ++++ .../Playback/PlayAndNavigateAdjustment.cs | 2 +- .../Volume/SpotifyVolumeAdjustment.cs | 15 ++-- src/{Win => SpotifyPremiumPlugin}/App.config | 0 .../DeviceSelectorCommandFolder.cs | 5 +- .../Commands/LoginToSpotifyCommand.cs | 3 +- .../Playback/ChangeRepeatStateCommand.cs | 10 +-- .../Commands/Playback/NextTrackCommand.cs | 8 +- .../Commands/Playback/PreviousTrackCommand.cs | 8 +- .../Commands/Playback/ShufflePlayCommand.cs | 8 +- .../Playback/TogglePlaybackCommand.cs | 8 +- .../Commands/ToggleLikeCommand.cs | 8 +- .../Commands/Volume/MuteCommand.cs | 8 +- .../Commands/Volume/ToggleMuteCommand.cs | 3 +- .../Commands/Volume/UnmuteCommand.cs | 8 +- .../Icons/PluginIcon16x16.png | Bin .../Icons/PluginIcon256x256.png | Bin .../Icons/PluginIcon32x32.png | Bin .../Icons/PluginIcon48x48.png | Bin .../Icons/Width50/Browse.png | Bin .../Icons/Width50/Devices.png | Bin .../Icons/Width50/Home2.png | Bin .../Icons/Width50/MuteVolume.png | Bin .../Icons/Width50/NextTrack.png | Bin .../Icons/Width50/Pause.png | Bin .../Icons/Width50/Play.png | Bin .../Icons/Width50/PlayAndNavigateTracks.png | Bin .../Icons/Width50/PlayPause.png | Bin .../Icons/Width50/PlayStop.png | Bin .../Icons/Width50/Playlist.png | Bin .../Icons/Width50/PreviousTrack.png | Bin .../Icons/Width50/Radio.png | Bin .../Icons/Width50/Repeat.png | Bin .../Icons/Width50/RepeatList.png | Bin .../Icons/Width50/RepeatOff.png | Bin .../Icons/Width50/Share.png | Bin .../Icons/Width50/Shuffle.png | Bin .../Icons/Width50/ShuffleList.png | Bin .../Icons/Width50/ShuffleOff.png | Bin .../Icons/Width50/SongDislike.png | Bin .../Icons/Width50/SongLike.png | Bin .../Icons/Width50/Volume.png | Bin .../Icons/Width80/Browse.png | Bin .../Icons/Width80/Devices.png | Bin .../Icons/Width80/Home2.png | Bin .../Icons/Width80/MuteVolume.png | Bin .../Icons/Width80/NextTrack.png | Bin .../Icons/Width80/Pause.png | Bin .../Icons/Width80/Play.png | Bin .../Icons/Width80/PlayAndNavigateTracks.png | Bin .../Icons/Width80/PlayPause.png | Bin .../Icons/Width80/PlayStop.png | Bin .../Icons/Width80/Playlist.png | Bin .../Icons/Width80/PreviousTrack.png | Bin .../Icons/Width80/Radio.png | Bin .../Icons/Width80/Repeat.png | Bin .../Icons/Width80/RepeatList.png | Bin .../Icons/Width80/RepeatOff.png | Bin .../Icons/Width80/Share.png | Bin .../Icons/Width80/Shuffle.png | Bin .../Icons/Width80/ShuffleList.png | Bin .../Icons/Width80/ShuffleOff.png | Bin .../Icons/Width80/SongDislike.png | Bin .../Icons/Width80/SongLike.png | Bin .../Icons/Width80/Volume.png | Bin .../DirectVolumeCommand.cs | 8 +- .../SaveToPlaylistCommand.cs | 8 +- .../StartPlaylistCommand.cs | 8 +- .../PluginConfiguration.json | 0 .../Properties/AssemblyInfo.cs | 0 .../Properties/Settings.Designer.cs | 0 .../Properties/Settings.settings | 0 .../SpotifyPremiumApplication.cs | 0 .../SpotifyPremiumPlugin.Installer.cs | 0 .../SpotifyPremiumPlugin.Statuses.cs | 6 +- .../SpotifyPremiumPlugin.cs | 5 +- .../SpotifyPremiumPlugin.csproj | 3 +- .../SpotifyPremiumPluginApiCommands.cs | 0 .../Events/SpotifyWrapper.EventArgs.cs} | 11 --- .../Wrapper/Events/SpotifyWrapper.Events.cs | 15 ++++ .../SpotifyWrapper.Authentification.cs | 70 +++++++++--------- .../Wrapper/SpotifyWrapper.Cache.cs | 2 +- .../Wrapper/SpotifyWrapper.Responses.cs | 0 .../Wrapper/SpotifyWrapper.cs | 44 +++-------- .../packages.config | 0 .../spotify-client-template.txt | 0 src/SpotifyPremiumPluginWin.sln | 2 +- 87 files changed, 126 insertions(+), 165 deletions(-) rename .editorconfig => src/.editorconfig (94%) rename src/{Win => SpotifyPremiumPlugin}/Adjustments/Playback/PlayAndNavigateAdjustment.cs (99%) rename src/{Win => SpotifyPremiumPlugin}/Adjustments/Volume/SpotifyVolumeAdjustment.cs (73%) rename src/{Win => SpotifyPremiumPlugin}/App.config (100%) rename src/{Win => SpotifyPremiumPlugin}/CommandFolders/DeviceSelectorCommandFolder.cs (95%) rename src/{Win => SpotifyPremiumPlugin}/Commands/LoginToSpotifyCommand.cs (74%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Playback/ChangeRepeatStateCommand.cs (86%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Playback/NextTrackCommand.cs (77%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Playback/PreviousTrackCommand.cs (76%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Playback/ShufflePlayCommand.cs (81%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Playback/TogglePlaybackCommand.cs (80%) rename src/{Win => SpotifyPremiumPlugin}/Commands/ToggleLikeCommand.cs (82%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Volume/MuteCommand.cs (80%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Volume/ToggleMuteCommand.cs (88%) rename src/{Win => SpotifyPremiumPlugin}/Commands/Volume/UnmuteCommand.cs (79%) rename src/{Win => SpotifyPremiumPlugin}/Icons/PluginIcon16x16.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/PluginIcon256x256.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/PluginIcon32x32.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/PluginIcon48x48.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Browse.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Devices.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Home2.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/MuteVolume.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/NextTrack.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Pause.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Play.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/PlayAndNavigateTracks.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/PlayPause.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/PlayStop.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Playlist.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/PreviousTrack.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Radio.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Repeat.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/RepeatList.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/RepeatOff.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Share.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Shuffle.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/ShuffleList.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/ShuffleOff.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/SongDislike.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/SongLike.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width50/Volume.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Browse.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Devices.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Home2.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/MuteVolume.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/NextTrack.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Pause.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Play.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/PlayAndNavigateTracks.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/PlayPause.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/PlayStop.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Playlist.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/PreviousTrack.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Radio.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Repeat.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/RepeatList.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/RepeatOff.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Share.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Shuffle.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/ShuffleList.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/ShuffleOff.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/SongDislike.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/SongLike.png (100%) rename src/{Win => SpotifyPremiumPlugin}/Icons/Width80/Volume.png (100%) rename src/{Win => SpotifyPremiumPlugin}/ParameterizedCommands/DirectVolumeCommand.cs (83%) rename src/{Win => SpotifyPremiumPlugin}/ParameterizedCommands/SaveToPlaylistCommand.cs (87%) rename src/{Win => SpotifyPremiumPlugin}/ParameterizedCommands/StartPlaylistCommand.cs (87%) rename src/{Win => SpotifyPremiumPlugin}/PluginConfiguration.json (100%) rename src/{Win => SpotifyPremiumPlugin}/Properties/AssemblyInfo.cs (100%) rename src/{Win => SpotifyPremiumPlugin}/Properties/Settings.Designer.cs (100%) rename src/{Win => SpotifyPremiumPlugin}/Properties/Settings.settings (100%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumApplication.cs (100%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumPlugin.Installer.cs (100%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumPlugin.Statuses.cs (95%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumPlugin.cs (92%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumPlugin.csproj (98%) rename src/{Win => SpotifyPremiumPlugin}/SpotifyPremiumPluginApiCommands.cs (100%) rename src/{Win/Wrapper/SpotifyWrapper.Events.cs => SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.EventArgs.cs} (61%) create mode 100644 src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.Events.cs rename src/{Win => SpotifyPremiumPlugin}/Wrapper/SpotifyWrapper.Authentification.cs (76%) rename src/{Win => SpotifyPremiumPlugin}/Wrapper/SpotifyWrapper.Cache.cs (99%) rename src/{Win => SpotifyPremiumPlugin}/Wrapper/SpotifyWrapper.Responses.cs (100%) rename src/{Win => SpotifyPremiumPlugin}/Wrapper/SpotifyWrapper.cs (94%) rename src/{Win => SpotifyPremiumPlugin}/packages.config (100%) rename src/{Win => SpotifyPremiumPlugin}/spotify-client-template.txt (100%) diff --git a/.editorconfig b/src/.editorconfig similarity index 94% rename from .editorconfig rename to src/.editorconfig index 3de7e81..8ec3771 100644 --- a/.editorconfig +++ b/src/.editorconfig @@ -207,21 +207,36 @@ dotnet_diagnostic.CA1308.severity = none dotnet_diagnostic.CA1716.severity = none dotnet_diagnostic.CA1720.severity = none dotnet_diagnostic.CA2101.severity = none +dotnet_diagnostic.CA2234.severity = none +dotnet_diagnostic.CA5350.severity = none dotnet_diagnostic.CA9998.severity = none dotnet_diagnostic.CS1591.severity = none dotnet_diagnostic.IDE0002.severity = none +dotnet_diagnostic.IDE0021.severity = warning +dotnet_diagnostic.IDE0022.severity = warning dotnet_diagnostic.IDE0058.severity = none dotnet_diagnostic.IDE0059.severity = none +dotnet_diagnostic.SA1108.severity = none +dotnet_diagnostic.SA1117.severity = none dotnet_diagnostic.SA1121.severity = none +dotnet_diagnostic.SA1122.severity = none dotnet_diagnostic.SA1131.severity = none dotnet_diagnostic.SA1201.severity = none dotnet_diagnostic.SA1202.severity = none +dotnet_diagnostic.SA1203.severity = none +dotnet_diagnostic.SA1204.severity = none +dotnet_diagnostic.SA1214.severity = none dotnet_diagnostic.SA1309.severity = none dotnet_diagnostic.SA1512.severity = none +dotnet_diagnostic.SA1513.severity = none dotnet_diagnostic.SA1600.severity = none dotnet_diagnostic.SA1601.severity = none +dotnet_diagnostic.SA1602.severity = none dotnet_diagnostic.SA1629.severity = none dotnet_diagnostic.SA1633.severity = none + +dotnet_diagnostic.SX1309.severity = warning +dotnet_diagnostic.SX1309S.severity = warning diff --git a/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs b/src/SpotifyPremiumPlugin/Adjustments/Playback/PlayAndNavigateAdjustment.cs similarity index 99% rename from src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs rename to src/SpotifyPremiumPlugin/Adjustments/Playback/PlayAndNavigateAdjustment.cs index 99d1027..7173560 100644 --- a/src/Win/Adjustments/Playback/PlayAndNavigateAdjustment.cs +++ b/src/SpotifyPremiumPlugin/Adjustments/Playback/PlayAndNavigateAdjustment.cs @@ -3,7 +3,7 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - + internal class PlayAndNavigateAdjustment : PluginDynamicAdjustment { public PlayAndNavigateAdjustment() diff --git a/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs b/src/SpotifyPremiumPlugin/Adjustments/Volume/SpotifyVolumeAdjustment.cs similarity index 73% rename from src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs rename to src/SpotifyPremiumPlugin/Adjustments/Volume/SpotifyVolumeAdjustment.cs index 22bbc5f..fbbf12f 100644 --- a/src/Win/Adjustments/Volume/SpotifyVolumeAdjustment.cs +++ b/src/SpotifyPremiumPlugin/Adjustments/Volume/SpotifyVolumeAdjustment.cs @@ -7,21 +7,16 @@ namespace Loupedeck.SpotifyPremiumPlugin internal class SpotifyVolumeAdjustment : PluginDynamicAdjustment { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - - public SpotifyVolumeAdjustment() : base("Spotify Volume", "Spotify Volume description", "Spotify Volume", true) - { - } - protected override void ApplyAdjustment(String actionParameter, Int32 ticks) + public SpotifyVolumeAdjustment() + : base("Spotify Volume", "Spotify Volume description", "Spotify Volume", true) { - this.SpotifyPremiumPlugin.Wrapper.SetVolume(ticks); } + protected override void ApplyAdjustment(String actionParameter, Int32 ticks) => this.SpotifyPremiumPlugin.Wrapper.SetVolume(ticks); + // Overwrite the RunCommand method that is called every time the user presses the encoder to which this command is assigned - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/App.config b/src/SpotifyPremiumPlugin/App.config similarity index 100% rename from src/Win/App.config rename to src/SpotifyPremiumPlugin/App.config diff --git a/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs b/src/SpotifyPremiumPlugin/CommandFolders/DeviceSelectorCommandFolder.cs similarity index 95% rename from src/Win/CommandFolders/DeviceSelectorCommandFolder.cs rename to src/SpotifyPremiumPlugin/CommandFolders/DeviceSelectorCommandFolder.cs index f15b6f0..a14ed2c 100644 --- a/src/Win/CommandFolders/DeviceSelectorCommandFolder.cs +++ b/src/SpotifyPremiumPlugin/CommandFolders/DeviceSelectorCommandFolder.cs @@ -54,9 +54,6 @@ public override String GetCommandDisplayName(String commandParameter, PluginImag return deviceDisplayName; } - public override void RunCommand(String commandParameter) - { - this.SpotifyPremiumPlugin.Wrapper.TransferPlayback(commandParameter); - } + public override void RunCommand(String commandParameter) => this.SpotifyPremiumPlugin.Wrapper.TransferPlayback(commandParameter); } } \ No newline at end of file diff --git a/src/Win/Commands/LoginToSpotifyCommand.cs b/src/SpotifyPremiumPlugin/Commands/LoginToSpotifyCommand.cs similarity index 74% rename from src/Win/Commands/LoginToSpotifyCommand.cs rename to src/SpotifyPremiumPlugin/Commands/LoginToSpotifyCommand.cs index baf77ba..10bedc7 100644 --- a/src/Win/Commands/LoginToSpotifyCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/LoginToSpotifyCommand.cs @@ -7,7 +7,8 @@ namespace Loupedeck.SpotifyPremiumPlugin internal class LoginToSpotifyCommand : PluginDynamicCommand { - public LoginToSpotifyCommand() : base("Login to Spotify", "Premium user login to Spotify API", "Login") + public LoginToSpotifyCommand() + : base("Login to Spotify", "Premium user login to Spotify API", "Login") { } diff --git a/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs b/src/SpotifyPremiumPlugin/Commands/Playback/ChangeRepeatStateCommand.cs similarity index 86% rename from src/Win/Commands/Playback/ChangeRepeatStateCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Playback/ChangeRepeatStateCommand.cs index 289abd0..437efca 100644 --- a/src/Win/Commands/Playback/ChangeRepeatStateCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Playback/ChangeRepeatStateCommand.cs @@ -4,19 +4,17 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; using SpotifyAPI.Web.Enums; - + internal class ChangeRepeatStateCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public ChangeRepeatStateCommand() : base("Change Repeat State", "Change Repeat State description", "Playback") + public ChangeRepeatStateCommand() + : base("Change Repeat State", "Change Repeat State description", "Playback") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.ChangeRepeatState(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.ChangeRepeatState(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Playback/NextTrackCommand.cs b/src/SpotifyPremiumPlugin/Commands/Playback/NextTrackCommand.cs similarity index 77% rename from src/Win/Commands/Playback/NextTrackCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Playback/NextTrackCommand.cs index a47f796..669b8b2 100644 --- a/src/Win/Commands/Playback/NextTrackCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Playback/NextTrackCommand.cs @@ -8,14 +8,12 @@ internal class NextTrackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public NextTrackCommand() : base("Next Track", "Next Track description", "Playback") + public NextTrackCommand() + : base("Next Track", "Next Track description", "Playback") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToNext(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToNext(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Playback/PreviousTrackCommand.cs b/src/SpotifyPremiumPlugin/Commands/Playback/PreviousTrackCommand.cs similarity index 76% rename from src/Win/Commands/Playback/PreviousTrackCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Playback/PreviousTrackCommand.cs index 445dedf..8053640 100644 --- a/src/Win/Commands/Playback/PreviousTrackCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Playback/PreviousTrackCommand.cs @@ -8,14 +8,12 @@ internal class PreviousTrackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public PreviousTrackCommand() : base("Previous Track", "Previous Track description", "Playback") + public PreviousTrackCommand() + : base("Previous Track", "Previous Track description", "Playback") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToPrevious(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.SkipPlaybackToPrevious(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Playback/ShufflePlayCommand.cs b/src/SpotifyPremiumPlugin/Commands/Playback/ShufflePlayCommand.cs similarity index 81% rename from src/Win/Commands/Playback/ShufflePlayCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Playback/ShufflePlayCommand.cs index 9b21c1c..99ebdd1 100644 --- a/src/Win/Commands/Playback/ShufflePlayCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Playback/ShufflePlayCommand.cs @@ -8,14 +8,12 @@ internal class ShufflePlayCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public ShufflePlayCommand() : base( "Shuffle Play", "Shuffle Play description", "Playback") + public ShufflePlayCommand() + : base("Shuffle Play", "Shuffle Play description", "Playback") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.ShufflePlay(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.ShufflePlay(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Playback/TogglePlaybackCommand.cs b/src/SpotifyPremiumPlugin/Commands/Playback/TogglePlaybackCommand.cs similarity index 80% rename from src/Win/Commands/Playback/TogglePlaybackCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Playback/TogglePlaybackCommand.cs index a7b77f0..c1b0c5b 100644 --- a/src/Win/Commands/Playback/TogglePlaybackCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Playback/TogglePlaybackCommand.cs @@ -8,14 +8,12 @@ internal class TogglePlaybackCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public TogglePlaybackCommand() : base("Toggle Playback", "Toggles audio playback", "Playback") + public TogglePlaybackCommand() + : base("Toggle Playback", "Toggles audio playback", "Playback") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.TogglePlayback(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/ToggleLikeCommand.cs b/src/SpotifyPremiumPlugin/Commands/ToggleLikeCommand.cs similarity index 82% rename from src/Win/Commands/ToggleLikeCommand.cs rename to src/SpotifyPremiumPlugin/Commands/ToggleLikeCommand.cs index 777877c..893761c 100644 --- a/src/Win/Commands/ToggleLikeCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/ToggleLikeCommand.cs @@ -8,14 +8,12 @@ internal class ToggleLikeCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public ToggleLikeCommand() : base("Toggle Like", "Toggle Like", "Others") + public ToggleLikeCommand() + : base("Toggle Like", "Toggle Like", "Others") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.ToggleLike(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.ToggleLike(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Volume/MuteCommand.cs b/src/SpotifyPremiumPlugin/Commands/Volume/MuteCommand.cs similarity index 80% rename from src/Win/Commands/Volume/MuteCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Volume/MuteCommand.cs index dcfc4d3..75ade7b 100644 --- a/src/Win/Commands/Volume/MuteCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Volume/MuteCommand.cs @@ -8,14 +8,12 @@ internal class MuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public MuteCommand() : base("Mute", "Mute description", "Spotify Volume") + public MuteCommand() + : base("Mute", "Mute description", "Spotify Volume") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.Mute(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.Mute(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Commands/Volume/ToggleMuteCommand.cs b/src/SpotifyPremiumPlugin/Commands/Volume/ToggleMuteCommand.cs similarity index 88% rename from src/Win/Commands/Volume/ToggleMuteCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Volume/ToggleMuteCommand.cs index fae433f..0118ead 100644 --- a/src/Win/Commands/Volume/ToggleMuteCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Volume/ToggleMuteCommand.cs @@ -8,7 +8,8 @@ internal class ToggleMuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public ToggleMuteCommand() : base("Toggle Mute", "Toggles audio mute state", "Spotify Volume") + public ToggleMuteCommand() + : base("Toggle Mute", "Toggles audio mute state", "Spotify Volume") { } diff --git a/src/Win/Commands/Volume/UnmuteCommand.cs b/src/SpotifyPremiumPlugin/Commands/Volume/UnmuteCommand.cs similarity index 79% rename from src/Win/Commands/Volume/UnmuteCommand.cs rename to src/SpotifyPremiumPlugin/Commands/Volume/UnmuteCommand.cs index 360af96..8ab92eb 100644 --- a/src/Win/Commands/Volume/UnmuteCommand.cs +++ b/src/SpotifyPremiumPlugin/Commands/Volume/UnmuteCommand.cs @@ -8,14 +8,12 @@ internal class UnmuteCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public UnmuteCommand() : base("Unmute", "Unmute description", "Spotify Volume") + public UnmuteCommand() + : base("Unmute", "Unmute description", "Spotify Volume") { } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.Unmute(); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.Unmute(); protected override BitmapImage GetCommandImage(String actionParameter, PluginImageSize imageSize) { diff --git a/src/Win/Icons/PluginIcon16x16.png b/src/SpotifyPremiumPlugin/Icons/PluginIcon16x16.png similarity index 100% rename from src/Win/Icons/PluginIcon16x16.png rename to src/SpotifyPremiumPlugin/Icons/PluginIcon16x16.png diff --git a/src/Win/Icons/PluginIcon256x256.png b/src/SpotifyPremiumPlugin/Icons/PluginIcon256x256.png similarity index 100% rename from src/Win/Icons/PluginIcon256x256.png rename to src/SpotifyPremiumPlugin/Icons/PluginIcon256x256.png diff --git a/src/Win/Icons/PluginIcon32x32.png b/src/SpotifyPremiumPlugin/Icons/PluginIcon32x32.png similarity index 100% rename from src/Win/Icons/PluginIcon32x32.png rename to src/SpotifyPremiumPlugin/Icons/PluginIcon32x32.png diff --git a/src/Win/Icons/PluginIcon48x48.png b/src/SpotifyPremiumPlugin/Icons/PluginIcon48x48.png similarity index 100% rename from src/Win/Icons/PluginIcon48x48.png rename to src/SpotifyPremiumPlugin/Icons/PluginIcon48x48.png diff --git a/src/Win/Icons/Width50/Browse.png b/src/SpotifyPremiumPlugin/Icons/Width50/Browse.png similarity index 100% rename from src/Win/Icons/Width50/Browse.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Browse.png diff --git a/src/Win/Icons/Width50/Devices.png b/src/SpotifyPremiumPlugin/Icons/Width50/Devices.png similarity index 100% rename from src/Win/Icons/Width50/Devices.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Devices.png diff --git a/src/Win/Icons/Width50/Home2.png b/src/SpotifyPremiumPlugin/Icons/Width50/Home2.png similarity index 100% rename from src/Win/Icons/Width50/Home2.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Home2.png diff --git a/src/Win/Icons/Width50/MuteVolume.png b/src/SpotifyPremiumPlugin/Icons/Width50/MuteVolume.png similarity index 100% rename from src/Win/Icons/Width50/MuteVolume.png rename to src/SpotifyPremiumPlugin/Icons/Width50/MuteVolume.png diff --git a/src/Win/Icons/Width50/NextTrack.png b/src/SpotifyPremiumPlugin/Icons/Width50/NextTrack.png similarity index 100% rename from src/Win/Icons/Width50/NextTrack.png rename to src/SpotifyPremiumPlugin/Icons/Width50/NextTrack.png diff --git a/src/Win/Icons/Width50/Pause.png b/src/SpotifyPremiumPlugin/Icons/Width50/Pause.png similarity index 100% rename from src/Win/Icons/Width50/Pause.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Pause.png diff --git a/src/Win/Icons/Width50/Play.png b/src/SpotifyPremiumPlugin/Icons/Width50/Play.png similarity index 100% rename from src/Win/Icons/Width50/Play.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Play.png diff --git a/src/Win/Icons/Width50/PlayAndNavigateTracks.png b/src/SpotifyPremiumPlugin/Icons/Width50/PlayAndNavigateTracks.png similarity index 100% rename from src/Win/Icons/Width50/PlayAndNavigateTracks.png rename to src/SpotifyPremiumPlugin/Icons/Width50/PlayAndNavigateTracks.png diff --git a/src/Win/Icons/Width50/PlayPause.png b/src/SpotifyPremiumPlugin/Icons/Width50/PlayPause.png similarity index 100% rename from src/Win/Icons/Width50/PlayPause.png rename to src/SpotifyPremiumPlugin/Icons/Width50/PlayPause.png diff --git a/src/Win/Icons/Width50/PlayStop.png b/src/SpotifyPremiumPlugin/Icons/Width50/PlayStop.png similarity index 100% rename from src/Win/Icons/Width50/PlayStop.png rename to src/SpotifyPremiumPlugin/Icons/Width50/PlayStop.png diff --git a/src/Win/Icons/Width50/Playlist.png b/src/SpotifyPremiumPlugin/Icons/Width50/Playlist.png similarity index 100% rename from src/Win/Icons/Width50/Playlist.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Playlist.png diff --git a/src/Win/Icons/Width50/PreviousTrack.png b/src/SpotifyPremiumPlugin/Icons/Width50/PreviousTrack.png similarity index 100% rename from src/Win/Icons/Width50/PreviousTrack.png rename to src/SpotifyPremiumPlugin/Icons/Width50/PreviousTrack.png diff --git a/src/Win/Icons/Width50/Radio.png b/src/SpotifyPremiumPlugin/Icons/Width50/Radio.png similarity index 100% rename from src/Win/Icons/Width50/Radio.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Radio.png diff --git a/src/Win/Icons/Width50/Repeat.png b/src/SpotifyPremiumPlugin/Icons/Width50/Repeat.png similarity index 100% rename from src/Win/Icons/Width50/Repeat.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Repeat.png diff --git a/src/Win/Icons/Width50/RepeatList.png b/src/SpotifyPremiumPlugin/Icons/Width50/RepeatList.png similarity index 100% rename from src/Win/Icons/Width50/RepeatList.png rename to src/SpotifyPremiumPlugin/Icons/Width50/RepeatList.png diff --git a/src/Win/Icons/Width50/RepeatOff.png b/src/SpotifyPremiumPlugin/Icons/Width50/RepeatOff.png similarity index 100% rename from src/Win/Icons/Width50/RepeatOff.png rename to src/SpotifyPremiumPlugin/Icons/Width50/RepeatOff.png diff --git a/src/Win/Icons/Width50/Share.png b/src/SpotifyPremiumPlugin/Icons/Width50/Share.png similarity index 100% rename from src/Win/Icons/Width50/Share.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Share.png diff --git a/src/Win/Icons/Width50/Shuffle.png b/src/SpotifyPremiumPlugin/Icons/Width50/Shuffle.png similarity index 100% rename from src/Win/Icons/Width50/Shuffle.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Shuffle.png diff --git a/src/Win/Icons/Width50/ShuffleList.png b/src/SpotifyPremiumPlugin/Icons/Width50/ShuffleList.png similarity index 100% rename from src/Win/Icons/Width50/ShuffleList.png rename to src/SpotifyPremiumPlugin/Icons/Width50/ShuffleList.png diff --git a/src/Win/Icons/Width50/ShuffleOff.png b/src/SpotifyPremiumPlugin/Icons/Width50/ShuffleOff.png similarity index 100% rename from src/Win/Icons/Width50/ShuffleOff.png rename to src/SpotifyPremiumPlugin/Icons/Width50/ShuffleOff.png diff --git a/src/Win/Icons/Width50/SongDislike.png b/src/SpotifyPremiumPlugin/Icons/Width50/SongDislike.png similarity index 100% rename from src/Win/Icons/Width50/SongDislike.png rename to src/SpotifyPremiumPlugin/Icons/Width50/SongDislike.png diff --git a/src/Win/Icons/Width50/SongLike.png b/src/SpotifyPremiumPlugin/Icons/Width50/SongLike.png similarity index 100% rename from src/Win/Icons/Width50/SongLike.png rename to src/SpotifyPremiumPlugin/Icons/Width50/SongLike.png diff --git a/src/Win/Icons/Width50/Volume.png b/src/SpotifyPremiumPlugin/Icons/Width50/Volume.png similarity index 100% rename from src/Win/Icons/Width50/Volume.png rename to src/SpotifyPremiumPlugin/Icons/Width50/Volume.png diff --git a/src/Win/Icons/Width80/Browse.png b/src/SpotifyPremiumPlugin/Icons/Width80/Browse.png similarity index 100% rename from src/Win/Icons/Width80/Browse.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Browse.png diff --git a/src/Win/Icons/Width80/Devices.png b/src/SpotifyPremiumPlugin/Icons/Width80/Devices.png similarity index 100% rename from src/Win/Icons/Width80/Devices.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Devices.png diff --git a/src/Win/Icons/Width80/Home2.png b/src/SpotifyPremiumPlugin/Icons/Width80/Home2.png similarity index 100% rename from src/Win/Icons/Width80/Home2.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Home2.png diff --git a/src/Win/Icons/Width80/MuteVolume.png b/src/SpotifyPremiumPlugin/Icons/Width80/MuteVolume.png similarity index 100% rename from src/Win/Icons/Width80/MuteVolume.png rename to src/SpotifyPremiumPlugin/Icons/Width80/MuteVolume.png diff --git a/src/Win/Icons/Width80/NextTrack.png b/src/SpotifyPremiumPlugin/Icons/Width80/NextTrack.png similarity index 100% rename from src/Win/Icons/Width80/NextTrack.png rename to src/SpotifyPremiumPlugin/Icons/Width80/NextTrack.png diff --git a/src/Win/Icons/Width80/Pause.png b/src/SpotifyPremiumPlugin/Icons/Width80/Pause.png similarity index 100% rename from src/Win/Icons/Width80/Pause.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Pause.png diff --git a/src/Win/Icons/Width80/Play.png b/src/SpotifyPremiumPlugin/Icons/Width80/Play.png similarity index 100% rename from src/Win/Icons/Width80/Play.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Play.png diff --git a/src/Win/Icons/Width80/PlayAndNavigateTracks.png b/src/SpotifyPremiumPlugin/Icons/Width80/PlayAndNavigateTracks.png similarity index 100% rename from src/Win/Icons/Width80/PlayAndNavigateTracks.png rename to src/SpotifyPremiumPlugin/Icons/Width80/PlayAndNavigateTracks.png diff --git a/src/Win/Icons/Width80/PlayPause.png b/src/SpotifyPremiumPlugin/Icons/Width80/PlayPause.png similarity index 100% rename from src/Win/Icons/Width80/PlayPause.png rename to src/SpotifyPremiumPlugin/Icons/Width80/PlayPause.png diff --git a/src/Win/Icons/Width80/PlayStop.png b/src/SpotifyPremiumPlugin/Icons/Width80/PlayStop.png similarity index 100% rename from src/Win/Icons/Width80/PlayStop.png rename to src/SpotifyPremiumPlugin/Icons/Width80/PlayStop.png diff --git a/src/Win/Icons/Width80/Playlist.png b/src/SpotifyPremiumPlugin/Icons/Width80/Playlist.png similarity index 100% rename from src/Win/Icons/Width80/Playlist.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Playlist.png diff --git a/src/Win/Icons/Width80/PreviousTrack.png b/src/SpotifyPremiumPlugin/Icons/Width80/PreviousTrack.png similarity index 100% rename from src/Win/Icons/Width80/PreviousTrack.png rename to src/SpotifyPremiumPlugin/Icons/Width80/PreviousTrack.png diff --git a/src/Win/Icons/Width80/Radio.png b/src/SpotifyPremiumPlugin/Icons/Width80/Radio.png similarity index 100% rename from src/Win/Icons/Width80/Radio.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Radio.png diff --git a/src/Win/Icons/Width80/Repeat.png b/src/SpotifyPremiumPlugin/Icons/Width80/Repeat.png similarity index 100% rename from src/Win/Icons/Width80/Repeat.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Repeat.png diff --git a/src/Win/Icons/Width80/RepeatList.png b/src/SpotifyPremiumPlugin/Icons/Width80/RepeatList.png similarity index 100% rename from src/Win/Icons/Width80/RepeatList.png rename to src/SpotifyPremiumPlugin/Icons/Width80/RepeatList.png diff --git a/src/Win/Icons/Width80/RepeatOff.png b/src/SpotifyPremiumPlugin/Icons/Width80/RepeatOff.png similarity index 100% rename from src/Win/Icons/Width80/RepeatOff.png rename to src/SpotifyPremiumPlugin/Icons/Width80/RepeatOff.png diff --git a/src/Win/Icons/Width80/Share.png b/src/SpotifyPremiumPlugin/Icons/Width80/Share.png similarity index 100% rename from src/Win/Icons/Width80/Share.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Share.png diff --git a/src/Win/Icons/Width80/Shuffle.png b/src/SpotifyPremiumPlugin/Icons/Width80/Shuffle.png similarity index 100% rename from src/Win/Icons/Width80/Shuffle.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Shuffle.png diff --git a/src/Win/Icons/Width80/ShuffleList.png b/src/SpotifyPremiumPlugin/Icons/Width80/ShuffleList.png similarity index 100% rename from src/Win/Icons/Width80/ShuffleList.png rename to src/SpotifyPremiumPlugin/Icons/Width80/ShuffleList.png diff --git a/src/Win/Icons/Width80/ShuffleOff.png b/src/SpotifyPremiumPlugin/Icons/Width80/ShuffleOff.png similarity index 100% rename from src/Win/Icons/Width80/ShuffleOff.png rename to src/SpotifyPremiumPlugin/Icons/Width80/ShuffleOff.png diff --git a/src/Win/Icons/Width80/SongDislike.png b/src/SpotifyPremiumPlugin/Icons/Width80/SongDislike.png similarity index 100% rename from src/Win/Icons/Width80/SongDislike.png rename to src/SpotifyPremiumPlugin/Icons/Width80/SongDislike.png diff --git a/src/Win/Icons/Width80/SongLike.png b/src/SpotifyPremiumPlugin/Icons/Width80/SongLike.png similarity index 100% rename from src/Win/Icons/Width80/SongLike.png rename to src/SpotifyPremiumPlugin/Icons/Width80/SongLike.png diff --git a/src/Win/Icons/Width80/Volume.png b/src/SpotifyPremiumPlugin/Icons/Width80/Volume.png similarity index 100% rename from src/Win/Icons/Width80/Volume.png rename to src/SpotifyPremiumPlugin/Icons/Width80/Volume.png diff --git a/src/Win/ParameterizedCommands/DirectVolumeCommand.cs b/src/SpotifyPremiumPlugin/ParameterizedCommands/DirectVolumeCommand.cs similarity index 83% rename from src/Win/ParameterizedCommands/DirectVolumeCommand.cs rename to src/SpotifyPremiumPlugin/ParameterizedCommands/DirectVolumeCommand.cs index 3e968ab..6551faf 100644 --- a/src/Win/ParameterizedCommands/DirectVolumeCommand.cs +++ b/src/SpotifyPremiumPlugin/ParameterizedCommands/DirectVolumeCommand.cs @@ -8,7 +8,8 @@ internal class DirectVolumeCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public DirectVolumeCommand() : base() + public DirectVolumeCommand() + : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Direct Volume"; // so this will be shown as "group name" for parameterized commands @@ -17,9 +18,6 @@ public DirectVolumeCommand() : base() this.MakeProfileAction("text;Enter volume level to set 0-100:"); } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.SetVolume(actionParameter); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.SetVolume(actionParameter); } } diff --git a/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs b/src/SpotifyPremiumPlugin/ParameterizedCommands/SaveToPlaylistCommand.cs similarity index 87% rename from src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs rename to src/SpotifyPremiumPlugin/ParameterizedCommands/SaveToPlaylistCommand.cs index 3d421be..f49224b 100644 --- a/src/Win/ParameterizedCommands/SaveToPlaylistCommand.cs +++ b/src/SpotifyPremiumPlugin/ParameterizedCommands/SaveToPlaylistCommand.cs @@ -9,7 +9,8 @@ internal class SaveToPlaylistCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public SaveToPlaylistCommand() : base() + public SaveToPlaylistCommand() + : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Save To Playlist"; // so this will be shown as "group name" for parameterized commands @@ -18,10 +19,7 @@ public SaveToPlaylistCommand() : base() this.MakeProfileAction("list;Select playlist to save:"); } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.SaveToPlaylist(actionParameter); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.SaveToPlaylist(actionParameter); protected override PluginActionParameter[] GetParameters() { diff --git a/src/Win/ParameterizedCommands/StartPlaylistCommand.cs b/src/SpotifyPremiumPlugin/ParameterizedCommands/StartPlaylistCommand.cs similarity index 87% rename from src/Win/ParameterizedCommands/StartPlaylistCommand.cs rename to src/SpotifyPremiumPlugin/ParameterizedCommands/StartPlaylistCommand.cs index 328149e..bcf2595 100644 --- a/src/Win/ParameterizedCommands/StartPlaylistCommand.cs +++ b/src/SpotifyPremiumPlugin/ParameterizedCommands/StartPlaylistCommand.cs @@ -9,7 +9,8 @@ internal class StartPlaylistCommand : PluginDynamicCommand { private SpotifyPremiumPlugin SpotifyPremiumPlugin => this.Plugin as SpotifyPremiumPlugin; - public StartPlaylistCommand() : base() + public StartPlaylistCommand() + : base() { // Profile actions do not belong to a group in the current UI, they are on the top level this.DisplayName = "Start Playlist"; // so this will be shown as "group name" for parameterized commands @@ -18,10 +19,7 @@ public StartPlaylistCommand() : base() this.MakeProfileAction("list;Select playlist to play:"); } - protected override void RunCommand(String actionParameter) - { - this.SpotifyPremiumPlugin.Wrapper.StartPlaylist(actionParameter); - } + protected override void RunCommand(String actionParameter) => this.SpotifyPremiumPlugin.Wrapper.StartPlaylist(actionParameter); protected override PluginActionParameter[] GetParameters() { diff --git a/src/Win/PluginConfiguration.json b/src/SpotifyPremiumPlugin/PluginConfiguration.json similarity index 100% rename from src/Win/PluginConfiguration.json rename to src/SpotifyPremiumPlugin/PluginConfiguration.json diff --git a/src/Win/Properties/AssemblyInfo.cs b/src/SpotifyPremiumPlugin/Properties/AssemblyInfo.cs similarity index 100% rename from src/Win/Properties/AssemblyInfo.cs rename to src/SpotifyPremiumPlugin/Properties/AssemblyInfo.cs diff --git a/src/Win/Properties/Settings.Designer.cs b/src/SpotifyPremiumPlugin/Properties/Settings.Designer.cs similarity index 100% rename from src/Win/Properties/Settings.Designer.cs rename to src/SpotifyPremiumPlugin/Properties/Settings.Designer.cs diff --git a/src/Win/Properties/Settings.settings b/src/SpotifyPremiumPlugin/Properties/Settings.settings similarity index 100% rename from src/Win/Properties/Settings.settings rename to src/SpotifyPremiumPlugin/Properties/Settings.settings diff --git a/src/Win/SpotifyPremiumApplication.cs b/src/SpotifyPremiumPlugin/SpotifyPremiumApplication.cs similarity index 100% rename from src/Win/SpotifyPremiumApplication.cs rename to src/SpotifyPremiumPlugin/SpotifyPremiumApplication.cs diff --git a/src/Win/SpotifyPremiumPlugin.Installer.cs b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.Installer.cs similarity index 100% rename from src/Win/SpotifyPremiumPlugin.Installer.cs rename to src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.Installer.cs diff --git a/src/Win/SpotifyPremiumPlugin.Statuses.cs b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.Statuses.cs similarity index 95% rename from src/Win/SpotifyPremiumPlugin.Statuses.cs rename to src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.Statuses.cs index 8e5d81b..03e9efd 100644 --- a/src/Win/SpotifyPremiumPlugin.Statuses.cs +++ b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.Statuses.cs @@ -10,12 +10,10 @@ namespace Loupedeck.SpotifyPremiumPlugin /// public partial class SpotifyPremiumPlugin : Plugin { - internal void WrapperStatusParser(Object o, WrapperChangedEventArgs e) - { + internal void WrapperStatusParser(Object o, WrapperChangedEventArgs e) => this.OnPluginStatusChanged(this.GetPluginStatus(e.WrapperStatus), e.Message, e.SupportUrl); - } - private PluginStatus GetPluginStatus(WrapperStatus wrapperStatus) + private PluginStatus GetPluginStatus(WrapperStatus wrapperStatus) { switch (wrapperStatus) { diff --git a/src/Win/SpotifyPremiumPlugin.cs b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.cs similarity index 92% rename from src/Win/SpotifyPremiumPlugin.cs rename to src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.cs index 294bb7b..22995b2 100644 --- a/src/Win/SpotifyPremiumPlugin.cs +++ b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.cs @@ -26,10 +26,7 @@ public override void Load() this.Wrapper.WrapperStatusChanged += this.WrapperStatusParser; } - public override void Unload() - { - this.Wrapper.WrapperStatusChanged -= this.WrapperStatusParser; - } + public override void Unload() => this.Wrapper.WrapperStatusChanged -= this.WrapperStatusParser; public override void RunCommand(String commandName, String parameter) { diff --git a/src/Win/SpotifyPremiumPlugin.csproj b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.csproj similarity index 98% rename from src/Win/SpotifyPremiumPlugin.csproj rename to src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.csproj index ef43047..46c4a7a 100644 --- a/src/Win/SpotifyPremiumPlugin.csproj +++ b/src/SpotifyPremiumPlugin/SpotifyPremiumPlugin.csproj @@ -88,10 +88,11 @@ + - + diff --git a/src/Win/SpotifyPremiumPluginApiCommands.cs b/src/SpotifyPremiumPlugin/SpotifyPremiumPluginApiCommands.cs similarity index 100% rename from src/Win/SpotifyPremiumPluginApiCommands.cs rename to src/SpotifyPremiumPlugin/SpotifyPremiumPluginApiCommands.cs diff --git a/src/Win/Wrapper/SpotifyWrapper.Events.cs b/src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.EventArgs.cs similarity index 61% rename from src/Win/Wrapper/SpotifyWrapper.Events.cs rename to src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.EventArgs.cs index 706ec8e..3768fa9 100644 --- a/src/Win/Wrapper/SpotifyWrapper.Events.cs +++ b/src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.EventArgs.cs @@ -2,17 +2,6 @@ { using System; - public partial class SpotifyWrapper - { - public event EventHandler WrapperStatusChanged; - - public void OnWrapperStatusChanged(WrapperStatus wrapperStatus, String message, String supportUrl) - { - var status = new WrapperChangedEventArgs(wrapperStatus, message, supportUrl); - this.WrapperStatusChanged?.Invoke(this, status); - } - } - public class WrapperChangedEventArgs : EventArgs { public WrapperStatus WrapperStatus { get; set; } diff --git a/src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.Events.cs b/src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.Events.cs new file mode 100644 index 0000000..19cefe4 --- /dev/null +++ b/src/SpotifyPremiumPlugin/Wrapper/Events/SpotifyWrapper.Events.cs @@ -0,0 +1,15 @@ +namespace Loupedeck.SpotifyPremiumPlugin +{ + using System; + + public partial class SpotifyWrapper + { + public event EventHandler WrapperStatusChanged; + + public void OnWrapperStatusChanged(WrapperStatus wrapperStatus, String message, String supportUrl) + { + var status = new WrapperChangedEventArgs(wrapperStatus, message, supportUrl); + this.WrapperStatusChanged?.Invoke(this, status); + } + } +} diff --git a/src/Win/Wrapper/SpotifyWrapper.Authentification.cs b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Authentification.cs similarity index 76% rename from src/Win/Wrapper/SpotifyWrapper.Authentification.cs rename to src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Authentification.cs index 41ca001..4f77dad 100644 --- a/src/Win/Wrapper/SpotifyWrapper.Authentification.cs +++ b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Authentification.cs @@ -16,13 +16,13 @@ public partial class SpotifyWrapper { - private static Token token = new Token(); - private static AuthorizationCodeAuth auth; - private static String spotifyTokenFilePath; + private Token _token = new Token(); + private AuthorizationCodeAuth _auth; + private String _spotifyTokenFilePath; - private static Dictionary _spotifyConfiguration; + private Dictionary _spotifyConfiguration; - private List tcpPorts = new List(); + private List _tcpPorts = new List(); public Boolean SpotifyApiConnected() { @@ -34,9 +34,9 @@ public Boolean SpotifyApiConnected() // and skip action for now return false; } - else if (token != null && DateTime.Now > token.CreateDate.AddSeconds(token.ExpiresIn) && !String.IsNullOrEmpty(token.RefreshToken)) + else if (this._token != null && DateTime.Now > this._token.CreateDate.AddSeconds(this._token.ExpiresIn) && !String.IsNullOrEmpty(this._token.RefreshToken)) { - this.RefreshToken(token.RefreshToken); + this.RefreshToken(this._token.RefreshToken); } return true; @@ -55,7 +55,7 @@ private Boolean ReadConfigurationFile() // Create the file using (FileStream fileStream = File.Create(spotifyClientConfigurationFile)) { - var info = new UTF8Encoding(true).GetBytes($"{_clientId}{Environment.NewLine}{_clientSecret}{Environment.NewLine}{_tcpPorts}"); + var info = new UTF8Encoding(true).GetBytes($"{_clientIdName}{Environment.NewLine}{_clientSecretName}{Environment.NewLine}{_tcpPortsName}"); // Add parameter titles to file. fileStream.Write(info, 0, info.Length); @@ -66,28 +66,28 @@ private Boolean ReadConfigurationFile() } // Read configuration file, skip # comments, trim key and value - _spotifyConfiguration = File.ReadAllLines(spotifyClientConfigurationFile) + this._spotifyConfiguration = File.ReadAllLines(spotifyClientConfigurationFile) .Where(x => !x.StartsWith("#")) .Select(x => x.Split('=')) .ToDictionary(x => x[0].Trim(), x => x[1].Trim()); - if (!(_spotifyConfiguration.ContainsKey(_clientId) && - _spotifyConfiguration.ContainsKey(_clientSecret) && - _spotifyConfiguration.ContainsKey(_tcpPorts))) + if (!(this._spotifyConfiguration.ContainsKey(_clientIdName) && + this._spotifyConfiguration.ContainsKey(_clientSecretName) && + this._spotifyConfiguration.ContainsKey(_tcpPortsName))) { this.OnWrapperStatusChanged(WrapperStatus.Error, $"Check Spotify API app 'ClientId' / 'ClientSecret' and 'TcpPorts' in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); return false; } // Check TCP Ports - this.tcpPorts = _spotifyConfiguration[_tcpPorts] + this._tcpPorts = this._spotifyConfiguration[_tcpPortsName] .Split(',') .Select(x => new { valid = Int32.TryParse(x.Trim(), out var val), port = val }) .Where(x => x.valid) .Select(x => x.port) .ToList(); - if (this.tcpPorts.Count == 0) + if (this._tcpPorts.Count == 0) { this.OnWrapperStatusChanged(WrapperStatus.Error, $"Check 'TcpPorts' values in configuration file. Click More Details below", $"file:/{spotifyClientConfigurationFile}"); return false; @@ -104,28 +104,28 @@ public void ReadSpotifyConfiguration() } // Is there a token available - token = null; - spotifyTokenFilePath = Path.Combine(this._cacheDirectory, "spotify.json"); - if (File.Exists(spotifyTokenFilePath)) + this._token = null; + this._spotifyTokenFilePath = Path.Combine(this._cacheDirectory, "spotify.json"); + if (File.Exists(this._spotifyTokenFilePath)) { - token = this.ReadTokenFromLocalFile(); + this._token = this.ReadTokenFromLocalFile(); } // Check token and the expiration datetime - if (token != null && DateTime.Now < token.CreateDate.AddSeconds(token.ExpiresIn)) + if (this._token != null && DateTime.Now < this._token.CreateDate.AddSeconds(this._token.ExpiresIn)) { // Use the existing token this.Api = new SpotifyWebAPI { - AccessToken = token.AccessToken, + AccessToken = this._token.AccessToken, TokenType = "Bearer", }; this.OnWrapperStatusChanged(WrapperStatus.Normal, "Connected", null); } - else if (!String.IsNullOrEmpty(token?.RefreshToken)) + else if (!String.IsNullOrEmpty(this._token?.RefreshToken)) { // Get a new access token based on the Refresh Token - this.RefreshToken(token.RefreshToken); + this.RefreshToken(this._token.RefreshToken); } else { @@ -136,7 +136,7 @@ public void ReadSpotifyConfiguration() private Token ReadTokenFromLocalFile() { - var json = File.ReadAllText(spotifyTokenFilePath); + var json = File.ReadAllText(this._spotifyTokenFilePath); var localToken = JsonConvert.DeserializeObject(json); // Decrypt refresh token @@ -159,14 +159,14 @@ private void SaveTokenToLocalFile(Token newToken, String refreshToken) var secret = ProtectedData.Protect(plain, null, DataProtectionScope.CurrentUser); newToken.RefreshToken = Convert.ToBase64String(secret); - File.WriteAllText(spotifyTokenFilePath, JsonConvert.SerializeObject(newToken)); + File.WriteAllText(this._spotifyTokenFilePath, JsonConvert.SerializeObject(newToken)); } public void RefreshToken(String refreshToken) { - auth = this.GetAuthorizationCodeAuth(out var timeout); + this._auth = this.GetAuthorizationCodeAuth(out var timeout); - Token newToken = auth.RefreshToken(refreshToken).Result; + Token newToken = this._auth.RefreshToken(refreshToken).Result; if (!String.IsNullOrWhiteSpace(newToken.Error)) { @@ -191,21 +191,21 @@ public void RefreshToken(String refreshToken) public void LoginToSpotify() { - auth = this.GetAuthorizationCodeAuth(out var timeout); + this._auth = this.GetAuthorizationCodeAuth(out var timeout); - auth.AuthReceived += this.Auth_AuthReceived; + this._auth.AuthReceived += this.Auth_AuthReceived; - auth.Start(); - auth.OpenBrowser(); + this._auth.Start(); + this._auth.OpenBrowser(); } private async void Auth_AuthReceived(Object sender, AuthorizationCode payload) { try { - auth.Stop(); + this._auth.Stop(); - var previousToken = await auth.ExchangeCode(payload.Code); + var previousToken = await this._auth.ExchangeCode(payload.Code); if (!String.IsNullOrWhiteSpace(previousToken.Error)) { Tracer.Error($"Error happened during adding Spotify account: {previousToken.Error}: {previousToken.ErrorDescription}"); @@ -232,7 +232,7 @@ public AuthorizationCodeAuth GetAuthorizationCodeAuth(out Int32 timeout) { timeout = 240000; // ?!? - if (!NetworkHelpers.TryGetFreeTcpPort(this.tcpPorts, out var selectedPort)) + if (!NetworkHelpers.TryGetFreeTcpPort(this._tcpPorts, out var selectedPort)) { Tracer.Error("No available ports for Spotify!"); return null; @@ -256,8 +256,8 @@ public AuthorizationCodeAuth GetAuthorizationCodeAuth(out Int32 timeout) return !this.ReadConfigurationFile() ? null : new AuthorizationCodeAuth( - _spotifyConfiguration[_clientId], // Spotify API Client Id - _spotifyConfiguration[_clientSecret], // Spotify API Client Secret + this._spotifyConfiguration[_clientIdName], // Spotify API Client Id + this._spotifyConfiguration[_clientSecretName], // Spotify API Client Secret $"http://localhost:{selectedPort}", // selectedPort must correspond to that on the Spotify developers's configuration! $"http://localhost:{selectedPort}", scopes); diff --git a/src/Win/Wrapper/SpotifyWrapper.Cache.cs b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Cache.cs similarity index 99% rename from src/Win/Wrapper/SpotifyWrapper.Cache.cs rename to src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Cache.cs index 34962e3..91a2d72 100644 --- a/src/Win/Wrapper/SpotifyWrapper.Cache.cs +++ b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Cache.cs @@ -2,7 +2,7 @@ { using System; using System.IO; - + public partial class SpotifyWrapper { private readonly String _cacheDirectory; diff --git a/src/Win/Wrapper/SpotifyWrapper.Responses.cs b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Responses.cs similarity index 100% rename from src/Win/Wrapper/SpotifyWrapper.Responses.cs rename to src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.Responses.cs diff --git a/src/Win/Wrapper/SpotifyWrapper.cs b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.cs similarity index 94% rename from src/Win/Wrapper/SpotifyWrapper.cs rename to src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.cs index 75a7a0d..e47172a 100644 --- a/src/Win/Wrapper/SpotifyWrapper.cs +++ b/src/SpotifyPremiumPlugin/Wrapper/SpotifyWrapper.cs @@ -1,10 +1,10 @@ namespace Loupedeck.SpotifyPremiumPlugin { using System; - using System.Net; + using System.Collections.Generic; using System.Linq; + using System.Net; using System.Timers; - using System.Collections.Generic; using SpotifyAPI.Web; using SpotifyAPI.Web.Enums; @@ -12,14 +12,12 @@ public partial class SpotifyWrapper : IDisposable { - private const String _clientId = "ClientId"; - private const String _clientSecret = "ClientSecret"; - private const String _tcpPorts = "TcpPorts"; + private const String _clientIdName = "ClientId"; + private const String _clientSecretName = "ClientSecret"; + private const String _tcpPortsName = "TcpPorts"; private PrivateProfile _privateProfile; - //private SpotifyPremiumPlugin Plugin { get; } - internal SpotifyWebAPI Api { get; set; } public RepeatState CachedRepeatState { get; private set; } @@ -49,15 +47,10 @@ public SpotifyWrapper(String cacheDirectory) this.CurrentDeviceId = this.GetCachedDeviceID(); } - public void Dispose() - { - this.Api?.Dispose(); - } - - #region Volume + public void Dispose() => this.Api?.Dispose(); /// - /// This is our most recently known Volume. Used when muting to remember the previous volume. Used for dials when + /// Gets or sets Volume. Used when muting to remember the previous volume. Used for dials when /// incrementing rapidly. /// internal Int32 PreviousVolume { get; set; } @@ -100,7 +93,7 @@ public void AdjustVolume(Int32 ticks) // Because this can be called in rapid succession with a dial turn, and it take Spotify a bit of time to register // volume changes round trip to the api, we don't want to Get the current Volume from Spotify if we've very recently set it - // a few times. Thus, we have a 2 second buffer after the last volume set, before we try to get the actual current volume + // a few times. Thus, we have a 2 second buffer after the last volume set, before we try to get the actual current volume // from Spotify. if (this._volumeCallsBlocked) { @@ -184,10 +177,6 @@ public Boolean ToggleMute() } } - #endregion Volume - - #region Playback - public const String _activeDevice = "activedevice"; public void TransferPlayback(String commandParameter) @@ -223,7 +212,7 @@ public Boolean TogglePlayback() public void SkipPlaybackToNext() => this.CheckSpotifyResponse(this.Api.SkipPlaybackToNext, this.CurrentDeviceId); public void SkipPlaybackToPrevious() => this.CheckSpotifyResponse(this.Api.SkipPlaybackToPrevious, this.CurrentDeviceId); - + public RepeatState ChangeRepeatState() { var playback = this.Api.GetPlayback(); @@ -271,10 +260,6 @@ public Boolean ShufflePlay() return shuffleState; } - #endregion Playback - - #region Playlists - public void StartPlaylist(String contextUri) { ErrorResponse Func() => this.Api.ResumePlayback(this.CurrentDeviceId, contextUri, null, String.Empty); @@ -342,10 +327,6 @@ private Paging GetUserPlaylists(Int32 offset = 0) }; } - #endregion Playlists - - #region Devices - public List GetDevices() { var devices = this.Api?.GetDevices()?.Devices; @@ -358,10 +339,6 @@ public List GetDevices() return devices; } - #endregion Devices - - #region Likes - public Boolean ToggleLike() { var playback = this.Api.GetPlayback(); @@ -393,8 +370,5 @@ public Boolean ToggleLike() return this.CachedMuteState = false; } } - - #endregion Likes - } } \ No newline at end of file diff --git a/src/Win/packages.config b/src/SpotifyPremiumPlugin/packages.config similarity index 100% rename from src/Win/packages.config rename to src/SpotifyPremiumPlugin/packages.config diff --git a/src/Win/spotify-client-template.txt b/src/SpotifyPremiumPlugin/spotify-client-template.txt similarity index 100% rename from src/Win/spotify-client-template.txt rename to src/SpotifyPremiumPlugin/spotify-client-template.txt diff --git a/src/SpotifyPremiumPluginWin.sln b/src/SpotifyPremiumPluginWin.sln index 364dea6..adf1602 100644 --- a/src/SpotifyPremiumPluginWin.sln +++ b/src/SpotifyPremiumPluginWin.sln @@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpotifyPremiumPlugin", "win\SpotifyPremiumPlugin.csproj", "{D7B32254-4248-4A43-B127-706810EFCAFA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpotifyPremiumPlugin", "SpotifyPremiumPlugin\SpotifyPremiumPlugin.csproj", "{D7B32254-4248-4A43-B127-706810EFCAFA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution