예제 #1
0
        /// <summary>
        ///    Converts a raw ASF picture into an <see cref="IPicture"
        ///    /> object.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing raw ASF
        ///    picture data.
        /// </param>
        /// <returns>
        ///    A <see cref="IPicture" /> object to read from the raw
        ///    data.
        /// </returns>
        private static IPicture PictureFromData(ByteVector data)
        {
            if (data.Count < 9)
            {
                return(null);
            }

            int     offset = 0;
            Picture p      = new Picture();

            // Get the picture type:

            p.Type  = (PictureType)data [offset];
            offset += 1;

            // Get the picture size:

            int size = (int)data.Mid(offset, 4).ToUInt(false);

            offset += 4;

            // Get the mime-type:

            int found = data.Find(ByteVector.TextDelimiter(
                                      StringType.UTF16LE), offset, 2);

            if (found < 0)
            {
                return(null);
            }

            p.MimeType = data.ToString(StringType.UTF16LE, offset,
                                       found - offset);
            offset = found + 2;

            // Get the description:

            found = data.Find(ByteVector.TextDelimiter(
                                  StringType.UTF16LE), offset, 2);
            if (found < 0)
            {
                return(null);
            }

            p.Description = data.ToString(StringType.UTF16LE,
                                          offset, found - offset);
            offset = found + 2;

            p.Data = data.Mid(offset, size);

            return(p);
        }
예제 #2
0
        /// <summary>
        ///    Performs the actual parsing of the raw data.
        /// </summary>
        /// <remarks>
        ///    Because of the high parsing cost and relatively low usage
        ///    of the class, <see cref="ParseFields" /> only stores the
        ///    field data so it can be parsed on demand. Whenever a
        ///    property or method is called which requires the data,
        ///    this method is called, and only on the first call does it
        ///    actually parse the data.
        /// </remarks>
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }

            ByteVector data = raw_data;

            raw_data = null;

            var field_list = new List <string> ();

            ByteVector delim = ByteVector.TextDelimiter(encoding);

            if (FrameId != FrameType.WXXX)
            {
                field_list.AddRange(data.ToStrings(StringType.Latin1, 0));
            }
            else if (data.Count > 1 && !data.Mid(0,
                                                 delim.Count).Equals(delim))
            {
                string value = data.ToString(StringType.Latin1, 1,
                                             data.Count - 1);

                // Do a fast removal of end bytes.
                if (value.Length > 1 &&
                    value[value.Length - 1] == 0)
                {
                    for (int i = value.Length - 1; i >= 0; i--)
                    {
                        if (value[i] != 0)
                        {
                            value = value.Substring(0, i + 1);
                            break;
                        }
                    }
                }

                field_list.Add(value);
            }

            // Bad tags may have one or more nul characters at the
            // end of a string, resulting in empty strings at the
            // end of the FieldList. Strip them off.
            while (field_list.Count != 0 && string.IsNullOrEmpty(field_list[field_list.Count - 1]))
            {
                field_list.RemoveAt(field_list.Count - 1);
            }

            text_fields = field_list.ToArray();
        }
예제 #3
0
        /// <summary>
        ///    Populates the current instance by reading in a raw APEv2
        ///    item.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the item to
        ///    read.
        /// </param>
        /// <param name="offset">
        ///    A <see cref="int" /> value specifying the offset in
        ///    <paramref name="data" /> at which the item data begins.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///    <paramref name="data" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///    <paramref name="offset" /> is less than zero.
        /// </exception>
        /// <exception cref="CorruptFileException">
        ///    A complete item could not be read.
        /// </exception>
        protected void Parse(ByteVector data, int offset)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset");
            }


            // 11 bytes is the minimum size for an APE item
            if (data.Count < offset + 11)
            {
                throw new CorruptFileException(
                          "Not enough data for APE Item");
            }

            uint value_length = data.Mid(offset, 4).ToUInt(false);
            uint flags        = data.Mid(offset + 4, 4).ToUInt(false);

            ReadOnly = (flags & 1) == 1;
            Type     = (ItemType)((flags >> 1) & 3);

            int pos = data.Find(ByteVector.TextDelimiter(
                                    StringType.UTF8), offset + 8);

            key = data.ToString(StringType.UTF8,
                                offset + 8, pos - offset - 8);

            if (value_length > data.Count - pos - 1)
            {
                throw new CorruptFileException(
                          "Invalid data length.");
            }

            size_on_disk = pos + 1 + (int)value_length - offset;

            if (Type == ItemType.Binary)
            {
                this.data = new ReadOnlyByteVector(
                    data.Mid(pos + 1, (int)value_length));
            }
            else
            {
                this.text = data.Mid(pos + 1,
                                     (int)value_length).ToStrings(
                    StringType.UTF8, 0);
            }
        }
