예제 #1
0
        ///// <summary>
        ///// find the first non-zero character in the stream
        ///// then back up one, so it will be the first char that gets read
        ///// and the stream position is pointing to the start of the non-zero (e.g. audio) data
        ///// </summary>
        ///// <param name="stream"></param>
        ///// <returns></returns>
        //static private uint SeekEndOfPadding( Stream stream )
        //{
        //    uint index = 0;
        //    while( stream.ReadByte() == 0 )
        //    {
        //        ++index;
        //    }
        //    stream.Seek(-1, SeekOrigin.Current);
        //    return index;
        //}

        /// <summary>
        /// Save the ID3v2 frames to a binary stream
        /// </summary>
        /// <param name="frameModel">Model keeping the ID3 Tag structure</param>
        /// <param name="stream">Stream keeping the ID3 Tag</param>
        public static void Serialize(FrameModel frameModel, Stream stream)
        {
            if (frameModel.Count <= 0)
            {
                throw new InvalidTagException("Can't serialize a ID3v2 tag without any frames, there must be at least one present.");
            }

            MemoryStream memory = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(memory);

            FrameHelper frameHelper = new FrameHelper(frameModel.Header);

            // Write the frames in binary format
            foreach (IFrame frameBase in frameModel)
            {
                //TODO: Do validations on tag name correctness
                byte[] frameId = new byte[4];
                UTF8Encoding.UTF8.GetBytes(frameBase.FrameId, 0, 4, frameId, 0);
                writer.Write(frameId); // Write the 4 byte text tag
                byte[] frame     = frameHelper.Make(frameBase);
                uint   frameSize = (uint)frame.Length;

                if (frameModel.Header.Version == 4)
                {
                    Sync.Safe(frameSize);
                }

                writer.Write(Swap.UInt32(frameSize));
                writer.Write(Swap.UInt16(frameBase.Flags));
                writer.Write(frame);
            }

            uint id3TagSize = (uint)memory.Position;

            // Skip the header 10 bytes for now, we will come back and write the Header
            // with the correct size once have the tag size + padding
            stream.Seek(10, SeekOrigin.Begin);

            // TODO: Add extended header handling
            if (frameModel.Header.Unsync == true)
            {
                id3TagSize += Sync.Safe(memory, stream, id3TagSize);
            }
            else
            {
                memory.WriteTo(stream);
            }

            // update the TagSize stored in the tagModel
            frameModel.Header.TagSize = id3TagSize;

            // next write the padding of zeros, if any
            if (frameModel.Header.Padding)
            {
                byte[] bytes = new byte[frameModel.Header.PaddingSize];
                stream.Write(bytes, 0, (int)frameModel.Header.PaddingSize);
            }

            // next write the footer, if any
            if (frameModel.Header.Footer)
            {
                frameModel.Header.SerializeFooter(stream);
            }

            // Now seek back to the start and write the header
            long position = stream.Position;

            stream.Seek(0, SeekOrigin.Begin);
            frameModel.Header.Serialize(stream);

            // reset position to the end of the tag
            stream.Position = position;
        }
