/// <summary> /// Load header from the stream. /// </summary> /// <param name="stream">Stream to load header</param> public void Deserialize(Stream stream) { BinaryReader reader = new BinaryReader(stream); byte[] idTag = new byte[3]; // Read the tag identifier reader.Read(idTag, 0, 3); // Compare the readed tag if (Memory.Compare(_id3, idTag, 3) == false) { throw new TagNotFoundException("ID3v2 tag identifier was not found"); } // Get the id3v2 version byte _id3Version = reader.ReadByte(); if (_id3Version == 0xff) { throw new InvalidTagException("Corrupt header, invalid ID3v2 version."); } // Get the id3v2 revision byte _id3Revision = reader.ReadByte(); if (_id3Revision == 0xff) { throw new InvalidTagException("Corrupt header, invalid ID3v2 revision."); } // Get the id3v2 flag byte, only read what I understand _id3Flags = (byte)(0xf0 & reader.ReadByte()); // Get the id3v2 size, swap and unsync the integer _id3RawSize = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); if (_id3RawSize == 0) { throw new InvalidTagException("Corrupt header, tag size can't be zero."); } }
/// <summary> /// Create a frame depending on the tag form its binary representation. /// </summary> /// <param name="frameId">type of frame</param> /// <param name="flags">frame flags</param> /// <param name="frame">binary frame</param> /// <returns>Frame of tag type</returns> public FrameBase Build(string frameId, ushort flags, byte[] buffer) { // Build a frame var frame = FrameFactory.Build(frameId); SetFlags(frame, flags); uint index = 0; uint size = (uint)buffer.Length; Stream stream = new MemoryStream(buffer, false); var reader = new BinaryReader(stream); if (GetGrouping(flags) == true) { frame.Group = reader.ReadByte(); index++; } if (frame.Compression == true) { switch (Version) { case 3: { size = Swap.UInt32(reader.ReadUInt32()); break; } case 4: { size = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); break; } default: { throw new NotImplementedException("ID3v2 Version " + Version + " is not supported."); } } index = 0; stream = new InflaterInputStream(stream); } if (frame.Encryption == true) { throw new NotImplementedException("Encryption is not implemented, consequently it is not supported."); } if (frame.Unsynchronisation == true) { var memoryStream = new MemoryStream(); size = Sync.Unsafe(stream, memoryStream, size); index = 0; memoryStream.Seek(0, SeekOrigin.Begin); stream = memoryStream; } byte[] frameBuffer = new byte[size - index]; stream.Read(frameBuffer, 0, (int)(size - index)); frame.Parse(frameBuffer); return(frame); }
/// <summary> /// Load the ID3 extended header from a stream /// </summary> /// <param name="stream">Binary stream containing a ID3 extended header</param> public void Deserialize(Stream stream) { BinaryReader reader = new BinaryReader(stream); _size = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); if (_size < 6) { throw new InvalidFrameException("Corrupt id3 extended header."); } // TODO: implement the extended header, copy for now since it's optional _extendedHeader = new Byte[_size]; stream.Read(_extendedHeader, 0, (int)_size); }
/// <summary> /// Load the ID3 extended header from a stream /// </summary> /// <param name="stream">Binary stream containing a ID3 extended header</param> public void Deserialize([NotNull] Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } using (var reader = new BinaryReader(stream, Encoding.UTF8, true)) Size = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); if (Size < 6) { throw new InvalidFrameException("Corrupt id3 extended header."); } // TODO: implement the extended header, copy for now since it's optional _extendedHeader = new byte[Size]; stream.Read(_extendedHeader, 0, (int)Size); }
/// <summary> /// Build a binary data frame form the frame object. /// </summary> /// <param name="frame">ID3 Frame</param> /// <returns>binary frame representation</returns> public byte[] Make(FrameBase frame, out ushort flags) { flags = GetFlags(frame); var buffer = frame.Make(); var memoryStream = new MemoryStream(); var writer = new BinaryWriter(memoryStream); if (frame.Group.HasValue == true) { writer.Write((byte)frame.Group); } if (frame.Compression == true) { switch (Version) { case 3: { writer.Write(Swap.Int32(buffer.Length)); break; } case 4: { writer.Write(Sync.UnsafeBigEndian(Swap.UInt32((uint)buffer.Length))); break; } default: { throw new NotImplementedException("ID3v2 Version " + Version + " is not supported."); } } var buf = new byte[2048]; var deflater = new Deflater(Deflater.BEST_COMPRESSION); deflater.SetInput(buffer, 0, buffer.Length); deflater.Finish(); while (!deflater.IsNeedingInput) { int len = deflater.Deflate(buf, 0, buf.Length); if (len <= 0) { break; } memoryStream.Write(buf, 0, len); } if (!deflater.IsNeedingInput) { //TODO: Skip and remove invalid frames. throw new InvalidFrameException("Can't decompress frame '" + frame.FrameId + "' missing data"); } } else { memoryStream.Write(buffer, 0, buffer.Length); } if (frame.Encryption == true) { //TODO: Encryption throw new NotImplementedException("Encryption is not implemented, consequently it is not supported."); } if (frame.Unsynchronisation == true) { MemoryStream synchStream = new MemoryStream(); Sync.Unsafe(memoryStream, synchStream, (uint)memoryStream.Position); memoryStream = synchStream; } return(memoryStream.ToArray()); }
internal FrameBase Build([NotNull] string frameId, ushort flags, [NotNull] byte[] buffer) { // Build a frame var frame = FrameFactory.Build(frameId); SetFlags(frame, flags); var index = 0; var size = (uint)buffer.Length; Stream stream = new MemoryStream(buffer, false); var streamsToClose = new List <Stream>(3) { stream }; try { using (var reader = new BinaryReader(stream, Encoding.UTF8, false)) { if (GetGrouping(flags)) { frame.Group = reader.ReadByte(); index++; } if (frame.Compression) { switch (_version) { case 3: size = Swap.UInt32(reader.ReadUInt32()); break; case 4: size = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); break; default: throw new NotImplementedException($"ID3v2 Version {_version} is not supported."); } index = 0; stream = new InflaterInputStream(stream); streamsToClose.Add(stream); } if (frame.Encryption) { throw new NotImplementedException( "Encryption is not implemented, consequently it is not supported."); } if (frame.Unsynchronisation) { var memoryStream = new MemoryStream(); streamsToClose.Add(memoryStream); size = Sync.Unsafe(stream, memoryStream, size); index = 0; memoryStream.Seek(0, SeekOrigin.Begin); stream = memoryStream; } var frameBuffer = new byte[size - index]; stream.Read(frameBuffer, 0, (int)(size - index)); frame.Parse(frameBuffer); return(frame); } } finally { foreach (var streamToClose in streamsToClose) { streamToClose.Close(); } } }
internal byte[] Make([NotNull] FrameBase frame, out ushort flags) { flags = GetFlags(frame); var buffer = frame.Make(); var memoryStream = new MemoryStream(); var streamsToClose = new List <Stream>(2) { memoryStream }; try { using (var writer = new BinaryWriter(memoryStream, Encoding.UTF8, true)) { if (frame.Group.HasValue) { writer.Write((byte)frame.Group); } if (frame.Compression) { switch (_version) { case 3: writer.Write(Swap.Int32(buffer.Length)); break; case 4: writer.Write(Sync.UnsafeBigEndian(Swap.UInt32((uint)buffer.Length))); break; default: throw new NotImplementedException($"ID3v2 Version {_version} is not supported."); } var buf = new byte[2048]; var deflater = new Deflater(Deflater.BEST_COMPRESSION); deflater.SetInput(buffer, 0, buffer.Length); deflater.Finish(); while (!deflater.IsNeedingInput) { var len = deflater.Deflate(buf, 0, buf.Length); if (len <= 0) { break; } memoryStream.Write(buf, 0, len); } //TODO: Skip and remove invalid frames. if (!deflater.IsNeedingInput) { throw new InvalidFrameException($"Can't decompress frame '{frame.FrameId}' missing data"); } } else { memoryStream.Write(buffer, 0, buffer.Length); } //TODO: Encryption if (frame.Encryption) { throw new NotImplementedException( "Encryption is not implemented, consequently it is not supported."); } if (frame.Unsynchronisation) { var synchStream = new MemoryStream(); streamsToClose.Add(synchStream); Sync.Unsafe(memoryStream, synchStream, (uint)memoryStream.Position); memoryStream = synchStream; } return(memoryStream.ToArray()); } } finally { foreach (var streamToClose in streamsToClose) { streamToClose.Close(); } } }
/// <summary> /// Create a frame depending on the tag form its binary representation. /// </summary> /// <param name="frameId">type of frame</param> /// <param name="flags">frame flags</param> /// <param name="frame">binary frame</param> /// <returns>Frame of tag type</returns> public IFrame Build(string frameId, ushort options, byte[] frame) { // Build a frame IFrame frameBase = FrameFactory.Build(frameId); frameBase.Flags = options; flagHandler.Flags = options; uint index = 0; uint size = (uint)frame.Length; Stream stream = new MemoryStream(frame, false); BinaryReader reader = new BinaryReader(stream); if (flagHandler.Grouping == true) { //TODO: Implement grouping when watching grass grow stops beeing intresting. /* The byte readed here is the group, we are skiping it for now*/ reader.ReadByte(); index++; } if (flagHandler.Compression == true) { switch (flagHandler.Version) { case 3: { size = Swap.UInt32(reader.ReadUInt32()); break; } case 4: { size = Swap.UInt32(Sync.UnsafeBigEndian(reader.ReadUInt32())); break; } default: { throw new NotImplementedException("ID3v2 Version " + flagHandler.Version + " is not supported."); } } index = 0; stream = new InflaterInputStream(stream); } if (flagHandler.Encryption == true) { //TODO: Encryption throw new NotImplementedException("Encryption is not implemented, consequently it is not supported."); } if (flagHandler.Unsynchronisation == true) { Stream memStream = new MemoryStream(); size = Sync.Unsafe(stream, memStream, size); index = 0; stream = memStream; } byte[] frameBuffer = new byte[size - index]; stream.Read(frameBuffer, 0, (int)(size - index)); frameBase.Parse(frameBuffer); return(frameBase); }
/// <summary> /// Build a binary data frame form the frame object. /// </summary> /// <param name="frameBase">ID3 Frame</param> /// <returns>binary frame representation</returns> public byte[] Make(IFrame frameBase) { flagHandler.Flags = frameBase.Flags; byte[] frame = frameBase.Make(); MemoryStream memoryStream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(memoryStream); if (flagHandler.Grouping == true) { //TODO: Do grouping some place in the universe byte _group = 0; writer.Write(_group); } if (flagHandler.Compression == true) { switch (flagHandler.Version) { case 3: { writer.Write(Swap.Int32(frame.Length)); break; } case 4: { writer.Write(Sync.UnsafeBigEndian(Swap.UInt32((uint)frame.Length))); break; } default: { throw new NotImplementedException("ID3v2 Version " + flagHandler.Version + " is not supported."); } } byte[] buf = new byte[2048]; Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION); deflater.SetInput(frame, 0, frame.Length); deflater.Finish(); while (!deflater.IsNeedingInput) { int len = deflater.Deflate(buf, 0, buf.Length); if (len <= 0) { break; } memoryStream.Write(buf, 0, len); } if (!deflater.IsNeedingInput) { //TODO: Skip and remove invalid frames. throw new InvalidFrameException("Can't decompress frame '" + frameBase.FrameId + "' missing data"); } } else { memoryStream.Write(frame, 0, frame.Length); } if (flagHandler.Encryption == true) { //TODO: Encryption throw new NotImplementedException("Encryption is not implemented, consequently it is not supported."); } if (flagHandler.Unsynchronisation == true) { MemoryStream synchStream = new MemoryStream(); Sync.Unsafe(memoryStream, synchStream, (uint)memoryStream.Position); memoryStream = synchStream; } return(memoryStream.ToArray()); }