Exemple #1
0
        /// <summary>Creates the specified header.</summary>
        /// <param name="header">The header.</param>
        /// <param name="flags">The flags.</param>
        /// <param name="description">The description.</param>
        /// <param name="type">The type.</param>
        /// <param name="mimeType">Type of the MIME.</param>
        /// <param name="imageData">The image data.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public static ID3v2APICFrame Create(ID3v2Header header, ID3v2FrameFlags flags, string description, ID3v2PictureType type, string mimeType, byte[] imageData)
        {
            ID3v2EncodingType encoding = ID3v2Encoding.Select(header, description + mimeType);

            // header, encoding[1], mimeType+0, pitureType[1], description+0, data
            byte[] descriptionBytes = ID3v2Encoding.GetBytes(encoding, description, true);
            byte[] mimeTypeBytes    = ID3v2Encoding.GetBytes(encoding, mimeType, true);
            int    contentSize      = descriptionBytes.Length + mimeTypeBytes.Length + 1 + 1 + imageData.Length;
            var    frameHeader      = ID3v2FrameHeader.Create(header, "APIC", flags, contentSize);

            using (var ms = new MemoryStream())
            {
                var writer = new DataWriter(ms);
                writer.Write(frameHeader.Data);
                writer.Write((byte)encoding);
                writer.Write(mimeTypeBytes);
                writer.Write((byte)type);
                writer.Write(descriptionBytes);
                writer.Write(imageData);
                if (frameHeader.HeaderSize + contentSize != ms.Position)
                {
                    throw new Exception();
                }

                return(new ID3v2APICFrame(new ID3v2Frame(header, ms.ToArray())));
            }
        }
        /// <summary>
        /// Creates a <see cref="ID3v2FrameFlags"/> instance from the specified <see cref="ID3v2d3FrameFlags"/>.
        /// </summary>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static ID3v2FrameFlags FromID3v2d3(ID3v2d3FrameFlags flags)
        {
            var result = new ID3v2FrameFlags();

            result.Compression           = (flags & ID3v2d3FrameFlags.Compression) != 0;
            result.Encryption            = (flags & ID3v2d3FrameFlags.Encryption) != 0;
            result.FileAlterPreservation = (flags & ID3v2d3FrameFlags.FileAlterPreservation) != 0;
            result.GroupingIdentity      = (flags & ID3v2d3FrameFlags.GroupingIdentity) != 0;
            result.ReadOnly             = (flags & ID3v2d3FrameFlags.ReadOnly) != 0;
            result.TagAlterPreservation = (flags & ID3v2d3FrameFlags.TagAlterPreservation) != 0;
            return(result);
        }
        /// <summary>
        /// Creates a <see cref="ID3v2FrameFlags"/> instance from the specified <see cref="ID3v2d4FrameFlags"/>.
        /// </summary>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static ID3v2FrameFlags FromID3v2d4(ID3v2d4FrameFlags flags)
        {
            var result = new ID3v2FrameFlags();

            result.Compression           = (flags & ID3v2d4FrameFlags.Compression) != 0;
            result.DataLengthIndicator   = (flags & ID3v2d4FrameFlags.DataLengthIndicator) != 0;
            result.Encryption            = (flags & ID3v2d4FrameFlags.Encryption) != 0;
            result.FileAlterPreservation = (flags & ID3v2d4FrameFlags.FileAlterPreservation) != 0;
            result.GroupingIdentity      = (flags & ID3v2d4FrameFlags.GroupingIdentity) != 0;
            result.ReadOnly             = (flags & ID3v2d4FrameFlags.ReadOnly) != 0;
            result.TagAlterPreservation = (flags & ID3v2d4FrameFlags.TagAlterPreservation) != 0;
            result.Unsynchronisation    = (flags & ID3v2d4FrameFlags.Unsynchronisation) != 0;
            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Creates a new header.
        /// </summary>
        /// <param name="header">The tag header.</param>
        /// <param name="flags">The flags.</param>
        /// <param name="description">The description.</param>
        /// <param name="type">The type.</param>
        /// <param name="image">The image.</param>
        /// <param name="imageFormat">The image format.</param>
        /// <param name="quality">The quality.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static ID3v2APICFrame Create(ID3v2Header header, ID3v2FrameFlags flags, string description, ID3v2PictureType type,
                                            SkiaSharp.SKImage image, SkiaSharp.SKEncodedImageFormat imageFormat = SkiaSharp.SKEncodedImageFormat.Jpeg, int quality = 99)
        {
            var    data = image.Encode(imageFormat, quality);
            string mimeType;

            switch (imageFormat)
            {
            case SkiaSharp.SKEncodedImageFormat.Jpeg: mimeType = MimeTypes.FromExtension(".jpg"); break;

            case SkiaSharp.SKEncodedImageFormat.Png: mimeType = MimeTypes.FromExtension(".png"); break;

            default: throw new ArgumentOutOfRangeException(string.Format("ImageFormat {0} not suppoerted!", imageFormat));
            }
            return(Create(header, flags, description, type, mimeType, data.ToArray()));
        }
