Merge pull request #50 from Mrnikbobjeff/master

Several little improvements and minor functionality extending
This commit is contained in:
Jonas Dellinger 2015-10-28 16:47:34 +01:00
commit cd74868a8d
50 changed files with 653 additions and 257 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> </startup>
</configuration> </configuration>

View File

@ -1,10 +1,10 @@
using System; using SpotifyAPI.Local;
using SpotifyAPI.Local.Enums;
using SpotifyAPI.Local.Models;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Windows.Forms; using System.Windows.Forms;
using SpotifyAPI.Local;
using SpotifyAPI.Local.Enums;
using SpotifyAPI.Local.Models;
namespace SpotifyAPI.Example namespace SpotifyAPI.Example
{ {
@ -102,23 +102,23 @@ namespace SpotifyAPI.Example
isPlayingLabel.Text = playing.ToString(); 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); 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); UpdateTrack(e.NewTrack);
} }
void _spotify_OnPlayStateChange(PlayStateEventArgs e) private void _spotify_OnPlayStateChange(PlayStateEventArgs e)
{ {
UpdatePlayingStatus(e.Playing); UpdatePlayingStatus(e.Playing);
} }

View File

@ -1,18 +1,15 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace SpotifyAPI.Example namespace SpotifyAPI.Example
{ {
static class Program internal static class Program
{ {
/// <summary> /// <summary>
/// Der Haupteinstiegspunkt für die Anwendung. /// Der Haupteinstiegspunkt für die Anwendung.
/// </summary> /// </summary>
[STAThread] [STAThread]
static void Main() private static void Main()
{ {
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);

View File

@ -1,5 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden // Allgemeine Informationen über eine Assembly werden über die folgenden

View File

@ -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.Collections.Generic;
using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using SpotifyAPI.Web;
using SpotifyAPI.Web.Auth;
using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
using Image = System.Drawing.Image; using Image = System.Drawing.Image;
namespace SpotifyAPI.Example namespace SpotifyAPI.Example
@ -37,7 +36,7 @@ namespace SpotifyAPI.Example
_auth.OnResponseReceivedEvent += _auth_OnResponseReceivedEvent; _auth.OnResponseReceivedEvent += _auth_OnResponseReceivedEvent;
} }
void _auth_OnResponseReceivedEvent(Token token, string state) private void _auth_OnResponseReceivedEvent(Token token, string state)
{ {
_auth.StopHttpServer(); _auth.StopHttpServer();
@ -77,7 +76,7 @@ namespace SpotifyAPI.Example
_savedTracks.ForEach(track => savedTracksListView.Items.Add(new ListViewItem() _savedTracks.ForEach(track => savedTracksListView.Items.Add(new ListViewItem()
{ {
Text = track.Name, 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(); _playlists = GetPlaylists();

View File

@ -1,5 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden // Allgemeine Informationen über eine Assembly werden über die folgenden

View File

@ -1,11 +1,11 @@
using System; using Moq;
using System.IO;
using System.Linq;
using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using SpotifyAPI.Web; using SpotifyAPI.Web;
using SpotifyAPI.Web.Models; using SpotifyAPI.Web.Models;
using System;
using System.IO;
using System.Linq;
namespace SpotifyAPI.Tests namespace SpotifyAPI.Tests
{ {

View File

@ -1,5 +1,5 @@
using System; using SpotifyAPI.Local.Models;
using SpotifyAPI.Local.Models; using System;
namespace SpotifyAPI.Local namespace SpotifyAPI.Local
{ {
@ -11,6 +11,7 @@ namespace SpotifyAPI.Local
public Track OldTrack { get; set; } public Track OldTrack { get; set; }
public Track NewTrack { get; set; } public Track NewTrack { get; set; }
} }
/// <summary> /// <summary>
/// Event gets triggered, when the Playin-state is changed (e.g Play --> Pause) /// Event gets triggered, when the Playin-state is changed (e.g Play --> Pause)
/// </summary> /// </summary>
@ -18,6 +19,7 @@ namespace SpotifyAPI.Local
{ {
public Boolean Playing { get; set; } public Boolean Playing { get; set; }
} }
/// <summary> /// <summary>
/// Event gets triggered, when the volume changes /// Event gets triggered, when the volume changes
/// </summary> /// </summary>
@ -26,6 +28,7 @@ namespace SpotifyAPI.Local
public double OldVolume { get; set; } public double OldVolume { get; set; }
public double NewVolume { get; set; } public double NewVolume { get; set; }
} }
/// <summary> /// <summary>
/// Event gets triggered, when the tracktime changes /// Event gets triggered, when the tracktime changes
/// </summary> /// </summary>

View File

@ -5,7 +5,7 @@ namespace SpotifyAPI.Local.Models
/// <summary> /// <summary>
/// JSON Response, used internaly /// JSON Response, used internaly
/// </summary> /// </summary>
class Cfid internal class Cfid
{ {
public Error Error { get; set; } public Error Error { get; set; }
public String Token { get; set; } public String Token { get; set; }
@ -17,7 +17,7 @@ namespace SpotifyAPI.Local.Models
/// <summary> /// <summary>
/// JSON Response, used internaly /// JSON Response, used internaly
/// </summary> /// </summary>
class Error internal class Error
{ {
public String Type { get; set; } public String Type { get; set; }
public String Message { get; set; } public String Message { get; set; }

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Local.Models namespace SpotifyAPI.Local.Models
{ {
@ -7,6 +7,7 @@ namespace SpotifyAPI.Local.Models
{ {
[JsonProperty("private_session")] [JsonProperty("private_session")]
public Boolean PrivateSession { get; set; } public Boolean PrivateSession { get; set; }
[JsonProperty("posting_disabled")] [JsonProperty("posting_disabled")]
public Boolean PostingDisabled { get; set; } public Boolean PostingDisabled { get; set; }
} }

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Local.Models namespace SpotifyAPI.Local.Models
{ {
@ -7,8 +7,10 @@ namespace SpotifyAPI.Local.Models
{ {
[JsonProperty("name")] [JsonProperty("name")]
public String Name { get; set; } public String Name { get; set; }
[JsonProperty("uri")] [JsonProperty("uri")]
public String Uri { get; set; } public String Uri { get; set; }
[JsonProperty("location")] [JsonProperty("location")]
public TrackResourceLocation Location { get; set; } public TrackResourceLocation Location { get; set; }
} }

View File

@ -6,30 +6,43 @@ namespace SpotifyAPI.Local.Models
{ {
[JsonProperty("version")] [JsonProperty("version")]
public int Version { get; set; } public int Version { get; set; }
[JsonProperty("client_version")] [JsonProperty("client_version")]
public string ClientVersion { get; set; } public string ClientVersion { get; set; }
[JsonProperty("playing")] [JsonProperty("playing")]
public bool Playing { get; set; } public bool Playing { get; set; }
[JsonProperty("schuffle")] [JsonProperty("schuffle")]
public bool Shuffle { get; set; } public bool Shuffle { get; set; }
[JsonProperty("repeat")] [JsonProperty("repeat")]
public bool Repeat { get; set; } public bool Repeat { get; set; }
[JsonProperty("play_enabled")] [JsonProperty("play_enabled")]
public bool PlayEnabled { get; set; } public bool PlayEnabled { get; set; }
[JsonProperty("prev_enabled")] [JsonProperty("prev_enabled")]
public bool PrevEnabled { get; set; } public bool PrevEnabled { get; set; }
[JsonProperty("next_enabled")] [JsonProperty("next_enabled")]
public bool NextEnabled { get; set; } public bool NextEnabled { get; set; }
[JsonProperty("track")] [JsonProperty("track")]
public Track Track { get; set; } public Track Track { get; set; }
[JsonProperty("playing_position")] [JsonProperty("playing_position")]
public double PlayingPosition { get; set; } public double PlayingPosition { get; set; }
[JsonProperty("server_time")] [JsonProperty("server_time")]
public int ServerTime { get; set; } public int ServerTime { get; set; }
[JsonProperty("volume")] [JsonProperty("volume")]
public double Volume { get; set; } public double Volume { get; set; }
[JsonProperty("online")] [JsonProperty("online")]
public bool Online { get; set; } public bool Online { get; set; }
[JsonProperty("running")] [JsonProperty("running")]
public bool Running { get; set; } public bool Running { get; set; }
} }

View File

@ -1,10 +1,10 @@
using System; using Newtonsoft.Json;
using SpotifyAPI.Local.Enums;
using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
using SpotifyAPI.Local.Enums;
namespace SpotifyAPI.Local.Models namespace SpotifyAPI.Local.Models
{ {
@ -12,12 +12,16 @@ namespace SpotifyAPI.Local.Models
{ {
[JsonProperty("track_resource")] [JsonProperty("track_resource")]
public SpotifyResource TrackResource { get; set; } public SpotifyResource TrackResource { get; set; }
[JsonProperty("artist_resource")] [JsonProperty("artist_resource")]
public SpotifyResource ArtistResource { get; set; } public SpotifyResource ArtistResource { get; set; }
[JsonProperty("album_resource")] [JsonProperty("album_resource")]
public SpotifyResource AlbumResource { get; set; } public SpotifyResource AlbumResource { get; set; }
[JsonProperty("length")] [JsonProperty("length")]
public int Length { get; set; } public int Length { get; set; }
[JsonProperty("track_type")] [JsonProperty("track_type")]
public string TrackType { get; set; } public string TrackType { get; set; }
@ -50,9 +54,11 @@ namespace SpotifyAPI.Local.Models
case AlbumArtSize.Size160: case AlbumArtSize.Size160:
albumsize = 160; albumsize = 160;
break; break;
case AlbumArtSize.Size320: case AlbumArtSize.Size320:
albumsize = 320; albumsize = 320;
break; break;
case AlbumArtSize.Size640: case AlbumArtSize.Size640:
albumsize = 640; albumsize = 640;
break; break;
@ -125,7 +131,7 @@ namespace SpotifyAPI.Local.Models
{ {
wc.Proxy = null; wc.Proxy = null;
String url = GetAlbumArtUrl(size); String url = GetAlbumArtUrl(size);
if (url == "") if (String.IsNullOrEmpty(url))
return null; return null;
var data = wc.DownloadData(url); var data = wc.DownloadData(url);
using (MemoryStream ms = new MemoryStream(data)) using (MemoryStream ms = new MemoryStream(data))
@ -146,7 +152,7 @@ namespace SpotifyAPI.Local.Models
{ {
wc.Proxy = null; wc.Proxy = null;
String url = GetAlbumArtUrl(size); String url = GetAlbumArtUrl(size);
if (url == "") if (String.IsNullOrEmpty(url))
return null; return null;
return wc.DownloadData(url); return wc.DownloadData(url);
} }

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Local.Models namespace SpotifyAPI.Local.Models
{ {

View File

@ -1,10 +1,10 @@
using System; using Newtonsoft.Json;
using SpotifyAPI.Local.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json;
using SpotifyAPI.Local.Models;
namespace SpotifyAPI.Local namespace SpotifyAPI.Local
{ {
@ -19,7 +19,7 @@ namespace SpotifyAPI.Local
{ {
OauthKey = GetOAuthKey(); OauthKey = GetOAuthKey();
CfidKey = GetCfid(); CfidKey = GetCfid();
return CfidKey != ""; return !String.IsNullOrEmpty(CfidKey);
} }
internal async void SendPauseRequest() internal async void SendPauseRequest()
@ -46,7 +46,7 @@ namespace SpotifyAPI.Local
internal StatusResponse GetNewStatus() internal StatusResponse GetNewStatus()
{ {
String response = Query("remote/status.json", true, true, -1); String response = Query("remote/status.json", true, true, -1);
if (response == "") if (String.IsNullOrEmpty(response))
{ {
return null; return null;
} }
@ -77,7 +77,7 @@ namespace SpotifyAPI.Local
if (cfidList == null) if (cfidList == null)
return ""; return "";
if (cfidList.Count != 1) 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 : ""; return cfidList[0].Error == null ? cfidList[0].Token : "";
} }
@ -114,9 +114,9 @@ namespace SpotifyAPI.Local
response = "[ " + wc.DownloadString(address) + " ]"; response = "[ " + wc.DownloadString(address) + " ]";
} }
} }
catch (Exception) catch
{ {
return ""; return String.Empty;
} }
return response; return response;
@ -145,7 +145,7 @@ namespace SpotifyAPI.Local
parameters += "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap"; parameters += "&returnon=login%2Clogout%2Cplay%2Cpause%2Cerror%2Cap";
} }
string address = "http://" + Host + ":4380/" + request + parameters ; string address = "http://" + Host + ":4380/" + request + parameters;
string response = ""; string response = "";
try try
{ {
@ -155,9 +155,9 @@ namespace SpotifyAPI.Local
response = "[ " + await wc.DownloadStringTaskAsync(new Uri(address)) + " ]"; response = "[ " + await wc.DownloadStringTaskAsync(new Uri(address)) + " ]";
} }
} }
catch (Exception) catch
{ {
return ""; return String.Empty;
} }
return response; return response;

View File

@ -1,10 +1,11 @@
using System; using SpotifyAPI.Local.Models;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Timers; using System.Timers;
using SpotifyAPI.Local.Models;
namespace SpotifyAPI.Local namespace SpotifyAPI.Local
{ {
@ -12,10 +13,9 @@ namespace SpotifyAPI.Local
{ {
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); 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; private bool _listenForEvents;
public bool ListenForEvents public bool ListenForEvents
{ {
get get
@ -30,6 +30,7 @@ namespace SpotifyAPI.Local
} }
private ISynchronizeInvoke _synchronizingObject; private ISynchronizeInvoke _synchronizingObject;
public ISynchronizeInvoke SynchronizingObject public ISynchronizeInvoke SynchronizingObject
{ {
get get
@ -43,22 +44,29 @@ namespace SpotifyAPI.Local
} }
} }
const byte VkMediaNextTrack = 0xb0; private const byte VkMediaNextTrack = 0xb0;
const byte VkMediaPrevTrack = 0xb1; private const byte VkMediaPrevTrack = 0xb1;
const int KeyeventfExtendedkey = 0x1; private const int KeyeventfExtendedkey = 0x1;
const int KeyeventfKeyup = 0x2; private const int KeyeventfKeyup = 0x2;
readonly RemoteHandler _rh; private readonly RemoteHandler _rh;
private readonly Timer _eventTimer; private readonly Timer _eventTimer;
private StatusResponse _eventStatusResponse; private StatusResponse _eventStatusResponse;
public delegate void TrackChangeEventHandler(TrackChangeEventArgs e); public delegate void TrackChangeEventHandler(TrackChangeEventArgs e);
public delegate void PlayStateEventHandler(PlayStateEventArgs e); public delegate void PlayStateEventHandler(PlayStateEventArgs e);
public delegate void VolumeChangeEventHandler(VolumeChangeEventArgs e); public delegate void VolumeChangeEventHandler(VolumeChangeEventArgs e);
public delegate void TrackTimeChangeEventHandler(TrackTimeChangeEventArgs e); public delegate void TrackTimeChangeEventHandler(TrackTimeChangeEventArgs e);
public event TrackChangeEventHandler OnTrackChange; public event TrackChangeEventHandler OnTrackChange;
public event PlayStateEventHandler OnPlayStateChange; public event PlayStateEventHandler OnPlayStateChange;
public event VolumeChangeEventHandler OnVolumeChange; public event VolumeChangeEventHandler OnVolumeChange;
public event TrackTimeChangeEventHandler OnTrackTimeChange; public event TrackTimeChangeEventHandler OnTrackTimeChange;
public SpotifyLocalAPI() public SpotifyLocalAPI()
@ -149,21 +157,83 @@ namespace SpotifyAPI.Local
} }
/// <summary> /// <summary>
/// Mutes Spotify (Requires nircmd.dll) /// Mutes Spotify (Requires Windows 7 or newer)
/// </summary> /// </summary>
public void Mute() public void Mute()
{ {
if (File.Exists("nircmd.dll")) //Windows < Windows Vista Check
DoNirCmd("muteappvolume spotify.exe 1"); 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);
} }
/// <summary> /// <summary>
/// Unmutes Spotify (Requires nircmd.dll) /// Unmutes Spotify (Requires Windows 7 or newer)
/// </summary> /// </summary>
public void UnMute() public void UnMute()
{ {
if (File.Exists("nircmd.dll")) //Windows < Windows Vista Check
DoNirCmd("muteappvolume spotify.exe 0"); 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);
}
/// <summary>
/// Checks whether Spotify is muted in the Volume Mixer control (required Windows 7 or newer)
/// </summary>
/// <returns>Null if an error occured, otherwise the muted state</returns>
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();
}
/// <summary>
/// Sets the Volume Mixer volume (requires Windows 7 or newer)
/// </summary>
/// <param name="volume">A value between 0 and 100</param>
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);
}
/// <summary>
/// Return the Volume Mixer volume of Spotify (requires Windows 7 or newer)
/// </summary>
/// <returns>Null if an error occured, otherwise a float between 0 and 100</returns>
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();
} }
/// <summary> /// <summary>
@ -254,7 +324,7 @@ namespace SpotifyAPI.Local
/// </summary> /// </summary>
public static void RunSpotify() 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")); Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"spotify\spotify.exe"));
} }
@ -263,8 +333,14 @@ namespace SpotifyAPI.Local
/// </summary> /// </summary>
public static void RunSpotifyWebHelper() 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")); 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"));
}
} }
} }
} }

View File

@ -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);
}
}
}

