/// <summary> /// Parses a given buffer of ID3 information into a readable Track object. /// Called once per MP3 link. /// </summary> /// <param name="buffer">Data from the download process of the ID3 Tag</param> /// <returns>Full Track object, either with data or NULL if error.</returns> private static Track ParseID3(byte[] buffer) { Track m_Track = new Track(); try { byte[] bytes_ID3 = new byte[3]; Array.Copy(buffer, 0, bytes_ID3, 0, bytes_ID3.Length); string ID3_Identifier = encoder.GetString(bytes_ID3); if (ID3_Identifier == "ID3") //Basic Validation for misaligned/misformed headers. { uint count = 10; while ((count+8) < buffer.Length) { byte[] frameData = new byte[8]; Array.Copy(buffer, count, frameData, 0, frameData.Length); byte[] bytes_FrameID = new byte[4]; Array.Copy(frameData, 0, bytes_FrameID, 0, 4); string frameID = encoder.GetString(bytes_FrameID).Trim('\0'); //GET THE FRAME NAME: byte[] bytes_RawFrameSize = new byte[4]; Array.Copy(frameData, 4, bytes_RawFrameSize, 0, bytes_RawFrameSize.Length); if (BitConverter.IsLittleEndian) Array.Reverse(bytes_RawFrameSize); uint frameSize = BitConverter.ToUInt32(bytes_RawFrameSize, 0); if (frameID.Equals("TALB")) //Track Album Name { m_Track.Album = TryParseFrameData(buffer, count, frameSize); } else if (frameID.Equals("TIT1") || frameID.Equals("TIT2")) //Track Title { m_Track.Title = TryParseFrameData(buffer, count, frameSize); } else if (frameID.Equals("TPE1") || frameID.Equals("TPE2")) //Track Artist { m_Track.Artist = TryParseFrameData(buffer, count, frameSize); } //Increase count to the start of the next frame. count += (frameSize + 10); if (!(string.IsNullOrEmpty(m_Track.Album)) && !(string.IsNullOrEmpty(m_Track.Artist)) && !(string.IsNullOrEmpty(m_Track.Title))) { //EVERYTHING IS FULL. return m_Track; } } return null; //Completely parsed the buffer, nothing gained, failed? Yes. } else return null; //No valid ID3 Header Magic found. Failed. } catch (Exception ex) { Console.Write("ParseID3: {0}\n", ex.Message); return null; } //Just flat-out failed, log the reason for later fixing. }
/// <summary> /// Downloads the ID3 tag data from a given URI /// Runs Syncronously, so should preferably used in conjun. with BackgroundWorker.DoWork() /// </summary> /// <param name="targetString">The target strings to download from.</param> /// <returns>An array of all data.</returns> public static List<Track> DownloadID3(List<string> targetStrings, int targetcount) { int bytecount = 1024; List<Track> TrackObjects = new List<Track>(); Parallel.ForEach(targetStrings, (string targetString, ParallelLoopState loopState) => { Track currentTrack = new Track(); WebRequest m_WebRequestHEAD = null; WebRequest m_WebRequest = null; try { m_WebRequestHEAD = (HttpWebRequest)WebRequest.Create(targetString); m_WebRequestHEAD.Method = "HEAD"; m_WebRequestHEAD.Timeout = 2000; m_WebRequest = (HttpWebRequest)WebRequest.Create(targetString); m_WebRequest.Timeout = 2000; } catch (WebException ex) { Console.Write("WebException Caught: " + ex.Message); return; } catch (UriFormatException ufi) { Console.Write("UriFormatException Caught: " + ufi.Message); return; } WebResponse wResponseHEAD = null; try { wResponseHEAD = m_WebRequestHEAD.GetResponse(); } catch (WebException ex) { Console.WriteLine("WebException Caught: m_WebRequestHEAD.GetResponse()\n"+ex.Message); return; } // Parse the content length to check for 'preview' or 'demo' files. int cLen = 0; if ((wResponseHEAD != null) && int.TryParse(wResponseHEAD.Headers.Get("Content-Length"), out cLen)) { if (cLen < 1500000) { return; } } wResponseHEAD.Close(); WebResponse wResponse = null; try { wResponse = m_WebRequest.GetResponse(); } catch (Exception ex) { Console.WriteLine("Exception Caught: m_WebRequest.GetResponse()\n"+ex.Message); return; } using (var m_WebResponse = m_WebRequest.GetResponse().GetResponseStream()) { byte[] buffer = new byte[bytecount]; m_WebResponse.Read(buffer, 0, bytecount); //Get the ID3 Track Info currentTrack = ParseID3(buffer); if ((currentTrack != null) && (!currentTrack.Title.StartsWith("??"))) { currentTrack.Link = targetString; TrackObjects.Add(currentTrack); } } }); return TrackObjects; }
/// <summary> /// Gets the selected row's MP3 Link and uses the WindowsMediaPlayer to play it. /// </summary> private void lst_TrackListView_MouseDoubleClick(object sender, MouseEventArgs e) { if (lst_TrackListView.FocusedItem != null) { //Set the Now Playing Track to the current selected. NowPlaying = new Track(lst_TrackListView.FocusedItem.SubItems[0].Text, lst_TrackListView.FocusedItem.SubItems[1].Text, lst_TrackListView.FocusedItem.SubItems[2].Text, lst_TrackListView.FocusedItem.Tag.ToString()); LoadMedia(NowPlaying); } }
private void LoadMedia(Track newTrack) { //Load the track: axWMP.currentMedia = axWMP.newMedia(newTrack.Link); MediaState = PlayStates.Playing; //Sort out any GUI settings required: picPlayButton.Image = Properties.Resources.PauseButton; lblNowPlaying.Text = NowPlaying.Title; lblNowPlayingOther.Text = NowPlaying.Artist + " - " + NowPlaying.Album; axWMP.Ctlcontrols.play(); }
/// <summary> /// Loads a file containing Track data from a local file on cache. /// </summary> /// <param name="strSearchTerm"></param> /// <returns></returns> private List<Track> LoadCachedResult(string strSearchTerm) { strSearchTerm = strSearchTerm.Replace("/", "±"); string cachedResult = cacheDirectory + "\\" + strSearchTerm; //If there's a cached result, and the Search Term isn't nothing: if (File.Exists(cachedResult) && !String.IsNullOrEmpty(strSearchTerm)) { try { List<Track> TrackList = new List<Track>(); //Load the cached Results from local disk: using (StreamReader reader = new StreamReader(cachedResult, System.Text.Encoding.UTF8, false)) { String trackline = reader.ReadLine(); while (trackline != null) { String[] trackitems = trackline.Split(';'); Track track = new Track(trackitems[0], trackitems[1], trackitems[2], trackitems[3]); TrackList.Add(track); trackline = reader.ReadLine(); } return TrackList; //Got the cached result in a usable form! } } catch (Exception) { return null; /*It wasn't formatted right? Get new.*/ } } else return null; //File either doesn't exist or has a blank search (so obviously non-existant) }
private void changeMediaAfterLastOneFinishes() { //Long method name or longest method name? //Either get the current Track if it's not the same (selected index changed) //or get next(;;) next != current Track. if (lst_TrackListView.FocusedItem != null) { Track lastTrack = NowPlaying; int si = (int)lst_TrackListView.SelectedIndicies[0]; while (lst_TrackListView.Items[si].SubItems[0].Text == lastTrack.Title) { lst_TrackListView.Items[si].Selected = false; si++; lst_TrackListView.Items[si].Selected = true; //Have we hit the last one? Should we go to the top? if (si >= lst_TrackListView.Items.Count) si = 0; } //Set the Now Playing Track to the current selected. NowPlaying = new Track(lst_TrackListView.Items[si].SubItems[0].Text, lst_TrackListView.Items[si].SubItems[1].Text, lst_TrackListView.Items[si].SubItems[2].Text, lst_TrackListView.Items[si].Tag.ToString()); LoadMedia(NowPlaying); } }