예제 #1
0
        /// <summary>
        /// Writes the given metadata into the given stream using the ID3v1.1 standard
        /// NB : Metadata fields that are not supported by ID3v1.1 standard (e.g. Composer) won't be written into the stream, even though their value are set
        /// </summary>
        /// <param name="tag">Metadata to be written</param>
        /// <param name="w">Stream to be used</param>
        /// <returns>True if operation completed successfuly; else false</returns>
        protected override Int32 write(TagData tag, BinaryWriter w, String zone)
        {
            // ID3v1 tags are C-String(null-terminated)-based tags
            // they are not unicode-encoded, hence the use of ReadOneByteChars
            w.Write(ID3V1_ID.ToCharArray());

            w.Write(Utils.BuildStrictLengthString(tag.Title, 30, '\0').ToCharArray());
            w.Write(Utils.BuildStrictLengthString(tag.Artist, 30, '\0').ToCharArray());
            w.Write(Utils.BuildStrictLengthString(tag.Album, 30, '\0').ToCharArray());
            // ID3v1 standard requires the year
            w.Write(Utils.BuildStrictLengthString(TrackUtils.ExtractStrYear(tag.RecordingYear), 4, '\0').ToCharArray());
            w.Write(Utils.BuildStrictLengthString(tag.Comment, 28, '\0').ToCharArray());

            // ID3v1.1 standard
            w.Write('\0');
            w.Write((Byte)Math.Min(TrackUtils.ExtractTrackNumber(tag.TrackNumber), Byte.MaxValue));

            Byte genre = 0;

            if (tag.Genre != null)
            {
                for (Byte i = 0; i < MAX_MUSIC_GENRES; i++)
                {
                    if (tag.Genre.ToUpper().Equals(MusicGenre[i].ToUpper()))
                    {
                        genre = i;
                        break;
                    }
                }
            }
            w.Write(genre);

            return(7);
        }
예제 #2
0
        private void writeSubChunk(BinaryWriter writer, byte frameCode, string text)
        {
            writer.Write(frameCode);

            byte type = 1;

            if (extendedFrameTypes.ContainsKey(frameCode))
            {
                type = extendedFrameTypes[frameCode];
            }
            writer.Write(type);

            switch (type)
            {
            case XID6_TVAL:
                if (frameCode == XID6_TRACK)     // Specific case : upper byte is the number 0-99, lower byte is an optional ASCII character
                {
                    byte trackValue = (byte)Math.Min((ushort)0xFF, TrackUtils.ExtractTrackNumber(text));
                    writer.Write('\0');     // Optional char support is not implemented
                    writer.Write(trackValue);
                }
                else
                {
                    writer.Write(ushort.Parse(text));     // Value is directly written as an ushort into the length field
                }
                break;

            case XID6_TSTR:
                if (text.Length > 255)
                {
                    text = text.Substring(0, 255);
                }
                else if (text.Length < 3)
                {
                    text = Utils.BuildStrictLengthString(text, 3, ' ');
                }

                byte[] textBinary = Utils.Latin1Encoding.GetBytes(text);
                writer.Write((ushort)(textBinary.Length + 1));
                writer.Write(textBinary);
                writer.Write('\0');
                break;

            case XID6_TINT:
                writer.Write((ushort)4);
                writer.Write(Int32.Parse(text));
                break;
            }
        }
예제 #3
0
        public void TrackUtils_ExtractTrackNumber()
        {
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber("15"));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber(" 15"));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber(" 15 "));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber("15 "));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber("15.1"));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber("15,1"));
            Assert.AreEqual(15, TrackUtils.ExtractTrackNumber("a15a"));

            Assert.AreEqual(0, TrackUtils.ExtractTrackNumber(""));
            Assert.AreEqual(0, TrackUtils.ExtractTrackNumber(null));
            Assert.AreEqual(0, TrackUtils.ExtractTrackNumber("aaa"));
            Assert.AreEqual(0, TrackUtils.ExtractTrackNumber("99999999"));
        }
