Example #1
0
        public static MusicFileTag ConvertTagToMusicFileTag(TagLib.Id3v1.Tag tagV1, TagLib.Id3v2.Tag tagV2, string filePath)
        {
            var tmp = new MusicFileTag
            {
                // File Details
                FilePath = filePath,
                FileName = Path.GetFileName(filePath),
                FileSize = Logic.BasicFunctions.FormatFileSize(new FileInfo(filePath).Length),
            };

            // TagTypes
            TagTypes myTagTypes = TagLib.File.Create(filePath).TagTypesOnDisk;

            tmp.EnabledV1 = myTagTypes.ToString().ToLower().Contains("id3v1") ? true : false;
            tmp.EnabledV2 = myTagTypes.ToString().ToLower().Contains("id3v2") ? true : false;

            // V1
            if (tmp.EnabledV1)
            {
                tmp.ArtistV1  = tagV1.FirstPerformer == null ? "" : tagV1.FirstPerformer.Replace("�", string.Empty);
                tmp.AlbumV1   = tagV1.Album == null ? "" : tagV1.Album.Replace("�", string.Empty);
                tmp.GenreV1   = tagV1.FirstGenre == null ? "" : tagV1.FirstGenre.Replace("�", string.Empty);
                tmp.YearV1    = tagV1.Year.ToString() == null ? "" : tagV1.Year.ToString().Replace("�", string.Empty);
                tmp.TitleV1   = tagV1.Title == null ? "" : tagV1.Title.Replace("�", string.Empty);
                tmp.CommentV1 = tagV1.Comment == null ? "" : tagV1.Comment.Replace("�", string.Empty);
                tmp.TrackV1   = tagV1.Track.ToString() == null ? "" : tagV1.Track.ToString().Replace("�", string.Empty);
            }

            // V2
            if (tmp.EnabledV2)
            {
                tmp.VersionV2 = tagV2.Version.ToString();

                // Version 3
                tmp.PlayListDelayV2      = Logic.TaggingLogic.GetTagContent(tagV2, "TDLY").Replace("�", string.Empty);
                tmp.TrackNumberV2        = Logic.TaggingLogic.GetTagContent(tagV2, "TRCK").Replace("�", string.Empty);
                tmp.PartOfSetV2          = Logic.TaggingLogic.GetTagContent(tagV2, "TPOS").Replace("�", string.Empty);
                tmp.BPMV2                = Logic.TaggingLogic.GetTagContent(tagV2, "TBPM").Replace("�", string.Empty);
                tmp.ArtistV2             = Logic.TaggingLogic.GetTagContent(tagV2, "TPE1").Replace("�", string.Empty);
                tmp.GenreV2              = Logic.TaggingLogic.GetTagContent(tagV2, "TCON").Replace("�", string.Empty);
                tmp.LanguageV2           = Logic.TaggingLogic.GetTagContent(tagV2, "TLAN").Replace("�", string.Empty);
                tmp.KeyV2                = Logic.TaggingLogic.GetTagContent(tagV2, "TKEY").Replace("�", string.Empty);
                tmp.SetSubtitleV2        = Logic.TaggingLogic.GetTagContent(tagV2, "TSST").Replace("�", string.Empty);
                tmp.ContentDescriptionV2 = Logic.TaggingLogic.GetTagContent(tagV2, "TIT1").Replace("�", string.Empty);
                tmp.InterpretedV2        = Logic.TaggingLogic.GetTagContent(tagV2, "TPE4").Replace("�", string.Empty);
                tmp.AlbumV2              = Logic.TaggingLogic.GetTagContent(tagV2, "TALB").Replace("�", string.Empty);
                tmp.TitleV2              = Logic.TaggingLogic.GetTagContent(tagV2, "TIT2").Replace("�", string.Empty);

                /// Frames from
                /// http://id3.org/id3v2.3.0#Declared_ID3v2_frames

                // + Version 4
                if (tagV2.Version == 4)
                {
                    tmp.TitleSortV2 = Logic.TaggingLogic.GetTagContent(tagV2, "TSOT").Replace("�", string.Empty);
                    tmp.AlbumSortV2 = Logic.TaggingLogic.GetTagContent(tagV2, "TSOA").Replace("�", string.Empty);
                    tmp.MoodV2      = Logic.TaggingLogic.GetTagContent(tagV2, "TMOO").Replace("�", string.Empty);
                    tmp.SubtitleV2  = Logic.TaggingLogic.GetTagContent(tagV2, "TIT3").Replace("�", string.Empty);
                }
            }
            else
            {
                tmp.VersionV2 = "4";
            }

            return(tmp);
        }