Exemple #5
0
        /// <summary>Creates a new ID3v2TextFrame.</summary>
        /// <param name="header">The header.</param>
        /// <param name="flags">The flags.</param>
        /// <param name="id">The identifier.</param>
        /// <param name="text">The text.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public static ID3v2TextFrame Create(ID3v2Header header, ID3v2FrameFlags flags, string id, string text)
        {
            var encoding = ID3v2Encoding.Select(header, text);

            // header, encoding[1], name+0
            var textBytes   = ID3v2Encoding.GetBytes(encoding, text, true);
            var contentSize = 1 + textBytes.Length;
            var frameHeader = ID3v2FrameHeader.Create(header, id, flags, contentSize);

            using var ms = new MemoryStream();
            var writer = new DataWriter(ms);

            writer.Write(frameHeader.Data);
            writer.Write((byte)encoding);
            writer.Write(textBytes);
            return(new ID3v2TextFrame(new ID3v2Frame(header, ms.ToArray())));
        }
        /// <summary>Creates a new header.</summary>
        /// <param name="header">The tag header.</param>
        /// <param name="flags">The flags.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">Unsupported Header Version.</exception>
        public static ID3v2XSLTFrame Create(ID3v2Header header, ID3v2FrameFlags flags, byte[] data)
        {
            switch (header.Version)
            {
            case 3:
            case 4: break;

            default: throw new NotSupportedException("Unsupported Header Version");
            }
            var frameHeader = ID3v2FrameHeader.Create(header, "XSLT", flags, data.Length);

            using var ms = new MemoryStream();
            var writer = new DataWriter(ms);

            writer.Write(frameHeader.Data);
            writer.Write(data);
            return(new ID3v2XSLTFrame(new ID3v2Frame(header, ms.ToArray())));
        }
        /// <summary>Creates a new header.</summary>
        /// <param name="header">The tag header.</param>
        /// <param name="flags">The flags.</param>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public static ID3v2TXXXFrame Create(ID3v2Header header, ID3v2FrameFlags flags, string name, string value)
        {
            var encoding = ID3v2Encoding.Select(header, name + value);

            // header, encoding[1], name+0, value+0
            var nameBytes   = ID3v2Encoding.GetBytes(encoding, name, true);
            var valueBytes  = ID3v2Encoding.GetBytes(encoding, value, true);
            var contentSize = nameBytes.Length + valueBytes.Length + 1;
            var frameHeader = ID3v2FrameHeader.Create(header, "TXXX", flags, contentSize);

            using var ms = new MemoryStream();
            var writer = new DataWriter(ms);

            writer.Write(frameHeader.Data);
            writer.Write((byte)encoding);
            writer.Write(nameBytes);
            writer.Write(valueBytes);
            return(new ID3v2TXXXFrame(new ID3v2Frame(header, ms.ToArray())));
        }
