Example #1
0
        protected ByteVector Render(bool isHeader)
        {
            ByteVector vector = new ByteVector();

            // add the file identifier -- "APETAGEX"

            vector.Add(FileIdentifier);

            // add the version number -- we always render a 2.000 tag regardless of what
            // the tag originally was.
            vector.Add(ByteVector.FromUInt(2000, false));

            // add the tag size
            vector.Add(ByteVector.FromUInt(tagSize, false));

            // add the item count
            vector.Add(ByteVector.FromUInt(itemCount, false));

            // render and add the flags
            uint flags = 0;

            flags |= (uint)((HeaderPresent ? 1 : 0) << 31);
            // footer is always present
            flags |= (uint)((isHeader ? 1 : 0) << 29);

            vector.Add(ByteVector.FromUInt(flags, false));

            // add the reserved 64bit

            vector.Add(ByteVector.FromLong(0));

            return(vector);
        }
Example #2
0
        public override void Save()
        {
            ClearPageData();             // Force re-reading of the file.

            xiph_comment_data = comment.Render();

            // Create FLAC metadata-block:

            // Put the size in the first 32 bit (I assume no more than 24 bit are used)

            ByteVector v = ByteVector.FromUInt((uint)xiph_comment_data.Count);

            // Set the type of the metadata-block to be a Xiph / Vorbis comment

            v[0] = 4;

            // Append the comment-data after the 32 bit header

            v.Add(xiph_comment_data);

            // Save the packet at the old spot
            // FIXME: Use padding if size is increasing

            SetPacket(comment_packet, v);

            base.Save();
        }
Example #3
0
        public ByteVector Render()
        {
            ByteVector data  = new ByteVector();
            uint       flags = (uint)((ReadOnly) ? 1 : 0) | ((uint)Type << 1);

            if (IsEmpty)
            {
                return(data);
            }

            if (type != ApeItemType.Binary)
            {
                value = new ByteVector();
                for (int i = 0; i < text.Count; i++)
                {
                    if (i != 0)
                    {
                        value.Add((byte)0);
                    }

                    value.Add(ByteVector.FromString(text[i], StringType.UTF8));
                }
            }

            data.Add(ByteVector.FromUInt((uint)value.Count, false));
            data.Add(ByteVector.FromUInt(flags, false));
            data.Add(ByteVector.FromString(key, StringType.UTF8));
            data.Add((byte)0);
            data.Add(value);

            return(data);
        }
Example #4
0
 public ByteVector Render()
 {
     return(ByteVector.FromUInt(part1, false).Mid(0, 4)
            + ByteVector.FromShort(part2, false).Mid(0, 2)
            + ByteVector.FromShort(part3, false).Mid(0, 2)
            + ByteVector.FromShort(part4, true).Mid(0, 2)
            + ByteVector.FromLong(part5, true).Mid(2, 6));
 }
        /// <summary>
        /// Render this box with the version and flags info at the beginning.
        /// </summary>
        /// <param name="data">The data to render</param>
        /// <returns>A ByteVector of the rendered data</returns>
        protected override ByteVector Render(ByteVector data)
        {
            ByteVector output = new ByteVector();

            output += (byte)version;
            output += ByteVector.FromUInt(flags).Mid(1, 3);
            output += data;

            return(base.Render(output));
        }
Example #6
0
        private List <uint> offsets;        //uint[] offsets;
        #endregion

        #region Private Methods
        private ByteVector UpdateOffsetInternal(int sizeDifference)
        {
            ByteVector output = ByteVector.FromUInt((uint)offsets.Count);

            for (int i = 0; i < offsets.Count; i++)
            {
                offsets[i] = (uint)(offsets[i] + sizeDifference);
                output    += ByteVector.FromUInt(offsets[i]);
            }

            return(output);
        }
Example #7
0
        public ByteVector Render()
        {
            ByteVector data = new ByteVector();

            // capture patern
            data.Add("OggS");

            // stream structure version
            data.Add(0);

            // header type flag
            byte flags = 0;

            if (firstPacketContinued)
            {
                flags |= 1;
            }
            if (pageSequenceNumber == 0)
            {
                flags |= 2;
            }
            if (lastPageOfStream)
            {
                flags |= 4;
            }

            data.Add(flags);

            // absolute granular position
            data.Add(ByteVector.FromLong(absoluteGranularPosition, false));

            // stream serial number
            data.Add(ByteVector.FromUInt(streamSerialNumber, false));

            // page sequence number
            data.Add(ByteVector.FromUInt((uint)pageSequenceNumber, false));

            // checksum -- this is left empty and should be filled in by the Ogg::Page
            // class
            data.Add(new ByteVector(4, 0));

            // page segment count and page segment table
            ByteVector page_segments = LacingValues;

            data.Add((byte)page_segments.Count);
            data.Add(page_segments);

            return(data);
        }
