Code cleanup

This commit is contained in:
Laura Hausmann 2022-03-22 16:02:03 +01:00
parent 0c27cf02c8
commit 210958db35
Signed by: zotan
GPG key ID: D044E84C5BE01605
5 changed files with 159 additions and 195 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ obj/
/packages/ /packages/
riderModule.iml riderModule.iml
/_ReSharper.Caches/ /_ReSharper.Caches/
.DS_Store

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ContentModelUserStore"> <component name="UserContentModel">
<attachedFolders /> <attachedFolders />
<explicitIncludes /> <explicitIncludes />
<explicitExcludes /> <explicitExcludes />

View file

@ -42,108 +42,80 @@ using System.Text;
* Please compare against the latest Java version at http://www.DaveKoelle.com * Please compare against the latest Java version at http://www.DaveKoelle.com
* to see the most recent modifications * to see the most recent modifications
*/ */
namespace AutoTag.cli namespace AutoTag.cli;
{
public class AlphanumComparator : IComparer<string>
{
private enum ChunkType {Alphanumeric, Numeric};
private bool InChunk(char ch, char otherCh)
{
var type = ChunkType.Alphanumeric;
if (char.IsDigit(otherCh)) public class AlphanumComparator : IComparer<string> {
{ public int Compare(string x, string y) {
type = ChunkType.Numeric;
}
if (type == ChunkType.Alphanumeric && char.IsDigit(ch)
|| type == ChunkType.Numeric && !char.IsDigit(ch))
{
return false;
}
return true;
}
public int Compare(string x, string y)
{
var s1 = x; var s1 = x;
var s2 = y; var s2 = y;
if (s1 == null || s2 == null) if (s1 == null || s2 == null)
{
return 0; return 0;
}
var thisMarker = 0; var thisMarker = 0;
var thatMarker = 0; var thatMarker = 0;
while (thisMarker < s1.Length || thatMarker < s2.Length) while (thisMarker < s1.Length || thatMarker < s2.Length) {
{
if (thisMarker >= s1.Length) if (thisMarker >= s1.Length)
{
return -1; return -1;
} if (thatMarker >= s2.Length)
else if (thatMarker >= s2.Length)
{
return 1; return 1;
}
var thisCh = s1[thisMarker]; var thisCh = s1[thisMarker];
var thatCh = s2[thatMarker]; var thatCh = s2[thatMarker];
var thisChunk = new StringBuilder(); var thisChunk = new StringBuilder();
var thatChunk = new StringBuilder(); var thatChunk = new StringBuilder();
while (thisMarker < s1.Length && (thisChunk.Length==0 ||InChunk(thisCh, thisChunk[0]))) while (thisMarker < s1.Length && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0]))) {
{
thisChunk.Append(thisCh); thisChunk.Append(thisCh);
thisMarker++; thisMarker++;
if (thisMarker < s1.Length) if (thisMarker < s1.Length)
{
thisCh = s1[thisMarker]; thisCh = s1[thisMarker];
} }
}
while (thatMarker < s2.Length && (thatChunk.Length==0 ||InChunk(thatCh, thatChunk[0]))) while (thatMarker < s2.Length && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0]))) {
{
thatChunk.Append(thatCh); thatChunk.Append(thatCh);
thatMarker++; thatMarker++;
if (thatMarker < s2.Length) if (thatMarker < s2.Length)
{
thatCh = s2[thatMarker]; thatCh = s2[thatMarker];
} }
}
var result = 0; var result = 0;
// If both chunks contain numeric characters, sort them numerically // If both chunks contain numeric characters, sort them numerically
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) {
{
var thisNumericChunk = Convert.ToInt32(thisChunk.ToString()); var thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
var thatNumericChunk = Convert.ToInt32(thatChunk.ToString()); var thatNumericChunk = Convert.ToInt32(thatChunk.ToString());
if (thisNumericChunk < thatNumericChunk) if (thisNumericChunk < thatNumericChunk)
{
result = -1; result = -1;
}
if (thisNumericChunk > thatNumericChunk) if (thisNumericChunk > thatNumericChunk)
{
result = 1; result = 1;
} }
} else {
else
{
result = string.Compare(thisChunk.ToString(), thatChunk.ToString(), StringComparison.Ordinal); result = string.Compare(thisChunk.ToString(), thatChunk.ToString(), StringComparison.Ordinal);
} }
if (result != 0) if (result != 0)
{
return result; return result;
} }
}
return 0; return 0;
} }
private static bool InChunk(char ch, char otherCh) {
var type = ChunkType.Alphanumeric;
if (char.IsDigit(otherCh))
type = ChunkType.Numeric;
return (type != ChunkType.Alphanumeric || !char.IsDigit(ch)) && (type != ChunkType.Numeric || char.IsDigit(ch));
}
private enum ChunkType {
Alphanumeric,
Numeric
} }
} }