View File

@ -1,5 +1,4 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden // Allgemeine Informationen über eine Assembly werden über die folgenden

View File

@ -24,6 +24,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\SpotifyAPI.XML</DocumentationFile> <DocumentationFile>bin\Debug\SpotifyAPI.XML</DocumentationFile>
<NoWarn>1591</NoWarn> <NoWarn>1591</NoWarn>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -55,6 +56,7 @@
<Compile Include="Local\ExtendedWebClient.cs"> <Compile Include="Local\ExtendedWebClient.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Local\VolumeMixerControl.cs" />
<Compile Include="Web\IClient.cs" /> <Compile Include="Web\IClient.cs" />
<Compile Include="Local\Models\CFID.cs" /> <Compile Include="Local\Models\CFID.cs" />
<Compile Include="Local\Enums\AlbumArtSize.cs" /> <Compile Include="Local\Enums\AlbumArtSize.cs" />

View File

@ -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.Collections.Specialized;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Newtonsoft.Json;
using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
namespace SpotifyAPI.Web.Auth namespace SpotifyAPI.Web.Auth
{ {

View File

@ -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.Collections.Specialized;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
using Newtonsoft.Json;
using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
namespace SpotifyAPI.Web.Auth namespace SpotifyAPI.Web.Auth
{ {

View File

@ -1,9 +1,9 @@
using System; using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models;
namespace SpotifyAPI.Web.Auth namespace SpotifyAPI.Web.Auth
{ {
@ -18,6 +18,7 @@ namespace SpotifyAPI.Web.Auth
public String State { get; set; } public String State { get; set; }
public Scope Scope { get; set; } public Scope Scope { get; set; }
public Boolean ShowDialog { get; set; } public Boolean ShowDialog { get; set; }
public event OnResponseReceived OnResponseReceivedEvent; public event OnResponseReceived OnResponseReceivedEvent;
/// <summary> /// <summary>

View File

@ -5,10 +5,19 @@ namespace SpotifyAPI.Web.Enums
[Flags] [Flags]
public enum AlbumType public enum AlbumType
{ {
[String("album")] Album = 1, [String("album")]
[String("single")] Single = 2, Album = 1,
[String("compilation")] Compilation = 4,
[String("appears_on")] AppearsOn = 8, [String("single")]
[String("album,single,compilation,appears_on")] All = 16 Single = 2,
[String("compilation")]
Compilation = 4,
[String("appears_on")]
AppearsOn = 8,
[String("album,single,compilation,appears_on")]
All = 16
} }
} }

View File

@ -5,7 +5,10 @@ namespace SpotifyAPI.Web.Enums
[Flags] [Flags]
public enum FollowType public enum FollowType
{ {
[String("artist")] Artist = 1, [String("artist")]
[String("user")] User = 2 Artist = 1,
[String("user")]
User = 2
} }
} }

View File

@ -5,17 +5,40 @@ namespace SpotifyAPI.Web.Enums
[Flags] [Flags]
public enum Scope public enum Scope
{ {
[String("")] None = 1, [String("")]
[String("playlist-modify-public")] PlaylistModifyPublic = 2, None = 1,
[String("playlist-modify-private")] PlaylistModifyPrivate = 4,
[String("playlist-read-private")] PlaylistReadPrivate = 8, [String("playlist-modify-public")]
[String("streaming")] Streaming = 16, PlaylistModifyPublic = 2,
[String("user-read-private")] UserReadPrivate = 32,
[String("user-read-email")] UserReadEmail = 64, [String("playlist-modify-private")]
[String("user-library-read")] UserLibrarayRead = 128, PlaylistModifyPrivate = 4,
[String("user-library-modify")] UserLibraryModify = 256,
[String("user-follow-modify")] UserFollowModify = 512, [String("playlist-read-private")]
[String("user-follow-read")] UserFollowRead = 1024, PlaylistReadPrivate = 8,
[String("user-read-birthdate")] UserReadBirthdate = 2048
[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
} }
} }

View File

@ -5,9 +5,16 @@ namespace SpotifyAPI.Web.Enums
[Flags] [Flags]
public enum SearchType public enum SearchType
{ {
[String("artist")] Artist = 1, [String("artist")]
[String("album")] Album = 2, Artist = 1,
[String("track")] Track = 4,
[String("track,album,artist")] All = 8 [String("album")]
Album = 2,
[String("track")]
Track = 4,
[String("track,album,artist")]
All = 8
} }
} }

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
{ {

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,7 +1,7 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -1,5 +1,5 @@
using System; using Newtonsoft.Json;
using Newtonsoft.Json; using System;
namespace SpotifyAPI.Web.Models namespace SpotifyAPI.Web.Models
{ {

View File

@ -17,7 +17,7 @@ namespace SpotifyAPI.Web
{ {
public class HttpProcessor 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 const int BufSize = 4096;
private readonly TcpClient _socket; private readonly TcpClient _socket;
private readonly HttpServer _srv; private readonly HttpServer _srv;
@ -79,15 +79,13 @@ namespace SpotifyAPI.Web
HandlePostRequest(); HandlePostRequest();
} }
} }
catch (Exception e) catch
{ {
Console.WriteLine("Exception: " + e);
WriteFailure(); WriteFailure();
} }
OutputStream.Flush(); OutputStream.Flush();
// bs.Flush(); // flush any remaining output
_inputStream = null; _inputStream = null;
OutputStream = null; // bs = null; OutputStream = null;
_socket.Close(); _socket.Close();
} }
@ -97,7 +95,7 @@ namespace SpotifyAPI.Web
string[] tokens = request.Split(' '); string[] tokens = request.Split(' ');
if (tokens.Length < 2) if (tokens.Length < 2)
{ {
throw new Exception("invalid http request line"); throw new Exception("Invalid HTTP request line");
} }
HttpMethod = tokens[0].ToUpper(); HttpMethod = tokens[0].ToUpper();
HttpUrl = tokens[1]; HttpUrl = tokens[1];
@ -108,7 +106,7 @@ namespace SpotifyAPI.Web
String line; String line;
while ((line = StreamReadLine(_inputStream)) != null) while ((line = StreamReadLine(_inputStream)) != null)
{ {
if (line.Equals("")) if (String.IsNullOrEmpty(line))
{ {
return; return;
} }
@ -116,7 +114,7 @@ namespace SpotifyAPI.Web
int separator = line.IndexOf(':'); int separator = line.IndexOf(':');
if (separator == -1) 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); String name = line.Substring(0, separator);
int pos = separator + 1; int pos = separator + 1;
@ -149,9 +147,7 @@ namespace SpotifyAPI.Web
var contentLen = Convert.ToInt32(HttpHeaders["Content-Length"]); var contentLen = Convert.ToInt32(HttpHeaders["Content-Length"]);
if (contentLen > MaxPostSize) if (contentLen > MaxPostSize)
{ {
throw new Exception( throw new Exception(String.Format("POST Content-Length({0}) too big for this simple server", contentLen));
String.Format("POST Content-Length({0}) too big for this simple server",
contentLen));
} }
byte[] buf = new byte[BufSize]; byte[] buf = new byte[BufSize];
int toRead = contentLen; int toRead = contentLen;
@ -164,7 +160,7 @@ namespace SpotifyAPI.Web
{ {
break; break;
} }
throw new Exception("client disconnected during post"); throw new Exception("Client disconnected during post");
} }
toRead -= numread; toRead -= numread;
ms.Write(buf, 0, numread); ms.Write(buf, 0, numread);
@ -207,6 +203,7 @@ namespace SpotifyAPI.Web
{ {
IsActive = false; IsActive = false;
_listener.Stop(); _listener.Stop();
GC.SuppressFinalize(this);
} }
public void Listen() public void Listen()
@ -232,6 +229,7 @@ namespace SpotifyAPI.Web
} }
public abstract void HandleGetRequest(HttpProcessor p); public abstract void HandleGetRequest(HttpProcessor p);
public abstract void HandlePostRequest(HttpProcessor p, StreamReader inputData); public abstract void HandlePostRequest(HttpProcessor p, StreamReader inputData);
} }
@ -239,6 +237,7 @@ namespace SpotifyAPI.Web
{ {
//Code can be an AccessToken or an Exchange Code //Code can be an AccessToken or an Exchange Code
public String Code { get; set; } public String Code { get; set; }
public String TokenType { get; set; } public String TokenType { get; set; }
public String State { get; set; } public String State { get; set; }
public String Error { get; set; } public String Error { get; set; }
@ -264,7 +263,6 @@ namespace SpotifyAPI.Web
if (p.HttpUrl == "/favicon.ico") if (p.HttpUrl == "/favicon.ico")
return; return;
Thread t; Thread t;
if (_type == AuthType.Authorization) if (_type == AuthType.Authorization)
{ {
@ -276,8 +274,7 @@ namespace SpotifyAPI.Web
p.OutputStream.WriteLine("<html><body><h1>Spotify Auth canceled!</h1></body></html>"); p.OutputStream.WriteLine("<html><body><h1>Spotify Auth canceled!</h1></body></html>");
t = new Thread(o => t = new Thread(o =>
{ {
//_funcOne(null, col.Get(1), col.Get(0)); if (OnAuth != null)
if(OnAuth != null)
OnAuth(new AuthEventArgs() OnAuth(new AuthEventArgs()
{ {
State = col.Get(1), State = col.Get(1),
@ -290,7 +287,7 @@ namespace SpotifyAPI.Web
p.OutputStream.WriteLine("<html><body><h1>Spotify Auth successful!</h1><script>window.close();</script></body></html>"); p.OutputStream.WriteLine("<html><body><h1>Spotify Auth successful!</h1><script>window.close();</script></body></html>");
t = new Thread(o => t = new Thread(o =>
{ {
if(OnAuth != null) if (OnAuth != null)
OnAuth(new AuthEventArgs() OnAuth(new AuthEventArgs()
{ {
Code = col.Get(0), Code = col.Get(0),

View File

@ -1,15 +1,15 @@
using System; using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using SpotifyAPI.Web.Enums; using SpotifyAPI.Web.Enums;
using SpotifyAPI.Web.Models; using SpotifyAPI.Web.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
{ {
public class SpotifyWebAPI : IDisposable public sealed class SpotifyWebAPI : IDisposable
{ {
public const String APIBase = "https://api.spotify.com/v1"; public const String APIBase = "https://api.spotify.com/v1";
@ -35,6 +35,7 @@ namespace SpotifyAPI.Web
public void Dispose() public void Dispose()
{ {
WebClient.Dispose(); WebClient.Dispose();
GC.SuppressFinalize(this);
} }
#region Search #region Search
@ -56,12 +57,12 @@ namespace SpotifyAPI.Web
builder.Append("&type=" + type.GetStringAttribute(",")); builder.Append("&type=" + type.GetStringAttribute(","));
builder.Append("&limit=" + limit); builder.Append("&limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<SearchItem>(builder.ToString()); return DownloadData<SearchItem>(builder.ToString());
} }
#endregion #endregion Search
#region Albums #region Albums
@ -80,7 +81,7 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/albums/" + id + "/tracks"); StringBuilder builder = new StringBuilder(APIBase + "/albums/" + id + "/tracks");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<Paging<SimpleTrack>>(builder.ToString()); return DownloadData<Paging<SimpleTrack>>(builder.ToString());
} }
@ -93,7 +94,7 @@ namespace SpotifyAPI.Web
/// <returns></returns> /// <returns></returns>
public FullAlbum GetAlbum(String id, String market = "") public FullAlbum GetAlbum(String id, String market = "")
{ {
if (market == "") if (String.IsNullOrEmpty(market))
return DownloadData<FullAlbum>(APIBase + "/albums/" + id); return DownloadData<FullAlbum>(APIBase + "/albums/" + id);
return DownloadData<FullAlbum>(APIBase + "/albums/" + id + "?market=" + market); return DownloadData<FullAlbum>(APIBase + "/albums/" + id + "?market=" + market);
} }
@ -106,12 +107,12 @@ namespace SpotifyAPI.Web
/// <returns></returns> /// <returns></returns>
public SeveralAlbums GetSeveralAlbums(List<String> ids, String market = "") public SeveralAlbums GetSeveralAlbums(List<String> ids, String market = "")
{ {
if (market == "") if (String.IsNullOrEmpty(market))
return DownloadData<SeveralAlbums>(APIBase + "/albums?ids=" + string.Join(",", ids.Take(20))); return DownloadData<SeveralAlbums>(APIBase + "/albums?ids=" + string.Join(",", ids.Take(20)));
return DownloadData<SeveralAlbums>(APIBase + "/albums?market=" + market + "&ids=" + string.Join(",", ids.Take(20))); return DownloadData<SeveralAlbums>(APIBase + "/albums?market=" + market + "&ids=" + string.Join(",", ids.Take(20)));
} }
#endregion #endregion Albums
#region Artists #region Artists
@ -170,7 +171,7 @@ namespace SpotifyAPI.Web
builder.Append("?type=" + type.GetStringAttribute(",")); builder.Append("?type=" + type.GetStringAttribute(","));
builder.Append("&limit=" + limit); builder.Append("&limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<Paging<SimpleAlbum>>(builder.ToString()); return DownloadData<Paging<SimpleAlbum>>(builder.ToString());
} }
@ -185,7 +186,7 @@ namespace SpotifyAPI.Web
return DownloadData<SeveralArtists>(APIBase + "/artists?ids=" + string.Join(",", ids.Take(50))); return DownloadData<SeveralArtists>(APIBase + "/artists?ids=" + string.Join(",", ids.Take(50)));
} }
#endregion #endregion Artists
#region Browse #region Browse
@ -209,9 +210,9 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/browse/featured-playlists"); StringBuilder builder = new StringBuilder(APIBase + "/browse/featured-playlists");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (locale != "") if (!String.IsNullOrEmpty(locale))
builder.Append("&locale=" + locale); builder.Append("&locale=" + locale);
if (country != "") if (!String.IsNullOrEmpty(country))
builder.Append("&country=" + country); builder.Append("&country=" + country);
if (timestamp != default(DateTime)) if (timestamp != default(DateTime))
builder.Append("&timestamp=" + timestamp.ToString("yyyy-MM-ddTHH:mm:ss")); builder.Append("&timestamp=" + timestamp.ToString("yyyy-MM-ddTHH:mm:ss"));
@ -234,7 +235,7 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/browse/new-releases"); StringBuilder builder = new StringBuilder(APIBase + "/browse/new-releases");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (country != "") if (!String.IsNullOrEmpty(country))
builder.Append("&country=" + country); builder.Append("&country=" + country);
return DownloadData<NewAlbumReleases>(builder.ToString()); return DownloadData<NewAlbumReleases>(builder.ToString());
} }
@ -262,9 +263,9 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/browse/categories"); StringBuilder builder = new StringBuilder(APIBase + "/browse/categories");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (country != "") if (!String.IsNullOrEmpty(country))
builder.Append("&country=" + country); builder.Append("&country=" + country);
if (locale != "") if (!String.IsNullOrEmpty(locale))
builder.Append("&locale=" + locale); builder.Append("&locale=" + locale);
return DownloadData<CategoryList>(builder.ToString()); return DownloadData<CategoryList>(builder.ToString());
} }
@ -286,9 +287,9 @@ namespace SpotifyAPI.Web
public Category GetCategory(String categoryId, String country = "", String locale = "") public Category GetCategory(String categoryId, String country = "", String locale = "")
{ {
StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId); StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId);
if (country != "") if (!String.IsNullOrEmpty(country))
builder.Append("?country=" + country); builder.Append("?country=" + country);
if (locale != "") if (!String.IsNullOrEmpty(locale))
builder.Append((country == "" ? "?locale=" : "&locale=") + locale); builder.Append((country == "" ? "?locale=" : "&locale=") + locale);
return DownloadData<Category>(builder.ToString()); return DownloadData<Category>(builder.ToString());
} }
@ -308,12 +309,12 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId + "/playlists"); StringBuilder builder = new StringBuilder(APIBase + "/browse/categories/" + categoryId + "/playlists");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (country != "") if (!String.IsNullOrEmpty(country))
builder.Append("&country=" + country); builder.Append("&country=" + country);
return DownloadData<CategoryPlaylist>(builder.ToString()); return DownloadData<CategoryPlaylist>(builder.ToString());
} }
#endregion #endregion Browse
#region Follow #region Follow
@ -326,13 +327,13 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public FollowedArtists GetFollowedArtists(int limit = 20, String after = "") public FollowedArtists GetFollowedArtists(int limit = 20, String after = "")
{ {
if(!UseAuth) if (!UseAuth)
throw new InvalidOperationException("Auth is required for GetFollowedArtists"); throw new InvalidOperationException("Auth is required for GetFollowedArtists");
limit = Math.Max(limit, 50); limit = Math.Max(limit, 50);
const FollowType followType = FollowType.Artist; //currently only artist is supported. const FollowType followType = FollowType.Artist; //currently only artist is supported.
StringBuilder builder = new StringBuilder(APIBase + "/me/following?type=" + followType.GetStringAttribute("")); StringBuilder builder = new StringBuilder(APIBase + "/me/following?type=" + followType.GetStringAttribute(""));
builder.Append("&limit=" + limit); builder.Append("&limit=" + limit);
if (after != "") if (!String.IsNullOrEmpty(after))
builder.Append("&after=" + after); builder.Append("&after=" + after);
return DownloadData<FollowedArtists>(builder.ToString()); return DownloadData<FollowedArtists>(builder.ToString());
} }
@ -362,7 +363,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ErrorResponse Follow(FollowType followType, String id) public ErrorResponse Follow(FollowType followType, String id)
{ {
return Follow(followType, new List<string> {id}); return Follow(followType, new List<string> { id });
} }
/// <summary> /// <summary>
@ -390,7 +391,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ErrorResponse Unfollow(FollowType followType, String id) public ErrorResponse Unfollow(FollowType followType, String id)
{ {
return Unfollow(followType, new List<string> {id}); return Unfollow(followType, new List<string> { id });
} }
/// <summary> /// <summary>
@ -406,8 +407,8 @@ namespace SpotifyAPI.Web
throw new InvalidOperationException("Auth is required for IsFollowing"); throw new InvalidOperationException("Auth is required for IsFollowing");
JToken res = DownloadData<JToken>(APIBase + "/me/following/contains?type=" + followType.GetStringAttribute("") + "&ids=" + string.Join(",", ids)); JToken res = DownloadData<JToken>(APIBase + "/me/following/contains?type=" + followType.GetStringAttribute("") + "&ids=" + string.Join(",", ids));
if (res is JArray) if (res is JArray)
return new ListResponse<Boolean> {List = res.ToObject<List<Boolean>>(), Error = null}; return new ListResponse<Boolean> { List = res.ToObject<List<Boolean>>(), Error = null };
return new ListResponse<Boolean> {List = null, Error = res["error"].ToObject<Error>()}; return new ListResponse<Boolean> { List = null, Error = res["error"].ToObject<Error>() };
} }
/// <summary> /// <summary>
@ -419,7 +420,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ListResponse<Boolean> IsFollowing(FollowType followType, String id) public ListResponse<Boolean> IsFollowing(FollowType followType, String id)
{ {
return IsFollowing(followType, new List<string> {id}); return IsFollowing(followType, new List<string> { id });
} }
/// <summary> /// <summary>
@ -471,8 +472,8 @@ namespace SpotifyAPI.Web
throw new InvalidOperationException("Auth is required for IsFollowingPlaylist"); throw new InvalidOperationException("Auth is required for IsFollowingPlaylist");
JToken res = DownloadData<JToken>(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers/contains?ids=" + string.Join(",", ids)); JToken res = DownloadData<JToken>(APIBase + "/users/" + ownerId + "/playlists/" + playlistId + "/followers/contains?ids=" + string.Join(",", ids));
if (res is JArray) if (res is JArray)
return new ListResponse<Boolean> {List = res.ToObject<List<Boolean>>(), Error = null}; return new ListResponse<Boolean> { List = res.ToObject<List<Boolean>>(), Error = null };
return new ListResponse<Boolean> {List = null, Error = res["error"].ToObject<Error>()}; return new ListResponse<Boolean> { List = null, Error = res["error"].ToObject<Error>() };
} }
/// <summary> /// <summary>
@ -485,10 +486,10 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ListResponse<Boolean> IsFollowingPlaylist(String ownerId, String playlistId, String id) public ListResponse<Boolean> IsFollowingPlaylist(String ownerId, String playlistId, String id)
{ {
return IsFollowingPlaylist(ownerId, playlistId, new List<string> {id}); return IsFollowingPlaylist(ownerId, playlistId, new List<string> { id });
} }
#endregion #endregion Follow
#region Library #region Library
@ -512,7 +513,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ErrorResponse SaveTrack(String id) public ErrorResponse SaveTrack(String id)
{ {
return SaveTracks(new List<string> {id}); return SaveTracks(new List<string> { id });
} }
/// <summary> /// <summary>
@ -531,7 +532,7 @@ namespace SpotifyAPI.Web
StringBuilder builder = new StringBuilder(APIBase + "/me/tracks"); StringBuilder builder = new StringBuilder(APIBase + "/me/tracks");
builder.Append("?limit=" + limit); builder.Append("?limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<Paging<SavedTrack>>(builder.ToString()); return DownloadData<Paging<SavedTrack>>(builder.ToString());
} }
@ -560,11 +561,11 @@ namespace SpotifyAPI.Web
throw new InvalidOperationException("Auth is required for CheckSavedTracks"); throw new InvalidOperationException("Auth is required for CheckSavedTracks");
JToken res = DownloadData<JToken>(APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids)); JToken res = DownloadData<JToken>(APIBase + "/me/tracks/contains?ids=" + string.Join(",", ids));
if (res is JArray) if (res is JArray)
return new ListResponse<Boolean> {List = res.ToObject<List<Boolean>>(), Error = null}; return new ListResponse<Boolean> { List = res.ToObject<List<Boolean>>(), Error = null };
return new ListResponse<Boolean> {List = null, Error = res["error"].ToObject<Error>()}; return new ListResponse<Boolean> { List = null, Error = res["error"].ToObject<Error>() };
} }
#endregion #endregion Library
#region Playlists #region Playlists
@ -605,7 +606,7 @@ namespace SpotifyAPI.Web
throw new InvalidOperationException("Auth is required for GetPlaylist"); throw new InvalidOperationException("Auth is required for GetPlaylist");
StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists/" + playlistId); StringBuilder builder = new StringBuilder(APIBase + "/users/" + userId + "/playlists/" + playlistId);
builder.Append("?fields=" + fields); builder.Append("?fields=" + fields);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<FullPlaylist>(builder.ToString()); return DownloadData<FullPlaylist>(builder.ToString());
} }
@ -633,7 +634,7 @@ namespace SpotifyAPI.Web
builder.Append("?fields=" + fields); builder.Append("?fields=" + fields);
builder.Append("&limit=" + limit); builder.Append("&limit=" + limit);
builder.Append("&offset=" + offset); builder.Append("&offset=" + offset);
if (market != "") if (!String.IsNullOrEmpty(market))
builder.Append("&market=" + market); builder.Append("&market=" + market);
return DownloadData<Paging<PlaylistTrack>>(builder.ToString()); return DownloadData<Paging<PlaylistTrack>>(builder.ToString());
} }
@ -729,7 +730,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ErrorResponse RemovePlaylistTrack(String userId, String playlistId, DeleteTrackUri uri) public ErrorResponse RemovePlaylistTrack(String userId, String playlistId, DeleteTrackUri uri)
{ {
return RemovePlaylistTracks(userId, playlistId, new List<DeleteTrackUri> {uri}); return RemovePlaylistTracks(userId, playlistId, new List<DeleteTrackUri> { uri });
} }
/// <summary> /// <summary>
@ -763,7 +764,7 @@ namespace SpotifyAPI.Web
/// <remarks>AUTH NEEDED</remarks> /// <remarks>AUTH NEEDED</remarks>
public ErrorResponse AddPlaylistTrack(String userId, String playlistId, String uri, int? position = null) public ErrorResponse AddPlaylistTrack(String userId, String playlistId, String uri, int? position = null)
{ {
return AddPlaylistTracks(userId, playlistId, new List<string> {uri}, position); return AddPlaylistTracks(userId, playlistId, new List<string> { uri }, position);
} }
/// <summary> /// <summary>
@ -785,12 +786,12 @@ namespace SpotifyAPI.Web
{"range_length", rangeLength}, {"range_length", rangeLength},
{"insert_before", insertBefore} {"insert_before", insertBefore}
}; };
if (snapshotId != "") if (!String.IsNullOrEmpty(snapshotId))
body.Add("snapshot_id", snapshotId); body.Add("snapshot_id", snapshotId);
return UploadData<Snapshot>(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "PUT"); return UploadData<Snapshot>(APIBase + "/users/" + userId + "/playlists/" + playlistId + "/tracks", body.ToString(Formatting.None), "PUT");
} }
#endregion #endregion Playlists
#region Profiles #region Profiles
@ -816,7 +817,7 @@ namespace SpotifyAPI.Web
return DownloadData<PublicProfile>(APIBase + "/users/" + userId); return DownloadData<PublicProfile>(APIBase + "/users/" + userId);
} }
#endregion #endregion Profiles
#region Tracks #region Tracks
@ -828,7 +829,7 @@ namespace SpotifyAPI.Web
/// <returns></returns> /// <returns></returns>
public SeveralTracks GetSeveralTracks(List<String> ids, String market = "") public SeveralTracks GetSeveralTracks(List<String> ids, String market = "")
{ {
if (market == "") if (String.IsNullOrEmpty(market))
return DownloadData<SeveralTracks>(APIBase + "/tracks?ids=" + string.Join(",", ids.Take(50))); return DownloadData<SeveralTracks>(APIBase + "/tracks?ids=" + string.Join(",", ids.Take(50)));
return DownloadData<SeveralTracks>(APIBase + "/tracks?market=" + market + "&ids=" + string.Join(",", ids.Take(50))); return DownloadData<SeveralTracks>(APIBase + "/tracks?market=" + market + "&ids=" + string.Join(",", ids.Take(50)));
} }
@ -841,12 +842,12 @@ namespace SpotifyAPI.Web
/// <returns></returns> /// <returns></returns>
public FullTrack GetTrack(String id, String market = "") public FullTrack GetTrack(String id, String market = "")
{ {
if (market == "") if (String.IsNullOrEmpty(market))
return DownloadData<FullTrack>(APIBase + "/tracks/" + id); return DownloadData<FullTrack>(APIBase + "/tracks/" + id);
return DownloadData<FullTrack>(APIBase + "/tracks/" + id + "?market=" + market); return DownloadData<FullTrack>(APIBase + "/tracks/" + id + "?market=" + market);
} }
#endregion #endregion Tracks
#region Util #region Util
@ -868,6 +869,6 @@ namespace SpotifyAPI.Web
return WebClient.DownloadJson<T>(url); return WebClient.DownloadJson<T>(url);
} }
#endregion #endregion Util
} }
} }

View File

@ -1,10 +1,10 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using Newtonsoft.Json;
namespace SpotifyAPI.Web namespace SpotifyAPI.Web
{ {
@ -93,7 +93,7 @@ namespace SpotifyAPI.Web
public void RemoveHeader(string header) public void RemoveHeader(string header)
{ {
if(_webClient.Headers[header] != null) if (_webClient.Headers[header] != null)
_webClient.Headers.Remove(header); _webClient.Headers.Remove(header);
} }

View File

@ -24,9 +24,10 @@ namespace SpotifyAPI.Web
} }
} }
public class StringAttribute : Attribute public sealed class StringAttribute : Attribute
{ {
public String Text { get; set; } public String Text { get; set; }
public StringAttribute(String text) public StringAttribute(String text)
{ {
Text = text; Text = text;