Example #8
0
        public ByteVector Render(bool addFramingBit)
        {
            ByteVector data = new ByteVector();

            // Add the vendor ID length and the vendor ID.  It'field important to use the
            // lenght of the data(String::UTF8) rather than the lenght of the the string
            // since this is UTF8 type and there may be more characters in the data than
            // in the UTF16 string.

            ByteVector vendorData = ByteVector.FromString(vendorId, StringType.UTF8);

            data.Add(ByteVector.FromUInt((uint)vendorData.Count, false));
            data.Add(vendorData);

            // Add the number of fields.

            data.Add(ByteVector.FromUInt(FieldCount, false));

            // Iterate over the the field lists.  Our iterator returns a
            // std::pair<String, StringList> where the first String is the field name and
            // the StringList is the values associated with that field.

            foreach (System.Collections.Generic.KeyValuePair <string, StringCollection> entry in fieldList)             //(DictionaryEntry entry in fieldList)
            {
                // And now iterate over the values of the current text.

                string           fieldName = entry.Key;       //(string)entry.Key;
                StringCollection values    = entry.Value;     //(StringList)entry.Value;

                foreach (string value in values)
                {
                    ByteVector fieldData = ByteVector.FromString(fieldName, StringType.UTF8);
                    fieldData.Add((byte)'=');
                    fieldData.Add(ByteVector.FromString(value, StringType.UTF8));

                    data.Add(ByteVector.FromUInt((uint)fieldData.Count, false));
                    data.Add(fieldData);
                }
            }

            // Append the "framing bit".
            if (addFramingBit)
            {
                data.Add((byte)1);
            }

            return(data);
        }
Example #9
0
        public ByteVector Render()
        {
            // The size is zero because the box header was created not read.
            // Increase the sizes to account for this.
            if (size == 0)
            {
                size       = (uint)(extendedType != null ? 24 : 8);
                largeSize += size;
            }

            // Enlarge for large size if necessary. If large size is in use, the
            // header will be 16 or 32 big as opposed to 8 or 24.
            if ((size == 8 || size == 24) && largeSize > System.UInt32.MaxValue)
            {
                size      += 8;
                largeSize += 8;
            }

            // Get ready to output.
            ByteVector output = new ByteVector();

            // Add the box size and type to the output.
            output += ByteVector.FromUInt((size == 8 || size == 24) ? (uint)largeSize : 1);
            output += boxType;

            // If the box size is 16 or 32, we must have more a large header to
            // append.
            if (size == 16 || size == 32)
            {
                output += ByteVector.FromLong((long)largeSize);
            }

            // The only reason for such a big size is an extended type. Extend!!!
            if (size >= 24)
            {
                output += (extendedType != null) ? extendedType.Mid(0, 16) : new ByteVector(16);
            }

            return(output);
        }
Example #10
0
        public ByteVector Render()
        {
            ByteVector data = header.Render();

            if (packets.IsEmpty)
            {
                if (file != null)
                {
                    file.Seek(packetOffset);
                    data.Add(file.ReadBlock(dataSize));
                }
                else
                {
                    TagLibDebugger.Debug("Ogg.Page.Render() -- this page is empty!");
                }
            }
            else
            {
                foreach (ByteVector v in packets)
                {
                    data.Add(v);
                }
            }

            // Compute and set the checksum for the Ogg page.  The checksum is taken over
            // the entire page with the 4 buffer reserved for the checksum zeroed and then
            // inserted in buffer 22-25 of the page header.

            ByteVector checksum = ByteVector.FromUInt(data.Checksum, false);

            for (int i = 0; i < 4; i++)
            {
                data [i + 22] = checksum [i];
            }

            return(data);
        }
