From 2f75667f20786ea3802527ead863b87d2f6579d4 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Wed, 30 Oct 2024 17:33:36 -0700 Subject: [PATCH] Fast Forward Moving Picture Experts Group Used --- Metadata/Models/Stateless/Get.cs | 24 ++++--- .../Models/Stateless/Methods/IMetadata.cs | 4 +- Rename/Rename.cs | 69 ++++++++++--------- Shared/Models/Stateless/Methods/IRename.cs | 2 +- 4 files changed, 54 insertions(+), 45 deletions(-) diff --git a/Metadata/Models/Stateless/Get.cs b/Metadata/Models/Stateless/Get.cs index 9f2f301..81ded9d 100644 --- a/Metadata/Models/Stateless/Get.cs +++ b/Metadata/Models/Stateless/Get.cs @@ -31,17 +31,18 @@ internal static class Get return new(results); } - internal static Action SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) + internal static Action SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(bool, FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) { return file => { rename.Tick(); FileInfo fileInfo; - FilePath? ffmpegFilePath; ExifDirectory exifDirectory; - ReadOnlyCollection? ffmpegFiles; DeterministicHashCode deterministicHashCode; FileHolder fileHolder = FileHolder.Get(file); + bool fastForwardMovingPictureExpertsGroupUsed; + FilePath? fastForwardMovingPictureExpertsGroupFilePath; + ReadOnlyCollection? fastForwardMovingPictureExpertsGroupFiles; FilePath filePath = FilePath.Get(renameConfiguration.MetadataConfiguration, fileHolder, index: null); string key = $"{Path.Combine(fileHolder.DirectoryName ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}"; if (distinct.Contains(key)) @@ -50,22 +51,23 @@ internal static class Get { if (filePath.Id is not null) { - ffmpegFiles = null; + fastForwardMovingPictureExpertsGroupFiles = null; deterministicHashCode = new(null, filePath.Id, null); } else { - ffmpegFiles = rename.ConvertAndGetFfmpegFiles(renameConfiguration, filePath); - ffmpegFilePath = ffmpegFiles.Count == 0 ? null : FilePath.Get(renameConfiguration.MetadataConfiguration, FileHolder.Get(ffmpegFiles[0]), index: null); - deterministicHashCode = ffmpegFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(ffmpegFilePath); + fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(renameConfiguration, filePath); + fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(renameConfiguration.MetadataConfiguration, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null); + deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath); } + fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0; (fileInfo, exifDirectory) = metadata.GetMetadataCollection(renameConfiguration.MetadataConfiguration, filePath, deterministicHashCode); lock (collection) - collection.Add(new(filePath, fileInfo, exifDirectory, new([]))); - if (ffmpegFiles is not null) + collection.Add(new(fastForwardMovingPictureExpertsGroupUsed, filePath, fileInfo, exifDirectory, new([]))); + if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null) { - foreach (string ffmpegFile in ffmpegFiles) - File.Delete(ffmpegFile); + foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles) + File.Delete(fastForwardMovingPictureExpertsGroupFile); } } diff --git a/Metadata/Models/Stateless/Methods/IMetadata.cs b/Metadata/Models/Stateless/Methods/IMetadata.cs index 45f40c8..08331d0 100644 --- a/Metadata/Models/Stateless/Methods/IMetadata.cs +++ b/Metadata/Models/Stateless/Methods/IMetadata.cs @@ -57,9 +57,9 @@ public interface IMetadata static double? GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces = 1, DistanceUnit distanceUnit = DistanceUnit.Miles) => GPS.GetDistance(originLatitude, originLongitude, destinationLatitude, destinationLongitude, decimalPlaces, distanceUnit); - Action TestStatic_SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) => + Action TestStatic_SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(bool, FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) => SetExifDirectoryCollection(rename, renameConfiguration, metadata, distinct, collection); - static Action SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) => + static Action SetExifDirectoryCollection(IRename rename, IRenameConfiguration renameConfiguration, A_Metadata metadata, List distinct, List<(bool, FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection) => Get.SetExifDirectoryCollection(rename, renameConfiguration, metadata, distinct, collection); ReadOnlyDictionary> TestStatic_GetKeyValuePairs(IEnumerable files) => diff --git a/Rename/Rename.cs b/Rename/Rename.cs index 4fbbc5d..292291a 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -21,9 +21,9 @@ public partial class Rename : IRename, IDisposable private sealed record ToDo(string? Directory, FilePath FilePath, string File, bool JsonFile); - private sealed record RecordA(ExifDirectory ExifDirectory, FileInfo FileInfo, FilePath FilePath, ReadOnlyCollection SidecarFiles); + private sealed record RecordA(ExifDirectory ExifDirectory, bool FastForwardMovingPictureExpertsGroupUsed, FileInfo FileInfo, FilePath FilePath, ReadOnlyCollection SidecarFiles); - private sealed record RecordB(DateTime DateTime, ExifDirectory ExifDirectory, FilePath FilePath, ReadOnlyCollection SidecarFiles, bool HasDateTimeOriginal, bool HasIgnoreKeyword, string JsonFile); + private sealed record RecordB(DateTime DateTime, ExifDirectory ExifDirectory, bool FastForwardMovingPictureExpertsGroupUsed, FilePath FilePath, ReadOnlyCollection SidecarFiles, bool HasDateTimeOriginal, bool HasIgnoreKeyword, string JsonFile); private ProgressBar? _ProgressBar; @@ -49,7 +49,7 @@ public partial class Rename : IRename, IDisposable GC.SuppressFinalize(this); } - ReadOnlyCollection IRename.ConvertAndGetFfmpegFiles(IRenameConfiguration renameConfiguration, FilePath filePath) + ReadOnlyCollection IRename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IRenameConfiguration renameConfiguration, FilePath filePath) { List results = []; bool isValidVideoFormatExtensions = renameConfiguration.ValidVideoFormatExtensions.Contains(filePath.ExtensionLowered); @@ -117,7 +117,7 @@ public partial class Rename : IRename, IDisposable #pragma warning restore CA1416 - private void NonParallelismAndInPlace(RenameConfiguration renameConfiguration, ReadOnlyCollection ids, ExifDirectory exifDirectory, FileInfo fileInfo, FilePath filePath, ReadOnlyCollection sidecarFiles) + private void NonParallelismAndInPlace(RenameConfiguration renameConfiguration, ReadOnlyCollection ids, ExifDirectory exifDirectory, FileInfo fileInfo, FilePath filePath, bool fastForwardMovingPictureExpertsGroupUsed, ReadOnlyCollection sidecarFiles) { if (exifDirectory.Id is null) throw new NotImplementedException(); @@ -148,7 +148,7 @@ public partial class Rename : IRename, IDisposable if (renameConfiguration.InPlace) throw new NotSupportedException($"Must use {nameof(renameConfiguration.InPlaceWithOriginalName)} when sidecar file(s) are present!"); dateTime ??= IDate.GetMinimum(exifDirectory); - RecordB recordB = new(dateTime.Value, exifDirectory, filePath, sidecarFiles, hasDateTimeOriginal, hasIgnoreKeyword, fileInfo.FullName); + RecordB recordB = new(dateTime.Value, exifDirectory, fastForwardMovingPictureExpertsGroupUsed, filePath, sidecarFiles, hasDateTimeOriginal, hasIgnoreKeyword, fileInfo.FullName); toDoCollection.AddRange(GetSidecarFiles(metadataConfiguration, recordB, [], checkDirectory, paddedId)); } _ = RenameFilesInDirectories(renameConfiguration, new(toDoCollection)); @@ -156,7 +156,8 @@ public partial class Rename : IRename, IDisposable File.Move(fileInfo.FullName, jsonFile, overwrite: true); if (renameConfiguration.InPlaceWithOriginalName && ids.Count > 0) { - string idCheck = Path.Combine(checkDirectory, ids.Contains(exifDirectory.Id.Value) ? "_ Exists _" : "_ New _"); + string contains = ids.Contains(exifDirectory.Id.Value) ? "_ Exists _" : "_ New _"; + string idCheck = Path.Combine(checkDirectory, contains, fastForwardMovingPictureExpertsGroupUsed ? "Video" : "Image"); if (!Directory.Exists(idCheck)) _ = Directory.CreateDirectory(idCheck); } @@ -169,11 +170,12 @@ public partial class Rename : IRename, IDisposable int index = -1; FileInfo fileInfo; FilePath filePath; - FilePath? ffmpegFilePath; ExifDirectory exifDirectory; List sidecarFiles; - ReadOnlyCollection? ffmpegFiles; DeterministicHashCode deterministicHashCode; + bool fastForwardMovingPictureExpertsGroupUsed; + FilePath? fastForwardMovingPictureExpertsGroupFilePath; + ReadOnlyCollection? fastForwardMovingPictureExpertsGroupFiles; ReadOnlyDictionary> keyValuePairs = IMetadata.GetKeyValuePairs(files); foreach (KeyValuePair> keyValuePair in keyValuePairs) { @@ -194,16 +196,16 @@ public partial class Rename : IRename, IDisposable continue; if (!renameConfiguration.ForceNewId && filePath.Id is not null) { - ffmpegFiles = null; + fastForwardMovingPictureExpertsGroupFiles = null; deterministicHashCode = new(null, filePath.Id, null); if (renameConfiguration.InPlaceWithOriginalName || (renameConfiguration.InPlace && filePath.DirectoryName.EndsWith(filePath.Id.Value.ToString()))) continue; } else { - ffmpegFiles = rename.ConvertAndGetFfmpegFiles(renameConfiguration, filePath); - ffmpegFilePath = ffmpegFiles.Count == 0 ? null : FilePath.Get(renameConfiguration.MetadataConfiguration, FileHolder.Get(ffmpegFiles[0]), index); - deterministicHashCode = ffmpegFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(ffmpegFilePath); + fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(renameConfiguration, filePath); + fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(renameConfiguration.MetadataConfiguration, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index); + deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath); } sidecarFiles = []; for (int i = 0; i < keyValuePair.Value.Count; i++) @@ -219,14 +221,15 @@ public partial class Rename : IRename, IDisposable logger?.LogWarning("<{filePath}>", filePath.FullName); continue; } - if (ffmpegFiles is not null) + fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0; + if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null) { - foreach (string ffmpegFile in ffmpegFiles) - File.Delete(ffmpegFile); + foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles) + File.Delete(fastForwardMovingPictureExpertsGroupFile); } if (renameConfiguration.InPlace || renameConfiguration.InPlaceWithOriginalName) - NonParallelismAndInPlace(renameConfiguration, ids, exifDirectory, fileInfo, filePath, new(sidecarFiles)); - results.Add(new(exifDirectory, fileInfo, filePath, new(sidecarFiles))); + NonParallelismAndInPlace(renameConfiguration, ids, exifDirectory, fileInfo, filePath, fastForwardMovingPictureExpertsGroupUsed, new(sidecarFiles)); + results.Add(new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, fileInfo, filePath, new(sidecarFiles))); } } return results; @@ -246,7 +249,7 @@ public partial class Rename : IRename, IDisposable dateTime ??= IDate.GetMinimum(recordA.ExifDirectory); keywords = IMetadata.GetKeywords(recordA.ExifDirectory); hasIgnoreKeyword = metadataConfiguration.IgnoreRulesKeyWords.Any(l => keywords.Contains(l)); - results.Add(new(dateTime.Value, recordA.ExifDirectory, recordA.FilePath, recordA.SidecarFiles, hasDateTimeOriginal, hasIgnoreKeyword, recordA.FileInfo.FullName)); + results.Add(new(dateTime.Value, recordA.ExifDirectory, recordA.FastForwardMovingPictureExpertsGroupUsed, recordA.FilePath, recordA.SidecarFiles, hasDateTimeOriginal, hasIgnoreKeyword, recordA.FileInfo.FullName)); } return new(results); } @@ -266,13 +269,13 @@ public partial class Rename : IRename, IDisposable else { List distinct = []; - List<(FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection = []; + List<(bool, FilePath, FileInfo, ExifDirectory, ReadOnlyCollection)> collection = []; ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = appSettingsMaxDegreeOfParallelism }; files.AsParallel().ForAll(IMetadata.SetExifDirectoryCollection(rename, renameConfiguration, metadata, distinct, collection)); if (_ProgressBar.CurrentTick != recordACollection.Count) throw new NotSupportedException(); - foreach ((FilePath filePath, FileInfo fileInfo, ExifDirectory exifDirectory, ReadOnlyCollection sidecarFiles) in collection) - recordACollection.Add(new(exifDirectory, fileInfo, filePath, sidecarFiles)); + foreach ((bool fastForwardMovingPictureExpertsGroupUsed, FilePath filePath, FileInfo fileInfo, ExifDirectory exifDirectory, ReadOnlyCollection sidecarFiles) in collection) + recordACollection.Add(new(exifDirectory, fastForwardMovingPictureExpertsGroupUsed, fileInfo, filePath, sidecarFiles)); } _ProgressBar.Dispose(); results = GetRecordBCollection(renameConfiguration.MetadataConfiguration, recordACollection); @@ -281,32 +284,36 @@ public partial class Rename : IRename, IDisposable private static void VerifyIntMinValueLength(MetadataConfiguration metadataConfiguration, ReadOnlyCollection recordBCollection) { - foreach ((DateTime _, ExifDirectory exifDirectory, FilePath _, ReadOnlyCollection _, bool _, bool _, string _) in recordBCollection) + foreach (RecordB recordB in recordBCollection) { - if (exifDirectory.Id is null) + if (recordB.ExifDirectory.Id is null) continue; - if (metadataConfiguration.IntMinValueLength < exifDirectory.Id.Value.ToString().Length) + if (metadataConfiguration.IntMinValueLength < recordB.ExifDirectory.Id.Value.ToString().Length) throw new NotSupportedException(); } } - private static string? GetCheckDirectory(RenameConfiguration renameConfiguration, RecordB record, FilePath filePath, ReadOnlyCollection ids, bool multipleDirectoriesWithFiles) + private static string? GetCheckDirectory(RenameConfiguration renameConfiguration, RecordB record, ReadOnlyCollection ids, bool multipleDirectoriesWithFiles) { string? result; - if (filePath.DirectoryName is null) - throw new NullReferenceException(nameof(filePath.DirectoryName)); + if (record.FilePath.DirectoryName is null) + throw new NullReferenceException(nameof(record.FilePath.DirectoryName)); string year = record.DateTime.Year.ToString(); - string checkDirectoryName = Path.GetFileName(filePath.DirectoryName); + string checkDirectoryName = Path.GetFileName(record.FilePath.DirectoryName); if (multipleDirectoriesWithFiles && !checkDirectoryName.Contains(year)) result = null; else { string? maker = IMetadata.GetMaker(record.ExifDirectory); + string hasDateTimeOriginal = record.HasDateTimeOriginal ? "Has" : "Not"; (int seasonValue, string seasonName) = IDate.GetSeason(record.DateTime.DayOfYear); - string splat = filePath.DirectoryName[^3..][1] == '!' ? filePath.DirectoryName[^3..] : string.Empty; + string rootDirectory = renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory; + string splat = record.FilePath.DirectoryName[^3..][1] == '!' ? record.FilePath.DirectoryName[^3..] : string.Empty; + string fastForwardMovingPictureExpertsGroupUsed = record.FastForwardMovingPictureExpertsGroupUsed ? "Video" : "Image"; + string contains = record.ExifDirectory.Id is null || ids.Contains(record.ExifDirectory.Id.Value) ? "_ Exists _" : "_ New-Destination _"; string makerSplit = string.IsNullOrEmpty(maker) ? string.IsNullOrEmpty(renameConfiguration.DefaultMaker) ? string.Empty : renameConfiguration.DefaultMaker : $" {maker.Split(' ')[0]}"; string directoryName = $"{year}.{seasonValue} {seasonName}{makerSplit}{splat}"; - result = Path.Combine(renameConfiguration.MetadataConfiguration.ResultConfiguration.RootDirectory, record.ExifDirectory.Id is null || ids.Contains(record.ExifDirectory.Id.Value) ? "_ Exists _" : "_ New-Destination _", record.HasDateTimeOriginal ? "Has" : "Not", directoryName); + result = Path.Combine(rootDirectory, contains, fastForwardMovingPictureExpertsGroupUsed, hasDateTimeOriginal, directoryName); } return result; } @@ -385,7 +392,7 @@ public partial class Rename : IRename, IDisposable continue; if (record.FilePath.DirectoryName is null) continue; - checkDirectory = GetCheckDirectory(renameConfiguration, record, record.FilePath, ids, multipleDirectoriesWithFiles); + checkDirectory = GetCheckDirectory(renameConfiguration, record, ids, multipleDirectoriesWithFiles); if (string.IsNullOrEmpty(checkDirectory)) continue; checkFileExtension = record.FilePath.ExtensionLowered == jpeg ? jpg : record.FilePath.ExtensionLowered; diff --git a/Shared/Models/Stateless/Methods/IRename.cs b/Shared/Models/Stateless/Methods/IRename.cs index 803a392..22ebd63 100644 --- a/Shared/Models/Stateless/Methods/IRename.cs +++ b/Shared/Models/Stateless/Methods/IRename.cs @@ -6,7 +6,7 @@ namespace View_by_Distance.Shared.Models.Stateless.Methods; public interface IRename { - ReadOnlyCollection ConvertAndGetFfmpegFiles(IRenameConfiguration renameConfiguration, FilePath filePath); + ReadOnlyCollection ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(IRenameConfiguration renameConfiguration, FilePath filePath); DeterministicHashCode GetDeterministicHashCode(FilePath filePath); void Tick();