예제 #4
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            StringType encoding = CorrectEncoding(TextEncoding, version);
            ByteVector v        = new ByteVector();

            v.Add((byte)encoding);
            v.Add(ByteVector.FromString(Language, StringType.Latin1));
            v.Add(ByteVector.FromString(description, encoding));
            v.Add(ByteVector.TextDelimiter(encoding));
            v.Add(ByteVector.FromString(text, encoding));

            return(v);
        }
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            var encoding = CorrectEncoding(TextEncoding, version);
            var v        = new ByteVector {
                (byte)encoding,
                ByteVector.FromString(Language, StringType.Latin1),
                ByteVector.FromString(description, encoding),
                ByteVector.TextDelimiter(encoding),
                ByteVector.FromString(text, encoding)
            };

            return(v);
        }
예제 #6
0
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }
            int pos = 0;
            int offset;

            text_encoding = (StringType)raw_data[pos++];
            if (raw_version > 2)
            {
                offset = raw_data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);
                if (offset < pos)
                {
                    return;
                }
                mime_type = raw_data.ToString(StringType.Latin1, pos, offset - pos);
                pos       = offset + 1;
            }
            else
            {
                ByteVector ext = raw_data.Mid(pos, 3);
                if (ext == "JPG")
                {
                    mime_type = "image/jpeg";
                }
                else if (ext == "PNG")
                {
                    mime_type = "image/png";
                }
                else
                {
                    mime_type = "image/unknown";
                }
                pos += 3;
            }
            ByteVector delim = ByteVector.TextDelimiter(text_encoding);

            type   = (PictureType)raw_data[pos++];
            offset = raw_data.Find(delim, pos, delim.Count);
            if (offset < pos)
            {
                return;
            }
            description = raw_data.ToString(text_encoding, pos, offset - pos);
            pos         = offset + delim.Count;
            raw_data.RemoveRange(0, pos);
            this.data     = raw_data;
            this.raw_data = null;
        }
        protected override ByteVector RenderFields(byte version)
        {
            if (version < 4)
            {
                throw new NotImplementedException();
            }

            ByteVector data = new ByteVector();

            data.Add(ByteVector.FromString(identification,
                                           StringType.Latin1));
            data.Add(ByteVector.TextDelimiter(StringType.Latin1));

            for (byte i = 0; i < 9; i++)
            {
                if (!channels [i].IsSet)
                {
                    continue;
                }

                data.Add(i);
                unchecked {
                    data.Add(ByteVector.FromUShort(
                                 (ushort)channels [i]
                                 .VolumeAdjustmentIndex));
                }

                byte bits = 0;

                for (byte j = 0; j < 64; j++)
                {
                    if ((channels [i].PeakVolumeIndex &
                         (1UL << j)) != 0)
                    {
                        bits = (byte)(j + 1);
                    }
                }

                data.Add(bits);

                if (bits > 0)
                {
                    data.Add(ByteVector.FromULong(
                                 channels [i].PeakVolumeIndex)
                             .Mid(8 - BitsToBytes(bits)));
                }
            }

            return(data);
        }
예제 #8
0
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        protected override void ParseFields(ByteVector data, byte version)
        {
            if (data.Count < 1)
            {
                throw new CorruptFileException("A private frame must contain at least 1 byte.");
            }

            var l = ByteVectorCollection.Split(data, ByteVector.TextDelimiter(StringType.Latin1), 1, 2);

            if (l.Count == 2)
            {
                Owner       = l[0].ToString(StringType.Latin1);
                PrivateData = l[1];
            }
        }
예제 #9
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        /// <exception cref="NotImplementedException">
        ///    <paramref name="version" /> is less than 3. ID3v2.2 does
        ///    not support this frame.
        /// </exception>
        protected override ByteVector RenderFields(byte version)
        {
            if (version < 3)
            {
                throw new NotImplementedException();
            }

            ByteVector v = new ByteVector();

            v.Add(ByteVector.FromString(owner, StringType.Latin1));
            v.Add(ByteVector.TextDelimiter(StringType.Latin1));
            v.Add(data);

            return(v);
        }