Example #11
0
        public override void Save()
        {
            if (IsReadOnly)
            {
                throw new ReadOnlyException();
            }

            Mode = FileAccessMode.Write;

            long flac_data_begin;
            long flac_data_end;

            // Update ID3 tags
            if (id3v2_tag != null)
            {
                ByteVector id3v2_tag_data = id3v2_tag.Render();

                long id3v2_location = FindId3v2();
                if (id3v2_location >= 0)
                {
                    int id3v2_size = 0;

                    Seek(id3v2_location);
                    Id3v2Header header = new Id3v2Header(ReadBlock((int)Id3v2Header.Size));

                    if (header.TagSize == 0)
                    {
                        TagLibDebugger.Debug("Flac.File.Save() -- Id3v2 header is broken. Ignoring.");
                    }
                    else
                    {
                        id3v2_size = (int)header.CompleteTagSize;
                    }

                    Insert(id3v2_tag_data, id3v2_location, id3v2_size);
                    System.Console.WriteLine("ID3v2: " + id3v2_size + " " + id3v2_tag_data.Count);
                    flac_data_begin = id3v2_location + id3v2_tag_data.Count;
                }
                else
                {
                    Insert(id3v2_tag_data, 0, 0);
                    flac_data_begin = id3v2_tag_data.Count;
                }
            }
            else
            {
                flac_data_begin = 0;
            }

            if (id3v1_tag != null)
            {
                long id3v1_location = FindId3v1();

                if (id3v1_location >= 0)
                {
                    Seek(id3v1_location);
                }
                else
                {
                    Seek(0, System.IO.SeekOrigin.End);
                }

                flac_data_end = Tell;
                WriteBlock(id3v1_tag.Render());
            }
            else
            {
                flac_data_end = Length;
            }


            // Create new vorbis comments is they don'type exist.
            FindTag(TagTypes.Xiph, true);

            xiph_comment_data = comment.Render(false);

            ByteVector v = ByteVector.FromUInt((uint)xiph_comment_data.Count);

            // Set the type of the comment to be a Xiph / Vorbis comment
            // (See scan() for comments on header-format)
            v[0] = 4;
            v.Add(xiph_comment_data);


            // If file already have comment => find and update it
            //                       if not => insert one

            scanned = false;

            if (Scan(flac_data_begin, flac_data_end) != null)
            {
                long next_page_offset = flac_start;
                Seek(next_page_offset);
                ByteVector header = ReadBlock(4);
                uint       length = header.Mid(1, 3).ToUInt();

                next_page_offset += length + 4;

                // Search through the remaining metadata

                byte block_type = (byte)(header[0] & 0x7f);
                bool last_block = (header[0] & 0x80) != 0;

                while (!last_block)
                {
                    Seek(next_page_offset);

                    header     = ReadBlock(4);
                    block_type = (byte)(header[0] & 0x7f);
                    last_block = (header[0] & 0x80) != 0;
                    length     = header.Mid(1, 3).ToUInt();

                    // Type is vorbiscomment
                    if (block_type == 4)
                    {
                        long next_keep = (last_block ? 0 : FindPaddingBreak(next_page_offset + length + 4,
                                                                            next_page_offset + XiphCommentData.Count + 8,
                                                                            ref last_block));
                        uint padding_length;
                        if (next_keep != 0)
                        {
                            // There is space for comment and padding blocks without rewriting the whole file.
                            // Note this can not overflow.
                            padding_length = (uint)(next_keep - (next_page_offset + XiphCommentData.Count + 8));
                        }
                        else
                        {
                            // Not enough space, so we will have to rewrite the whole file following this block
                            padding_length = (uint)XiphCommentData.Count;
                            if (padding_length < 4096)
                            {
                                padding_length = 4096;
                            }
                            next_keep = next_page_offset + length + 4;
                        }

                        ByteVector padding = ByteVector.FromUInt(padding_length);
                        padding[0] = 1;
                        if (last_block)
                        {
                            padding[0] = (byte)(padding[0] | 0x80);
                        }
                        padding.Resize((int)(padding_length + 4));

                        Insert(v + padding, next_page_offset, next_keep - next_page_offset);
                        //System.Console.WriteLine ("OGG: " + (next_keep - next_page_offset) + " " + (vector.Count + padding.Count));

                        break;
                    }

                    next_page_offset += length + 4;
                }
            }
            else
            {
                long next_page_offset = flac_start;

                Seek(next_page_offset);

                ByteVector header     = ReadBlock(4);
                bool       last_block = (header[0] & 0x80) != 0;
                uint       length     = header.Mid(1, 3).ToUInt();

                // If last block was last, make this one last

                if (last_block)
                {
                    // Copy the bottom seven bits into the new value

                    ByteVector h = (byte)(header[0] & 0x7F);
                    Insert(h, next_page_offset, 1);

                    // Set the last bit
                    v[0] = (byte)(v[0] | 0x80);
                }

                Insert(v, next_page_offset + length + 4, 0);
            }

            Mode = FileAccessMode.Closed;
        }