Example #2
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <param name="caller"></param>
        public virtual void Parse(Stream input, TagTypes caller)
        {
            BinaryReader br = new BinaryReader(input);

            this._width = br.ReadUInt16();

            if (caller.Equals(TagTypes.DefineShape) || caller.Equals(TagTypes.DefineShape2))
            {
                this._color = new Rgb(this._SwfVersion);

                try
                {
                    this._color.Parse(input);
                }
                catch(SwfFormatException e)
                {
                    throw e;
                }

            }
            else if (caller.Equals(TagTypes.DefineShape3))
            {
                this._color = new Rgba(this._SwfVersion);

                try
                {
                    this._color.Parse(input);
                }
                catch (SwfFormatException e)
                {
                    throw e;
                }

            }
            else
            {
                SwfFormatException e = new SwfFormatException("LineStyle was called by illegal TagType (" + caller.ToString() +").");
               Log.Error(this, e.Message);
            }
        }
Example #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <param name="caller"></param>
        public void Parse(Stream input, TagTypes caller)
        {
            BinaryReader br = new BinaryReader(input);

            this._caller = caller;
            this._fillStyleType = (FillStyleType)br.ReadByte();

            if (this._fillStyleType.Equals(FillStyleType.SolidFill))
            {
                if (caller.Equals(TagTypes.DefineShape3) )
                {
                    this._color = new Rgba(this._SwfVersion);

                    try
                    {
                        this._color.Parse(input);
                        //Log.InfoFormat("Valid fill style type. FillstyleType: 0x{0:X2} at address: 0x{1:X2} in {2}", (Int32)this._fillStyleType, ((Int32)input.Position) - 1, caller);
                    }
                    catch (SwfFormatException e)
                    {
                        throw e;
                    }

                }
                else if (caller.Equals(TagTypes.DefineShape4))
                {
                    this._color = new Rgba(this._SwfVersion);

                    try
                    {
                        this._color.Parse(input);
                    }
                    catch (SwfFormatException e)
                    {
                        throw e;
                    }
                }
                else
                {
                    this._color = new Rgb(this._SwfVersion);

                    try
                    {
                        this._color.Parse(input);
                    }
                    catch (SwfFormatException e)
                    {
                        throw e;
                    }
                }
            }
            else if (this._fillStyleType.Equals(FillStyleType.LinearGradientFill) || this._fillStyleType.Equals(FillStyleType.RadialGradientFill))
            {
                this._gradientMatrix = new Matrix(this._SwfVersion);

                try
                {
                    this._gradientMatrix.Parse(input);
                }
                catch (SwfFormatException e)
                {
                    throw e;
                }

                this._gradient = new Gradient(this._SwfVersion);

                try
                {
                    this._gradient.Parse(input, caller);
                    //Log.InfoFormat("Valid fill style type. FillstyleType: 0x{0:X2} at address: 0x{1:X4} in {2}", (Int32)this._fillStyleType, ((Int32)input.Position) - 1, caller);
                }
                catch (SwfFormatException e)
                {
                    throw e;
                }

            }
            else if (this._fillStyleType.Equals(FillStyleType.FocalRadialGradientFill))
            {
                if (this._SwfVersion >= 8)
                {
                    this._gradientMatrix = new Matrix(this._SwfVersion);

                    try
                    {
                        this._gradientMatrix.Parse(input);

                    }
                    catch(SwfFormatException e)
                    {
                        throw e;
                    }

                    this._gradient = new FocalGradient(this._SwfVersion);

                    try
                    {
                        this._gradient.Parse(input, caller);
                        //Log.InfoFormat("Valid fill style type. FillstyleType: 0x{0:X2} at address: 0x{1:X4} in {2}", (Int32)this._fillStyleType, ((Int32)input.Position) - 1, caller);
                    }
                    catch (SwfFormatException e)
                    {
                        throw e;
                    }

                }
                else
                {
                    SwfFormatException e = new SwfFormatException("Focal gradients are supported by Swf 8 and later only. This version is: " + this._SwfVersion.ToString());
                   Log.Error(this, e);
                }
            }
            else if (this._fillStyleType.Equals(FillStyleType.RepeatingBitmapFill) ||
                      this._fillStyleType.Equals(FillStyleType.ClippedBitmapFill) ||
                      this._fillStyleType.Equals(FillStyleType.NonSmoothedRepeatingBitmap) ||
                      this._fillStyleType.Equals(FillStyleType.NonSmoothedClippedBitmap))
            {
                this._bitmapID = br.ReadUInt16();
                this._bitmapMatrix = new Matrix(this._SwfVersion);

                try
                {
                    this._bitmapMatrix.Parse(input);
                    //Log.InfoFormat("Valid fill style type. FillstyleType: 0x{0:X2} at address: 0x{1:X4} in {2}", (Int32)this._fillStyleType, ((Int32)input.Position) - 1, caller);
                }
                catch (SwfFormatException e)
                {
                    throw e;
                }

            }
            else
            {
                SwfFormatException e = new SwfFormatException("Invalid fill style type! (" + this._fillStyleType +")" +" caller: " + caller.ToString());
                Log.Error(this, e);
                throw e;
            }
        }
        // --- Main Process Method ---
        private static TagWriterReturnCode WriteTagsForRow(Entry entry, int processed, DebugStack ds)
        {
            TagLib.File file;
            ds.Log("#" + processed + " - " + entry.fileName);

            // Check if the entry is mapped to a file
            if (entry.isMapped == false)
            {
                string message = "Entry is not matched to file";
                ds.LogWarning(" -> " + message);
                entryErrors.TryAdd(entry, message);
                return(TagWriterReturnCode.Unmapped);
            }

            bool isRetry = false;

Retry:

            // Create TagLib file representation, catch to see if the file is valid
            try
            {
                file = TagLib.File.Create(entry.mappedFilePath, isRetry ? ReadStyle.Average : ReadStyle.PictureLazy);
            }
            catch (Exception exception)
            {
                var    type         = exception.GetType();
                string errorMessage = "";
                TagWriterReturnCode returnCode;

                if (type == typeof(UnsupportedFormatException))
                {
                    errorMessage = "File format with extension \"" + Path.GetExtension(entry.mappedFilePath) + "\" is unsupported (" + exception.Message + ")";
                    returnCode   = TagWriterReturnCode.UnsupportedFormat;
                }
                else if (type == typeof(CorruptFileException))
                {
                    errorMessage = "File appears corrupt! " + exception.Message;
                    returnCode   = TagWriterReturnCode.CorruptFile;
                }
                else if (type == typeof(IOException))
                {
                    errorMessage = "An IO exception occured while loading the file! " + exception.Message;

                    // Get the locking processes (if any)
                    var lockingProcesses = FileLockUtility.GetProcessesLockingFile(entry.mappedFilePath);

                    // Log locking processes
                    if (lockingProcesses != null && lockingProcesses.Count > 0)
                    {
                        Debug.LogError("\tThe file appears to be locked by the process(es): " +
                                       string.Join(", ", lockingProcesses.Select(p => p.ProcessName).ToArray()));
                    }

                    returnCode = TagWriterReturnCode.IOEError;
                }
                else
                {
                    errorMessage = "An error occured while loading the file! " + exception.Message;
                    returnCode   = TagWriterReturnCode.OtherError;
                }

                ds.LogError(" -> " + errorMessage);
                entryErrors.TryAdd(entry, errorMessage);
                return(returnCode);
            }

            // Before doing anything, remove any tags that aren't on the disk.
            TagTypes tagLibCreatedTags = file.TagTypes ^ file.TagTypesOnDisk;

            file.RemoveTags(tagLibCreatedTags);

            // Then create a new tag type if needed
            TagLibUtility.CreateTagIfRequired(file, out TagTypes usedTagTypes);

            // Remove the ID3v1 tag if set in the settings at this point
            if (Settings.Current.removeID3v1 && file.TagTypes.HasFlag(TagTypes.Id3v1))
            {
                file.RemoveTags(TagTypes.Id3v1);
            }

            // --- RESUME COPYING OVER FROM HERE ---

            // If we're in remove move
            if (args.removeTags)
            {
                if (!args.skipDateAdded)
                {
                    TagLibUtility.RemoveCustomTag(file, Consts.TAG_DATE_ADDED, ds);
                }
                if (!args.skipLastPlayed)
                {
                    TagLibUtility.RemoveCustomTag(file, Consts.TAG_LAST_PLAYED, ds);
                }
                if (!args.skipPlayCount)
                {
                    TagLibUtility.RemoveCustomTag(file, Consts.TAG_PLAY_COUNT, ds);
                }
                if (!args.skipRating)
                {
                    TagLibUtility.RemoveRating(file, ds);
                }

                entry.wroteTags = false;
            }

            // If we're in writing mode
            else
            {
                // Date Added
                if (!args.skipDateAdded && entry.dateAdded != DateTime.MinValue)
                {
                    // Create LDAP/Windows File Time long
                    long dateAddedWinTime = entry.dateAdded.ToFileTime();

                    if (Settings.Current.fullLogging)
                    {
                        ds.Log(string.Format("\tWriting {0}: {1}\n\t-> Converted to {3} (or {2})", Consts.PLIST_KEY_DATE_ADDED, entry.dateAdded.ToString("o", System.Globalization.CultureInfo.InvariantCulture), entry.dateAdded.ToString(), dateAddedWinTime));
                    }

                    // Write the tag
                    TagLibUtility.WriteCustomTag(file, Consts.TAG_DATE_ADDED, dateAddedWinTime.ToString(), ds);
                }

                // Last Played
                if (!args.skipLastPlayed && entry.lastPlayed != DateTime.MinValue)
                {
                    // Create LDAP/Windows File Time long
                    long lastPlayedWinTime = entry.lastPlayed.ToFileTime();

                    if (Settings.Current.fullLogging)
                    {
                        ds.Log(string.Format("\tWriting {0}: {1}\n\t-> Converted to {3} (or {2})", Consts.PLIST_KEY_LAST_PLAYED, entry.lastPlayed.ToString("o", System.Globalization.CultureInfo.InvariantCulture), entry.lastPlayed.ToString(), lastPlayedWinTime));
                    }

                    // Write the tag
                    TagLibUtility.WriteCustomTag(file, Consts.TAG_LAST_PLAYED, lastPlayedWinTime.ToString(), ds);
                }

                // Play Count
                if (!args.skipPlayCount && entry.playCount > 0)
                {
                    if (Settings.Current.fullLogging)
                    {
                        ds.Log(string.Format("\tWriting {0}: {1}", Consts.PLIST_KEY_PLAY_COUNT, entry.playCount));
                    }

                    // Write the tag
                    TagLibUtility.WriteCustomTag(file, Consts.TAG_PLAY_COUNT, entry.playCount.ToString(), ds);
                }

                // Rating
                if (!args.skipRating && entry.rating != Rating.Unrated)
                {
                    int ratingInStars = (int)entry.rating;

                    if (Settings.Current.fullLogging)
                    {
                        ds.Log(string.Format("\tWriting {0}: {1} ({2} stars)", Consts.PLIST_KEY_RATING, ratingInStars * 20, ratingInStars));
                    }

                    // Write the tag
                    TagLibUtility.WriteRating(file, ratingInStars, ds);
                }

                // Process WAV files (after writing stats, since an ID3v2 tag should exist then)
                if (Settings.Current.writeInfoToWavFiles && file.MimeType == "taglib/wav")
                {
                    // This will compare the file with the entry, and will write any missing info that is present in the entry - but not present in the file. Limited to the following tags: Name, Artist, Album Artist, Album, Genre, Comments, Year, Disc Number, Disc Count, Track Number, Track Count

                    ds.Log("\tWriting WAV info:");

                    // Create an Id3v2 tag if it doesn't already exist.
                    var id3v2tag = (TagLib.Id3v2.Tag)file.GetTag(TagTypes.Id3v2, true);

                    // Create a RIFF INFO tag if it doesn't already exist
                    // foobar2000 seems to require a RIFF INFO chunk with at least one tag to detect the ID3v2 tags
                    var riffInfo = (TagLib.Riff.InfoTag)file.GetTag(TagTypes.RiffInfo, true);

                    // Write track title
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_TITLE)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_TITLE)) && !string.IsNullOrEmpty(entry.trackTitle))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_TITLE, entry.trackTitle, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_TITLE, entry.trackTitle, ds);
                    }

                    // Write artist
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_ARTIST)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_ARTIST)) && !string.IsNullOrEmpty(entry.artist))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_ARTIST, entry.artist, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_ARTIST, entry.artist, ds);
                    }

                    // Write album artist (ID3v2 only)
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_ALBUM_ARTIST)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_ALBUM)) && !string.IsNullOrEmpty(entry.albumArtist))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_ALBUM_ARTIST, entry.albumArtist, ds);
                    }

                    // Write album
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_ALBUM)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_ALBUM)) && !string.IsNullOrEmpty(entry.album))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_ALBUM, entry.album);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_ALBUM, entry.album);
                    }

                    // Write genre
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_GENRE)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_GENRE)) && !string.IsNullOrEmpty(entry.genre))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_GENRE, entry.genre, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_GENRE, entry.genre, ds);
                    }

                    // Write year
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_DATE)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_YEAR)) && !string.IsNullOrEmpty(entry.year))
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_DATE, entry.year, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_YEAR, entry.year, ds);
                    }

                    // Write track number
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_TRACK_NUMBER)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_TRACK_NUMBER)) && entry.trackNumber != null)
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_TRACK_NUMBER, entry.trackNumberDisplay, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_TRACK_NUMBER, entry.trackNumberDisplay, ds);
                    }

                    // Write disc number (ID3v2 only)
                    if (string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.ID3v2_FRAME_DISC_NUMBER)) && entry.discNumber != null)
                    {
                        TagLibUtility.WriteTextTag(id3v2tag, Consts.ID3v2_FRAME_DISC_NUMBER, entry.discNumberDisplay, ds);
                    }

                    // Write comments
                    if (string.IsNullOrEmpty(TagLibUtility.GetCommentsTag(file)) &&
                        string.IsNullOrEmpty(TagLibUtility.GetTextTag(file, Consts.RIFF_ID_COMMENTS)) && !string.IsNullOrEmpty(entry.comments))
                    {
                        TagLibUtility.WriteCommentsTag(file, entry.comments, ds);
                        //TagLibUtility.WriteTextTag(riffInfo, Consts.RIFF_ID_COMMENTS, entry.comments, ds);
                    }
                }

                entry.wroteTags = true;
            }

            // Write the modified tags to the file
            try
            {
                if (Settings.Current.fullLogging)
                {
                    TagTypes newTags = file.TagTypesOnDisk ^ file.TagTypes;

                    ds.Log("\tTags for writing:\t" + file.TagTypes.ToString());
                    ds.Log("\t    New tags:\t\t" + newTags.ToString());
                    ds.Log("\t    Existing tags:\t" + file.TagTypesOnDisk.ToString());
                }

                if (!Settings.Current.dryRun)
                {
                    file.Save();
                }

                // If we're here, it means the TagLib.File was saved correctly

                if (isRetry)
                {
                    ds.LogSuccess("\tReattempt succeeded");
                }
            }
            catch (IOException ioex)
            {
                // If this was a retry...
                if (isRetry)
                {
                    string message = "Could not save file after retry. An exception occurred: " + ioex.Message;
                    ds.LogError("\t" + message);

                    entryErrors.TryAdd(entry, message);
                    return(TagWriterReturnCode.IOEError);
                }
                else
                {
                    ds.LogError("\t-> An IO exception occured while saving tags to the file \"" + entry.fileName + "\"");

                    // Get the locking processes (if any)
                    var lockingProcesses = FileLockUtility.GetProcessesLockingFile(entry.mappedFilePath);

                    // Print the process(es) that are locking the file
                    if (lockingProcesses != null && lockingProcesses.Count > 0)
                    {
                        string message = "The file appears to be locked by the process: " + string.Join(", ", lockingProcesses.Select(p => p.ProcessName).ToArray());
                        ds.LogError("\t" + message);

                        entryErrors.TryAdd(entry, message);
                        return(TagWriterReturnCode.IOEError);
                    }

                    // Otherwise if there is no locking process, this is a known issue in TagLib while using ReadStyle.PictureLazy.
                    // Reattempt, using the default ReadStyle.Average
                    else
                    {
                        ds.LogError("\t-> Reattempting load with different parameters...");
                        isRetry = true;
                        goto Retry;
                    }
                }
            }
            catch (Exception ex)
            {
                string message = "An error occurred while saving tags to \"" + entry.fileName + "\": (" + ex.Message + ")";
                ds.LogError("\t" + message);
                entryErrors.TryAdd(entry, message);
                return(TagWriterReturnCode.OtherError);
            }

            file.Dispose();
            return(TagWriterReturnCode.Success);
        }