View file

@ -2,11 +2,11 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net60</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="TagLibSharp" Version="2.2.0" /> <PackageReference Include="TagLibSharp" Version="2.2.0"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -2,50 +2,47 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using static AutoTag.cli.Helpers; using static AutoTag.cli.Helpers;
using TagFile = TagLib.File; using TagFile = TagLib.File;
namespace AutoTag.cli { namespace AutoTag.cli;
internal static class AutoTag {
internal static class AutoTag {
private static void Main(string[] args) { private static void Main(string[] args) {
if (args.Length != 3 || args[0] != "albums" && args[0] != "playlists") { if (args.Length != 3 || args[0] != "albums" && args[0] != "playlists") {
Console.WriteLine("Usage: autotag <albums/playlists> <inputfolder> <outputfolder>"); Console.WriteLine("Usage: autotag <albums/playlists> <inputfolder> <outputfolder>");
Environment.Exit(1); Environment.Exit(1);
} }
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var type = args[0] == "albums" ? FolderType.Albums : FolderType.Playlists; var type = args[0] == "albums" ? FolderType.Albums : FolderType.Playlists;
var inputDir = new Folder(args[1], type); var inputDir = new Folder(args[1], type);
var outputDir = args[2]; var outputDir = args[2];
switch (inputDir.Type) { switch (inputDir.Type) {
case FolderType.Albums: { case FolderType.Albums: {
foreach (var track in Directory.EnumerateFiles(inputDir.Path, "*.*", SearchOption.AllDirectories) foreach (var track in Directory.EnumerateFiles(inputDir.Path, "*.*", SearchOption.AllDirectories).Where(IsAllowed)) {
.Where(IsAllowed)) {
Console.WriteLine("<- " + track); Console.WriteLine("<- " + track);
var tagFile = TagFile.Create(track); var tagFile = TagFile.Create(track);
if (tagFile.Tag.AlbumArtists.Length == 0) if (tagFile.Tag.AlbumArtists.Length == 0)
tagFile.Tag.AlbumArtists = new[] {tagFile.Tag.Performers[0]}; tagFile.Tag.AlbumArtists = new[] { tagFile.Tag.Performers[0] };
var outputFileDirectory = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), var outputFileDirectory = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album));
CleanFileName(tagFile.Tag.Album));
Directory.CreateDirectory(outputFileDirectory); Directory.CreateDirectory(outputFileDirectory);
var outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), var outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album),
CleanFileName(tagFile.Tag.Album),
CleanFileName($"{tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}")); CleanFileName($"{tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}"));
if (tagFile.Tag.Disc != 0 && tagFile.Tag.Disc != 1) {
outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]),
CleanFileName(tagFile.Tag.Album),
CleanFileName($"Disc{tagFile.Tag.Disc} - {tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}"));
}
if (tagFile.Tag.Disc != 0 && tagFile.Tag.Disc != 1)
outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album),
CleanFileName($"Disc{tagFile.Tag.Disc} - {tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}"));
tagFile.Save();
File.Copy(track, outputFilePath, true); File.Copy(track, outputFilePath, true);
var newTagFile = TagFile.Create(outputFilePath); var newTagFile = TagFile.Create(outputFilePath);
newTagFile.Tag.Comment = null; newTagFile.Tag.Comment = null;
newTagFile.Tag.Genres = null; newTagFile.Tag.Genres = null;
newTagFile.Save(); newTagFile.Save();
Console.WriteLine("-> " + outputFilePath); Console.WriteLine("-> " + outputFilePath);
Console.WriteLine(); Console.WriteLine();
} }
@ -54,9 +51,7 @@ namespace AutoTag.cli {
} }
case FolderType.Playlists: { case FolderType.Playlists: {
foreach (var playlist in Directory.GetDirectories(inputDir.Path)) { foreach (var playlist in Directory.GetDirectories(inputDir.Path)) {
var tracks = Directory.EnumerateFiles(playlist, "*.*", SearchOption.AllDirectories) var tracks = Directory.EnumerateFiles(playlist, "*.*", SearchOption.AllDirectories).Where(IsAllowed).OrderBy(s => s, new AlphanumComparator());
.Where(IsAllowed)
.OrderBy(s => s, new AlphanumComparator());
uint i = 1; uint i = 1;
var trackCount = tracks.Count(); var trackCount = tracks.Count();
@ -65,27 +60,30 @@ namespace AutoTag.cli {
foreach (var track in tracks) { foreach (var track in tracks) {
Console.WriteLine("<- " + track); Console.WriteLine("<- " + track);
var tagFile = TagFile.Create(track); var tagFile = TagFile.Create(track);
var outputFileDirectory = var outputFileDirectory = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName));
Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName));
Directory.CreateDirectory(outputFileDirectory); Directory.CreateDirectory(outputFileDirectory);
var outputFilePath = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName), var outputFilePath = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName),
CleanFileName(tagFile.Tag.Performers.Length == 0 CleanFileName(tagFile.Tag.Performers.Length == 0
? $"{i}. {tagFile.Tag.Title}{Path.GetExtension(track)}" ? $"{i}. {tagFile.Tag.Title}{Path.GetExtension(track)}"
: $"{i}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}")); : $"{i}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}"));
tagFile.Save();
File.Copy(track, outputFilePath, true); File.Copy(track, outputFilePath, true);
var newTagFile = TagFile.Create(outputFilePath); var newTagFile = TagFile.Create(outputFilePath);
newTagFile.Tag.Comment = null; newTagFile.Tag.Comment = null;
newTagFile.Tag.Genres = null; newTagFile.Tag.Genres = null;
newTagFile.Tag.Album = playlistName; newTagFile.Tag.Album = playlistName;
newTagFile.Tag.Track = i++; newTagFile.Tag.Track = i++;
newTagFile.Tag.TrackCount = (uint) trackCount; newTagFile.Tag.TrackCount = (uint)trackCount;
newTagFile.Tag.AlbumArtists = new[] {"Various Artists"}; newTagFile.Tag.AlbumArtists = new[] { "Various Artists" };
if (newTagFile.Tag.Performers.Length == 0) if (newTagFile.Tag.Performers.Length == 0)
newTagFile.Tag.Performers = new[] {"Various Artists"}; newTagFile.Tag.Performers = new[] { "Various Artists" };
newTagFile.Save(); newTagFile.Save();
Console.WriteLine("-> " + outputFilePath); Console.WriteLine("-> " + outputFilePath);
Console.WriteLine(); Console.WriteLine();
} }
@ -96,9 +94,9 @@ namespace AutoTag.cli {
default: throw new ArgumentOutOfRangeException(); default: throw new ArgumentOutOfRangeException();
} }
} }
} }
internal class Folder { internal class Folder {
public readonly string Path; public readonly string Path;
public readonly FolderType Type; public readonly FolderType Type;
@ -106,26 +104,19 @@ namespace AutoTag.cli {
Path = path; Path = path;
Type = type; Type = type;
} }
} }
internal enum FolderType { internal enum FolderType {
Albums, Albums,
Playlists Playlists
} }
internal static class Helpers { internal static class Helpers {
private static readonly List<string> AllowedFileTypes = new List<string> {".flac", ".opus", ".mp3", ".m4a"}; private static readonly List<string> AllowedFileTypes = new() { ".flac", ".opus", ".mp3", ".m4a" };
internal static bool IsAllowed(string filename) => AllowedFileTypes.Any(filename.EndsWith); internal static bool IsAllowed(string filename) => AllowedFileTypes.Any(filename.EndsWith);
internal static string CleanFileName(string fileName) { internal static string CleanFileName(string fileName) {
return Path.GetInvalidFileNameChars() return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty)).Replace(":", " -").Replace("\\", " ");
.Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty))
.Replace(":", " -")
.Replace("\\", " ");
//var tempBytes = Encoding.GetEncoding("ISO-8859-8").GetBytes(str);
//return Encoding.UTF8.GetString(tempBytes);
}
} }
} }