예제 #2
0
        /// <summary>
        /// Save the ID3v2 frames to a binary stream
        /// </summary>
        /// <param name="frameModel">Model keeping the ID3 Tag structure</param>
        /// <param name="stream">Stream keeping the ID3 Tag</param>
        public static void Serialize(TagModel frameModel, Stream stream)
        {
            if (frameModel.Count <= 0)
                throw new InvalidTagException("Can't serialize a ID3v2 tag without any frames, there must be at least one present.");

            var memory = new MemoryStream();
            var writer = new BinaryWriter(memory);

            var frameHelper = new FrameHelper(frameModel.Header);
            // Write the frames in binary format
            foreach (FrameBase frame in frameModel)
            {
                //TODO: Do validations on tag name correctness
                byte[] frameId = new byte[4];
                UTF8Encoding.UTF8.GetBytes(frame.FrameId, 0, 4, frameId, 0);
                string s = UTF8Encoding.UTF8.GetString(frameId);
                writer.Write(frameId); // Write the 4 byte text tag
                ushort flags;
                byte[] buffer = frameHelper.Make(frame, out flags);
                s = UTF8Encoding.UTF8.GetString(buffer);
                uint frameSize = (uint)buffer.Length;

                if (frameModel.Header.Version == 4)
                    frameSize = Sync.Safe(frameSize);

                writer.Write(Swap.UInt32(frameSize));
                writer.Write(Swap.UInt16(flags));
                writer.Write(buffer);
            }

            uint id3TagSize = (uint)memory.Position;

            // Skip the header 10 bytes for now, we will come back and write the Header
            // with the correct size once have the tag size + padding
            stream.Seek(10, SeekOrigin.Begin);

            // TODO: Add extended header handling
            if (frameModel.Header.Unsync == true)
                id3TagSize += Sync.Safe(memory, stream, id3TagSize);
            else
                memory.WriteTo(stream);

            // update the TagSize stored in the tagModel
            frameModel.Header.TagSize = id3TagSize;

            // next write the padding of zeros, if any
            if (frameModel.Header.Padding)
            {
                for (int i = 0; i < frameModel.Header.PaddingSize; i++)
                    stream.WriteByte(0);
            }

            // next write the footer, if any
            if (frameModel.Header.Footer)
                frameModel.Header.SerializeFooter(stream);

            // Now seek back to the start and write the header
            long position = stream.Position;
            stream.Seek(0, SeekOrigin.Begin);
            frameModel.Header.Serialize(stream);

            // reset position to the end of the tag
            stream.Position = position;
        }
예제 #3
0
        /// <summary>
        /// Save the ID3v2 frames to a binary stream
        /// </summary>
        /// <param name="frameModel">Model keeping the ID3 Tag structure</param>
        /// <param name="stream">Stream keeping the ID3 Tag</param>
        public static void Serialize([NotNull] TagModel frameModel, [NotNull] Stream stream)
        {
            if (frameModel.Count <= 0)
            {
                throw new InvalidTagException("Can't serialize a ID3v2 tag without any frames, there must be at least one present.");
            }

            using (var memory = new MemoryStream())
                using (var writer = new BinaryWriter(memory, Encoding.UTF8, true))
                {
                    var frameHelper = new FrameHelper(frameModel.Header);

                    // Write the frames in binary format
                    foreach (var frame in frameModel)
                    {
                        //TODO: Do validations on tag name correctness
                        var frameId = new byte[4];
                        Encoding.UTF8.GetBytes(frame.FrameId, 0, 4, frameId, 0);
                        writer.Write(frameId); // Write the 4 byte text tag
                        var buffer    = frameHelper.Make(frame, out var flags);
                        var frameSize = (uint)buffer.Length;

                        if (frameModel.Header.Version == 4)
                        {
                            frameSize = Sync.Safe(frameSize);
                        }

                        writer.Write(Swap.UInt32(frameSize));
                        writer.Write(Swap.UInt16(flags));
                        writer.Write(buffer);
                    }

                    var id3TagSize = (uint)memory.Position;

                    // Skip the header 10 bytes for now, we will come back and write the Header
                    // with the correct size once have the tag size + padding
                    stream.Seek(10, SeekOrigin.Begin);

                    // TODO: Add extended header handling
                    if (frameModel.Header.Unsync)
                    {
                        id3TagSize += Sync.Safe(memory, stream, id3TagSize);
                    }
                    else
                    {
                        memory.WriteTo(stream);
                    }

                    // update the TagSize stored in the tagModel
                    frameModel.Header.TagSize = id3TagSize;

                    // If padding + tag size is too big, shrink the padding (rather than throwing an exception)
                    frameModel.Header.PaddingSize =
                        Math.Min(frameModel.Header.PaddingSize, 0x10000000 - id3TagSize);

                    // next write the padding of zeros, if any
                    if (frameModel.Header.Padding)
                    {
                        for (var i = 0; i < frameModel.Header.PaddingSize; i++)
                        {
                            stream.WriteByte(0);
                        }
                    }

                    // next write the footer, if any
                    if (frameModel.Header.Footer)
                    {
                        frameModel.Header.SerializeFooter(stream);
                    }

                    // Now seek back to the start and write the header
                    var position = stream.Position;
                    stream.Seek(0, SeekOrigin.Begin);
                    frameModel.Header.Serialize(stream);

                    // reset position to the end of the tag
                    stream.Position = position;
                }
        }