diff --git a/BasicNodes/File/Renamer.cs b/BasicNodes/File/Renamer.cs index e524eed6..75408e66 100644 --- a/BasicNodes/File/Renamer.cs +++ b/BasicNodes/File/Renamer.cs @@ -62,12 +62,21 @@ newFile = Regex.Replace(newFile, @"\s(\.[\w\d]+)$", "$1"); newFile = newFile.Replace(" \\", "\\"); + string destFolder = args.ReplaceVariables(DestinationPath ?? string.Empty, stripMissing: true, cleanSpecialCharacters: true); if (string.IsNullOrEmpty(destFolder)) destFolder = new FileInfo(args.WorkingFile).Directory?.FullName ?? ""; var dest = args.GetSafeName(Path.Combine(destFolder, newFile)); + if (string.IsNullOrEmpty(dest.Extension) == false) + { + // just ensures extensions are lowercased + dest = new FileInfo(dest.FullName.Substring(0, dest.FullName.LastIndexOf(dest.Extension)) + dest.Extension.ToLower()); + } + + + args.Logger?.ILog("Renaming file to: " + dest.FullName); if (string.IsNullOrEmpty(CsvFile) == false) diff --git a/MusicNodes/MusicInfoHelper.cs b/MusicNodes/MusicInfoHelper.cs index be75c203..85bdfb97 100644 --- a/MusicNodes/MusicInfoHelper.cs +++ b/MusicNodes/MusicInfoHelper.cs @@ -31,6 +31,8 @@ namespace FileFlows.MusicNodes return mi; } + mi = ReadMetaData(filename); + try { using (var process = new Process()) @@ -90,9 +92,12 @@ namespace FileFlows.MusicNodes mi.Language = line.Substring(colonIndex + 1).Trim(); else if (lowLine.StartsWith("track") && lowLine.Contains("total") == false) { - var trackMatch = Regex.Match(line.Substring(colonIndex + 1).Trim(), @"^[\d]+"); - if (trackMatch.Success && int.TryParse(trackMatch.Value, out int value)) - mi.Track = value; + if (mi.Track < 1) + { + var trackMatch = Regex.Match(line.Substring(colonIndex + 1).Trim(), @"^[\d]+"); + if (trackMatch.Success && int.TryParse(trackMatch.Value, out int value)) + mi.Track = value; + } } else if (lowLine.StartsWith("artist") || lowLine.StartsWith("album_artist")) { @@ -101,11 +106,14 @@ namespace FileFlows.MusicNodes } else if (lowLine.StartsWith("title") && lowLine.Contains(".jpg") == false) { - if(string.IsNullOrWhiteSpace(mi.Title)) + if (string.IsNullOrWhiteSpace(mi.Title)) mi.Title = line.Substring(colonIndex + 1).Trim(); } else if (lowLine.StartsWith("album")) - mi.Album = line.Substring(colonIndex + 1).Trim(); + { + if (string.IsNullOrWhiteSpace(mi.Album)) + mi.Album = line.Substring(colonIndex + 1).Trim(); + } else if (lowLine.StartsWith("disc")) { if (int.TryParse(line.Substring(colonIndex + 1).Trim(), out int value)) @@ -116,28 +124,34 @@ namespace FileFlows.MusicNodes if (int.TryParse(line.Substring(colonIndex + 1).Trim(), out int value)) mi.TotalDiscs = value; } - else if (lowLine.StartsWith("date") && mi.Date < new DateTime(1900, 1, 1)) + else if (lowLine.StartsWith("date") || lowLine.StartsWith("retail date") || lowLine.StartsWith("retaildate") || lowLine.StartsWith("originaldate") || lowLine.StartsWith("original date")) { if (int.TryParse(line.Substring(colonIndex + 1).Trim(), out int value)) - mi.Date = new DateTime(value, 1, 1); - } - else if (lowLine.StartsWith("retail date")) - { - if (DateTime.TryParse(line.Substring(colonIndex + 1).Trim(), out DateTime value)) - mi.Date = value; + { + if(mi.Date < new DateTime(1900, 1, 1)) + mi.Date = new DateTime(value, 1, 1); + } + else if(DateTime.TryParse(line.Substring(colonIndex + 1).Trim(), out DateTime dtValue) && dtValue.Year > 1900) + mi.Date = dtValue; } else if (lowLine.StartsWith("genre")) - mi.Genres = line.Substring(colonIndex + 1).Trim().Split(' '); + { + if(mi.Genres?.Any() != true) + mi.Genres = line.Substring(colonIndex + 1).Trim().Split(' '); + } else if (lowLine.StartsWith("encoder")) mi.Encoder = line.Substring(colonIndex + 1).Trim(); else if (lowLine.StartsWith("duration")) { - string temp = line.Substring(colonIndex + 1).Trim(); - if (temp.IndexOf(",") > 0) + if (mi.Duration < 1) { - temp = temp.Substring(0, temp.IndexOf(",")); - if (TimeSpan.TryParse(temp, out TimeSpan value)) - mi.Duration = (long)value.TotalSeconds; + string temp = line.Substring(colonIndex + 1).Trim(); + if (temp.IndexOf(",") > 0) + { + temp = temp.Substring(0, temp.IndexOf(",")); + if (TimeSpan.TryParse(temp, out TimeSpan value)) + mi.Duration = (long)value.TotalSeconds; + } } } @@ -174,5 +188,32 @@ namespace FileFlows.MusicNodes return mi; } + public MusicInfo ReadMetaData(string file) + { + using var tfile = TagLib.File.Create(file); + MusicInfo info = new MusicInfo(); + try + { + info.Title = tfile.Tag.Title; + info.Duration = (long)tfile.Properties.Duration.TotalSeconds; + info.TotalDiscs = Convert.ToInt32(tfile.Tag.DiscCount); + if (info.TotalDiscs < 1) + info.TotalDiscs = 1; + info.Disc = Convert.ToInt32(tfile.Tag.Disc); + if (info.Disc < 1) + info.Disc = 1; + info.Artist = String.Join(", ", tfile.Tag.AlbumArtists); + info.Album = tfile.Tag.Album; + info.Track = Convert.ToInt32(tfile.Tag.Track); + if(tfile.Tag.Year > 1900) + { + info.Date = new DateTime(Convert.ToInt32(tfile.Tag.Year), 1, 1); + } + info.Genres = tfile.Tag.Genres.SelectMany(x => x.Split(new[] { ";", "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())).ToArray(); + } + catch (Exception) { } + return info; + } + } } \ No newline at end of file diff --git a/MusicNodes/MusicNodes.csproj b/MusicNodes/MusicNodes.csproj index 4d391142..d81ff2a8 100644 Binary files a/MusicNodes/MusicNodes.csproj and b/MusicNodes/MusicNodes.csproj differ diff --git a/MusicNodes/Tests/MusicInfoTests.cs b/MusicNodes/Tests/MusicInfoTests.cs index 4e339c2f..1cc36f53 100644 --- a/MusicNodes/Tests/MusicInfoTests.cs +++ b/MusicNodes/Tests/MusicInfoTests.cs @@ -45,6 +45,19 @@ namespace FileFlows.MusicNodes.Tests Assert.AreEqual(8, musicInfo.Track); } + + [TestMethod] + public void MusicInfo_GetMetaData() + { + const string ffmpegExe = @"C:\utils\ffmpeg\ffmpeg.exe"; + var logger = new TestLogger(); + foreach (string file in Directory.GetFiles(@"D:\videos\music")) + { + var args = new FileFlows.Plugin.NodeParameters(file, logger, false, string.Empty); + var info = new MusicInfoHelper(ffmpegExe, logger).Read(file); + Assert.IsNotNull(info); + } + } } }