예제 #10
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        /// <exception cref="NotImplementedException">
        ///    <paramref name="version" /> is less than 3. ID3v2.2 does
        ///    not support this frame.
        /// </exception>
        protected override ByteVector RenderFields(byte version)
        {
            if (version < 3)
            {
                throw new NotImplementedException();
            }

            var v = new ByteVector {
                ByteVector.FromString(Owner, StringType.Latin1),
                ByteVector.TextDelimiter(StringType.Latin1),
                PrivateData
            };

            return(v);
        }
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        protected override void ParseFields(ByteVector data, byte version)
        {
            if (data.Count < 6)
            {
                throw new CorruptFileException("Not enough bytes in field.");
            }

            TextEncoding = (StringType)data[0];
            language     = data.ToString(StringType.Latin1, 1, 3);
            Format       = (TimestampFormat)data[4];
            Type         = (SynchedTextType)data[5];

            var delim       = ByteVector.TextDelimiter(TextEncoding);
            int delim_index = data.Find(delim, 6, delim.Count);

            if (delim_index < 0)
            {
                throw new CorruptFileException("Text delimiter expected.");
            }

            Description = data.ToString(TextEncoding, 6, delim_index - 6);

            int offset = delim_index + delim.Count;
            var l      = new List <SynchedText> ();

            while (offset + delim.Count + 4 < data.Count)
            {
                delim_index = data.Find(delim, offset, delim.Count);

                if (delim_index < offset)
                {
                    throw new CorruptFileException("Text delimiter expected.");
                }

                string text = data.ToString(TextEncoding, offset, delim_index - offset);
                offset = delim_index + delim.Count;

                if (offset + 4 > data.Count)
                {
                    break;
                }

                l.Add(new SynchedText(data.Mid(offset, 4).ToUInt(), text));
                offset += 4;
            }

            this.text = l.ToArray();
        }
예제 #12
0
        protected override void ParseFields(ByteVector data, byte version)
        {
            ByteVector delim = ByteVector.TextDelimiter(StringType.Latin1);
            int        index = data.Find(delim);

            if (index < 0)
            {
                throw new CorruptFileException("Popularimeter frame does not contain a text delimiter");
            }
            if (index + 2 > data.Count)
            {
                throw new CorruptFileException("Popularimeter is too short");
            }
            user       = data.ToString(StringType.Latin1, 0, index);
            rating     = data[index + 1];
            play_count = data.Mid(index + 2).ToULong();
        }
예제 #13
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            if (raw_data != null && raw_version == version)
            {
                return(raw_data);
            }

            StringType encoding = CorrectEncoding(TextEncoding,
                                                  version);
            ByteVector data = new ByteVector();

            data.Add((byte)encoding);

            if (version == 2)
            {
                switch (MimeType)
                {
                case "image/png":
                    data.Add("PNG");
                    break;

                case "image/jpeg":
                    data.Add("JPG");
                    break;

                default:
                    data.Add("XXX");
                    break;
                }
            }
            else
            {
                data.Add(ByteVector.FromString(MimeType,
                                               StringType.Latin1));
                data.Add(ByteVector.TextDelimiter(
                             StringType.Latin1));
            }

            data.Add((byte)type);
            data.Add(ByteVector.FromString(Description, encoding));
            data.Add(ByteVector.TextDelimiter(encoding));
            data.Add(this.data);

            return(data);
        }
예제 #14
0
        protected override ByteVector RenderFields(byte version)
        {
            StringType encoding = CorrectEncoding(TextEncoding, version);
            ByteVector delim    = ByteVector.TextDelimiter(encoding);
            ByteVector v        = new ByteVector();

            v.Add((byte)encoding);
            v.Add(ByteVector.FromString(Language, StringType.Latin1));
            v.Add((byte)timestamp_format);
            v.Add((byte)lyrics_type);
            v.Add(ByteVector.FromString(description, encoding));
            v.Add(delim);
            foreach (SynchedText t in text)
            {
                v.Add(ByteVector.FromString(t.Text, encoding));
                v.Add(delim);
                v.Add(ByteVector.FromUInt((uint)t.Time));
            }
            return(v);
        }
