/// <summary> /// What is the status of the fetching of lyrics for the given song? /// </summary> /// <param name="s"></param> /// <returns>This can only return Waiting, Fetching or NotFound.</returns> public LyricsFetchStatus GetStatus(Song song) { if (this.songStatusMap.ContainsKey(song)) return this.GetFetchRequestData(song).Status; else return LyricsFetchStatus.NotFound; }
protected override void QueueInternal(Song song) { MetaDataLookup lookup = new MetaDataLookup(song); this.songStatusMap[song] = lookup; lookup.StatusEvent += new EventHandler<MetaDataEventArgs>(lookupStatusEvent); lookup.ChangeState(MetaDataStatus.Waiting); }
/// <summary> /// Start the given song playing /// </summary> /// <param name="song">The song to play</param> public override void Play(Song song) { WmpSong wmpSong = song as WmpSong; if (wmpSong != null) { Wmp.Instance.Player.currentPlaylist.appendItem(wmpSong.Media); Wmp.Instance.Player.controls.playItem(wmpSong.Media); } }
/// <summary> /// Is the given song currently playing /// </summary> /// <param name="song">The song to check</param> /// <returns>Is the given song playing</returns> public override bool IsPlaying(Song song) { WmpSong wmpSong = song as WmpSong; if (wmpSong == null) return false; if (Wmp.Instance.Player.playState != WMPPlayState.wmppsPlaying) return false; return Wmp.Instance.Player.currentMedia.get_isIdentical(wmpSong.Media); }
/// <summary> /// Return a textual description of the status of the fetch request /// </summary> /// <param name="song"></param> /// <returns></returns> public string GetStatusString(Song song) { LyricsFetchStatus status = this.GetStatus(song); switch (status) { case LyricsFetchStatus.NotFound: return "Not found"; case LyricsFetchStatus.Fetching: FetchRequestData data = this.GetFetchRequestData(song); if (data != null) { ILyricsSource source = data.Source; if (source != null) return String.Format("Trying {0}...", source.Name); } return "Trying ..."; default: return status.ToString(); } }
/// <summary> /// Add the song to the list of songs for whom some information is being fetched. /// </summary> /// <param name="song">The song to be queued</param> /// <remarks>This should add an entry into the songStatusMap to track /// the fetch status of the song</remarks> protected abstract void QueueInternal(Song song);
/// <summary> /// Start the given song playing /// </summary> /// <param name="song">The song to play</param> public abstract void Play(Song song);
/// <summary> /// Fetch the lyrics for the given song /// </summary> /// <param name="s">The song whose lyrics are to be fetched</param> /// <returns>The lyrics or an empty string if the lyrics could not be found</returns> public string GetLyrics(Song s) { string queryUrl = String.Format("http://lyricsfly.com/api/api.php?i={0}&a={1}&t={2}", UserId, s.Artist, s.Title); WebClient client = new WebClient(); string result = client.DownloadString(queryUrl); if (result == String.Empty) return String.Empty; /* * The following is taken from the LyricsFly website (http://lyricsfly.com/api/) * All API calls return an XML document. The following is an example of the output: <?xml version="1.0" encoding="utf-8"?> -<start> -<sg> <cs>14eb6fba81</cs> <id>1438</id> <ar>U2</ar> <tt>Beautiful Day</tt> <al>All that you can't leave behind</al> -<tx> . . . . . Lyrics provided by lyricsfly.com [br] </tx> </sg> </start> Each call can return a total of 3 possible titles. Because of some album duplicates such as live performances as well as re-releases, we give you an option to pick the best result that suits your needs. Tag description <sg> - song <cs> - checksum (for original URL link back construction) <id> - song ID in the database (for original URL link back construction) <ar> - artist name <tt> - title of the song <al> - album name <tx> - lyrics text separated by [br] for line break (replace with <br>) * */ try { XPathDocument doc = new XPathDocument(new StringReader(result)); XPathNavigator nav = doc.CreateNavigator(); if (nav.MoveToChild("start", "")) { if (nav.MoveToChild("sg", "")) { if (nav.MoveToChild("tx", "")) return nav.Value.Replace("[br]", System.Environment.NewLine).Trim(); } } } catch (XmlException) { // Not much we can do here } return string.Empty; }
/// <summary> /// Get the lyrics for the given song from the cache. /// </summary> /// <param name="song">The Song whose lyrics are to be returned</param> /// <returns>The lyrics or null if the lyrics aren't found.</returns> public string GetLyrics(Song song) { string lyrics; this.lyricsCache.TryGetValue(this.GetKey(song), out lyrics); return lyrics; }
/// <summary> /// Update the lyrics of the given song with its matched /// value from the cache. /// </summary> /// <param name="song">The song whose lyrics are to be updated</param> /// <returns>Returns true if the lyrics were updated</returns> public bool UpdateLyrics(Song song) { if (!this.HasLyrics(song)) return false; song.Lyrics = this.GetLyrics(song); return true; }
/// <summary> /// Remember the lyrics of the given song. /// </summary> /// <param name="song">The Song whose lyrics are to be remembered</param> public void PutLyrics(Song song) { this.lyricsCache[this.GetKey(song)] = song.Lyrics; }
/// <summary> /// Cache the lyrics of the given song /// </summary> /// <param name="song">The song whose lyrics are to be cache</param> public void CacheLyrics(Song song) { this.Cache.PutLyrics(song); }
private void UpdateLyrics(Song s, string lyrics, ILyricsSource source) { lyrics = lyrics.Trim(); if (lyrics == "") { // If we didn't find lyrics, we only write out a Failed marker, if the songs doesn't // have any lyrics or if it only has an old failed marker. // We do NOT want to replace existing lyrics with a failed marker :) if (s.LyricsStatus != LyricsStatus.Success) { string sources = ""; foreach (ILyricsSource x in this.Sources) sources += (x.Name + " "); s.Lyrics = String.Format( "[[LyricsFetcher failed to find lyrics\r\nSources: {1}\r\nDate: {2:yyyy-MM-dd HH:mm:ss}]]", lyrics, sources, DateTime.Now); try { s.Commit(); } catch (COMException) { // There are quite a few reasons why these might fail. If the track // is locked, or the underlying file has been deleted/moved. // There is nothing we can do if this fails. } } } else { s.Lyrics = String.Format( "{0}\r\n\r\n[[Found by LyricsFetcher\r\nSource: {1}\r\nDate: {2:yyyy-MM-dd HH:mm:ss}]]", lyrics, source.Name, DateTime.Now); try { s.Commit(); } catch (COMException) { // There are quite a few reasons why these might fail. If the track // is locked, or the underlying file has been deleted/moved. // There is nothing we can do if this fails. } } }
private FetchRequestData GetFetchRequestData(Song song) { return ((FetchRequestData)this.songStatusMap[song]); }
protected override void StartInternal(Song song) { this.GetFetchRequestData(song).Status = LyricsFetchStatus.Fetching; LyricsFetcher fetcher = new LyricsFetcher(); fetcher.Sources = this.Sources; fetcher.StatusEvent += new EventHandler<LyricsFetchStatusEventArgs>(fetcher_StatusEvent); Thread thread = new Thread(new ParameterizedThreadStart(fetcher.FetchSongLyrics)); thread.IsBackground = true; thread.Start(song); }
/// <summary> /// Add the song to the list of songs whose lyrics are being fetched /// </summary> /// <param name="song"></param> protected override void QueueInternal(Song song) { this.songStatusMap[song] = new FetchRequestData(); LyricsFetchStatusEventArgs args = new LyricsFetchStatusEventArgs(); args.Song = song; args.Status = LyricsFetchStatus.Waiting; this.OnStatusEvent(args); }
/// <summary> /// Remove the given song from those being operated on. /// </summary> /// <param name="song">The song to be removed</param> protected override void CancelInternal(Song song) { LyricsFetchStatusEventArgs args = new LyricsFetchStatusEventArgs(); args.Song = song; args.Status = LyricsFetchStatus.Cancelled; this.OnStatusEvent(args); }
/// <summary> /// Add the given song to our list of loaded songs, reading /// the lyrics of the song from the cache if possible. /// </summary> /// <param name="song">The newly loaded song</param> protected void AddSong(Song song) { // If we couldn't get the lyrics of the song from the cache, load // them from the songs source itself. if (this.LyricsCache == null) song.GetLyrics(); else { if (!this.LyricsCache.UpdateLyrics(song)) { song.GetLyrics(); this.LyricsCache.PutLyrics(song); } } this.Songs.Add(song); }
/// <summary> /// Start a long running thread to process the given song /// </summary> protected abstract void StartInternal(Song song);
/// <summary> /// Does the cache have lyrics for the given song. /// </summary> /// <param name="song">The Song whose lyrics are to be returned</param> /// <returns>The lyrics or null if the lyrics aren't found.</returns> public bool HasLyrics(Song song) { return this.lyricsCache.ContainsKey(this.GetKey(song)); }
/// <summary> /// Cancel the fetching of lyrics of the given song /// </summary> /// <param name="s"></param> public void Cancel(Song song) { this.CancelOne(song); this.PossibleStartNewThreads(); }
/// <summary> /// Remove the lyrics of the given song from the cache /// </summary> /// <param name="song">The Song whose lyrics are to be removed</param> public void RemoveLyrics(Song song) { this.lyricsCache.Remove(this.GetKey(song)); }
/// <summary> /// Add the song to the list of songs whose lyrics are being fetched /// </summary> /// <param name="song"></param> public void Queue(Song song) { this.Queue(new Song[] { song }); }
/// <summary> /// Calculate a key that can be used to identify the lyrics of this song /// </summary> /// <param name="song">The song whose cache key is required</param> /// <returns>A key</returns> private string GetKey(Song song) { return String.Format("{0}\\{1}", song.Title, song.Artist); }
/// <summary> /// Fetch the lyrics for the given song /// </summary> /// <param name="s">The song whose lyrics are to be fetched</param> /// <returns>The lyrics or an empty string if the lyrics could not be found</returns> public string GetLyrics(Song s) { string queryUrl = String.Format("http://lyricsfly.com/api/api.php?i={0}&a={1}&t={2}", UserId, s.Artist, s.Title); WebClient client = new WebClient(); string result = client.DownloadString(queryUrl); if (result == String.Empty) { return(String.Empty); } /* * The following is taken from the LyricsFly website (http://lyricsfly.com/api/) * * All API calls return an XML document. The following is an example of the output: * <?xml version="1.0" encoding="utf-8"?> * -<start> * -<sg> * <cs>14eb6fba81</cs> * <id>1438</id> * <ar>U2</ar> * <tt>Beautiful Day</tt> * <al>All that you can't leave behind</al> * -<tx> . . . . . Lyrics provided by lyricsfly.com [br] * </tx> * </sg> * </start> * * Each call can return a total of 3 possible titles. Because of some album duplicates such as live performances as well as re-releases, we give you an option to pick the best result that suits your needs. * * Tag description * <sg> - song * <cs> - checksum (for original URL link back construction) * <id> - song ID in the database (for original URL link back construction) * <ar> - artist name * <tt> - title of the song * <al> - album name * <tx> - lyrics text separated by [br] for line break (replace with <br>) * */ try { XPathDocument doc = new XPathDocument(new StringReader(result)); XPathNavigator nav = doc.CreateNavigator(); if (nav.MoveToChild("start", "")) { if (nav.MoveToChild("sg", "")) { if (nav.MoveToChild("tx", "")) { return(nav.Value.Replace("[br]", System.Environment.NewLine).Trim()); } } } } catch (XmlException) { // Not much we can do here } return(string.Empty); }
/// <summary> /// Fetch the lyrics for the given song /// </summary> /// <param name="s">The song whose lyrics are to be fetched</param> /// <returns>The lyrics or an empty string if the lyrics could not be found</returns> public string GetLyrics(Song s) { // Lyrdb can't handle single or double quotes in the title (as of 12/1/2008) // So we just remove them string title = s.Title.Replace("'", ""); title = title.Replace("\"", ""); WebClient client = new WebClient(); string result = String.Empty; try { // If we have both the title and the artist, we can look for a perfect match if (!String.IsNullOrEmpty(s.Artist)) { string queryUrl = String.Format("http://webservices.lyrdb.com/lookup.php?q={0}|{1}&for=match&agent={2}/{3}", s.Artist, title, PROGRAM_NAME, PROGRAM_VERSION); result = client.DownloadString(queryUrl); } // If we only have the title or the perfect match failed, do a full text search using // whatever information we have if (result == String.Empty) { string queryUrl = String.Format("http://webservices.lyrdb.com/lookup.php?q={0}&for=trackname&agent={2}/{3}", title, s.Artist, PROGRAM_NAME, PROGRAM_VERSION); result = client.DownloadString(queryUrl); } } catch (Exception ex) { // Many things can do wrong here, but there's nothing we can do it fix them System.Diagnostics.Debug.WriteLine("Lyrdb GetLyrics failed:"); System.Diagnostics.Debug.WriteLine(ex); return String.Empty; } // Still didn't work? Give up. if (result == String.Empty || result.StartsWith("error:")) return String.Empty; foreach (string x in result.Split('\n')) { string id = x.Split('\\')[0]; string lyrics = client.DownloadString("http://webservices.lyrdb.com/getlyr.php?q=" + id); if (lyrics != String.Empty && !lyrics.StartsWith("error:")) { Encoding latin1 = Encoding.GetEncoding("ISO-8859-1"); string str = Encoding.UTF8.GetString(latin1.GetBytes(lyrics)); str = str.Replace("\r", String.Empty); return str.Replace("\n", System.Environment.NewLine); } } return String.Empty; }
/// <summary> /// Cancel the work on the given song /// </summary> /// <param name="song">The song to be cancelled</param> protected void CancelOne(Song song) { this.CancelInternal(song); this.waitingSongs.Remove(song); this.fetchingSongs.Remove(song); this.songStatusMap.Remove(song); }
/// <summary> /// Fetch the lyrics for the given song /// </summary> /// <param name="s">The song whose lyrics are to be fetched</param> /// <returns>The lyrics or an empty string if the lyrics could not be found</returns> public string GetLyrics(Song s) { WebClient client = new WebClient(); string queryUrl = "http://www.lyricsplugin.com/plugin/?title=" + s.Title + "&artist=" + s.Artist; try { string result = client.DownloadString(queryUrl); const string lyricsMarker = @"<div id=""lyrics"">"; int index = result.IndexOf(lyricsMarker); if (index >= 0) { result = result.Substring(index + lyricsMarker.Length); index = result.IndexOf("</div>"); if (index > 0) { result = result.Substring(0, index); result = result.Replace("<br />\n", Environment.NewLine); result = result.Replace("<br />", ""); result = result.Replace("’", "'"); Encoding latin1 = Encoding.GetEncoding("ISO-8859-1"); result = Encoding.UTF8.GetString(latin1.GetBytes(result)); return result.Trim(); } } } catch (WebException ex) { System.Diagnostics.Debug.WriteLine("LyricsPlugin GetLyrics failed:"); System.Diagnostics.Debug.WriteLine(ex); return String.Empty; } return String.Empty; }
/// <summary> /// The given song has finished being worked on. Cleanup its /// resources and start new tasks /// </summary> /// <param name="song"></param> protected void CleanupOne(Song song) { this.fetchingSongs.Remove(song); this.songStatusMap.Remove(song); this.PossibleStartNewThreads(); }
/// <summary> /// Remove the given song from those being operated on. /// </summary> /// <param name="song">The song to be removed</param> protected abstract void CancelInternal(Song song);
/// <summary> /// Is the given song currently playing /// </summary> /// <param name="song">The song to check</param> /// <returns>Is the given song playing</returns> public abstract bool IsPlaying(Song song);