public void ReadID3v1(string file) { // read id3 stuff id3v1 = new ID3v1(file); id3v1.Read(); this.hasID3v1 = id3v1.hasTag;; }
public void LoadTags(string filename) { ID3v2 t2 = ID3v2.FromFile(filename); ID3v1 t1 = ID3v1.FromFile(filename); if (t2 != null) { Title = t2.QuickInfo.Title; Artist = t2.QuickInfo.Artist; Album = t2.QuickInfo.Album; Year = t2.QuickInfo.Year.ToString(); LeadPerformers = t2.QuickInfo.LeadPerformers; Genre = t2.QuickInfo.Genre.ToString(); TrackNumber = t2.QuickInfo.TrackNumber.ToString(); Comments = t2.QuickInfo.Comments; if (t2.QuickInfo.Image != null) { if (Image != null) { (Image as BitmapImage).StreamSource.Dispose(); Image = null; } MemoryStream imgstream = new MemoryStream(); t2.QuickInfo.Image.Save(imgstream, System.Drawing.Imaging.ImageFormat.Png); var img = new BitmapImage(); img.BeginInit(); imgstream.Seek(0, SeekOrigin.Begin); img.StreamSource = imgstream; img.EndInit(); Image = img; } } if (t1 != null) { if (String.IsNullOrWhiteSpace(Title)) { Title = t1.Title; } if (String.IsNullOrWhiteSpace(Artist)) { Artist = t1.Artist; } if (String.IsNullOrWhiteSpace(Album)) { Album = t1.Album; } if (String.IsNullOrWhiteSpace(Year)) { Year = t1.Year.ToString(); } if (string.IsNullOrWhiteSpace(Comments)) { Comments = t1.Comment; } Genre = t1.Genre.ToString(); } }
public void CommentTest() { ID3v1 target = new ID3v1(filePath, true); string expected = string.Empty; string actual = target.Comment; Assert.AreEqual(expected, actual); }
public void SaveTest() { string filePath = string.Empty; // TODO: Initialize to an appropriate value bool LoadData = false; // TODO: Initialize to an appropriate value ID3v1 target = new ID3v1(filePath, LoadData); // TODO: Initialize to an appropriate value target.Save(); Assert.Inconclusive("A method that does not return a value cannot be verified."); }
/// <summary> /// append or overwrite ID3v1 tag at the end of the audio /// </summary> /// <param name="stream"></param> private void WriteID3v1(Stream stream) { ID3v1 v1tag = new ID3v1(); v1tag.FrameModel = TagModel; stream.Seek(_audioStart + _audio.NumPayloadBytes, SeekOrigin.Begin); v1tag.WriteAtStreamPosition(stream); }
/// <summary> /// Create new ID3 Info class /// </summary> /// <param name="FileAddress">FileAddress for read ID3 info</param> /// <param name="LoadData">Indicate load data in constructor or not</param> public ID3Info(string FilePath, bool LoadData) { _ID3v1 = new ID3v1(FilePath, LoadData); try { _ID3v2 = new ID3v2(FilePath, LoadData); } catch { // Falls oben was schiefging haben wir immerhin noch die Daten aus id3v1 } }
public ID3vDetails(string filename) { ImageMP3 = new ID3Info(filename, true); foreach (AttachedPictureFrame frame in ImageMP3.ID3v2Info.AttachedPictureFrames) { Image temp = frame.Picture; attach = temp; } MP3 = new ID3v1(filename, true); namemp3 = MP3.FileName; title = MP3.Title; artist = MP3.Artist; album = MP3.Album; year = MP3.Year; }
public MpegAudio(String path) { const int dataLength = MaxMpegFrameLength * 2; ResetData(); using (BinaryReader br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) { int startPos = ID3v2.GetTagSize(br.BaseStream); // Get file length m_FileLength = br.BaseStream.Length; // Seek past ID3v2 tag br.BaseStream.Seek(startPos, SeekOrigin.Begin); // Read first block of data and search for a frame Byte[] data = br.ReadBytes(dataLength); FindFrame(data, ref m_VBR); m_VendorID = FindVendorID(data); // Try to search in the middle of the file if no frame at the beginning found if (!m_Frame.Found) { br.BaseStream.Seek((m_FileLength - startPos) / 2, SeekOrigin.Begin); data = br.ReadBytes(dataLength); FindFrame(data, ref m_VBR); } // Search for vendor ID at the end if CBR encoded if (m_Frame.Found && String.IsNullOrEmpty(m_VendorID)) { br.BaseStream.Seek(-(data.Length + ID3v1.GetTagSize(br.BaseStream)), SeekOrigin.End); data = br.ReadBytes(dataLength); FindFrame(data, ref m_VBR); m_VendorID = FindVendorID(data); } } if (m_Frame.Found == false) { ResetData(); } }
public MP3FileReader(Stream stream) { CSCore.Tags.ID3.ID3v2.SkipTag(stream); dataStartIndex = stream.Position; var id3v1Tag = ID3v1.FromStream(stream); if (id3v1Tag != null) { dataLength = stream.Length - dataStartIndex - 128; //128 = id3v1 length } else { dataLength = stream.Length - dataStartIndex; } stream.Position = dataStartIndex; dataStream = new MP3Stream(stream, true, id3v1Tag != null ? 128 : 0); }
/// <summary> /// Creates a new MP3Reader for the specified stream. /// </summary> /// <param name="stream">The stream to load.</param> public MP3Reader(Stream stream) { Name = stream.ToString(); long endOfStream = 0; if (stream.CanSeek && (stream.Position == 0) && (stream.Length > 128)) { // try loading ID3v1 first try { stream.Seek(-128, SeekOrigin.End); var buffer = new byte[128]; stream.Read(buffer, 0, 128); if ((buffer[0] == (byte)'T') && (buffer[1] == (byte)'A') && (buffer[2] == (byte)'G')) { m_ID3v1 = new ID3v1(buffer); endOfStream = stream.Length - 128; } } catch { } stream.Seek(0, SeekOrigin.Begin); } m_Reader = new DataFrameReader(stream, endOfStream); }
private void AddSongs(string[] FileNames) { if (FileNames == null) { return; } if (FileNames.Length >= 100) { if (ShowMessageBoxOkCancel("您选择的歌曲数量超过100,这样可能会导致软件占用较多内存,确定要继续吗?\n(推荐您分次处理,每次处理的歌曲控制在100以内)") == 0) { return; } } char[] CharToDelete = { '\0', ' ' }; Image_Helper.Visibility = Visibility.Hidden; Label_URL.Visibility = Visibility.Hidden; foreach (string FileName in FileNames) { if (System.IO.Path.GetExtension(FileName).ToUpper() != ".MP3") { continue; } BitmapImage HasAlbum = null; string HasLyrics = null; string Title = "", Artist = "", Album = ""; ID3v2 id3v2 = new ID3v2(FileName, true); if (id3v2.TextWithLanguageFrames.Count > 0) { for (int i = 0; i < id3v2.TextWithLanguageFrames.Count; i++) { if (id3v2.TextWithLanguageFrames.Items[i].FrameID == "USLT") { HasLyrics = id3v2.TextWithLanguageFrames.Items[i].Text.Trim(); break; } } } if (id3v2.AttachedPictureFrames.Count > 0) { for (int i = 0; i < id3v2.AttachedPictureFrames.Count; i++) { if (id3v2.AttachedPictureFrames.Items[i].FrameID == "APIC") { HasAlbum = new BitmapImage(); HasAlbum.BeginInit(); HasAlbum.StreamSource = id3v2.AttachedPictureFrames.Items[0].Data; try { HasAlbum.EndInit(); } catch { HasAlbum = null; } break; } } } if (id3v2.TextFrames.Count > 0) { for (int i = 0; i < id3v2.TextFrames.Count; i++) { if (id3v2.TextFrames.Items[i].FrameID == "TIT2") { Title = id3v2.TextFrames.Items[i].Text; } if (id3v2.TextFrames.Items[i].FrameID == "TPE1") { Artist = id3v2.TextFrames.Items[i].Text; } if (id3v2.TextFrames.Items[i].FrameID == "TALB") { Album = id3v2.TextFrames.Items[i].Text; } } } ID3v1 id3v1 = new ID3v1(FileName, true); Title = IsStringNullOrEmpry(Title) ? id3v1.Title : Title; Artist = IsStringNullOrEmpry(Artist) ? id3v1.Artist : Artist; Album = IsStringNullOrEmpry(Album) ? id3v1.Album : Album; if (IsStringNullOrEmpry(Title)) { Title = ""; } if (IsStringNullOrEmpry(Artist)) { Artist = ""; } if (IsStringNullOrEmpry(Album)) { Album = ""; } SongList.Add(new Song(FileName, Title.TrimEnd(CharToDelete), Artist.TrimEnd(CharToDelete), Album.TrimEnd(CharToDelete), HasAlbum, HasLyrics)); System.Windows.Forms.Application.DoEvents(); //这个地方加多线程实在是不好加 因为有一个OpenFileDialog 而且结果是一个string[] 直接用object传到多线程里面会出问题 //其实DoEvents的效果也挺好的 就用这个代替了! } }
public ID3Wrapper(ID3v1 id3v1Tag, ID3v2 id3v2Tag) { this.id3v1Tag = id3v1Tag; this.id3v2Tag = id3v2Tag; }
public void ID3v1ConstructorTest() { ID3v1 target = new ID3v1(filePath, false); Assert.IsNotNull(target); }
public async Task RetagFileAsync(string mp3FilePath) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $"File: \"{mp3FilePath}\"")); using (var stream = new FileStream(mp3FilePath, FileMode.Open, _options.DryRunMode ? FileAccess.Read : FileAccess.ReadWrite)) { TagHandler tag1 = null; TagHandler tag2 = null; ID3v1 tagModel1 = null; try { // Read ID3v1 tags... stream.Seek(0, SeekOrigin.Begin); tagModel1 = new ID3v1(); tagModel1.Deserialize(stream); tag1 = new TagHandler(tagModel1.FrameModel); } catch (Exception ex) { VerboseOutput?.Invoke(this, new VerboseInfo(3, () => $" Could not read ID3v1 tags: {ex.ToString()}", isError: true)); } try { // Read ID3v2 tags... stream.Seek(0, SeekOrigin.Begin); var tagModel2 = TagManager.Deserialize(stream); tag2 = new TagHandler(tagModel2); } catch (Exception ex) { VerboseOutput?.Invoke(this, new VerboseInfo(3, () => $" Could not read ID3v2 tags: {ex.ToString()}", isError: true)); } if (tag1 == null && tag2 == null) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" No ID3 tags found. No changes.", isError: true)); return; } if (string.IsNullOrWhiteSpace(tag1?.Year) && tag2 != null) { tag1 = null; // prefer storing the year in v2 by checking v1 first } if (string.IsNullOrWhiteSpace(tag2?.Year) && tag1 != null) { tag2 = null; // The year is stored in the v1 tag only } string artist = (tag2?.Artist ?? tag1?.Artist).Trim(new char[] { ' ', '\n', '\0' }).Trim(); string title = (tag2?.Title ?? tag1?.Title).Trim(new char[] { ' ', '\n', '\0' }).Trim(); string year = (tag2?.Year ?? tag1?.Year).Trim(new char[] { ' ', '\n', '\0' }).Trim(); if (tag1 != null && tag2 != null && tag1.Year != tag2.Year) { year = $"{tag1.Year} & {tag2.Year}"; } if (string.IsNullOrWhiteSpace(artist) || string.IsNullOrWhiteSpace(title)) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" Title and/or artist tags are missing or contain empty values. No changes.", isError: true)); return; } VerboseOutput?.Invoke(this, new VerboseInfo(1, () => $" Found MP3 Tags: \"{artist}\" \"{title}\" ({year})")); var oldestReleaseDate = await GetOldestReleaseDateAsync(artist, title); if (oldestReleaseDate == null) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" Oldest release date could not be determined. Online lookup failed. No changes.", isError: true)); return; } if (year == oldestReleaseDate.Value.Year.ToString()) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" Year is already correct. No changes.")); return; } if (_options.DryRunMode) { VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" DRY RUN MODE: Year WOULD HAVE BEEN updated to ({oldestReleaseDate.Value.Year}).")); } else { // Update the year with the new looked up year if (tag1 != null) { tag1.Year = oldestReleaseDate.Value.Year.ToString(); tagModel1.FrameModel = tag1.FrameModel; tagModel1.Serialize(stream); } if (tag2 != null) { tag2.Year = oldestReleaseDate.Value.Year.ToString(); TagManager.Serialize(tag2.FrameModel, stream); } VerboseOutput?.Invoke(this, new VerboseInfo(0, () => $" Year updated to ({oldestReleaseDate.Value.Year}).")); } } }
/// <summary> /// Parse ID3 tags from stream and calculate where the audio must be /// </summary> /// <remarks> /// if this throws an exception, the File is not usable. /// </remarks> private void Initialise() { // create an empty framemodel, to use if we don't parse anything better FrameModel tagModel = new FrameModel(); // clear out any previous taghandler _tagHandler = null; // don't know how big the audio is until we've parsed the tags _audio = null; UInt32 audioNumBytes; using (FileStream sourceStream = _sourceFileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { // all the header calculations use UInt32; // this guarantees all the file offsets we have to deal with fit in a UInt32 if (sourceStream.Length > UInt32.MaxValue) { throw new InvalidAudioFrameException("MP3 file can't be bigger than 4gb"); } // in the absence of any recognised tags, // audio starts at the start _audioStart = 0; // audio is entire file length audioNumBytes = (UInt32)sourceStream.Length; // try to read an ID3v1 block. // If ID3v2 block exists, its values overwrite these // Otherwise, if ID3V1 block exists, its values are used // The audio is anything that's left after all the tags are excluded. try { ID3v1 id3v1 = new ID3v1(); id3v1.Deserialize(sourceStream); // fill in ID3v2 block from the ID3v1 data tagModel = id3v1.FrameModel; // audio is shorter by the length of the id3v1 tag audioNumBytes -= ID3v1.TagLength; } catch (TagNotFoundException) { // ignore "no ID3v1 block" // everything else isn't caught here, and throws out to the caller } try { sourceStream.Seek(0, SeekOrigin.Begin); tagModel = FrameManager.Deserialize(sourceStream); // audio starts after the tag _audioStart = (uint)sourceStream.Position; // audio is shorter by the length of the id3v2 tag audioNumBytes -= _audioStart; } catch (TagNotFoundException) { // ignore "no ID3v2 block" // everything else isn't caught here, and throws out to the caller } // create a taghandler to hold the tagmodel we've parsed, if any _tagHandler = new TagHandler(tagModel); } // closes sourceStream // save the location of the audio in the original file // passing in audio size and id3 length tag (if any) to help with bitrate calculations _audio = new AudioFile(_sourceFileInfo, _audioStart, audioNumBytes, _tagHandler.Length); _audioReplaced = false; }
public virtual void SetId3v1Tag(ID3v1 id3v1Tag) { this.id3v1Tag = id3v1Tag; }
public void FilePathTest() { ID3v1 target = new ID3v1(filePath, false); Assert.AreEqual(filePath, target.FilePath); }
public virtual void RemoveId3v1Tag() { this.id3v1Tag = null; }
public void HaveTagTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual(true, target.HaveTag); }
public void TitleTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual("Perfumed Planet", target.Title); }
public void TrackNumberTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual(1, target.TrackNumber); }
public void YearTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual(string.Empty, target.Year); }
/// <exception cref="System.IO.IOException"></exception> private void InitId3v1Tag(RandomAccessFile file) { byte[] bytes = new byte[ID3v1Tag.TAG_LENGTH]; file.Seek(GetLength() - ID3v1Tag.TAG_LENGTH); int bytesRead = file.Read(bytes, 0, ID3v1Tag.TAG_LENGTH); if (bytesRead < ID3v1Tag.TAG_LENGTH) { throw new IOException("Not enough bytes read"); } try { id3v1Tag = new ID3v1Tag(bytes); } catch (NoSuchTagException) { id3v1Tag = null; } }
/// <summary> /// Create new ID3 Info class /// </summary> /// <param name="FileAddress">FileAddress for read ID3 info</param> /// <param name="LoadData">Indicate load data in constructor or not</param> public ID3Info(string FilePath, bool LoadData) { _ID3v1 = new ID3v1(FilePath, LoadData); _ID3v2 = new ID3v2(FilePath, LoadData); file = TagLib.File.Create(FilePath); // InvariantStartPosition }
public void ArtistTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual("Andre Norton", target.Artist); }
/// <summary> /// Create new ID3 Info class /// </summary> /// <param name="FileAddress">FileAddress for read ID3 info</param> /// <param name="LoadData">Indicate load data in constructor or not</param> public ID3Info(string FilePath, bool LoadData) { _ID3v1 = new ID3v1(FilePath, LoadData); _ID3v2 = new ID3v2(FilePath, LoadData); }
public void AlbumTest() { ID3v1 target = new ID3v1(filePath, true); Assert.AreEqual("Plague Ship", target.Album); }
public void GenreTest() { ID3v1 target = new ID3v1(filePath, false); Assert.AreEqual(Genre.Blues, target.Genre); }
/// <summary> /// Gets the next frame. /// </summary> /// <returns>Returns the next frame or null (at end of stream).</returns> public AudioFrame GetNextFrame() { while (true) { #region return buffered frames first (if any) // got a decoded frame at the cache ? if (m_BufferedFrame != null) { AudioFrame result; if (m_InvalidFrame != null) { result = m_InvalidFrame; m_InvalidFrame = null; } else { result = m_BufferedFrame; m_BufferedFrame = null; } return(result); } #endregion #region search next frame start // search the next interesting position var searchResult = FindFrame(); if (searchResult == null) { #region end of stream cleanup // invalid data at end of stream ? if (m_Reader.Available > 0) { // yes buffer InvalidData(m_Reader.GetBuffer()); } // got an invalid frame ? if (m_InvalidFrame != null) { // return invalid frame AudioFrame result = m_InvalidFrame; m_InvalidFrame = null; return(result); } // got an id3v1 ? if (m_ID3v1 != null) { // return id3v1 AudioFrame result = m_ID3v1; m_ID3v1 = null; return(result); } // everything done, return null return(null); #endregion } #endregion #region check search result // got garbage at the beginning? if (searchResult.Index > 0) { // yes, invalid data InvalidData(m_Reader.GetBuffer(searchResult.Index)); continue; } #endregion #region decode frame // try to decode frame try { var valid = false; AudioFrame frame = null; switch (searchResult.Match) { #region decode mp3 frame case MatchType.MP3Frame: var audioFrame = new MP3AudioFrame(); valid = audioFrame.Parse(m_Reader); frame = audioFrame; break; #endregion #region decode id3 frame case MatchType.ID3Frame: frame = new ID3v2(); valid = frame.Parse(m_Reader); break; #endregion default: throw new NotImplementedException(string.Format("Unknown frame type {0}", searchResult.Match)); } // parsed successfully? if (valid) { // yes, cache frame m_BufferedFrame = frame; } else { // no invalidate InvalidData(m_Reader.GetBuffer(1)); } } catch (Exception ex) { Trace.TraceError(string.Format("Error while decoding {0} in stream {1}", searchResult.Match, m_Reader)); Trace.TraceError(ex.ToString()); // invalid frame or decoder error, move ahead var count = (searchResult.Index < 0) ? 1 : searchResult.Index + 1; InvalidData(m_Reader.GetBuffer(count)); } #endregion } }