예제 #15
0
        /// <summary>
        ///    Populates the values in the current instance by parsing
        ///    its field data in a specified version.
        /// </summary>
        /// <param name="data">
        ///    A <see cref="ByteVector" /> object containing the
        ///    extracted field data.
        /// </param>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is encoded in.
        /// </param>
        /// <exception cref="CorruptFileException">
        ///    <paramref name="data" /> contains less than 5 bytes.
        /// </exception>
        protected override void ParseFields(ByteVector data,
                                            byte version)
        {
            int pos = data.Find(ByteVector.TextDelimiter(
                                    StringType.Latin1));

            if (pos < 0)
            {
                return;
            }

            identification = data.ToString(StringType.Latin1, 0,
                                           pos++);

            // Each channel is at least 4 bytes.

            while (pos <= data.Count - 4)
            {
                int type = data[pos++];

                unchecked
                {
                    channels[type].VolumeAdjustmentIndex =
                        (short)data.Mid(pos,
                                        2).ToUShort();
                }
                pos += 2;

                int bytes = BitsToBytes(data[pos++]);

                if (data.Count < pos + bytes)
                {
                    break;
                }

                channels[type].PeakVolumeIndex = data.Mid(pos,
                                                          bytes).ToULong();
                pos += bytes;
            }
        }
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            var encoding = CorrectEncoding(TextEncoding, version);
            var delim    = ByteVector.TextDelimiter(encoding);
            var v        = new ByteVector {
                (byte)encoding,
                ByteVector.FromString(Language, StringType.Latin1),
                (byte)Format,
                (byte)Type,
                ByteVector.FromString(Description, encoding),
                delim
            };

            foreach (SynchedText t in text)
            {
                v.Add(ByteVector.FromString(t.Text, encoding));
                v.Add(delim);
                v.Add(ByteVector.FromUInt((uint)t.Time));
            }

            return(v);
        }
예제 #17
0
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }
            ByteVector data = raw_data;

            raw_data = null;
            List <string> field_list = new List <string>();
            ByteVector    delim      = ByteVector.TextDelimiter(encoding);

            if (FrameId != FrameType.WXXX)
            {
                field_list.AddRange(data.ToStrings(StringType.Latin1, 0));
            }
            else if (data.Count > 1 && !data.Mid(0, delim.Count).Equals(delim))
            {
                string value = data.ToString(StringType.Latin1, 1, data.Count - 1);
                if (value.Length > 1 && value[value.Length - 1] == 0)
                {
                    for (int i = value.Length - 1; i >= 0; i--)
                    {
                        if (value[i] != 0)
                        {
                            value = value.Substring(0, i + 1);
                            break;
                        }
                    }
                }
                field_list.Add(value);
            }
            while (field_list.Count != 0 && string.IsNullOrEmpty(field_list[field_list.Count - 1]))
            {
                field_list.RemoveAt(field_list.Count - 1);
            }
            text_fields = field_list.ToArray();
        }
예제 #18
0
        protected override void ParseFields(ByteVector data, byte version)
        {
            if (data.Count < 4)
            {
                throw new CorruptFileException("An object frame must contain at least 4 bytes.");
            }
            int start = 0;

            encoding = (StringType)data[start++];
            int end = data.Find(ByteVector.TextDelimiter(StringType.Latin1), start);

            if (end < start)
            {
                return;
            }
            mime_type = data.ToString(StringType.Latin1, start, end - start);
            ByteVector delim = ByteVector.TextDelimiter(encoding);

            start = end + 1;
            end   = data.Find(delim, start, delim.Count);
            if (end < start)
            {
                return;
            }
            file_name = data.ToString(encoding, start, end - start);
            start     = end + delim.Count;
            end       = data.Find(delim, start, delim.Count);
            if (end < start)
            {
                return;
            }
            description = data.ToString(encoding, start, end - start);
            start       = end + delim.Count;
            data.RemoveRange(0, start);
            this.data = data;
        }