예제 #4
0
        private void readHeaderTags(BinaryReader source, ref SPCHeader header, ReadTagParams readTagParams)
        {
            long initialPosition = source.BaseStream.Position;

            SetMetaField(HEADER_TITLE.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_ALBUM.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_DUMPERNAME.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(16)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_COMMENT.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);

            byte[] date, song, fade;

            // NB : Dump date is used to determine if the tag is binary or text-based.
            // It won't be recorded as a property of TSPC
            date = source.ReadBytes(11);
            song = source.ReadBytes(3);
            fade = source.ReadBytes(5);

            bool bin;
            int  dateRes = isText(date);
            int  songRes = isText(song);
            int  fadeRes = isText(fade);

            //if ( 0 == (dateRes | songRes | fadeRes) ) // No time nor date -> use default
            //{
            bin = true;
            //}
            //else
            if ((songRes != -1) && (fadeRes != -1)) // No time, or time is text
            {
                if (dateRes > 0)                    //If date is text, then tag is text
                {
                    bin = false;
                }
                else if (0 == dateRes)              //No date
                {
                    bin = PREFER_BIN;               //Times could still be binary (ex. 56 bin = '8' txt)
                }
                else if (-1 == dateRes)             //Date contains invalid characters
                {
                    bin = true;
                    for (int i = 4; i < 8; i++)
                    {
                        bin = bin && (0 == date[i]);
                    }
                }
            }
            else
            {
                bin = true;
            }

            int fadeVal;
            int songVal;

            if (bin)
            {
                fadeVal =
                    fade[0] * 0x000001 +
                    fade[1] * 0x0000FF +
                    fade[2] * 0x00FF00 +
                    fade[3] * 0xFF0000;
                if (fadeVal > 59999)
                {
                    fadeVal = 59999;
                }

                songVal = song[0] * 0x01 + song[1] * 0x10;
                if (songVal > 959)
                {
                    songVal = 959;
                }

                source.BaseStream.Seek(-1, SeekOrigin.Current); // We're one byte ahead
                SetMetaField(HEADER_FADE.ToString(), Utils.Latin1Encoding.GetString(fade), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            }
            else
            {
                fadeVal = TrackUtils.ExtractTrackNumber(Utils.Latin1Encoding.GetString(fade));
                songVal = TrackUtils.ExtractTrackNumber(Utils.Latin1Encoding.GetString(song));

                SetMetaField(HEADER_FADE.ToString(), Utils.Latin1Encoding.GetString(fade), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            }

            SetMetaField(HEADER_DUMPDATE.ToString(), Utils.Latin1Encoding.GetString(date), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            SetMetaField(HEADER_SONGLENGTH.ToString(), Utils.Latin1Encoding.GetString(song), readTagParams.ReadAllMetaFrames, ZONE_HEADER);

            // if fadeval > 0 alone, the fade is applied on the default 3:00 duration without extending it
            if (songVal > 0)
            {
                duration = Math.Round((double)fadeVal) + songVal;
            }

            SetMetaField(HEADER_ARTIST.ToString(), Utils.Latin1Encoding.GetString(source.ReadBytes(32)).Replace("\0", "").Trim(), readTagParams.ReadAllMetaFrames, ZONE_HEADER);
            header.Size += source.BaseStream.Position - initialPosition;

            if (readTagParams.PrepareForWriting)
            {
                structureHelper.AddZone(initialPosition, (int)(source.BaseStream.Position - initialPosition), ZONE_HEADER);
            }
        }
예제 #5
0
        protected void readExistingTagsOnFile(AudioDataManager theFile, int nbPictures = 2)
        {
            Assert.IsTrue(theFile.ReadFromFile(true, true));

            Assert.IsNotNull(theFile.getMeta(tagType));
            IMetaDataIO meta = theFile.getMeta(tagType);

            Assert.IsTrue(meta.Exists);

            // Supported fields
            if (testData.Title != null)
            {
                Assert.AreEqual(testData.Title, meta.Title);
            }
            if (testData.Album != null)
            {
                Assert.AreEqual(testData.Album, meta.Album);
            }
            if (testData.Artist != null)
            {
                Assert.AreEqual(testData.Artist, meta.Artist);
            }
            if (testData.AlbumArtist != null)
            {
                Assert.AreEqual(testData.AlbumArtist, meta.AlbumArtist);
            }
            if (testData.Comment != null)
            {
                Assert.AreEqual(testData.Comment, meta.Comment);
            }
            if (testData.RecordingYear != null)
            {
                Assert.AreEqual(testData.RecordingYear, meta.Year);
            }
            //if (testData.RecordingDate != null) Assert.AreEqual(testData.RecordingDate, meta.);
            if (testData.Genre != null)
            {
                Assert.AreEqual(testData.Genre, meta.Genre);
            }
            if (testData.Rating != null)
            {
                if (Utils.IsNumeric(testData.Rating))
                {
                    float f = float.Parse(testData.Rating);
                    Assert.AreEqual((f / 5.0).ToString(), meta.Popularity.ToString());
                }
                else if (0 == testData.Rating.Length)
                {
                    Assert.AreEqual("0", meta.Popularity.ToString());
                }
                else
                {
                    Assert.AreEqual(testData.Rating, meta.Popularity.ToString());
                }
            }
            if (testData.TrackNumber != null)
            {
                Assert.AreEqual(TrackUtils.ExtractTrackNumber(testData.TrackNumber).ToString(), meta.Track.ToString());
            }
            if (testData.Composer != null)
            {
                Assert.AreEqual(testData.Composer, meta.Composer);
            }
            if (testData.DiscNumber != null)
            {
                Assert.AreEqual(TrackUtils.ExtractTrackNumber(testData.DiscNumber).ToString(), meta.Disc.ToString());
            }
            if (testData.Conductor != null)
            {
                Assert.AreEqual(testData.Conductor, meta.Conductor);
            }
            if (testData.Publisher != null)
            {
                Assert.AreEqual(testData.Publisher, meta.Publisher);
            }
            if (testData.Copyright != null)
            {
                Assert.AreEqual(testData.Copyright, meta.Copyright);
            }
            if (testData.GeneralDescription != null)
            {
                Assert.AreEqual(testData.GeneralDescription, meta.GeneralDescription);
            }

            // Unsupported field
            if (testData.AdditionalFields != null && testData.AdditionalFields.Count > 0)
            {
                foreach (MetaFieldInfo field in testData.AdditionalFields)
                {
                    Assert.IsTrue(meta.AdditionalFields.Keys.Contains(field.NativeFieldCode));
                    Assert.AreEqual(field.Value, meta.AdditionalFields[field.NativeFieldCode]);
                }
            }

            // Pictures
            if (testData.Pictures != null && testData.Pictures.Count > 0)
            {
                Assert.AreEqual(nbPictures, meta.EmbeddedPictures.Count);

                byte nbFound = 0;
                foreach (PictureInfo pic in meta.EmbeddedPictures)
                {
                    foreach (PictureInfo testPicInfo in testData.Pictures)
                    {
                        if (pic.NativePicCode.Equals(testPicInfo.NativePicCode) ||
                            (pic.NativePicCodeStr != null && pic.NativePicCodeStr.Equals(testPicInfo.NativePicCodeStr))
                            )
                        {
                            nbFound++;
                            pic.ComputePicHash();
                            Assert.AreEqual(testPicInfo.PictureHash, pic.PictureHash);
                        }
                    }
                }
                Assert.AreEqual(testData.Pictures.Count, nbFound);
            }
        }