diff --git a/SpotifyAPI.Example/App.config b/SpotifyAPI.Example/App.config index 8e156463..1f6eeef1 100644 --- a/SpotifyAPI.Example/App.config +++ b/SpotifyAPI.Example/App.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file diff --git a/SpotifyAPI.Example/ExampleForm.cs b/SpotifyAPI.Example/ExampleForm.cs index b53b2040..d311c0ef 100644 --- a/SpotifyAPI.Example/ExampleForm.cs +++ b/SpotifyAPI.Example/ExampleForm.cs @@ -9,4 +9,4 @@ namespace SpotifyAPI.Example InitializeComponent(); } } -} +} \ No newline at end of file diff --git a/SpotifyAPI.Example/LocalControl.cs b/SpotifyAPI.Example/LocalControl.cs index bb66fd8e..f43c34e4 100644 --- a/SpotifyAPI.Example/LocalControl.cs +++ b/SpotifyAPI.Example/LocalControl.cs @@ -1,10 +1,10 @@ -using System; +using SpotifyAPI.Local; +using SpotifyAPI.Local.Enums; +using SpotifyAPI.Local.Models; +using System; using System.Diagnostics; using System.Globalization; using System.Windows.Forms; -using SpotifyAPI.Local; -using SpotifyAPI.Local.Enums; -using SpotifyAPI.Local.Models; namespace SpotifyAPI.Example { @@ -102,23 +102,23 @@ namespace SpotifyAPI.Example isPlayingLabel.Text = playing.ToString(); } - void _spotify_OnVolumeChange(VolumeChangeEventArgs e) + private void _spotify_OnVolumeChange(VolumeChangeEventArgs e) { - volumeLabel.Text = (e.NewVolume*100).ToString(CultureInfo.InvariantCulture); + volumeLabel.Text = (e.NewVolume * 100).ToString(CultureInfo.InvariantCulture); } - void _spotify_OnTrackTimeChange(TrackTimeChangeEventArgs e) + private void _spotify_OnTrackTimeChange(TrackTimeChangeEventArgs e) { timeLabel.Text = FormatTime(e.TrackTime) + "/" + FormatTime(_currentTrack.Length); - timeProgressBar.Value = (int) e.TrackTime; + timeProgressBar.Value = (int)e.TrackTime; } - void _spotify_OnTrackChange(TrackChangeEventArgs e) + private void _spotify_OnTrackChange(TrackChangeEventArgs e) { UpdateTrack(e.NewTrack); } - void _spotify_OnPlayStateChange(PlayStateEventArgs e) + private void _spotify_OnPlayStateChange(PlayStateEventArgs e) { UpdatePlayingStatus(e.Playing); } @@ -162,4 +162,4 @@ namespace SpotifyAPI.Example return mins + ":" + secs; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI.Example/Program.cs b/SpotifyAPI.Example/Program.cs index f07fa459..bdfac8ea 100644 --- a/SpotifyAPI.Example/Program.cs +++ b/SpotifyAPI.Example/Program.cs @@ -1,22 +1,19 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using System.Windows.Forms; namespace SpotifyAPI.Example { - static class Program + internal static class Program { /// /// Der Haupteinstiegspunkt für die Anwendung. /// [STAThread] - static void Main() + private static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ExampleForm()); } } -} +} \ No newline at end of file diff --git a/SpotifyAPI.Example/Properties/AssemblyInfo.cs b/SpotifyAPI.Example/Properties/AssemblyInfo.cs index 4215e0a6..2dad8ee7 100644 --- a/SpotifyAPI.Example/Properties/AssemblyInfo.cs +++ b/SpotifyAPI.Example/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// Allgemeine Informationen über eine Assembly werden über die folgenden +// Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. [assembly: AssemblyTitle("SpotifyAPI.Example")] @@ -14,8 +13,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. [assembly: ComVisible(false)] @@ -25,12 +24,12 @@ using System.Runtime.InteropServices; // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: // // Hauptversion -// Nebenversion +// Nebenversion // Buildnummer // Revision // -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/SpotifyAPI.Example/WebControl.cs b/SpotifyAPI.Example/WebControl.cs index 9e8247a9..0a06679f 100644 --- a/SpotifyAPI.Example/WebControl.cs +++ b/SpotifyAPI.Example/WebControl.cs @@ -1,14 +1,13 @@ -using System; +using SpotifyAPI.Web; +using SpotifyAPI.Web.Auth; +using SpotifyAPI.Web.Enums; +using SpotifyAPI.Web.Models; +using System; using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Windows.Forms; -using SpotifyAPI.Web; -using SpotifyAPI.Web.Auth; -using SpotifyAPI.Web.Enums; -using SpotifyAPI.Web.Models; using Image = System.Drawing.Image; namespace SpotifyAPI.Example @@ -21,7 +20,7 @@ namespace SpotifyAPI.Example private PrivateProfile _profile; private List _savedTracks; private List _playlists; - + public WebControl() { InitializeComponent(); @@ -37,7 +36,7 @@ namespace SpotifyAPI.Example _auth.OnResponseReceivedEvent += _auth_OnResponseReceivedEvent; } - void _auth_OnResponseReceivedEvent(Token token, string state) + private void _auth_OnResponseReceivedEvent(Token token, string state) { _auth.StopHttpServer(); @@ -77,7 +76,7 @@ namespace SpotifyAPI.Example _savedTracks.ForEach(track => savedTracksListView.Items.Add(new ListViewItem() { Text = track.Name, - SubItems = {string.Join(",", track.Artists.Select(source => source.Name)), track.Album.Name} + SubItems = { string.Join(",", track.Artists.Select(source => source.Name)), track.Album.Name } })); _playlists = GetPlaylists(); @@ -134,4 +133,4 @@ namespace SpotifyAPI.Example _auth.DoAuth(); } } -} +} \ No newline at end of file diff --git a/SpotifyAPI.Tests/Properties/AssemblyInfo.cs b/SpotifyAPI.Tests/Properties/AssemblyInfo.cs index 07294755..a395e345 100644 --- a/SpotifyAPI.Tests/Properties/AssemblyInfo.cs +++ b/SpotifyAPI.Tests/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// Allgemeine Informationen über eine Assembly werden über die folgenden +// Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. [assembly: AssemblyTitle("SpotifyAPI.Tests")] @@ -14,8 +13,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. [assembly: ComVisible(false)] @@ -25,12 +24,12 @@ using System.Runtime.InteropServices; // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: // // Hauptversion -// Nebenversion +// Nebenversion // Buildnummer // Revision // -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/SpotifyAPI.Tests/TestClass.cs b/SpotifyAPI.Tests/TestClass.cs index 2c63271f..3fc90f3d 100644 --- a/SpotifyAPI.Tests/TestClass.cs +++ b/SpotifyAPI.Tests/TestClass.cs @@ -1,11 +1,11 @@ -using System; -using System.IO; -using System.Linq; -using Moq; +using Moq; using Newtonsoft.Json; using NUnit.Framework; using SpotifyAPI.Web; using SpotifyAPI.Web.Models; +using System; +using System.IO; +using System.Linq; namespace SpotifyAPI.Tests { @@ -67,4 +67,4 @@ namespace SpotifyAPI.Tests //Will add more tests once I decided if this is worth the effort (propably not?) } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/LocalEvents.cs b/SpotifyAPI/Local/LocalEvents.cs index 8ec39ff4..b0e16d62 100644 --- a/SpotifyAPI/Local/LocalEvents.cs +++ b/SpotifyAPI/Local/LocalEvents.cs @@ -1,5 +1,5 @@ -using System; -using SpotifyAPI.Local.Models; +using SpotifyAPI.Local.Models; +using System; namespace SpotifyAPI.Local { @@ -11,6 +11,7 @@ namespace SpotifyAPI.Local public Track OldTrack { get; set; } public Track NewTrack { get; set; } } + /// /// Event gets triggered, when the Playin-state is changed (e.g Play --> Pause) /// @@ -18,6 +19,7 @@ namespace SpotifyAPI.Local { public Boolean Playing { get; set; } } + /// /// Event gets triggered, when the volume changes /// @@ -26,6 +28,7 @@ namespace SpotifyAPI.Local public double OldVolume { get; set; } public double NewVolume { get; set; } } + /// /// Event gets triggered, when the tracktime changes /// @@ -33,4 +36,4 @@ namespace SpotifyAPI.Local { public double TrackTime { get; set; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/Models/CFID.cs b/SpotifyAPI/Local/Models/CFID.cs index aaf33380..242f57d4 100644 --- a/SpotifyAPI/Local/Models/CFID.cs +++ b/SpotifyAPI/Local/Models/CFID.cs @@ -5,7 +5,7 @@ namespace SpotifyAPI.Local.Models /// /// JSON Response, used internaly /// - class Cfid + internal class Cfid { public Error Error { get; set; } public String Token { get; set; } @@ -17,9 +17,9 @@ namespace SpotifyAPI.Local.Models /// /// JSON Response, used internaly /// - class Error + internal class Error { public String Type { get; set; } public String Message { get; set; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/Models/OpenGraphState.cs b/SpotifyAPI/Local/Models/OpenGraphState.cs index 384aaa5e..8f9df2b5 100644 --- a/SpotifyAPI/Local/Models/OpenGraphState.cs +++ b/SpotifyAPI/Local/Models/OpenGraphState.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Local.Models { @@ -7,6 +7,7 @@ namespace SpotifyAPI.Local.Models { [JsonProperty("private_session")] public Boolean PrivateSession { get; set; } + [JsonProperty("posting_disabled")] public Boolean PostingDisabled { get; set; } } diff --git a/SpotifyAPI/Local/Models/SpotifyResource.cs b/SpotifyAPI/Local/Models/SpotifyResource.cs index 97ef09e1..39d501a4 100644 --- a/SpotifyAPI/Local/Models/SpotifyResource.cs +++ b/SpotifyAPI/Local/Models/SpotifyResource.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Local.Models { @@ -7,9 +7,11 @@ namespace SpotifyAPI.Local.Models { [JsonProperty("name")] public String Name { get; set; } + [JsonProperty("uri")] public String Uri { get; set; } + [JsonProperty("location")] public TrackResourceLocation Location { get; set; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/Models/StatusResponse.cs b/SpotifyAPI/Local/Models/StatusResponse.cs index 16a4467d..1e5ea455 100644 --- a/SpotifyAPI/Local/Models/StatusResponse.cs +++ b/SpotifyAPI/Local/Models/StatusResponse.cs @@ -6,31 +6,44 @@ namespace SpotifyAPI.Local.Models { [JsonProperty("version")] public int Version { get; set; } + [JsonProperty("client_version")] public string ClientVersion { get; set; } + [JsonProperty("playing")] public bool Playing { get; set; } + [JsonProperty("schuffle")] public bool Shuffle { get; set; } + [JsonProperty("repeat")] public bool Repeat { get; set; } + [JsonProperty("play_enabled")] public bool PlayEnabled { get; set; } + [JsonProperty("prev_enabled")] public bool PrevEnabled { get; set; } + [JsonProperty("next_enabled")] public bool NextEnabled { get; set; } + [JsonProperty("track")] public Track Track { get; set; } + [JsonProperty("playing_position")] public double PlayingPosition { get; set; } + [JsonProperty("server_time")] public int ServerTime { get; set; } + [JsonProperty("volume")] public double Volume { get; set; } + [JsonProperty("online")] public bool Online { get; set; } + [JsonProperty("running")] public bool Running { get; set; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/Models/Track.cs b/SpotifyAPI/Local/Models/Track.cs index de2c4ecb..8c18ac0e 100644 --- a/SpotifyAPI/Local/Models/Track.cs +++ b/SpotifyAPI/Local/Models/Track.cs @@ -1,10 +1,10 @@ -using System; +using Newtonsoft.Json; +using SpotifyAPI.Local.Enums; +using System; using System.Drawing; using System.IO; using System.Net; using System.Threading.Tasks; -using Newtonsoft.Json; -using SpotifyAPI.Local.Enums; namespace SpotifyAPI.Local.Models { @@ -12,12 +12,16 @@ namespace SpotifyAPI.Local.Models { [JsonProperty("track_resource")] public SpotifyResource TrackResource { get; set; } + [JsonProperty("artist_resource")] public SpotifyResource ArtistResource { get; set; } + [JsonProperty("album_resource")] public SpotifyResource AlbumResource { get; set; } + [JsonProperty("length")] public int Length { get; set; } + [JsonProperty("track_type")] public string TrackType { get; set; } @@ -50,9 +54,11 @@ namespace SpotifyAPI.Local.Models case AlbumArtSize.Size160: albumsize = 160; break; + case AlbumArtSize.Size320: albumsize = 320; break; + case AlbumArtSize.Size640: albumsize = 640; break; @@ -125,7 +131,7 @@ namespace SpotifyAPI.Local.Models { wc.Proxy = null; String url = GetAlbumArtUrl(size); - if (url == "") + if (String.IsNullOrEmpty(url)) return null; var data = wc.DownloadData(url); using (MemoryStream ms = new MemoryStream(data)) @@ -146,10 +152,10 @@ namespace SpotifyAPI.Local.Models { wc.Proxy = null; String url = GetAlbumArtUrl(size); - if (url == "") + if (String.IsNullOrEmpty(url)) return null; return wc.DownloadData(url); } } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/Models/TrackResourceLocation.cs b/SpotifyAPI/Local/Models/TrackResourceLocation.cs index c0ed6a15..9008f0a9 100644 --- a/SpotifyAPI/Local/Models/TrackResourceLocation.cs +++ b/SpotifyAPI/Local/Models/TrackResourceLocation.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Local.Models { diff --git a/SpotifyAPI/Local/RemoteHandler.cs b/SpotifyAPI/Local/RemoteHandler.cs index b01cbd4a..c54608d8 100644 --- a/SpotifyAPI/Local/RemoteHandler.cs +++ b/SpotifyAPI/Local/RemoteHandler.cs @@ -1,10 +1,10 @@ -using System; +using Newtonsoft.Json; +using SpotifyAPI.Local.Models; +using System; using System.Collections.Generic; using System.Net; using System.Text; using System.Threading.Tasks; -using Newtonsoft.Json; -using SpotifyAPI.Local.Models; namespace SpotifyAPI.Local { @@ -19,7 +19,7 @@ namespace SpotifyAPI.Local { OauthKey = GetOAuthKey(); CfidKey = GetCfid(); - return CfidKey != ""; + return !String.IsNullOrEmpty(CfidKey); } internal async void SendPauseRequest() @@ -46,7 +46,7 @@ namespace SpotifyAPI.Local internal StatusResponse GetNewStatus() { String response = Query("remote/status.json", true, true, -1); - if (response == "") + if (String.IsNullOrEmpty(response)) { return null; } @@ -77,7 +77,7 @@ namespace SpotifyAPI.Local if (cfidList == null) return ""; if (cfidList.Count != 1) - throw new Exception("CFID couldn't be loaded"); + throw new Exception("CFID could not be loaded"); return cfidList[0].Error == null ? cfidList[0].Token : ""; } @@ -114,9 +114,9 @@ namespace SpotifyAPI.Local response = "[ " + wc.DownloadString(address) + " ]"; } } - catch (Exception) + catch { - return ""; + return String.Empty; } return response; @@ -145,7 +145,7 @@ namespace SpotifyAPI.Local parameters += "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap"; } - string address = "http://" + Host + ":4380/" + request + parameters ; + string address = "http://" + Host + ":4380/" + request + parameters; string response = ""; try { @@ -155,9 +155,9 @@ namespace SpotifyAPI.Local response = "[ " + await wc.DownloadStringTaskAsync(new Uri(address)) + " ]"; } } - catch (Exception) + catch { - return ""; + return String.Empty; } return response; @@ -168,4 +168,4 @@ namespace SpotifyAPI.Local return Convert.ToInt32((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds); } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/SpotifyLocalAPI.cs b/SpotifyAPI/Local/SpotifyLocalAPI.cs index 8c4d16c6..7d5ae8a6 100644 --- a/SpotifyAPI/Local/SpotifyLocalAPI.cs +++ b/SpotifyAPI/Local/SpotifyLocalAPI.cs @@ -1,10 +1,11 @@ -using System; +using SpotifyAPI.Local.Models; +using System; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.Contracts; using System.IO; using System.Runtime.InteropServices; using System.Timers; -using SpotifyAPI.Local.Models; namespace SpotifyAPI.Local { @@ -12,10 +13,9 @@ namespace SpotifyAPI.Local { [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); - [DllImport("nircmd.dll")] - private static extern bool DoNirCmd(String nirCmdStr); private bool _listenForEvents; + public bool ListenForEvents { get @@ -30,6 +30,7 @@ namespace SpotifyAPI.Local } private ISynchronizeInvoke _synchronizingObject; + public ISynchronizeInvoke SynchronizingObject { get @@ -43,22 +44,29 @@ namespace SpotifyAPI.Local } } - const byte VkMediaNextTrack = 0xb0; - const byte VkMediaPrevTrack = 0xb1; - const int KeyeventfExtendedkey = 0x1; - const int KeyeventfKeyup = 0x2; + private const byte VkMediaNextTrack = 0xb0; + private const byte VkMediaPrevTrack = 0xb1; + private const int KeyeventfExtendedkey = 0x1; + private const int KeyeventfKeyup = 0x2; - readonly RemoteHandler _rh; + private readonly RemoteHandler _rh; private readonly Timer _eventTimer; private StatusResponse _eventStatusResponse; public delegate void TrackChangeEventHandler(TrackChangeEventArgs e); + public delegate void PlayStateEventHandler(PlayStateEventArgs e); + public delegate void VolumeChangeEventHandler(VolumeChangeEventArgs e); + public delegate void TrackTimeChangeEventHandler(TrackTimeChangeEventArgs e); + public event TrackChangeEventHandler OnTrackChange; + public event PlayStateEventHandler OnPlayStateChange; + public event VolumeChangeEventHandler OnVolumeChange; + public event TrackTimeChangeEventHandler OnTrackTimeChange; public SpotifyLocalAPI() @@ -149,21 +157,83 @@ namespace SpotifyAPI.Local } /// - /// Mutes Spotify (Requires nircmd.dll) + /// Mutes Spotify (Requires Windows 7 or newer) /// public void Mute() { - if (File.Exists("nircmd.dll")) - DoNirCmd("muteappvolume spotify.exe 1"); + //Windows < Windows Vista Check + if (Environment.OSVersion.Version.Major < 6) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + //Windows Vista Check + if (Environment.OSVersion.Version.Major == 6) + if(Environment.OSVersion.Version.Minor == 0) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + VolumeMixerControl.MuteSpotify(true); } /// - /// Unmutes Spotify (Requires nircmd.dll) + /// Unmutes Spotify (Requires Windows 7 or newer) /// public void UnMute() { - if (File.Exists("nircmd.dll")) - DoNirCmd("muteappvolume spotify.exe 0"); + //Windows < Windows Vista Check + if (Environment.OSVersion.Version.Major < 6) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + //Windows Vista Check + if (Environment.OSVersion.Version.Major == 6) + if (Environment.OSVersion.Version.Minor == 0) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + VolumeMixerControl.MuteSpotify(false); + } + + /// + /// Checks whether Spotify is muted in the Volume Mixer control (required Windows 7 or newer) + /// + /// Null if an error occured, otherwise the muted state + public bool IsSpotifyMuted() + { + //Windows < Windows Vista Check + if (Environment.OSVersion.Version.Major < 6) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + //Windows Vista Check + if (Environment.OSVersion.Version.Major == 6) + if (Environment.OSVersion.Version.Minor == 0) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + return VolumeMixerControl.IsSpotifyMuted(); + } + + /// + /// Sets the Volume Mixer volume (requires Windows 7 or newer) + /// + /// A value between 0 and 100 + public void SetSpotifyVolume(float volume = 100) + { + //Windows < Windows Vista Check + if (Environment.OSVersion.Version.Major < 6) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + //Windows Vista Check + if (Environment.OSVersion.Version.Major == 6) + if (Environment.OSVersion.Version.Minor == 0) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + if (volume < 0 || volume > 100) + throw new ArgumentOutOfRangeException("Volume parameter has to be a value between 0 and 100"); + VolumeMixerControl.SetSpotifyVolume(volume); + } + + /// + /// Return the Volume Mixer volume of Spotify (requires Windows 7 or newer) + /// + /// Null if an error occured, otherwise a float between 0 and 100 + public float GetSpotifyVolume() + { + //Windows < Windows Vista Check + if (Environment.OSVersion.Version.Major < 6) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + //Windows Vista Check + if (Environment.OSVersion.Version.Major == 6) + if (Environment.OSVersion.Version.Minor == 0) + throw new NotSupportedException("This feature is only available on Windows 7 or newer"); + return VolumeMixerControl.GetSpotifyVolume(); } /// @@ -254,7 +324,7 @@ namespace SpotifyAPI.Local /// public static void RunSpotify() { - if (!IsSpotifyRunning()) + if (!IsSpotifyRunning() && File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\spotify.exe"))) Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\spotify.exe")); } @@ -263,8 +333,14 @@ namespace SpotifyAPI.Local /// public static void RunSpotifyWebHelper() { - if (!IsSpotifyWebHelperRunning()) + if (!IsSpotifyWebHelperRunning() && File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\data\spotifywebhelper.exe"))) + { Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\data\spotifywebhelper.exe")); + } + else if (!IsSpotifyWebHelperRunning() && File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\spotifywebhelper.exe"))) + { + Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\spotifywebhelper.exe")); + } } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Local/VolumeMixerControl.cs b/SpotifyAPI/Local/VolumeMixerControl.cs new file mode 100644 index 00000000..4a6c9f12 --- /dev/null +++ b/SpotifyAPI/Local/VolumeMixerControl.cs @@ -0,0 +1,258 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace SpotifyAPI.Local +{ + internal class VolumeMixerControl + { + private const String SPOTIFY_PROCESS_NAME = "spotify"; + + internal static float GetSpotifyVolume() + { + Process[] p = Process.GetProcessesByName(SPOTIFY_PROCESS_NAME); + if (p.Length == 0) + throw new Exception("Spotify process is not running or was not found!"); + + int pid = p[0].Id; + + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + { + Marshal.ReleaseComObject(volume); + throw new COMException("Volume object creation failed"); + } + + float level; + volume.GetMasterVolume(out level); + Marshal.ReleaseComObject(volume); + return level * 100; + } + + internal static bool IsSpotifyMuted() + { + Process[] p = Process.GetProcessesByName(SPOTIFY_PROCESS_NAME); + if (p.Length == 0) + throw new Exception("Spotify process is not running or was not found!"); + + int pid = p[0].Id; + + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + { + Marshal.ReleaseComObject(volume); + throw new COMException("Volume object creation failed"); + } + + bool mute; + volume.GetMute(out mute); + Marshal.ReleaseComObject(volume); + return mute; + } + + internal static void SetSpotifyVolume(float level) + { + Process[] p = Process.GetProcessesByName(SPOTIFY_PROCESS_NAME); + if (p.Length == 0) + throw new Exception("Spotify process is not running or was not found!"); + + int pid = p[0].Id; + + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + { + Marshal.ReleaseComObject(volume); + throw new COMException("Volume object creation failed"); + } + + Guid guid = Guid.Empty; + volume.SetMasterVolume(level / 100, ref guid); + Marshal.ReleaseComObject(volume); + } + + internal static void MuteSpotify(bool mute) + { + Process[] p = Process.GetProcessesByName(SPOTIFY_PROCESS_NAME); + if (p.Length == 0) + throw new Exception("Spotify process is not running or was not found!"); + + int pid = p[0].Id; + + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + { + Marshal.ReleaseComObject(volume); + throw new COMException("Volume object creation failed"); + } + + Guid guid = Guid.Empty; + volume.SetMute(mute, ref guid); + Marshal.ReleaseComObject(volume); + } + + private static ISimpleAudioVolume GetVolumeObject(int pid) + { + // get the speakers (1st render + multimedia) device + IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator()); + IMMDevice speakers; + deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers); + + // activate the session manager. we need the enumerator + Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID; + object o; + speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o); + IAudioSessionManager2 mgr = (IAudioSessionManager2)o; + + // enumerate sessions for on this device + IAudioSessionEnumerator sessionEnumerator; + mgr.GetSessionEnumerator(out sessionEnumerator); + int count; + sessionEnumerator.GetCount(out count); + + // search for an audio session with the required name + // NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2) + ISimpleAudioVolume volumeControl = null; + for (int i = 0; i < count; i++) + { + IAudioSessionControl2 ctl; + sessionEnumerator.GetSession(i, out ctl); + int cpid; + ctl.GetProcessId(out cpid); + + if (cpid == pid) + { + volumeControl = ctl as ISimpleAudioVolume; + break; + } + Marshal.ReleaseComObject(ctl); + } + Marshal.ReleaseComObject(sessionEnumerator); + Marshal.ReleaseComObject(mgr); + Marshal.ReleaseComObject(speakers); + Marshal.ReleaseComObject(deviceEnumerator); + return volumeControl; + } + + [ComImport] + [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] + private class MMDeviceEnumerator + { + + } + + private enum EDataFlow + { + eRender, + eCapture, + eAll, + EDataFlow_enum_count + } + + private enum ERole + { + eConsole, + eMultimedia, + eCommunications, + ERole_enum_count + } + + [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IMMDeviceEnumerator + { + int NotImpl1(); + + [PreserveSig] + int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice); + } + + [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IMMDevice + { + [PreserveSig] + int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface); + } + + [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IAudioSessionManager2 + { + int NotImpl1(); + + int NotImpl2(); + + [PreserveSig] + int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum); + } + + [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IAudioSessionEnumerator + { + [PreserveSig] + int GetCount(out int SessionCount); + + [PreserveSig] + int GetSession(int SessionCount, out IAudioSessionControl2 Session); + } + + [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface ISimpleAudioVolume + { + [PreserveSig] + int SetMasterVolume(float fLevel, ref Guid EventContext); + + [PreserveSig] + int GetMasterVolume(out float pfLevel); + + [PreserveSig] + int SetMute(bool bMute, ref Guid EventContext); + + [PreserveSig] + int GetMute(out bool pbMute); + } + + [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IAudioSessionControl2 + { + [PreserveSig] + int NotImpl0(); + + [PreserveSig] + int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int SetDisplayName([MarshalAs(UnmanagedType.LPWStr)]string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int SetIconPath([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int GetGroupingParam(out Guid pRetVal); + + [PreserveSig] + int SetGroupingParam([MarshalAs(UnmanagedType.LPStruct)] Guid Override, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int NotImpl1(); + + [PreserveSig] + int NotImpl2(); + + [PreserveSig] + int GetSessionIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int GetSessionInstanceIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int GetProcessId(out int pRetVal); + + [PreserveSig] + int IsSystemSoundsSession(); + + [PreserveSig] + int SetDuckingPreference(bool optOut); + } + } +} \ No newline at end of file diff --git a/SpotifyAPI/Properties/AssemblyInfo.cs b/SpotifyAPI/Properties/AssemblyInfo.cs index a56439af..5c4ae80d 100644 --- a/SpotifyAPI/Properties/AssemblyInfo.cs +++ b/SpotifyAPI/Properties/AssemblyInfo.cs @@ -1,8 +1,7 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// Allgemeine Informationen über eine Assembly werden über die folgenden +// Allgemeine Informationen über eine Assembly werden über die folgenden // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // die mit einer Assembly verknüpft sind. [assembly: AssemblyTitle("SpotifyLocalAPIClass")] @@ -14,8 +13,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. [assembly: ComVisible(false)] @@ -25,12 +24,12 @@ using System.Runtime.InteropServices; // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: // // Hauptversion -// Nebenversion +// Nebenversion // Buildnummer // Revision // -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/SpotifyAPI/SpotifyAPI.csproj b/SpotifyAPI/SpotifyAPI.csproj index 76cd3221..faaaafb5 100644 --- a/SpotifyAPI/SpotifyAPI.csproj +++ b/SpotifyAPI/SpotifyAPI.csproj @@ -24,6 +24,7 @@ 4 bin\Debug\SpotifyAPI.XML 1591 + MinimumRecommendedRules.ruleset pdbonly @@ -55,6 +56,7 @@ Component + diff --git a/SpotifyAPI/Web/Auth/AutorizationCodeAuth.cs b/SpotifyAPI/Web/Auth/AutorizationCodeAuth.cs index 5b0939b3..0be2c3ba 100644 --- a/SpotifyAPI/Web/Auth/AutorizationCodeAuth.cs +++ b/SpotifyAPI/Web/Auth/AutorizationCodeAuth.cs @@ -1,13 +1,13 @@ -using System; +using Newtonsoft.Json; +using SpotifyAPI.Web.Enums; +using SpotifyAPI.Web.Models; +using System; using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Threading; -using Newtonsoft.Json; -using SpotifyAPI.Web.Enums; -using SpotifyAPI.Web.Models; namespace SpotifyAPI.Web.Auth { @@ -51,7 +51,7 @@ namespace SpotifyAPI.Web.Auth "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(ClientId + ":" + clientSecret))); NameValueCollection col = new NameValueCollection { - {"grant_type", "refresh_token"}, + {"grant_type", "refresh_token"}, {"refresh_token", refreshToken} }; diff --git a/SpotifyAPI/Web/Auth/ClientCredentialsAuth.cs b/SpotifyAPI/Web/Auth/ClientCredentialsAuth.cs index 66ed60bf..27a3a6b9 100644 --- a/SpotifyAPI/Web/Auth/ClientCredentialsAuth.cs +++ b/SpotifyAPI/Web/Auth/ClientCredentialsAuth.cs @@ -1,11 +1,11 @@ -using System; +using Newtonsoft.Json; +using SpotifyAPI.Web.Enums; +using SpotifyAPI.Web.Models; +using System; using System.Collections.Specialized; using System.IO; using System.Net; using System.Text; -using Newtonsoft.Json; -using SpotifyAPI.Web.Enums; -using SpotifyAPI.Web.Models; namespace SpotifyAPI.Web.Auth { diff --git a/SpotifyAPI/Web/Auth/ImplicitGrantAuth.cs b/SpotifyAPI/Web/Auth/ImplicitGrantAuth.cs index e485d662..922a9d68 100644 --- a/SpotifyAPI/Web/Auth/ImplicitGrantAuth.cs +++ b/SpotifyAPI/Web/Auth/ImplicitGrantAuth.cs @@ -1,9 +1,9 @@ -using System; +using SpotifyAPI.Web.Enums; +using SpotifyAPI.Web.Models; +using System; using System.Diagnostics; using System.Text; using System.Threading; -using SpotifyAPI.Web.Enums; -using SpotifyAPI.Web.Models; namespace SpotifyAPI.Web.Auth { @@ -18,6 +18,7 @@ namespace SpotifyAPI.Web.Auth public String State { get; set; } public Scope Scope { get; set; } public Boolean ShowDialog { get; set; } + public event OnResponseReceived OnResponseReceivedEvent; /// @@ -74,4 +75,4 @@ namespace SpotifyAPI.Web.Auth _httpServer = null; } } -} +} \ No newline at end of file diff --git a/SpotifyAPI/Web/Enums/AlbumType.cs b/SpotifyAPI/Web/Enums/AlbumType.cs index 4b308052..c05df333 100644 --- a/SpotifyAPI/Web/Enums/AlbumType.cs +++ b/SpotifyAPI/Web/Enums/AlbumType.cs @@ -5,10 +5,19 @@ namespace SpotifyAPI.Web.Enums [Flags] public enum AlbumType { - [String("album")] Album = 1, - [String("single")] Single = 2, - [String("compilation")] Compilation = 4, - [String("appears_on")] AppearsOn = 8, - [String("album,single,compilation,appears_on")] All = 16 + [String("album")] + Album = 1, + + [String("single")] + Single = 2, + + [String("compilation")] + Compilation = 4, + + [String("appears_on")] + AppearsOn = 8, + + [String("album,single,compilation,appears_on")] + All = 16 } } \ No newline at end of file diff --git a/SpotifyAPI/Web/Enums/FollowType.cs b/SpotifyAPI/Web/Enums/FollowType.cs index d0fa2e10..6cd802bc 100644 --- a/SpotifyAPI/Web/Enums/FollowType.cs +++ b/SpotifyAPI/Web/Enums/FollowType.cs @@ -5,7 +5,10 @@ namespace SpotifyAPI.Web.Enums [Flags] public enum FollowType { - [String("artist")] Artist = 1, - [String("user")] User = 2 + [String("artist")] + Artist = 1, + + [String("user")] + User = 2 } } \ No newline at end of file diff --git a/SpotifyAPI/Web/Enums/Scope.cs b/SpotifyAPI/Web/Enums/Scope.cs index 1410f496..0240450a 100644 --- a/SpotifyAPI/Web/Enums/Scope.cs +++ b/SpotifyAPI/Web/Enums/Scope.cs @@ -5,17 +5,40 @@ namespace SpotifyAPI.Web.Enums [Flags] public enum Scope { - [String("")] None = 1, - [String("playlist-modify-public")] PlaylistModifyPublic = 2, - [String("playlist-modify-private")] PlaylistModifyPrivate = 4, - [String("playlist-read-private")] PlaylistReadPrivate = 8, - [String("streaming")] Streaming = 16, - [String("user-read-private")] UserReadPrivate = 32, - [String("user-read-email")] UserReadEmail = 64, - [String("user-library-read")] UserLibrarayRead = 128, - [String("user-library-modify")] UserLibraryModify = 256, - [String("user-follow-modify")] UserFollowModify = 512, - [String("user-follow-read")] UserFollowRead = 1024, - [String("user-read-birthdate")] UserReadBirthdate = 2048 + [String("")] + None = 1, + + [String("playlist-modify-public")] + PlaylistModifyPublic = 2, + + [String("playlist-modify-private")] + PlaylistModifyPrivate = 4, + + [String("playlist-read-private")] + PlaylistReadPrivate = 8, + + [String("streaming")] + Streaming = 16, + + [String("user-read-private")] + UserReadPrivate = 32, + + [String("user-read-email")] + UserReadEmail = 64, + + [String("user-library-read")] + UserLibrarayRead = 128, + + [String("user-library-modify")] + UserLibraryModify = 256, + + [String("user-follow-modify")] + UserFollowModify = 512, + + [String("user-follow-read")] + UserFollowRead = 1024, + + [String("user-read-birthdate")] + UserReadBirthdate = 2048 } } \ No newline at end of file diff --git a/SpotifyAPI/Web/Enums/SearchType.cs b/SpotifyAPI/Web/Enums/SearchType.cs index c2fae029..d40c0e19 100644 --- a/SpotifyAPI/Web/Enums/SearchType.cs +++ b/SpotifyAPI/Web/Enums/SearchType.cs @@ -5,9 +5,16 @@ namespace SpotifyAPI.Web.Enums [Flags] public enum SearchType { - [String("artist")] Artist = 1, - [String("album")] Album = 2, - [String("track")] Track = 4, - [String("track,album,artist")] All = 8 + [String("artist")] + Artist = 1, + + [String("album")] + Album = 2, + + [String("track")] + Track = 4, + + [String("track,album,artist")] + All = 8 } } \ No newline at end of file diff --git a/SpotifyAPI/Web/IClient.cs b/SpotifyAPI/Web/IClient.cs index 4ba8b94e..1ab1ae36 100644 --- a/SpotifyAPI/Web/IClient.cs +++ b/SpotifyAPI/Web/IClient.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web { diff --git a/SpotifyAPI/Web/Models/BasicModel.cs b/SpotifyAPI/Web/Models/BasicModel.cs index 8fd97d29..bb968613 100644 --- a/SpotifyAPI/Web/Models/BasicModel.cs +++ b/SpotifyAPI/Web/Models/BasicModel.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/Category.cs b/SpotifyAPI/Web/Models/Category.cs index 0c94efc2..a3322fcd 100644 --- a/SpotifyAPI/Web/Models/Category.cs +++ b/SpotifyAPI/Web/Models/Category.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/CursorPaging.cs b/SpotifyAPI/Web/Models/CursorPaging.cs index 5d7452d9..dc4060d5 100644 --- a/SpotifyAPI/Web/Models/CursorPaging.cs +++ b/SpotifyAPI/Web/Models/CursorPaging.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/FeaturedPlaylists.cs b/SpotifyAPI/Web/Models/FeaturedPlaylists.cs index 88b7939b..016a4ad0 100644 --- a/SpotifyAPI/Web/Models/FeaturedPlaylists.cs +++ b/SpotifyAPI/Web/Models/FeaturedPlaylists.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/FullAlbum.cs b/SpotifyAPI/Web/Models/FullAlbum.cs index 1df3e4a7..bd566bd2 100644 --- a/SpotifyAPI/Web/Models/FullAlbum.cs +++ b/SpotifyAPI/Web/Models/FullAlbum.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/FullArtist.cs b/SpotifyAPI/Web/Models/FullArtist.cs index b1982cbf..72eb586b 100644 --- a/SpotifyAPI/Web/Models/FullArtist.cs +++ b/SpotifyAPI/Web/Models/FullArtist.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/FullPlaylist.cs b/SpotifyAPI/Web/Models/FullPlaylist.cs index 14e0ac95..f6bf1de8 100644 --- a/SpotifyAPI/Web/Models/FullPlaylist.cs +++ b/SpotifyAPI/Web/Models/FullPlaylist.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/FullTrack.cs b/SpotifyAPI/Web/Models/FullTrack.cs index be76d17b..bbb713b2 100644 --- a/SpotifyAPI/Web/Models/FullTrack.cs +++ b/SpotifyAPI/Web/Models/FullTrack.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/GeneralModels.cs b/SpotifyAPI/Web/Models/GeneralModels.cs index 89dbe60d..bccfae85 100644 --- a/SpotifyAPI/Web/Models/GeneralModels.cs +++ b/SpotifyAPI/Web/Models/GeneralModels.cs @@ -1,7 +1,7 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/Paging.cs b/SpotifyAPI/Web/Models/Paging.cs index db25fb8d..d40a426e 100644 --- a/SpotifyAPI/Web/Models/Paging.cs +++ b/SpotifyAPI/Web/Models/Paging.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/PrivateProfile.cs b/SpotifyAPI/Web/Models/PrivateProfile.cs index 87349d60..09357c20 100644 --- a/SpotifyAPI/Web/Models/PrivateProfile.cs +++ b/SpotifyAPI/Web/Models/PrivateProfile.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/PublicProfile.cs b/SpotifyAPI/Web/Models/PublicProfile.cs index 098a99ef..93e0459d 100644 --- a/SpotifyAPI/Web/Models/PublicProfile.cs +++ b/SpotifyAPI/Web/Models/PublicProfile.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/SimpleAlbum.cs b/SpotifyAPI/Web/Models/SimpleAlbum.cs index 8f0f292f..e9dfbbf3 100644 --- a/SpotifyAPI/Web/Models/SimpleAlbum.cs +++ b/SpotifyAPI/Web/Models/SimpleAlbum.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/SimpleArtist.cs b/SpotifyAPI/Web/Models/SimpleArtist.cs index f20a0e0c..a368c66a 100644 --- a/SpotifyAPI/Web/Models/SimpleArtist.cs +++ b/SpotifyAPI/Web/Models/SimpleArtist.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/SimplePlaylist.cs b/SpotifyAPI/Web/Models/SimplePlaylist.cs index f6e9f497..1bb2f7cc 100644 --- a/SpotifyAPI/Web/Models/SimplePlaylist.cs +++ b/SpotifyAPI/Web/Models/SimplePlaylist.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/SimpleTrack.cs b/SpotifyAPI/Web/Models/SimpleTrack.cs index 2c78c6a0..7726db4d 100644 --- a/SpotifyAPI/Web/Models/SimpleTrack.cs +++ b/SpotifyAPI/Web/Models/SimpleTrack.cs @@ -1,6 +1,6 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/Snapshot.cs b/SpotifyAPI/Web/Models/Snapshot.cs index 798a4e82..4c54887d 100644 --- a/SpotifyAPI/Web/Models/Snapshot.cs +++ b/SpotifyAPI/Web/Models/Snapshot.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/Models/Token.cs b/SpotifyAPI/Web/Models/Token.cs index e6bf4ee1..8179147f 100644 --- a/SpotifyAPI/Web/Models/Token.cs +++ b/SpotifyAPI/Web/Models/Token.cs @@ -1,5 +1,5 @@ -using System; -using Newtonsoft.Json; +using Newtonsoft.Json; +using System; namespace SpotifyAPI.Web.Models { diff --git a/SpotifyAPI/Web/SimpleHttpServer.cs b/SpotifyAPI/Web/SimpleHttpServer.cs index eac076c3..7dcc7a20 100644 --- a/SpotifyAPI/Web/SimpleHttpServer.cs +++ b/SpotifyAPI/Web/SimpleHttpServer.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Web; // offered to the public domain for any use with no restriction -// and also with no warranty of any kind, please enjoy. - David Jeske. +// and also with no warranty of any kind, please enjoy. - David Jeske. // simple HTTP explanation // http://www.jmarshall.com/easy/http/ @@ -17,7 +17,7 @@ namespace SpotifyAPI.Web { public class HttpProcessor { - private const int MaxPostSize = 10*1024*1024; // 10MB + private const int MaxPostSize = 10 * 1024 * 1024; // 10MB private const int BufSize = 4096; private readonly TcpClient _socket; private readonly HttpServer _srv; @@ -79,15 +79,13 @@ namespace SpotifyAPI.Web HandlePostRequest(); } } - catch (Exception e) + catch { - Console.WriteLine("Exception: " + e); WriteFailure(); } OutputStream.Flush(); - // bs.Flush(); // flush any remaining output _inputStream = null; - OutputStream = null; // bs = null; + OutputStream = null; _socket.Close(); } @@ -97,7 +95,7 @@ namespace SpotifyAPI.Web string[] tokens = request.Split(' '); if (tokens.Length < 2) { - throw new Exception("invalid http request line"); + throw new Exception("Invalid HTTP request line"); } HttpMethod = tokens[0].ToUpper(); HttpUrl = tokens[1]; @@ -108,7 +106,7 @@ namespace SpotifyAPI.Web String line; while ((line = StreamReadLine(_inputStream)) != null) { - if (line.Equals("")) + if (String.IsNullOrEmpty(line)) { return; } @@ -116,7 +114,7 @@ namespace SpotifyAPI.Web int separator = line.IndexOf(':'); if (separator == -1) { - throw new Exception("invalid http header line: " + line); + throw new Exception("Invalid HTTP header line: " + line); } String name = line.Substring(0, separator); int pos = separator + 1; @@ -139,9 +137,9 @@ namespace SpotifyAPI.Web { // this post data processing just reads everything into a memory stream. // this is fine for smallish things, but for large stuff we should really - // hand an input stream to the request processor. However, the input stream - // we hand him needs to let him see the "end of the stream" at this content - // length, because otherwise he won't know when he's seen it all! + // hand an input stream to the request processor. However, the input stream + // we hand him needs to let him see the "end of the stream" at this content + // length, because otherwise he won't know when he's seen it all! MemoryStream ms = new MemoryStream(); if (HttpHeaders.ContainsKey("Content-Length")) @@ -149,9 +147,7 @@ namespace SpotifyAPI.Web var contentLen = Convert.ToInt32(HttpHeaders["Content-Length"]); if (contentLen > MaxPostSize) { - throw new Exception( - String.Format("POST Content-Length({0}) too big for this simple server", - contentLen)); + throw new Exception(String.Format("POST Content-Length({0}) too big for this simple server", contentLen)); } byte[] buf = new byte[BufSize]; int toRead = contentLen; @@ -164,7 +160,7 @@ namespace SpotifyAPI.Web { break; } - throw new Exception("client disconnected during post"); + throw new Exception("Client disconnected during post"); } toRead -= numread; ms.Write(buf, 0, numread); @@ -207,6 +203,7 @@ namespace SpotifyAPI.Web { IsActive = false; _listener.Stop(); + GC.SuppressFinalize(this); } public void Listen() @@ -232,6 +229,7 @@ namespace SpotifyAPI.Web } public abstract void HandleGetRequest(HttpProcessor p); + public abstract void HandlePostRequest(HttpProcessor p, StreamReader inputData); } @@ -239,6 +237,7 @@ namespace SpotifyAPI.Web { //Code can be an AccessToken or an Exchange Code public String Code { get; set; } + public String TokenType { get; set; } public String State { get; set; } public String Error { get; set; } @@ -264,7 +263,6 @@ namespace SpotifyAPI.Web if (p.HttpUrl == "/favicon.ico") return; - Thread t; if (_type == AuthType.Authorization) { @@ -276,8 +274,7 @@ namespace SpotifyAPI.Web p.OutputStream.WriteLine("

Spotify Auth canceled!

"); t = new Thread(o => { - //_funcOne(null, col.Get(1), col.Get(0)); - if(OnAuth != null) + if (OnAuth != null) OnAuth(new AuthEventArgs() { State = col.Get(1), @@ -290,7 +287,7 @@ namespace SpotifyAPI.Web p.OutputStream.WriteLine("

Spotify Auth successful!

"); t = new Thread(o => { - if(OnAuth != null) + if (OnAuth != null) OnAuth(new AuthEventArgs() { Code = col.Get(0), diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index 462503b5..84a9e9bc 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -1,15 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SpotifyAPI.Web.Enums; using SpotifyAPI.Web.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; namespace SpotifyAPI.Web { - public class SpotifyWebAPI : IDisposable + public sealed class SpotifyWebAPI : IDisposable { public const String APIBase = "https://api.spotify.com/v1"; @@ -35,6 +35,7 @@ namespace SpotifyAPI.Web public void Dispose() { WebClient.Dispose(); + GC.SuppressFinalize(this); } #region Search @@ -56,12 +57,12 @@ namespace SpotifyAPI.Web builder.Append("&type=" + type.GetStringAttribute(",")); builder.Append("&limit=" + limit); builder.Append("&offset=" + offset); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData(builder.ToString()); } - #endregion + #endregion Search #region Albums @@ -80,7 +81,7 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/albums/" + id + "/tracks"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData>(builder.ToString()); } @@ -93,7 +94,7 @@ namespace SpotifyAPI.Web /// public FullAlbum GetAlbum(String id, String market = "") { - if (market == "") + if (String.IsNullOrEmpty(market)) return DownloadData(APIBase + "/albums/" + id); return DownloadData(APIBase + "/albums/" + id + "?market=" + market); } @@ -106,12 +107,12 @@ namespace SpotifyAPI.Web /// public SeveralAlbums GetSeveralAlbums(List ids, String market = "") { - if (market == "") + if (String.IsNullOrEmpty(market)) return DownloadData(APIBase + "/albums?ids=" + string.Join(",", ids.Take(20))); return DownloadData(APIBase + "/albums?market=" + market + "&ids=" + string.Join(",", ids.Take(20))); } - #endregion + #endregion Albums #region Artists @@ -170,7 +171,7 @@ namespace SpotifyAPI.Web builder.Append("?type=" + type.GetStringAttribute(",")); builder.Append("&limit=" + limit); builder.Append("&offset=" + offset); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData>(builder.ToString()); } @@ -185,7 +186,7 @@ namespace SpotifyAPI.Web return DownloadData(APIBase + "/artists?ids=" + string.Join(",", ids.Take(50))); } - #endregion + #endregion Artists #region Browse @@ -209,9 +210,9 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/browse/featured-playlists"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (locale != "") + if (!String.IsNullOrEmpty(locale)) builder.Append("&locale=" + locale); - if (country != "") + if (!String.IsNullOrEmpty(country)) builder.Append("&country=" + country); if (timestamp != default(DateTime)) builder.Append("×tamp=" + timestamp.ToString("yyyy-MM-ddTHH:mm:ss")); @@ -234,7 +235,7 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/browse/new-releases"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (country != "") + if (!String.IsNullOrEmpty(country)) builder.Append("&country=" + country); return DownloadData(builder.ToString()); } @@ -262,9 +263,9 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/browse/categories"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (country != "") + if (!String.IsNullOrEmpty(country)) builder.Append("&country=" + country); - if (locale != "") + if (!String.IsNullOrEmpty(locale)) builder.Append("&locale=" + locale); return DownloadData(builder.ToString()); } @@ -286,9 +287,9 @@ namespace SpotifyAPI.Web public Category GetCategory(String categoryId, String country = "", String locale = "") { StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId); - if (country != "") + if (!String.IsNullOrEmpty(country)) builder.Append("?country=" + country); - if (locale != "") + if (!String.IsNullOrEmpty(locale)) builder.Append((country == "" ? "?locale=" : "&locale=") + locale); return DownloadData(builder.ToString()); } @@ -308,12 +309,12 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId + "/playlists"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (country != "") + if (!String.IsNullOrEmpty(country)) builder.Append("&country=" + country); return DownloadData(builder.ToString()); } - #endregion + #endregion Browse #region Follow @@ -326,13 +327,13 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public FollowedArtists GetFollowedArtists(int limit = 20, String after = "") { - if(!UseAuth) + if (!UseAuth) throw new InvalidOperationException("Auth is required for GetFollowedArtists"); limit = Math.Max(limit, 50); const FollowType followType = FollowType.Artist; //currently only artist is supported. StringBuilder builder = new StringBuilder(APIBase + "/me/following?type=" + followType.GetStringAttribute("")); builder.Append("&limit=" + limit); - if (after != "") + if (!String.IsNullOrEmpty(after)) builder.Append("&after=" + after); return DownloadData(builder.ToString()); } @@ -362,7 +363,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse Follow(FollowType followType, String id) { - return Follow(followType, new List {id}); + return Follow(followType, new List { id }); } /// @@ -390,7 +391,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse Unfollow(FollowType followType, String id) { - return Unfollow(followType, new List {id}); + return Unfollow(followType, new List { id }); } /// @@ -406,8 +407,8 @@ namespace SpotifyAPI.Web throw new InvalidOperationException("Auth is required for IsFollowing"); JToken res = DownloadData(APIBase + "/me/following/contains?type=" + followType.GetStringAttribute("") + "&ids=" + string.Join(",", ids)); if (res is JArray) - return new ListResponse {List = res.ToObject>(), Error = null}; - return new ListResponse {List = null, Error = res["error"].ToObject()}; + return new ListResponse { List = res.ToObject>(), Error = null }; + return new ListResponse { List = null, Error = res["error"].ToObject() }; } /// @@ -419,7 +420,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ListResponse IsFollowing(FollowType followType, String id) { - return IsFollowing(followType, new List {id}); + return IsFollowing(followType, new List { id }); } /// @@ -471,8 +472,8 @@ namespace SpotifyAPI.Web throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); JToken res = DownloadData(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers/contains?ids=" + string.Join(",", ids)); if (res is JArray) - return new ListResponse {List = res.ToObject>(), Error = null}; - return new ListResponse {List = null, Error = res["error"].ToObject()}; + return new ListResponse { List = res.ToObject>(), Error = null }; + return new ListResponse { List = null, Error = res["error"].ToObject() }; } /// @@ -485,10 +486,10 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ListResponse IsFollowingPlaylist(String ownerId, String playlistId, String id) { - return IsFollowingPlaylist(ownerId, playlistId, new List {id}); + return IsFollowingPlaylist(ownerId, playlistId, new List { id }); } - #endregion + #endregion Follow #region Library @@ -512,7 +513,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse SaveTrack(String id) { - return SaveTracks(new List {id}); + return SaveTracks(new List { id }); } /// @@ -531,7 +532,7 @@ namespace SpotifyAPI.Web StringBuilder builder = new StringBuilder(APIBase + "/me/tracks"); builder.Append("?limit=" + limit); builder.Append("&offset=" + offset); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData>(builder.ToString()); } @@ -560,11 +561,11 @@ namespace SpotifyAPI.Web throw new InvalidOperationException("Auth is required for CheckSavedTracks"); JToken res = DownloadData(APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids)); if (res is JArray) - return new ListResponse {List = res.ToObject>(), Error = null}; - return new ListResponse {List = null, Error = res["error"].ToObject()}; + return new ListResponse { List = res.ToObject>(), Error = null }; + return new ListResponse { List = null, Error = res["error"].ToObject() }; } - #endregion + #endregion Library #region Playlists @@ -605,7 +606,7 @@ namespace SpotifyAPI.Web throw new InvalidOperationException("Auth is required for GetPlaylist"); StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists/" + playlistId); builder.Append("?fields=" + fields); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData(builder.ToString()); } @@ -633,7 +634,7 @@ namespace SpotifyAPI.Web builder.Append("?fields=" + fields); builder.Append("&limit=" + limit); builder.Append("&offset=" + offset); - if (market != "") + if (!String.IsNullOrEmpty(market)) builder.Append("&market=" + market); return DownloadData>(builder.ToString()); } @@ -729,7 +730,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse RemovePlaylistTrack(String userId, String playlistId, DeleteTrackUri uri) { - return RemovePlaylistTracks(userId, playlistId, new List {uri}); + return RemovePlaylistTracks(userId, playlistId, new List { uri }); } /// @@ -763,7 +764,7 @@ namespace SpotifyAPI.Web /// AUTH NEEDED public ErrorResponse AddPlaylistTrack(String userId, String playlistId, String uri, int? position = null) { - return AddPlaylistTracks(userId, playlistId, new List {uri}, position); + return AddPlaylistTracks(userId, playlistId, new List { uri }, position); } /// @@ -785,12 +786,12 @@ namespace SpotifyAPI.Web {"range_length", rangeLength}, {"insert_before", insertBefore} }; - if (snapshotId != "") + if (!String.IsNullOrEmpty(snapshotId)) body.Add("snapshot_id", snapshotId); return UploadData(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "PUT"); } - #endregion + #endregion Playlists #region Profiles @@ -816,7 +817,7 @@ namespace SpotifyAPI.Web return DownloadData(APIBase + "/users/" + userId); } - #endregion + #endregion Profiles #region Tracks @@ -828,7 +829,7 @@ namespace SpotifyAPI.Web /// public SeveralTracks GetSeveralTracks(List ids, String market = "") { - if (market == "") + if (String.IsNullOrEmpty(market)) return DownloadData(APIBase + "/tracks?ids=" + string.Join(",", ids.Take(50))); return DownloadData(APIBase + "/tracks?market=" + market + "&ids=" + string.Join(",", ids.Take(50))); } @@ -841,12 +842,12 @@ namespace SpotifyAPI.Web /// public FullTrack GetTrack(String id, String market = "") { - if (market == "") + if (String.IsNullOrEmpty(market)) return DownloadData(APIBase + "/tracks/" + id); return DownloadData(APIBase + "/tracks/" + id + "?market=" + market); } - #endregion + #endregion Tracks #region Util @@ -868,6 +869,6 @@ namespace SpotifyAPI.Web return WebClient.DownloadJson(url); } - #endregion + #endregion Util } } \ No newline at end of file diff --git a/SpotifyAPI/Web/SpotifyWebClient.cs b/SpotifyAPI/Web/SpotifyWebClient.cs index d0a6c4b3..ea9769d7 100644 --- a/SpotifyAPI/Web/SpotifyWebClient.cs +++ b/SpotifyAPI/Web/SpotifyWebClient.cs @@ -1,10 +1,10 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; -using Newtonsoft.Json; namespace SpotifyAPI.Web { @@ -46,7 +46,7 @@ namespace SpotifyAPI.Web return response; } - public byte[] DownloadRaw(string url) + public byte[] DownloadRaw(string url) { return _webClient.DownloadData(url); } @@ -93,7 +93,7 @@ namespace SpotifyAPI.Web public void RemoveHeader(string header) { - if(_webClient.Headers[header] != null) + if (_webClient.Headers[header] != null) _webClient.Headers.Remove(header); } diff --git a/SpotifyAPI/Web/Util.cs b/SpotifyAPI/Web/Util.cs index bcd0d54f..ed01516a 100644 --- a/SpotifyAPI/Web/Util.cs +++ b/SpotifyAPI/Web/Util.cs @@ -24,12 +24,13 @@ namespace SpotifyAPI.Web } } - public class StringAttribute : Attribute + public sealed class StringAttribute : Attribute { public String Text { get; set; } + public StringAttribute(String text) { Text = text; } } -} +} \ No newline at end of file