예제 #19
0
        protected override ByteVector RenderFields(byte version)
        {
            StringType encoding = CorrectEncoding(this.encoding, version);
            ByteVector v        = new ByteVector();

            v.Add((byte)encoding);
            if (MimeType != null)
            {
                v.Add(ByteVector.FromString(MimeType, StringType.Latin1));
            }
            v.Add(ByteVector.TextDelimiter(StringType.Latin1));
            if (FileName != null)
            {
                v.Add(ByteVector.FromString(FileName, encoding));
            }
            v.Add(ByteVector.TextDelimiter(encoding));
            if (Description != null)
            {
                v.Add(ByteVector.FromString(Description, encoding));
            }
            v.Add(ByteVector.TextDelimiter(encoding));
            v.Add(data);
            return(v);
        }
예제 #20
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            if (file != null)
            {
                Load();
            }

            if (raw_data != null && raw_version == version)
            {
                return(raw_data);
            }

            StringType encoding = CorrectEncoding(TextEncoding, version);
            ByteVector data     = new ByteVector();

            if (header.FrameId == FrameType.APIC)
            {
                // Make an ID3v2 Attached Picture (APIC)

                data.Add((byte)encoding);

                if (version == 2)
                {
                    string ext = Picture.GetExtensionFromMime(MimeType);
                    data.Add(ext != null && ext.Length == 3 ?
                             ext.ToUpper() : "XXX");
                }
                else
                {
                    data.Add(ByteVector.FromString(MimeType, StringType.Latin1));
                    data.Add(ByteVector.TextDelimiter(StringType.Latin1));
                }

                data.Add((byte)type);
                data.Add(ByteVector.FromString(Description, encoding));
                data.Add(ByteVector.TextDelimiter(encoding));
            }
            else if (header.FrameId == FrameType.GEOB)
            {
                // Make an ID3v2 General Encapsulated Object (GEOB)

                data.Add((byte)encoding);

                if (MimeType != null)
                {
                    data.Add(ByteVector.FromString(MimeType, StringType.Latin1));
                }
                data.Add(ByteVector.TextDelimiter(StringType.Latin1));

                if (filename != null)
                {
                    data.Add(ByteVector.FromString(filename, encoding));
                }
                data.Add(ByteVector.TextDelimiter(encoding));

                if (Description != null)
                {
                    data.Add(ByteVector.FromString(Description, encoding));
                }
                data.Add(ByteVector.TextDelimiter(encoding));
            }
            else
            {
                throw new InvalidOperationException("Bad Frame type");
            }

            data.Add(this.data);
            return(data);
        }
예제 #21
0
        /// <summary>
        ///    Performs the actual parsing of the raw data.
        /// </summary>
        /// <remarks>
        ///    Because of the high parsing cost and relatively low usage
        ///    of the class, <see cref="ParseFields" /> only stores the
        ///    field data so it can be parsed on demand. Whenever a
        ///    property or method is called which requires the data,
        ///    this method is called, and only on the first call does it
        ///    actually parse the data.
        /// </remarks>
        protected void ParseRawData()
        {
            if (file != null)
            {
                Load();
            }

            if (raw_data == null)
            {
                return;
            }

            data     = raw_data;
            raw_data = null;

            int pos = 0;
            int offset;

            encoding = (StringType)data[pos++];

            ByteVector delim = ByteVector.TextDelimiter(encoding);

            if (header.FrameId == FrameType.APIC)
            {
                // Retrieve an ID3v2 Attached Picture (APIC)

                if (raw_version > 2)
                {
                    offset = data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);

                    if (offset < pos)
                    {
                        return;
                    }

                    mime_type = data.ToString(StringType.Latin1, pos, offset - pos);
                    pos       = offset + 1;
                }
                else
                {
                    ByteVector ext = data.Mid(pos, 3);
                    mime_type = Picture.GetMimeFromExtension(ext.ToString());
                    pos      += 3;
                }

                Type = (PictureType)data[pos++];

                offset = data.Find(delim, pos, delim.Count);
            }
            else if (header.FrameId == FrameType.GEOB)
            {
                // Retrieve an ID3v2 General Encapsulated Object (GEOB)

                offset = data.Find(ByteVector.TextDelimiter(StringType.Latin1), pos);

                if (offset < pos)
                {
                    return;
                }

                mime_type = data.ToString(StringType.Latin1, pos, offset - pos);

                pos    = offset + 1;
                offset = data.Find(delim, pos, delim.Count);

                if (offset < pos)
                {
                    return;
                }

                filename = data.ToString(encoding, pos, offset - pos);
                pos      = offset + delim.Count;
                offset   = data.Find(delim, pos, delim.Count);

                Type = PictureType.NotAPicture;
            }
            else
            {
                throw new InvalidOperationException("Bad Frame type");
            }

            if (offset < pos)
            {
                return;
            }

            description = data.ToString(encoding, pos, offset - pos);
            pos         = offset + delim.Count;

            data.RemoveRange(0, pos);
        }