Exemple #8
0
        private static Dictionary <ID3Tag, object> ParseID3v2(byte[] data)
        {
            // TODO: add support for ID3v2.2.0 shorter frame IDs

            Dictionary <ID3Tag, object> tags = new Dictionary <ID3Tag, object>();

            if (data.Length < 21) // there must be at least one header (10 bytes) containing one frame (at least 10 byte header + 1 byte)
            {
                return(tags);
            }

            using (MemoryStream stream = new MemoryStream(data))
            {
                byte[] header = new byte[10];
                if (stream.Read(header, 0, header.Length) != header.Length)
                {
                    throw new MetaParseException("Unable to read full ID3v2 tag header");
                }
                if (header[0] != 'I' || header[1] != 'D' || header[2] != '3')
                {
                    return(tags);
                }

                byte   versionMajor = header[3];
                byte   versionMinor = header[4];
                string version      = $"ID3v2.{versionMajor}.{versionMinor}";
                if (versionMajor != 3 && versionMajor != 4)
                {
                    throw new NotImplementedException($"Only ID3v2.3.0 and ID3v2.4.0 are supported. Detected version: {version}");
                }
                tags[ID3Tag.Version] = version;

                ID3v2HeaderFlags flags = (ID3v2HeaderFlags)header[5];
                int size = BitConverter.ToInt32(header.Skip(6).Take(4).Reverse().ToArray(), 0);

                if (flags.HasFlag(ID3v2HeaderFlags.ExtendedHeader))
                {
                    byte[] extendedHeader = new byte[10];
                    if (stream.Read(extendedHeader, 0, extendedHeader.Length) != extendedHeader.Length)
                    {
                        throw new MetaParseException("Unable to read full ID3v2 extended header");
                    }

                    int extendedSize = BitConverter.ToInt32(extendedHeader.Take(4).Reverse().ToArray(), 0);
                    ID3v2ExtendedFlags extendedFlags = (ID3v2ExtendedFlags)((extendedHeader[4] << 8) | extendedHeader[5]);
                    int sizeOfPadding = BitConverter.ToInt32(extendedHeader.Skip(6).Take(4).Reverse().ToArray(), 0);

                    Trace.WriteLine($"[{tags[ID3Tag.Version]}] Ignoring extended header");
                    stream.Position += extendedSize;
                }

                while (stream.Position < size - 10)
                {
                    byte[] frameHeader = new byte[10];
                    if (stream.Read(frameHeader, 0, frameHeader.Length) != frameHeader.Length)
                    {
                        throw new MetaParseException("Unable to read full ID3v2 frame header");
                    }
                    string frameID = Encoding.ASCII.GetString(frameHeader, 0, 4);
                    if (frameID == "\0\0\0\0")
                    {
                        break; // TODO: done?
                    }
                    int             frameSize  = BitConverter.ToInt32(frameHeader.Skip(4).Take(4).Reverse().ToArray(), 0);
                    ID3v2FrameFlags frameFlags = (ID3v2FrameFlags)((frameHeader[8] << 8) | frameHeader[9]);

                    switch (frameID)
                    {
                    case "TALB":
                        tags[ID3Tag.Album] = ParseTextualFrame(stream, frameSize);
                        break;

                    case "TIT2":
                        tags[ID3Tag.Title] = ParseTextualFrame(stream, frameSize);
                        break;

                    case "TPE2":
                        tags[ID3Tag.Artist] = ParseTextualFrame(stream, frameSize);
                        break;

                    case "TYER":
                        tags[ID3Tag.Year] = Int32.Parse(ParseTextualFrame(stream, frameSize));
                        break;

                    case "TRCK":
                        string track = ParseTextualFrame(stream, frameSize);
                        if (track.Contains('/'))
                        {
                            tags[ID3Tag.Track] = Int32.Parse(track.Split('/')[0]);     // "<current>/<total>"
                        }
                        else
                        {
                            tags[ID3Tag.Track] = Int32.Parse(track);
                        }
                        break;

                    default:
                        Trace.WriteLine($"[{tags[ID3Tag.Version]}] Ignoring frame ID: \"{frameID}\"");
                        stream.Position += frameSize;
                        break;
                    }
                }
            }

            return(tags);
        }