/// <summary> /// Creates the player form and starts the task that monitors Spotify for /// changes to its window title. /// </summary> public PlayerForm() { InitializeComponent(); // Get the cover art folder location and filename _appFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); _defaultCover = Path.Combine(_appFolder, "default_cover.png"); // Turn the full file path into a URI for the PictureBox Uri uri = new Uri(_defaultCover); _defaultCover = uri.AbsoluteUri; // Load the default CoverArt.Load(_defaultCover); Task.Run(() => { // Let the defaults load Thread.Sleep(1000); Process spotifyProcess = null; string spotifyTitle = string.Empty; // Look for the Spotify process and monitor its window title while (true) { if (spotifyProcess == null) { var processes = Process.GetProcessesByName("spotify"); if (processes.Length < 1) { Thread.Sleep(5000); continue; } spotifyProcess = processes[0]; } else { spotifyProcess.Refresh(); if (spotifyProcess.HasExited) { spotifyProcess = null; continue; } string title = spotifyProcess.MainWindowTitle; if (title != spotifyTitle) { spotifyTitle = title; SetLabel(title); } Thread.Sleep(5000); } } }); }
/// <summary> /// Using the main window text passed in from the Spotify process, this method /// extracts the artist and song title. It then uses the audio scrobbler web /// service to download details about the song so that we display accurate /// information. We also use audio scrobbler's album cover art to update the /// album art displayed. /// </summary> /// <param name="label">The window label (main window text) of the Spotify /// process</param> public void SetLabel(string label) { if (InvokeRequired) { Invoke(new SetLabelDelegate(SetLabel), label); } else { // Get rid of the "Spotify - " prefix and then split out the artist // and song string noSpotify = label.Replace("Spotify - ", string.Empty); var parts = noSpotify.Split('–'); if (parts.Length < 2) { // Well. Damn. It appears we weren't passed any meaningful text, // so go back to the defaults. _title = "Song Title"; Artist.Text = "Artist"; CoverArt.Load(_defaultCover); return; } string artist = parts[0].Trim(); string title = parts[1].Trim(); _title = title; Artist.Text = artist; Invalidate(); // Let's try to get the song details from Audio Scrobbler string url = "http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key={0}&autocorrect=1&artist={1}&track={2}"; artist = HttpUtility.UrlEncode(artist); title = HttpUtility.UrlEncode(title); url = string.Format(url, _scrobblerApiKey, artist, title); using (WebClient client = new WebClient()) { // Download the audioscrobbler XML for the given artist and song string xml = client.DownloadString(url); XDocument xmlDoc = XDocument.Load(new StringReader(xml)); var imgUrls = from img in xmlDoc.XPathSelectElements("//album/image") where img.Attribute("size").Value == "large" select img.Value; string imgUrl = imgUrls.FirstOrDefault(); // If we can't find an image URL, just use the default cover if (imgUrl == null) { CoverArt.LoadAsync(_defaultCover); } else { // Download the image data from audio scrobbler and dispose the previous // cover art image (prevents a memory leak) byte[] imageData = client.DownloadData(imgUrl); using (Stream stream = new MemoryStream(imageData)) { Image image = Image.FromStream(stream); Image old = CoverArt.Image; CoverArt.Image = image; old.Dispose(); } } } // Perform a quick GC and compact the large-object heap GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); } }