예제 #22
0
 public static ByteVector TextDelimiter(StringType type)
 {
     return(ByteVector.TextDelimiter(type));
 }
예제 #23
0
        /// <summary>
        ///    Renders the values in the current instance into field
        ///    data for a specified version.
        /// </summary>
        /// <param name="version">
        ///    A <see cref="byte" /> indicating the ID3v2 version the
        ///    field data is to be encoded in.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector" /> object containing the
        ///    rendered field data.
        /// </returns>
        protected override ByteVector RenderFields(byte version)
        {
            if (raw_data != null && raw_version == version)
            {
                return(raw_data);
            }

            StringType encoding = CorrectEncoding(TextEncoding,
                                                  version);

            bool wxxx = FrameId == FrameType.WXXX;

            ByteVector v;

            if (wxxx)
            {
                v = new ByteVector((byte)encoding);
            }
            else
            {
                v = new ByteVector();
            }
            string[] text = text_fields;

            if (version > 3 || wxxx)
            {
                if (wxxx)
                {
                    if (text.Length == 0)
                    {
                        text = new string[] { null, null }
                    }
                    ;
                    else if (text.Length == 1)
                    {
                        text = new string[] { text [0],
                                              null }
                    }
                    ;
                }

                for (int i = 0; i < text.Length; i++)
                {
                    // Since the field list is null
                    // delimited, if this is not the first
                    // element in the list, append the
                    // appropriate delimiter for this
                    // encoding.

                    if (i != 0)
                    {
                        v.Add(ByteVector.TextDelimiter(
                                  encoding));
                    }

                    if (text[i] != null)
                    {
                        v.Add(ByteVector.FromString(
                                  text[i],
                                  encoding));
                    }
                }
            }
            else
            {
                v.Add(ByteVector.FromString(
                          string.Join("/", text), StringType.Latin1));
            }

            return(v);
        }
