From dd77be8a8a38c523eae70ba8fbff0564daf16e90 Mon Sep 17 00:00:00 2001 From: Alessandro Attard Barbini <11708634+aleab@users.noreply.github.com> Date: Sun, 25 Mar 2018 19:39:19 +0200 Subject: [PATCH] Added support for proxy configuration (#224) * Create ProxyConfig class + Unit tests * Use ProxyConfig in SpotifyLocalAPI * Refactor WebProxy creation in ProxyConfig * Use ProxyConfig in SpotifyWebAPI * Add ProxyConfig parameter in GetAlbumArt methods * Add ProxyConfig to WebAPIFactory * Add proxy settings to Example app * Fix ArgumentNullException in GetAlbumArtUrl when not using proxy * Performed requested changes - Removed redundant "this". - Added necessary null checks. - Added a ProxyConfig property to SpotifyLocalAPIConfig and removed constructor overloads with it in SpotifyLocalAPI and RemoteHandler. * Updated Example app --- SpotifyAPI.Example/LocalControl.Designer.cs | 341 ++++++++++++++------ SpotifyAPI.Example/LocalControl.cs | 44 ++- SpotifyAPI.Example/WebControl.Designer.cs | 160 ++++++++- SpotifyAPI.Example/WebControl.cs | 15 +- SpotifyAPI.Tests/ProxyConfigTest.cs | 116 +++++++ SpotifyAPI.Tests/SpotifyAPI.Tests.csproj | 1 + SpotifyAPI/Local/Models/Track.cs | 53 +-- SpotifyAPI/Local/RemoteHandler.cs | 6 +- SpotifyAPI/Local/SpotifyLocalAPI.cs | 2 +- SpotifyAPI/Local/SpotifyLocalAPIConfig.cs | 2 + SpotifyAPI/ProxyConfig.cs | 77 +++++ SpotifyAPI/SpotifyAPI.csproj | 1 + SpotifyAPI/Web/Auth/WebApiFactory.cs | 15 +- SpotifyAPI/Web/SpotifyWebAPI.cs | 9 +- SpotifyAPI/Web/SpotifyWebClient.cs | 35 +- 15 files changed, 733 insertions(+), 144 deletions(-) create mode 100644 SpotifyAPI.Tests/ProxyConfigTest.cs create mode 100644 SpotifyAPI/ProxyConfig.cs diff --git a/SpotifyAPI.Example/LocalControl.Designer.cs b/SpotifyAPI.Example/LocalControl.Designer.cs index b445d654..0a058cb8 100644 --- a/SpotifyAPI.Example/LocalControl.Designer.cs +++ b/SpotifyAPI.Example/LocalControl.Designer.cs @@ -30,6 +30,10 @@ { this.bigAlbumPicture = new System.Windows.Forms.PictureBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.volumeMixerLabel = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.volumeUpBtn = new System.Windows.Forms.Button(); + this.volumeDownBtn = new System.Windows.Forms.Button(); this.repeatShuffleLabel = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.versionLabel = new System.Windows.Forms.Label(); @@ -55,27 +59,36 @@ this.timeLabel = new System.Windows.Forms.Label(); this.timeProgressBar = new System.Windows.Forms.ProgressBar(); this.label5 = new System.Windows.Forms.Label(); + this.smallAlbumPicture = new System.Windows.Forms.PictureBox(); this.label4 = new System.Windows.Forms.Label(); - this.label3 = new System.Windows.Forms.Label(); - this.albumLinkLabel = new System.Windows.Forms.LinkLabel(); this.artistLinkLabel = new System.Windows.Forms.LinkLabel(); this.titleLinkLabel = new System.Windows.Forms.LinkLabel(); - this.smallAlbumPicture = new System.Windows.Forms.PictureBox(); - this.volumeDownBtn = new System.Windows.Forms.Button(); - this.volumeUpBtn = new System.Windows.Forms.Button(); - this.label9 = new System.Windows.Forms.Label(); - this.volumeMixerLabel = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.albumLinkLabel = new System.Windows.Forms.LinkLabel(); + this.proxyGroupBox = new System.Windows.Forms.GroupBox(); + this.proxyPortUpDown = new System.Windows.Forms.NumericUpDown(); + this.proxyPasswordTextBox = new System.Windows.Forms.TextBox(); + this.label15 = new System.Windows.Forms.Label(); + this.proxyUsernameTextBox = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.proxyHostTextBox = new System.Windows.Forms.TextBox(); + this.label12 = new System.Windows.Forms.Label(); + this.applyProxyBtn = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.bigAlbumPicture)).BeginInit(); this.groupBox1.SuspendLayout(); this.trackInfoBox.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.smallAlbumPicture)).BeginInit(); + this.proxyGroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.proxyPortUpDown)).BeginInit(); this.SuspendLayout(); // // bigAlbumPicture // - this.bigAlbumPicture.Location = new System.Drawing.Point(330, 13); + this.bigAlbumPicture.Location = new System.Drawing.Point(407, 93); this.bigAlbumPicture.Name = "bigAlbumPicture"; - this.bigAlbumPicture.Size = new System.Drawing.Size(640, 640); + this.bigAlbumPicture.Size = new System.Drawing.Size(560, 560); + this.bigAlbumPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.bigAlbumPicture.TabIndex = 2; this.bigAlbumPicture.TabStop = false; // @@ -105,13 +118,57 @@ this.groupBox1.Controls.Add(this.label10); this.groupBox1.Controls.Add(this.label8); this.groupBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.groupBox1.Location = new System.Drawing.Point(3, 57); + this.groupBox1.Location = new System.Drawing.Point(3, 55); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(318, 286); + this.groupBox1.Size = new System.Drawing.Size(398, 286); this.groupBox1.TabIndex = 3; this.groupBox1.TabStop = false; this.groupBox1.Text = "Spotify Info"; // + // volumeMixerLabel + // + this.volumeMixerLabel.AutoSize = true; + this.volumeMixerLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.volumeMixerLabel.Location = new System.Drawing.Point(168, 117); + this.volumeMixerLabel.Name = "volumeMixerLabel"; + this.volumeMixerLabel.Size = new System.Drawing.Size(13, 17); + this.volumeMixerLabel.TabIndex = 35; + this.volumeMixerLabel.Text = "-"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label9.Location = new System.Drawing.Point(7, 117); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(155, 17); + this.label9.TabIndex = 34; + this.label9.Text = "Volume Mixer\'s volume:"; + // + // volumeUpBtn + // + this.volumeUpBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.volumeUpBtn.Location = new System.Drawing.Point(300, 114); + this.volumeUpBtn.Margin = new System.Windows.Forms.Padding(0); + this.volumeUpBtn.Name = "volumeUpBtn"; + this.volumeUpBtn.Size = new System.Drawing.Size(92, 24); + this.volumeUpBtn.TabIndex = 33; + this.volumeUpBtn.Text = "Volume+"; + this.volumeUpBtn.UseVisualStyleBackColor = true; + this.volumeUpBtn.Click += new System.EventHandler(this.volumeUpBtn_Click); + // + // volumeDownBtn + // + this.volumeDownBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.volumeDownBtn.Location = new System.Drawing.Point(300, 138); + this.volumeDownBtn.Margin = new System.Windows.Forms.Padding(0); + this.volumeDownBtn.Name = "volumeDownBtn"; + this.volumeDownBtn.Size = new System.Drawing.Size(92, 24); + this.volumeDownBtn.TabIndex = 32; + this.volumeDownBtn.Text = "Volume-"; + this.volumeDownBtn.UseVisualStyleBackColor = true; + this.volumeDownBtn.Click += new System.EventHandler(this.volumeDownBtn_Click); + // // repeatShuffleLabel // this.repeatShuffleLabel.AutoSize = true; @@ -175,9 +232,9 @@ // skipBtn // this.skipBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.skipBtn.Location = new System.Drawing.Point(245, 252); + this.skipBtn.Location = new System.Drawing.Point(300, 252); this.skipBtn.Name = "skipBtn"; - this.skipBtn.Size = new System.Drawing.Size(67, 23); + this.skipBtn.Size = new System.Drawing.Size(92, 23); this.skipBtn.TabIndex = 24; this.skipBtn.Text = "Skip"; this.skipBtn.UseVisualStyleBackColor = true; @@ -186,9 +243,9 @@ // prevBtn // this.prevBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.prevBtn.Location = new System.Drawing.Point(164, 252); + this.prevBtn.Location = new System.Drawing.Point(202, 252); this.prevBtn.Name = "prevBtn"; - this.prevBtn.Size = new System.Drawing.Size(75, 23); + this.prevBtn.Size = new System.Drawing.Size(92, 23); this.prevBtn.TabIndex = 23; this.prevBtn.Text = "Previous"; this.prevBtn.UseVisualStyleBackColor = true; @@ -197,9 +254,9 @@ // pauseBtn // this.pauseBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.pauseBtn.Location = new System.Drawing.Point(83, 252); + this.pauseBtn.Location = new System.Drawing.Point(104, 252); this.pauseBtn.Name = "pauseBtn"; - this.pauseBtn.Size = new System.Drawing.Size(75, 23); + this.pauseBtn.Size = new System.Drawing.Size(92, 23); this.pauseBtn.TabIndex = 22; this.pauseBtn.Text = "Pause"; this.pauseBtn.UseVisualStyleBackColor = true; @@ -210,7 +267,7 @@ this.playBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.playBtn.Location = new System.Drawing.Point(6, 252); this.playBtn.Name = "playBtn"; - this.playBtn.Size = new System.Drawing.Size(71, 23); + this.playBtn.Size = new System.Drawing.Size(92, 23); this.playBtn.TabIndex = 21; this.playBtn.Text = "Play"; this.playBtn.UseVisualStyleBackColor = true; @@ -231,15 +288,15 @@ this.contextTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.contextTextBox.Location = new System.Drawing.Point(9, 226); this.contextTextBox.Name = "contextTextBox"; - this.contextTextBox.Size = new System.Drawing.Size(232, 20); + this.contextTextBox.Size = new System.Drawing.Size(285, 20); this.contextTextBox.TabIndex = 19; // // playUrlBtn // this.playUrlBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.playUrlBtn.Location = new System.Drawing.Point(247, 165); + this.playUrlBtn.Location = new System.Drawing.Point(300, 165); this.playUrlBtn.Name = "playUrlBtn"; - this.playUrlBtn.Size = new System.Drawing.Size(65, 81); + this.playUrlBtn.Size = new System.Drawing.Size(92, 81); this.playUrlBtn.TabIndex = 18; this.playUrlBtn.Text = "PlayURL"; this.playUrlBtn.UseVisualStyleBackColor = true; @@ -250,7 +307,7 @@ this.playTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.playTextBox.Location = new System.Drawing.Point(6, 185); this.playTextBox.Name = "playTextBox"; - this.playTextBox.Size = new System.Drawing.Size(232, 20); + this.playTextBox.Size = new System.Drawing.Size(288, 20); this.playTextBox.TabIndex = 17; this.playTextBox.Text = "https://open.spotify.com/track/4myBMnNWZlgvVelYeTu55w"; // @@ -308,7 +365,7 @@ // this.connectBtn.Location = new System.Drawing.Point(3, 13); this.connectBtn.Name = "connectBtn"; - this.connectBtn.Size = new System.Drawing.Size(318, 23); + this.connectBtn.Size = new System.Drawing.Size(398, 36); this.connectBtn.TabIndex = 4; this.connectBtn.Text = "Connect to Spotify"; this.connectBtn.UseVisualStyleBackColor = true; @@ -320,16 +377,16 @@ this.trackInfoBox.Controls.Add(this.timeLabel); this.trackInfoBox.Controls.Add(this.timeProgressBar); this.trackInfoBox.Controls.Add(this.label5); + this.trackInfoBox.Controls.Add(this.smallAlbumPicture); this.trackInfoBox.Controls.Add(this.label4); - this.trackInfoBox.Controls.Add(this.label3); - this.trackInfoBox.Controls.Add(this.albumLinkLabel); this.trackInfoBox.Controls.Add(this.artistLinkLabel); this.trackInfoBox.Controls.Add(this.titleLinkLabel); - this.trackInfoBox.Controls.Add(this.smallAlbumPicture); + this.trackInfoBox.Controls.Add(this.label3); + this.trackInfoBox.Controls.Add(this.albumLinkLabel); this.trackInfoBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.trackInfoBox.Location = new System.Drawing.Point(3, 349); + this.trackInfoBox.Location = new System.Drawing.Point(3, 347); this.trackInfoBox.Name = "trackInfoBox"; - this.trackInfoBox.Size = new System.Drawing.Size(318, 304); + this.trackInfoBox.Size = new System.Drawing.Size(398, 306); this.trackInfoBox.TabIndex = 4; this.trackInfoBox.TabStop = false; this.trackInfoBox.Text = "Track Info"; @@ -346,7 +403,7 @@ // this.timeLabel.AutoSize = true; this.timeLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.timeLabel.Location = new System.Drawing.Point(6, 279); + this.timeLabel.Location = new System.Drawing.Point(7, 281); this.timeLabel.Name = "timeLabel"; this.timeLabel.Size = new System.Drawing.Size(13, 17); this.timeLabel.TabIndex = 29; @@ -354,58 +411,45 @@ // // timeProgressBar // - this.timeProgressBar.Location = new System.Drawing.Point(6, 253); + this.timeProgressBar.Location = new System.Drawing.Point(6, 255); this.timeProgressBar.Name = "timeProgressBar"; - this.timeProgressBar.Size = new System.Drawing.Size(306, 23); + this.timeProgressBar.Size = new System.Drawing.Size(386, 23); this.timeProgressBar.TabIndex = 28; // // label5 // this.label5.AutoSize = true; this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(6, 227); + this.label5.Location = new System.Drawing.Point(10, 227); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(51, 17); this.label5.TabIndex = 27; this.label5.Text = "Album:"; // + // smallAlbumPicture + // + this.smallAlbumPicture.Location = new System.Drawing.Point(123, 22); + this.smallAlbumPicture.Name = "smallAlbumPicture"; + this.smallAlbumPicture.Size = new System.Drawing.Size(150, 150); + this.smallAlbumPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.smallAlbumPicture.TabIndex = 5; + this.smallAlbumPicture.TabStop = false; + // // label4 // this.label4.AutoSize = true; this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(13, 204); + this.label4.Location = new System.Drawing.Point(17, 204); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(44, 17); this.label4.TabIndex = 26; this.label4.Text = "Artist:"; // - // label3 - // - this.label3.AutoSize = true; - this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(18, 182); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(39, 17); - this.label3.TabIndex = 25; - this.label3.Text = "Title:"; - // - // albumLinkLabel - // - this.albumLinkLabel.AutoSize = true; - this.albumLinkLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.albumLinkLabel.Location = new System.Drawing.Point(63, 227); - this.albumLinkLabel.Name = "albumLinkLabel"; - this.albumLinkLabel.Size = new System.Drawing.Size(13, 17); - this.albumLinkLabel.TabIndex = 7; - this.albumLinkLabel.TabStop = true; - this.albumLinkLabel.Text = "-"; - this.albumLinkLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // // artistLinkLabel // this.artistLinkLabel.AutoSize = true; this.artistLinkLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.artistLinkLabel.Location = new System.Drawing.Point(63, 204); + this.artistLinkLabel.Location = new System.Drawing.Point(67, 204); this.artistLinkLabel.Name = "artistLinkLabel"; this.artistLinkLabel.Size = new System.Drawing.Size(13, 17); this.artistLinkLabel.TabIndex = 6; @@ -420,7 +464,7 @@ | System.Windows.Forms.AnchorStyles.Right))); this.titleLinkLabel.AutoSize = true; this.titleLinkLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.titleLinkLabel.Location = new System.Drawing.Point(63, 182); + this.titleLinkLabel.Location = new System.Drawing.Point(67, 182); this.titleLinkLabel.Name = "titleLinkLabel"; this.titleLinkLabel.Size = new System.Drawing.Size(13, 17); this.titleLinkLabel.TabIndex = 5; @@ -428,62 +472,148 @@ this.titleLinkLabel.Text = "-"; this.titleLinkLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // smallAlbumPicture + // label3 // - this.smallAlbumPicture.Location = new System.Drawing.Point(81, 19); - this.smallAlbumPicture.Name = "smallAlbumPicture"; - this.smallAlbumPicture.Size = new System.Drawing.Size(160, 160); - this.smallAlbumPicture.TabIndex = 5; - this.smallAlbumPicture.TabStop = false; + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(22, 182); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(39, 17); + this.label3.TabIndex = 25; + this.label3.Text = "Title:"; // - // volumeDownBtn + // albumLinkLabel // - this.volumeDownBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.volumeDownBtn.Location = new System.Drawing.Point(247, 134); - this.volumeDownBtn.Margin = new System.Windows.Forms.Padding(0); - this.volumeDownBtn.Name = "volumeDownBtn"; - this.volumeDownBtn.Size = new System.Drawing.Size(65, 24); - this.volumeDownBtn.TabIndex = 32; - this.volumeDownBtn.Text = "Volume-"; - this.volumeDownBtn.UseVisualStyleBackColor = true; - this.volumeDownBtn.Click += new System.EventHandler(this.volumeDownBtn_Click); + this.albumLinkLabel.AutoSize = true; + this.albumLinkLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.albumLinkLabel.Location = new System.Drawing.Point(67, 227); + this.albumLinkLabel.Name = "albumLinkLabel"; + this.albumLinkLabel.Size = new System.Drawing.Size(13, 17); + this.albumLinkLabel.TabIndex = 7; + this.albumLinkLabel.TabStop = true; + this.albumLinkLabel.Text = "-"; + this.albumLinkLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // volumeUpBtn + // proxyGroupBox // - this.volumeUpBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.volumeUpBtn.Location = new System.Drawing.Point(247, 110); - this.volumeUpBtn.Margin = new System.Windows.Forms.Padding(0); - this.volumeUpBtn.Name = "volumeUpBtn"; - this.volumeUpBtn.Size = new System.Drawing.Size(65, 24); - this.volumeUpBtn.TabIndex = 33; - this.volumeUpBtn.Text = "Volume+"; - this.volumeUpBtn.UseVisualStyleBackColor = true; - this.volumeUpBtn.Click += new System.EventHandler(this.volumeUpBtn_Click); + this.proxyGroupBox.Controls.Add(this.proxyPortUpDown); + this.proxyGroupBox.Controls.Add(this.proxyPasswordTextBox); + this.proxyGroupBox.Controls.Add(this.label15); + this.proxyGroupBox.Controls.Add(this.proxyUsernameTextBox); + this.proxyGroupBox.Controls.Add(this.label14); + this.proxyGroupBox.Controls.Add(this.label13); + this.proxyGroupBox.Controls.Add(this.proxyHostTextBox); + this.proxyGroupBox.Controls.Add(this.label12); + this.proxyGroupBox.Controls.Add(this.applyProxyBtn); + this.proxyGroupBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F); + this.proxyGroupBox.Location = new System.Drawing.Point(407, 10); + this.proxyGroupBox.Name = "proxyGroupBox"; + this.proxyGroupBox.Size = new System.Drawing.Size(560, 77); + this.proxyGroupBox.TabIndex = 5; + this.proxyGroupBox.TabStop = false; + this.proxyGroupBox.Text = "Proxy Config"; // - // label9 + // proxyPortUpDown // - this.label9.AutoSize = true; - this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label9.Location = new System.Drawing.Point(7, 117); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(155, 17); - this.label9.TabIndex = 34; - this.label9.Text = "Volume Mixer\'s volume:"; + this.proxyPortUpDown.Location = new System.Drawing.Point(324, 18); + this.proxyPortUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.proxyPortUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.proxyPortUpDown.Name = "proxyPortUpDown"; + this.proxyPortUpDown.Size = new System.Drawing.Size(157, 24); + this.proxyPortUpDown.TabIndex = 6; + this.proxyPortUpDown.Value = new decimal(new int[] { + 80, + 0, + 0, + 0}); // - // volumeMixerLabel + // proxyPasswordTextBox // - this.volumeMixerLabel.AutoSize = true; - this.volumeMixerLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.volumeMixerLabel.Location = new System.Drawing.Point(168, 117); - this.volumeMixerLabel.Name = "volumeMixerLabel"; - this.volumeMixerLabel.Size = new System.Drawing.Size(13, 17); - this.volumeMixerLabel.TabIndex = 35; - this.volumeMixerLabel.Text = "-"; + this.proxyPasswordTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyPasswordTextBox.Location = new System.Drawing.Point(359, 47); + this.proxyPasswordTextBox.Name = "proxyPasswordTextBox"; + this.proxyPasswordTextBox.Size = new System.Drawing.Size(122, 20); + this.proxyPasswordTextBox.TabIndex = 42; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label15.Location = new System.Drawing.Point(280, 48); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(73, 17); + this.label15.TabIndex = 41; + this.label15.Text = "Password:"; + // + // proxyUsernameTextBox + // + this.proxyUsernameTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyUsernameTextBox.Location = new System.Drawing.Point(89, 47); + this.proxyUsernameTextBox.Name = "proxyUsernameTextBox"; + this.proxyUsernameTextBox.Size = new System.Drawing.Size(185, 20); + this.proxyUsernameTextBox.TabIndex = 40; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label14.Location = new System.Drawing.Point(6, 48); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(77, 17); + this.label14.TabIndex = 39; + this.label14.Text = "Username:"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label13.Location = new System.Drawing.Point(280, 22); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(38, 17); + this.label13.TabIndex = 37; + this.label13.Text = "Port:"; + // + // proxyHostTextBox + // + this.proxyHostTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyHostTextBox.Location = new System.Drawing.Point(49, 21); + this.proxyHostTextBox.Name = "proxyHostTextBox"; + this.proxyHostTextBox.Size = new System.Drawing.Size(225, 20); + this.proxyHostTextBox.TabIndex = 36; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label12.Location = new System.Drawing.Point(6, 22); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(41, 17); + this.label12.TabIndex = 36; + this.label12.Text = "Host:"; + // + // applyProxyBtn + // + this.applyProxyBtn.Location = new System.Drawing.Point(487, 15); + this.applyProxyBtn.Name = "applyProxyBtn"; + this.applyProxyBtn.Size = new System.Drawing.Size(67, 56); + this.applyProxyBtn.TabIndex = 0; + this.applyProxyBtn.Text = "Apply"; + this.applyProxyBtn.UseVisualStyleBackColor = true; + this.applyProxyBtn.Click += new System.EventHandler(this.applyProxyBtn_Click); // // LocalControl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.proxyGroupBox); this.Controls.Add(this.trackInfoBox); this.Controls.Add(this.connectBtn); this.Controls.Add(this.groupBox1); @@ -496,6 +626,9 @@ this.trackInfoBox.ResumeLayout(false); this.trackInfoBox.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.smallAlbumPicture)).EndInit(); + this.proxyGroupBox.ResumeLayout(false); + this.proxyGroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.proxyPortUpDown)).EndInit(); this.ResumeLayout(false); } @@ -539,5 +672,15 @@ private System.Windows.Forms.Button volumeDownBtn; private System.Windows.Forms.Label volumeMixerLabel; private System.Windows.Forms.Label label9; + private System.Windows.Forms.GroupBox proxyGroupBox; + private System.Windows.Forms.TextBox proxyPasswordTextBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox proxyUsernameTextBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox proxyHostTextBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Button applyProxyBtn; + private System.Windows.Forms.NumericUpDown proxyPortUpDown; } } diff --git a/SpotifyAPI.Example/LocalControl.cs b/SpotifyAPI.Example/LocalControl.cs index 32775ad3..31ed6af6 100644 --- a/SpotifyAPI.Example/LocalControl.cs +++ b/SpotifyAPI.Example/LocalControl.cs @@ -10,14 +10,20 @@ namespace SpotifyAPI.Example { public partial class LocalControl : UserControl { - private readonly SpotifyLocalAPI _spotify; + private readonly SpotifyLocalAPIConfig _config; + private SpotifyLocalAPI _spotify; private Track _currentTrack; public LocalControl() { InitializeComponent(); + + _config = new SpotifyLocalAPIConfig + { + ProxyConfig = new ProxyConfig() + }; - _spotify = new SpotifyLocalAPI(); + _spotify = new SpotifyLocalAPI(_config); _spotify.OnPlayStateChange += _spotify_OnPlayStateChange; _spotify.OnTrackChange += _spotify_OnTrackChange; _spotify.OnTrackTimeChange += _spotify_OnTrackTimeChange; @@ -99,8 +105,8 @@ namespace SpotifyAPI.Example trackInfoBox.Text = $@"Track Info - {uri?.Id}"; - bigAlbumPicture.Image = track.AlbumResource != null ? await track.GetAlbumArtAsync(AlbumArtSize.Size640) : null; - smallAlbumPicture.Image = track.AlbumResource != null ? await track.GetAlbumArtAsync(AlbumArtSize.Size160) : null; + bigAlbumPicture.Image = track.AlbumResource != null ? await track.GetAlbumArtAsync(AlbumArtSize.Size640, _config.ProxyConfig) : null; + smallAlbumPicture.Image = track.AlbumResource != null ? await track.GetAlbumArtAsync(AlbumArtSize.Size160, _config.ProxyConfig) : null; } public void UpdatePlayingStatus(bool playing) @@ -113,6 +119,36 @@ namespace SpotifyAPI.Example volumeMixerLabel.Text = _spotify.GetSpotifyVolume().ToString(CultureInfo.InvariantCulture); } + private void applyProxyBtn_Click(object sender, EventArgs e) + { + _config.ProxyConfig.Host = proxyHostTextBox.Text; + _config.ProxyConfig.Port = (int)proxyPortUpDown.Value; + _config.ProxyConfig.Username = proxyUsernameTextBox.Text; + _config.ProxyConfig.Password = proxyPasswordTextBox.Text; + + bool connected = _spotify.ListenForEvents; + if (connected) + { + // Reconnect using new proxy + _spotify.ListenForEvents = false; + _spotify.OnPlayStateChange -= _spotify_OnPlayStateChange; + _spotify.OnTrackChange -= _spotify_OnTrackChange; + _spotify.OnTrackTimeChange -= _spotify_OnTrackTimeChange; + _spotify.OnVolumeChange -= _spotify_OnVolumeChange; + + _spotify.Dispose(); + + _spotify = new SpotifyLocalAPI(_config); + _spotify.OnPlayStateChange += _spotify_OnPlayStateChange; + _spotify.OnTrackChange += _spotify_OnTrackChange; + _spotify.OnTrackTimeChange += _spotify_OnTrackTimeChange; + _spotify.OnVolumeChange += _spotify_OnVolumeChange; + + connectBtn.Text = @"Reconnecting..."; + Connect(); + } + } + private void _spotify_OnVolumeChange(object sender, VolumeChangeEventArgs e) { if (InvokeRequired) diff --git a/SpotifyAPI.Example/WebControl.Designer.cs b/SpotifyAPI.Example/WebControl.Designer.cs index dfd47631..4bbb6ba2 100644 --- a/SpotifyAPI.Example/WebControl.Designer.cs +++ b/SpotifyAPI.Example/WebControl.Designer.cs @@ -47,7 +47,19 @@ this.emailLabel = new System.Windows.Forms.Label(); this.accountLabel = new System.Windows.Forms.Label(); this.avatarPictureBox = new System.Windows.Forms.PictureBox(); + this.proxyGroupBox = new System.Windows.Forms.GroupBox(); + this.proxyPortUpDown = new System.Windows.Forms.NumericUpDown(); + this.proxyPasswordTextBox = new System.Windows.Forms.TextBox(); + this.label15 = new System.Windows.Forms.Label(); + this.proxyUsernameTextBox = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.proxyHostTextBox = new System.Windows.Forms.TextBox(); + this.label12 = new System.Windows.Forms.Label(); + this.applyProxyBtn = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.avatarPictureBox)).BeginInit(); + this.proxyGroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.proxyPortUpDown)).BeginInit(); this.SuspendLayout(); // // authButton @@ -64,7 +76,7 @@ // this.label3.AutoSize = true; this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label3.Location = new System.Drawing.Point(3, 73); + this.label3.Location = new System.Drawing.Point(3, 251); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(100, 17); this.label3.TabIndex = 5; @@ -74,7 +86,7 @@ // this.label4.AutoSize = true; this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label4.Location = new System.Drawing.Point(3, 90); + this.label4.Location = new System.Drawing.Point(3, 268); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(61, 17); this.label4.TabIndex = 6; @@ -84,7 +96,7 @@ // this.label5.AutoSize = true; this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label5.Location = new System.Drawing.Point(3, 107); + this.label5.Location = new System.Drawing.Point(3, 285); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(51, 17); this.label5.TabIndex = 7; @@ -94,7 +106,7 @@ // this.label1.AutoSize = true; this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.label1.Location = new System.Drawing.Point(3, 124); + this.label1.Location = new System.Drawing.Point(3, 302); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(100, 17); this.label1.TabIndex = 8; @@ -181,7 +193,7 @@ // this.displayNameLabel.AutoSize = true; this.displayNameLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.displayNameLabel.Location = new System.Drawing.Point(109, 73); + this.displayNameLabel.Location = new System.Drawing.Point(109, 251); this.displayNameLabel.Name = "displayNameLabel"; this.displayNameLabel.Size = new System.Drawing.Size(13, 17); this.displayNameLabel.TabIndex = 15; @@ -191,7 +203,7 @@ // this.countryLabel.AutoSize = true; this.countryLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.countryLabel.Location = new System.Drawing.Point(70, 90); + this.countryLabel.Location = new System.Drawing.Point(70, 268); this.countryLabel.Name = "countryLabel"; this.countryLabel.Size = new System.Drawing.Size(13, 17); this.countryLabel.TabIndex = 16; @@ -201,7 +213,7 @@ // this.emailLabel.AutoSize = true; this.emailLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.emailLabel.Location = new System.Drawing.Point(60, 107); + this.emailLabel.Location = new System.Drawing.Point(60, 285); this.emailLabel.Name = "emailLabel"; this.emailLabel.Size = new System.Drawing.Size(13, 17); this.emailLabel.TabIndex = 17; @@ -211,7 +223,7 @@ // this.accountLabel.AutoSize = true; this.accountLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.accountLabel.Location = new System.Drawing.Point(109, 124); + this.accountLabel.Location = new System.Drawing.Point(109, 302); this.accountLabel.Name = "accountLabel"; this.accountLabel.Size = new System.Drawing.Size(13, 17); this.accountLabel.TabIndex = 18; @@ -219,16 +231,133 @@ // // avatarPictureBox // - this.avatarPictureBox.Location = new System.Drawing.Point(3, 144); + this.avatarPictureBox.Location = new System.Drawing.Point(3, 322); this.avatarPictureBox.Name = "avatarPictureBox"; this.avatarPictureBox.Size = new System.Drawing.Size(234, 212); this.avatarPictureBox.TabIndex = 19; this.avatarPictureBox.TabStop = false; // + // proxyGroupBox + // + this.proxyGroupBox.Controls.Add(this.proxyPortUpDown); + this.proxyGroupBox.Controls.Add(this.proxyPasswordTextBox); + this.proxyGroupBox.Controls.Add(this.label15); + this.proxyGroupBox.Controls.Add(this.proxyUsernameTextBox); + this.proxyGroupBox.Controls.Add(this.label14); + this.proxyGroupBox.Controls.Add(this.label13); + this.proxyGroupBox.Controls.Add(this.proxyHostTextBox); + this.proxyGroupBox.Controls.Add(this.label12); + this.proxyGroupBox.Controls.Add(this.applyProxyBtn); + this.proxyGroupBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 11F); + this.proxyGroupBox.Location = new System.Drawing.Point(6, 73); + this.proxyGroupBox.Name = "proxyGroupBox"; + this.proxyGroupBox.Size = new System.Drawing.Size(231, 167); + this.proxyGroupBox.TabIndex = 20; + this.proxyGroupBox.TabStop = false; + this.proxyGroupBox.Text = "Proxy Config"; + // + // proxyPortUpDown + // + this.proxyPortUpDown.Location = new System.Drawing.Point(50, 47); + this.proxyPortUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.proxyPortUpDown.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.proxyPortUpDown.Name = "proxyPortUpDown"; + this.proxyPortUpDown.Size = new System.Drawing.Size(76, 24); + this.proxyPortUpDown.TabIndex = 6; + this.proxyPortUpDown.Value = new decimal(new int[] { + 80, + 0, + 0, + 0}); + // + // proxyPasswordTextBox + // + this.proxyPasswordTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyPasswordTextBox.Location = new System.Drawing.Point(85, 103); + this.proxyPasswordTextBox.Name = "proxyPasswordTextBox"; + this.proxyPasswordTextBox.Size = new System.Drawing.Size(140, 20); + this.proxyPasswordTextBox.TabIndex = 42; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label15.Location = new System.Drawing.Point(6, 104); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(73, 17); + this.label15.TabIndex = 41; + this.label15.Text = "Password:"; + // + // proxyUsernameTextBox + // + this.proxyUsernameTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyUsernameTextBox.Location = new System.Drawing.Point(89, 77); + this.proxyUsernameTextBox.Name = "proxyUsernameTextBox"; + this.proxyUsernameTextBox.Size = new System.Drawing.Size(136, 20); + this.proxyUsernameTextBox.TabIndex = 40; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label14.Location = new System.Drawing.Point(6, 78); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(77, 17); + this.label14.TabIndex = 39; + this.label14.Text = "Username:"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label13.Location = new System.Drawing.Point(6, 51); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(38, 17); + this.label13.TabIndex = 37; + this.label13.Text = "Port:"; + // + // proxyHostTextBox + // + this.proxyHostTextBox.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.proxyHostTextBox.Location = new System.Drawing.Point(49, 21); + this.proxyHostTextBox.Name = "proxyHostTextBox"; + this.proxyHostTextBox.Size = new System.Drawing.Size(176, 20); + this.proxyHostTextBox.TabIndex = 36; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label12.Location = new System.Drawing.Point(6, 22); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(41, 17); + this.label12.TabIndex = 36; + this.label12.Text = "Host:"; + // + // applyProxyBtn + // + this.applyProxyBtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.applyProxyBtn.Location = new System.Drawing.Point(147, 136); + this.applyProxyBtn.Name = "applyProxyBtn"; + this.applyProxyBtn.Size = new System.Drawing.Size(78, 25); + this.applyProxyBtn.TabIndex = 0; + this.applyProxyBtn.Text = "Apply"; + this.applyProxyBtn.UseVisualStyleBackColor = true; + this.applyProxyBtn.Click += new System.EventHandler(this.applyProxyBtn_Click); + // // WebControl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.proxyGroupBox); this.Controls.Add(this.avatarPictureBox); this.Controls.Add(this.accountLabel); this.Controls.Add(this.emailLabel); @@ -248,6 +377,9 @@ this.Name = "WebControl"; this.Size = new System.Drawing.Size(970, 670); ((System.ComponentModel.ISupportInitialize)(this.avatarPictureBox)).EndInit(); + this.proxyGroupBox.ResumeLayout(false); + this.proxyGroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.proxyPortUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -274,5 +406,15 @@ private System.Windows.Forms.Label emailLabel; private System.Windows.Forms.Label accountLabel; private System.Windows.Forms.PictureBox avatarPictureBox; + private System.Windows.Forms.GroupBox proxyGroupBox; + private System.Windows.Forms.NumericUpDown proxyPortUpDown; + private System.Windows.Forms.TextBox proxyPasswordTextBox; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox proxyUsernameTextBox; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.TextBox proxyHostTextBox; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Button applyProxyBtn; } } diff --git a/SpotifyAPI.Example/WebControl.cs b/SpotifyAPI.Example/WebControl.cs index 378a9c66..a195803f 100644 --- a/SpotifyAPI.Example/WebControl.cs +++ b/SpotifyAPI.Example/WebControl.cs @@ -15,6 +15,7 @@ namespace SpotifyAPI.Example { public partial class WebControl : UserControl { + private readonly ProxyConfig _proxyConfig; private SpotifyWebAPI _spotify; private PrivateProfile _profile; @@ -25,8 +26,9 @@ namespace SpotifyAPI.Example { InitializeComponent(); + _proxyConfig = new ProxyConfig(); + _savedTracks = new List(); - } private async void InitialSetup() @@ -109,7 +111,8 @@ namespace SpotifyAPI.Example "26d287105e31491889f3cd293d85bfea", Scope.UserReadPrivate | Scope.UserReadEmail | Scope.PlaylistReadPrivate | Scope.UserLibraryRead | Scope.UserReadPrivate | Scope.UserFollowRead | Scope.UserReadBirthdate | Scope.UserTopRead | Scope.PlaylistReadCollaborative | - Scope.UserReadRecentlyPlayed | Scope.UserReadPlaybackState | Scope.UserModifyPlaybackState); + Scope.UserReadRecentlyPlayed | Scope.UserReadPlaybackState | Scope.UserModifyPlaybackState, + _proxyConfig); try { @@ -125,5 +128,13 @@ namespace SpotifyAPI.Example InitialSetup(); } + + private void applyProxyBtn_Click(object sender, EventArgs e) + { + _proxyConfig.Host = proxyHostTextBox.Text; + _proxyConfig.Port = (int)proxyPortUpDown.Value; + _proxyConfig.Username = proxyUsernameTextBox.Text; + _proxyConfig.Password = proxyPasswordTextBox.Text; + } } } \ No newline at end of file diff --git a/SpotifyAPI.Tests/ProxyConfigTest.cs b/SpotifyAPI.Tests/ProxyConfigTest.cs new file mode 100644 index 00000000..d4b20b01 --- /dev/null +++ b/SpotifyAPI.Tests/ProxyConfigTest.cs @@ -0,0 +1,116 @@ +using System; +using NUnit.Framework; + +namespace SpotifyAPI.Tests +{ + [TestFixture] + public class ProxyConfigTest + { + #region GetUri + + [Test] + public void GetUri_HostNameWithScheme() + { + ProxyConfig config = new ProxyConfig { Host = "https://test-host.com" }; + CheckUri(config.GetUri(), "https", "test-host.com", 80); + } + + [Test] + public void GetUri_HostNameWithoutScheme() + { + ProxyConfig config = new ProxyConfig { Host = "test-host.com" }; + CheckUri(config.GetUri(), "http", "test-host.com", 80); + } + + [Test] + public void GetUri_HostNameWithSchemeAndPort() + { + ProxyConfig config = new ProxyConfig + { + Host = "https://test-host.com", + Port = 8080 + }; + CheckUri(config.GetUri(), "https", "test-host.com", 8080); + } + + [Test] + public void GetUri_HostAddressWithScheme() + { + ProxyConfig config = new ProxyConfig { Host = "https://192.168.0.1" }; + CheckUri(config.GetUri(), "https", "192.168.0.1", 80); + } + + [Test] + public void GetUri_HostAddressWithoutScheme() + { + ProxyConfig config = new ProxyConfig { Host = "192.168.0.1" }; + CheckUri(config.GetUri(), "http", "192.168.0.1", 80); + } + + [Test] + public void GetUri_HostAddressWithSchemeAndPort() + { + ProxyConfig config = new ProxyConfig + { + Host = "https://192.168.0.1", + Port = 8080 + }; + CheckUri(config.GetUri(), "https", "192.168.0.1", 8080); + } + + [Test] + public void GetUri_NullHost() + { + ProxyConfig config = new ProxyConfig { Host = null }; + Assert.Throws(() => config.GetUri()); + } + + [Test] + public void GetUri_EmptyHost() + { + ProxyConfig config = new ProxyConfig { Host = string.Empty }; + Assert.Throws(() => config.GetUri()); + } + + [Test] + public void GetUri_NegativePort() + { + ProxyConfig config = new ProxyConfig + { + Host = "test-host.com", + Port = -10 + }; + Assert.Throws(() => config.GetUri()); + } + + #endregion GetUri + + [Test] + public void Set_Null() + { + ProxyConfig config = new ProxyConfig + { + Host = "https://test-host.com", + Port = 1234, + Username = "admin", + Password = "password", + BypassProxyOnLocal = true + }; + config.Set(null); + + Assert.NotNull(config); + Assert.Null(config.Host); + Assert.AreEqual(80, config.Port); + Assert.Null(config.Username); + Assert.Null(config.Password); + Assert.False(config.BypassProxyOnLocal); + } + + private static void CheckUri(Uri uri, string expectedScheme, string expectedHost, int expectedPort) + { + Assert.AreEqual(expectedScheme, uri.Scheme); + Assert.AreEqual(expectedHost, uri.Host); + Assert.AreEqual(expectedPort, uri.Port); + } + } +} \ No newline at end of file diff --git a/SpotifyAPI.Tests/SpotifyAPI.Tests.csproj b/SpotifyAPI.Tests/SpotifyAPI.Tests.csproj index 492155bd..528cecaf 100644 --- a/SpotifyAPI.Tests/SpotifyAPI.Tests.csproj +++ b/SpotifyAPI.Tests/SpotifyAPI.Tests.csproj @@ -54,6 +54,7 @@ + diff --git a/SpotifyAPI/Local/Models/Track.cs b/SpotifyAPI/Local/Models/Track.cs index ea50741f..b6b93b1d 100755 --- a/SpotifyAPI/Local/Models/Track.cs +++ b/SpotifyAPI/Local/Models/Track.cs @@ -38,7 +38,7 @@ namespace SpotifyAPI.Local.Models return true; return false; } - + /// /// Checks if the track id of type "other" /// @@ -52,8 +52,14 @@ namespace SpotifyAPI.Local.Models /// Returns a URL to the album cover in the provided size /// /// AlbumArtSize (160,320,640) + /// Optional proxy settings /// A String, which is the URL to the Albumart - public string GetAlbumArtUrl(AlbumArtSize size) + public string GetAlbumArtUrl(AlbumArtSize size, ProxyConfig proxyConfig = null) + { + return GetAlbumArtUrl(size, proxyConfig?.CreateWebProxy()); + } + + private string GetAlbumArtUrl(AlbumArtSize size, IWebProxy proxy = null) { if (AlbumResource.Uri == null || !AlbumResource.Uri.Contains("spotify:album:") || AlbumResource.Uri.Contains("spotify:album:0000000000000000000000")) return ""; @@ -76,7 +82,8 @@ namespace SpotifyAPI.Local.Models string raw; using (WebClient wc = new WebClient()) { - wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); + wc.Proxy = proxy; + wc.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"); raw = wc.DownloadString("http://open.spotify.com/album/" + AlbumResource.Uri.Split(new[] { ":" }, StringSplitOptions.None)[2]); } raw = raw.Replace("\t", ""); @@ -102,32 +109,36 @@ namespace SpotifyAPI.Local.Models /// Returns a Bitmap of the album cover in the provided size asynchronous /// /// AlbumArtSize (160,320,640) + /// Optional proxy settings /// A Bitmap, which is the albumart - public async Task GetAlbumArtAsync(AlbumArtSize size) + public async Task GetAlbumArtAsync(AlbumArtSize size, ProxyConfig proxyConfig = null) { - using (WebClient wc = new WebClient()) + var data = await GetAlbumArtAsByteArrayAsync(size, proxyConfig).ConfigureAwait(false); + if (data != null) { - string url = GetAlbumArtUrl(size); - if (url == "") - return null; - var data = await wc.DownloadDataTaskAsync(url).ConfigureAwait(false); using (MemoryStream ms = new MemoryStream(data)) { return (Bitmap)Image.FromStream(ms); } } + + return null; } /// /// Returns a byte[] of the the album cover in the provided size asynchronous /// /// AlbumArtSize (160,320,640) + /// Optional proxy settings /// A byte[], which is the albumart in binary data - public Task GetAlbumArtAsByteArrayAsync(AlbumArtSize size) + public Task GetAlbumArtAsByteArrayAsync(AlbumArtSize size, ProxyConfig proxyConfig = null) { using (WebClient wc = new WebClient()) { - string url = GetAlbumArtUrl(size); + IWebProxy proxy = proxyConfig?.CreateWebProxy(); + wc.Proxy = proxy; + + string url = GetAlbumArtUrl(size, proxy); if (url == "") return null; return wc.DownloadDataTaskAsync(url); @@ -138,32 +149,36 @@ namespace SpotifyAPI.Local.Models /// Returns a Bitmap of the album cover in the provided size /// /// AlbumArtSize (160,320,640) + /// Optional proxy settings /// A Bitmap, which is the albumart - public Bitmap GetAlbumArt(AlbumArtSize size) + public Bitmap GetAlbumArt(AlbumArtSize size, ProxyConfig proxyConfig = null) { - using (WebClient wc = new WebClient()) + var data = GetAlbumArtAsByteArray(size, proxyConfig); + if (data != null) { - string url = GetAlbumArtUrl(size); - if (string.IsNullOrEmpty(url)) - return null; - var data = wc.DownloadData(url); using (MemoryStream ms = new MemoryStream(data)) { return (Bitmap)Image.FromStream(ms); } } + + return null; } /// /// Returns a byte[] of the album cover in the provided size /// /// AlbumArtSize (160,320,640) + /// Optional proxy settings /// A byte[], which is the albumart in binary data - public byte[] GetAlbumArtAsByteArray(AlbumArtSize size) + public byte[] GetAlbumArtAsByteArray(AlbumArtSize size, ProxyConfig proxyConfig = null) { using (WebClient wc = new WebClient()) { - string url = GetAlbumArtUrl(size); + IWebProxy proxy = proxyConfig?.CreateWebProxy(); + wc.Proxy = proxy; + + string url = GetAlbumArtUrl(size, proxy); if (string.IsNullOrEmpty(url)) return null; return wc.DownloadData(url); diff --git a/SpotifyAPI/Local/RemoteHandler.cs b/SpotifyAPI/Local/RemoteHandler.cs index 7c5e710a..2afbae92 100644 --- a/SpotifyAPI/Local/RemoteHandler.cs +++ b/SpotifyAPI/Local/RemoteHandler.cs @@ -182,8 +182,10 @@ namespace SpotifyAPI.Local internal WebClient GetWebClientWithUserAgentHeader() { - WebClient wc = new WebClient(); - + WebClient wc = new WebClient + { + Proxy = _config?.ProxyConfig?.CreateWebProxy() + }; wc.Headers.Add(HttpRequestHeader.UserAgent, "Spotify (1.0.50.41368.gbd68dbef)"); return wc; diff --git a/SpotifyAPI/Local/SpotifyLocalAPI.cs b/SpotifyAPI/Local/SpotifyLocalAPI.cs index 28b0777c..813d84b4 100644 --- a/SpotifyAPI/Local/SpotifyLocalAPI.cs +++ b/SpotifyAPI/Local/SpotifyLocalAPI.cs @@ -108,7 +108,7 @@ namespace SpotifyAPI.Local if (newStatusResponse.Track != null && _eventStatusResponse.Track != null) { if (newStatusResponse.Track.TrackResource?.Uri != _eventStatusResponse.Track.TrackResource?.Uri || - newStatusResponse.Track.IsOtherTrackType() && newStatusResponse.Track.Length != this._eventStatusResponse.Track.Length) + newStatusResponse.Track.IsOtherTrackType() && newStatusResponse.Track.Length != _eventStatusResponse.Track.Length) { OnTrackChange?.Invoke(this, new TrackChangeEventArgs() { diff --git a/SpotifyAPI/Local/SpotifyLocalAPIConfig.cs b/SpotifyAPI/Local/SpotifyLocalAPIConfig.cs index 7234675b..bd9bea54 100644 --- a/SpotifyAPI/Local/SpotifyLocalAPIConfig.cs +++ b/SpotifyAPI/Local/SpotifyLocalAPIConfig.cs @@ -8,5 +8,7 @@ public string HostUrl { get; set; } = "http://127.0.0.1"; public int Port { get; set; } = 4381; + + public ProxyConfig ProxyConfig { get; set; } } } \ No newline at end of file diff --git a/SpotifyAPI/ProxyConfig.cs b/SpotifyAPI/ProxyConfig.cs new file mode 100644 index 00000000..779666b2 --- /dev/null +++ b/SpotifyAPI/ProxyConfig.cs @@ -0,0 +1,77 @@ +using System; +using System.Net; + +namespace SpotifyAPI +{ + public class ProxyConfig + { + public string Host { get; set; } + + public int Port { get; set; } = 80; + + public string Username { get; set; } + + public string Password { get; set; } + + /// + /// Whether to bypass the proxy server for local addresses. + /// + public bool BypassProxyOnLocal { get; set; } + + public void Set(ProxyConfig proxyConfig) + { + Host = proxyConfig?.Host; + Port = proxyConfig?.Port ?? 80; + Username = proxyConfig?.Username; + Password = proxyConfig?.Password; + BypassProxyOnLocal = proxyConfig?.BypassProxyOnLocal ?? false; + } + + /// + /// Whether both and have valid values. + /// + /// + public bool IsValid() + { + return !string.IsNullOrWhiteSpace(Host) && Port > 0; + } + + /// + /// Create a from the host and port number + /// + /// A URI + public Uri GetUri() + { + UriBuilder uriBuilder = new UriBuilder(Host) + { + Port = Port + }; + return uriBuilder.Uri; + } + + /// + /// Creates a from the proxy details of this object. + /// + /// A or null if the proxy details are invalid. + public WebProxy CreateWebProxy() + { + if (!IsValid()) + return null; + + WebProxy proxy = new WebProxy + { + Address = GetUri(), + UseDefaultCredentials = true, + BypassProxyOnLocal = BypassProxyOnLocal + }; + + if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password)) + { + proxy.UseDefaultCredentials = false; + proxy.Credentials = new NetworkCredential(Username, Password); + } + + return proxy; + } + } +} \ No newline at end of file diff --git a/SpotifyAPI/SpotifyAPI.csproj b/SpotifyAPI/SpotifyAPI.csproj index f7ca413e..4fa3577e 100644 --- a/SpotifyAPI/SpotifyAPI.csproj +++ b/SpotifyAPI/SpotifyAPI.csproj @@ -61,6 +61,7 @@ + diff --git a/SpotifyAPI/Web/Auth/WebApiFactory.cs b/SpotifyAPI/Web/Auth/WebApiFactory.cs index 22fab8ee..55c11d31 100644 --- a/SpotifyAPI/Web/Auth/WebApiFactory.cs +++ b/SpotifyAPI/Web/Auth/WebApiFactory.cs @@ -13,21 +13,32 @@ namespace SpotifyAPI.Web.Auth private readonly string _clientId; private readonly TimeSpan _timeout; private readonly Scope _scope; + private readonly ProxyConfig _proxyConfig; private readonly string _xss; public WebAPIFactory(string redirectUrl, int listeningPort, string clientId, Scope scope) - : this(redirectUrl, listeningPort, clientId, scope, TimeSpan.FromSeconds(20)) + : this(redirectUrl, listeningPort, clientId, scope, null) { + } + public WebAPIFactory(string redirectUrl, int listeningPort, string clientId, Scope scope, ProxyConfig proxyConfig) + : this(redirectUrl, listeningPort, clientId, scope, TimeSpan.FromSeconds(20), proxyConfig) + { } public WebAPIFactory(string redirectUrl, int listeningPort, string clientId, Scope scope, TimeSpan timeout, string xss = "XSS") + : this(redirectUrl, listeningPort, clientId, scope, timeout, null, xss) + { + } + + public WebAPIFactory(string redirectUrl, int listeningPort, string clientId, Scope scope, TimeSpan timeout, ProxyConfig proxyConfig, string xss = "XSS") { _redirectUrl = redirectUrl; _listeningPort = listeningPort; _clientId = clientId; _scope = scope; _timeout = timeout; + _proxyConfig = proxyConfig; _xss = xss; } @@ -75,7 +86,7 @@ namespace SpotifyAPI.Web.Auth if (token.Error != null) throw new SpotifyWebApiException($"Error: {token.Error}"); - var spotifyWebApi = new SpotifyWebAPI + var spotifyWebApi = new SpotifyWebAPI(_proxyConfig) { UseAuth = true, AccessToken = token.AccessToken, diff --git a/SpotifyAPI/Web/SpotifyWebAPI.cs b/SpotifyAPI/Web/SpotifyWebAPI.cs index a4319209..ecaadf4d 100644 --- a/SpotifyAPI/Web/SpotifyWebAPI.cs +++ b/SpotifyAPI/Web/SpotifyWebAPI.cs @@ -20,7 +20,11 @@ namespace SpotifyAPI.Web private readonly SpotifyWebBuilder _builder; - public SpotifyWebAPI() + public SpotifyWebAPI() : this(null) + { + } + + public SpotifyWebAPI(ProxyConfig proxyConfig) { _builder = new SpotifyWebBuilder(); UseAuth = true; @@ -31,7 +35,8 @@ namespace SpotifyAPI.Web { NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.All - } + }, + ProxyConfig = proxyConfig }; } diff --git a/SpotifyAPI/Web/SpotifyWebClient.cs b/SpotifyAPI/Web/SpotifyWebClient.cs index 4205e381..0cd4a647 100644 --- a/SpotifyAPI/Web/SpotifyWebClient.cs +++ b/SpotifyAPI/Web/SpotifyWebClient.cs @@ -16,6 +16,8 @@ namespace SpotifyAPI.Web { public JsonSerializerSettings JsonSettings { get; set; } + public ProxyConfig ProxyConfig { get; set; } + private readonly Encoding _encoding = Encoding.UTF8; public Tuple Download(string url, Dictionary headers = null) @@ -32,7 +34,8 @@ namespace SpotifyAPI.Web public Tuple DownloadRaw(string url, Dictionary headers = null) { - using (HttpClient client = new HttpClient()) + HttpClientHandler clientHandler = CreateClientHandler(ProxyConfig); + using (HttpClient client = new HttpClient(clientHandler)) { if (headers != null) { @@ -54,7 +57,8 @@ namespace SpotifyAPI.Web public async Task> DownloadRawAsync(string url, Dictionary headers = null) { - using (HttpClient client = new HttpClient()) + HttpClientHandler clientHandler = CreateClientHandler(ProxyConfig); + using (HttpClient client = new HttpClient(clientHandler)) { if (headers != null) { @@ -100,7 +104,8 @@ namespace SpotifyAPI.Web public Tuple UploadRaw(string url, string body, string method, Dictionary headers = null) { - using (HttpClient client = new HttpClient()) + HttpClientHandler clientHandler = CreateClientHandler(ProxyConfig); + using (HttpClient client = new HttpClient(clientHandler)) { if (headers != null) { @@ -127,7 +132,8 @@ namespace SpotifyAPI.Web public async Task> UploadRawAsync(string url, string body, string method, Dictionary headers = null) { - using (HttpClient client = new HttpClient()) + HttpClientHandler clientHandler = CreateClientHandler(ProxyConfig); + using (HttpClient client = new HttpClient(clientHandler)) { if (headers != null) { @@ -181,5 +187,26 @@ namespace SpotifyAPI.Web } return newHeaders; } + + private static HttpClientHandler CreateClientHandler(ProxyConfig proxyConfig = null) + { + HttpClientHandler clientHandler = new HttpClientHandler + { + PreAuthenticate = false, + UseDefaultCredentials = true, + UseProxy = false + }; + + if (!string.IsNullOrWhiteSpace(proxyConfig?.Host)) + { + WebProxy proxy = proxyConfig.CreateWebProxy(); + clientHandler.UseProxy = true; + clientHandler.Proxy = proxy; + clientHandler.UseDefaultCredentials = proxy.UseDefaultCredentials; + clientHandler.PreAuthenticate = proxy.UseDefaultCredentials; + } + + return clientHandler; + } } } \ No newline at end of file