예제 #24
0
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }
            ByteVector data = raw_data;

            raw_data = null;
            encoding = (StringType)data[0];
            List <string> field_list = new List <string>();
            ByteVector    delim      = ByteVector.TextDelimiter(encoding);

            if (raw_version > 3 || FrameId == FrameType.TXXX)
            {
                field_list.AddRange(data.ToStrings(encoding, 1));
            }
            else if (data.Count > 1 && !data.Mid(1, delim.Count).Equals(delim))
            {
                string value      = data.ToString(encoding, 1, data.Count - 1);
                int    null_index = value.IndexOf('\x00');
                if (null_index >= 0)
                {
                    value = value.Substring(0, null_index);
                }
                if (FrameId == FrameType.TCOM || FrameId == FrameType.TEXT || FrameId == FrameType.TOLY || FrameId == FrameType.TOPE || FrameId == FrameType.TPE1 || FrameId == FrameType.TPE2 || FrameId == FrameType.TPE3 || FrameId == FrameType.TPE4)
                {
                    field_list.AddRange(value.Split('/'));
                }
                else if (FrameId == FrameType.TCON)
                {
                    while (value.Length > 1 && value[0] == '(')
                    {
                        int closing = value.IndexOf(')');
                        if (closing < 0)
                        {
                            break;
                        }
                        string number = value.Substring(1, closing - 1);
                        field_list.Add(number);
                        value = value.Substring(closing + 1).TrimStart('/', ' ');
                        string text = Genres.IndexToAudio(number);
                        if (text != null && value.StartsWith(text))
                        {
                            value = value.Substring(text.Length).TrimStart('/', ' ');
                        }
                    }
                    if (value.Length > 0)
                    {
                        field_list.AddRange(value.Split(new char[] { '/' }));
                    }
                }
                else
                {
                    field_list.Add(value);
                }
            }
            while (field_list.Count != 0 && string.IsNullOrEmpty(field_list[field_list.Count - 1]))
            {
                field_list.RemoveAt(field_list.Count - 1);
            }
            text_fields = field_list.ToArray();
        }
        protected override ByteVector RenderFields(byte version)
        {
            if (raw_data != null && raw_version == version)
            {
                return(raw_data);
            }

            StringType encoding = CorrectEncoding(TextEncoding,
                                                  version);
            ByteVector v = new ByteVector((byte)encoding);

            string [] text = text_fields;

            bool txxx = FrameId == FrameType.TXXX;

            if (version > 3 || txxx)
            {
                if (txxx)
                {
                    if (text.Length == 0)
                    {
                        text = new string [] { null, null }
                    }
                    ;
                    else if (text.Length == 1)
                    {
                        text = new string [] { text [0],
                                               null }
                    }
                    ;
                }

                for (int i = 0; i < text.Length; i++)
                {
                    // Since the field list is null
                    // delimited, if this is not the first
                    // element in the list, append the
                    // appropriate delimiter for this
                    // encoding.

                    if (i != 0)
                    {
                        v.Add(ByteVector.TextDelimiter(
                                  encoding));
                    }

                    if (text [i] != null)
                    {
                        v.Add(ByteVector.FromString(
                                  text [i],
                                  encoding));
                    }
                }
            }
            else if (FrameId == FrameType.TCON)
            {
                byte          id;
                bool          prev_value_indexed = true;
                StringBuilder data = new StringBuilder();
                foreach (string s in text)
                {
                    if (!prev_value_indexed)
                    {
                        data.Append("/").Append(s);
                        continue;
                    }

                    if (prev_value_indexed =
                            byte.TryParse(s, out id))
                    {
                        data.AppendFormat(
                            CultureInfo.InvariantCulture,
                            "({0})", id);
                    }
                    else
                    {
                        data.Append(s);
                    }
                }

                v.Add(ByteVector.FromString(data.ToString(),
                                            encoding));
            }
            else
            {
                v.Add(ByteVector.FromString(
                          string.Join("/", text), encoding));
            }

            return(v);
        }
        protected void ParseRawData()
        {
            if (raw_data == null)
            {
                return;
            }

            ByteVector data = raw_data;

            raw_data = null;

            // read the string data type (the first byte of the
            // field data)
            encoding = (StringType)data [0];
            List <string> field_list = new List <string> ();

            ByteVector delim = ByteVector.TextDelimiter(encoding);

            if (raw_version > 3 || FrameId == FrameType.TXXX)
            {
                field_list.AddRange(data.ToStrings(encoding, 1));
            }
            else if (data.Count > 1 && !data.Mid(1,
                                                 delim.Count).Equals(delim))
            {
                string value = data.ToString(encoding, 1,
                                             data.Count - 1);

                // Do a fast removal of end bytes.
                if (value.Length > 1 &&
                    value [value.Length - 1] == 0)
                {
                    for (int i = value.Length - 1; i >= 0; i--)
                    {
                        if (value [i] != 0)
                        {
                            value = value.Substring(0, i + 1);
                            break;
                        }
                    }
                }

                if (FrameId == FrameType.TCOM ||
                    FrameId == FrameType.TEXT ||
                    FrameId == FrameType.TOLY ||
                    FrameId == FrameType.TOPE ||
                    FrameId == FrameType.TPE1 ||
                    FrameId == FrameType.TPE2 ||
                    FrameId == FrameType.TPE3 ||
                    FrameId == FrameType.TPE4)
                {
                    field_list.AddRange(value.Split('/'));
                }
                else if (FrameId == FrameType.TCON)
                {
                    while (value.Length > 1 && value [0] == '(')
                    {
                        int closing = value.IndexOf(')');
                        if (closing < 0)
                        {
                            break;
                        }

                        field_list.Add(
                            value.Substring(1,
                                            closing - 1));

                        value = value.Substring(
                            closing + 1);
                    }

                    if (value.Length > 0)
                    {
                        field_list.AddRange(value.Split(new char [] { '/' }));
                    }
                }
                else
                {
                    field_list.Add(value);
                }
            }

            // Bad tags may have one or more nul characters at the
            // end of a string, resulting in empty strings at the
            // end of the FieldList. Strip them off.
            while (field_list.Count != 0 &&
                   string.IsNullOrEmpty(field_list [
                                            field_list.Count - 1]))
            {
                field_list.RemoveAt(field_list.Count - 1);
            }

            text_fields = field_list.ToArray();
        }