Code cleanup
This commit is contained in:
parent
0c27cf02c8
commit
210958db35
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,4 +2,5 @@ bin/
|
||||||
obj/
|
obj/
|
||||||
/packages/
|
/packages/
|
||||||
riderModule.iml
|
riderModule.iml
|
||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -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;
|
var s1 = x;
|
||||||
}
|
var s2 = y;
|
||||||
|
if (s1 == null || s2 == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (type == ChunkType.Alphanumeric && char.IsDigit(ch)
|
var thisMarker = 0;
|
||||||
|| type == ChunkType.Numeric && !char.IsDigit(ch))
|
var thatMarker = 0;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
while (thisMarker < s1.Length || thatMarker < s2.Length) {
|
||||||
}
|
if (thisMarker >= s1.Length)
|
||||||
|
return -1;
|
||||||
|
if (thatMarker >= s2.Length)
|
||||||
|
return 1;
|
||||||
|
|
||||||
public int Compare(string x, string y)
|
var thisCh = s1[thisMarker];
|
||||||
{
|
var thatCh = s2[thatMarker];
|
||||||
var s1 = x;
|
|
||||||
var s2 = y;
|
|
||||||
if (s1 == null || s2 == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var thisMarker = 0;
|
var thisChunk = new StringBuilder();
|
||||||
var thatMarker = 0;
|
var thatChunk = new StringBuilder();
|
||||||
|
|
||||||
while (thisMarker < s1.Length || thatMarker < s2.Length)
|
while (thisMarker < s1.Length && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0]))) {
|
||||||
{
|
thisChunk.Append(thisCh);
|
||||||
if (thisMarker >= s1.Length)
|
thisMarker++;
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (thatMarker >= s2.Length)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
var thisCh = s1[thisMarker];
|
|
||||||
var thatCh = s2[thatMarker];
|
|
||||||
|
|
||||||
var thisChunk = new StringBuilder();
|
if (thisMarker < s1.Length)
|
||||||
var thatChunk = new StringBuilder();
|
thisCh = s1[thisMarker];
|
||||||
|
}
|
||||||
|
|
||||||
while (thisMarker < s1.Length && (thisChunk.Length==0 ||InChunk(thisCh, thisChunk[0])))
|
while (thatMarker < s2.Length && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0]))) {
|
||||||
{
|
thatChunk.Append(thatCh);
|
||||||
thisChunk.Append(thisCh);
|
thatMarker++;
|
||||||
thisMarker++;
|
|
||||||
|
|
||||||
if (thisMarker < s1.Length)
|
if (thatMarker < s2.Length)
|
||||||
{
|
thatCh = s2[thatMarker];
|
||||||
thisCh = s1[thisMarker];
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (thatMarker < s2.Length && (thatChunk.Length==0 ||InChunk(thatCh, thatChunk[0])))
|
var result = 0;
|
||||||
{
|
// If both chunks contain numeric characters, sort them numerically
|
||||||
thatChunk.Append(thatCh);
|
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) {
|
||||||
thatMarker++;
|
var thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
|
||||||
|
var thatNumericChunk = Convert.ToInt32(thatChunk.ToString());
|
||||||
|
|
||||||
if (thatMarker < s2.Length)
|
if (thisNumericChunk < thatNumericChunk)
|
||||||
{
|
result = -1;
|
||||||
thatCh = s2[thatMarker];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = 0;
|
if (thisNumericChunk > thatNumericChunk)
|
||||||
// If both chunks contain numeric characters, sort them numerically
|
result = 1;
|
||||||
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
|
}
|
||||||
{
|
else {
|
||||||
var thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
|
result = string.Compare(thisChunk.ToString(), thatChunk.ToString(), StringComparison.Ordinal);
|
||||||
var thatNumericChunk = Convert.ToInt32(thatChunk.ToString());
|
}
|
||||||
|
|
||||||
if (thisNumericChunk < thatNumericChunk)
|
if (result != 0)
|
||||||
{
|
return result;
|
||||||
result = -1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (thisNumericChunk > thatNumericChunk)
|
return 0;
|
||||||
{
|
}
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = string.Compare(thisChunk.ToString(), thatChunk.ToString(), StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
private static bool InChunk(char ch, char otherCh) {
|
||||||
{
|
var type = ChunkType.Alphanumeric;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -2,130 +2,121 @@
|
||||||
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 {
|
|
||||||
private static void Main(string[] args) {
|
internal static class AutoTag {
|
||||||
if (args.Length != 3 || args[0] != "albums" && args[0] != "playlists") {
|
private static void Main(string[] args) {
|
||||||
Console.WriteLine("Usage: autotag <albums/playlists> <inputfolder> <outputfolder>");
|
if (args.Length != 3 || args[0] != "albums" && args[0] != "playlists") {
|
||||||
Environment.Exit(1);
|
Console.WriteLine("Usage: autotag <albums/playlists> <inputfolder> <outputfolder>");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = args[0] == "albums" ? FolderType.Albums : FolderType.Playlists;
|
||||||
|
var inputDir = new Folder(args[1], type);
|
||||||
|
var outputDir = args[2];
|
||||||
|
|
||||||
|
switch (inputDir.Type) {
|
||||||
|
case FolderType.Albums: {
|
||||||
|
foreach (var track in Directory.EnumerateFiles(inputDir.Path, "*.*", SearchOption.AllDirectories).Where(IsAllowed)) {
|
||||||
|
Console.WriteLine("<- " + track);
|
||||||
|
|
||||||
|
var tagFile = TagFile.Create(track);
|
||||||
|
if (tagFile.Tag.AlbumArtists.Length == 0)
|
||||||
|
tagFile.Tag.AlbumArtists = new[] { tagFile.Tag.Performers[0] };
|
||||||
|
var outputFileDirectory = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album));
|
||||||
|
Directory.CreateDirectory(outputFileDirectory);
|
||||||
|
var outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album),
|
||||||
|
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)}"));
|
||||||
|
|
||||||
|
tagFile.Save();
|
||||||
|
File.Copy(track, outputFilePath, true);
|
||||||
|
|
||||||
|
var newTagFile = TagFile.Create(outputFilePath);
|
||||||
|
newTagFile.Tag.Comment = null;
|
||||||
|
newTagFile.Tag.Genres = null;
|
||||||
|
newTagFile.Save();
|
||||||
|
|
||||||
|
Console.WriteLine("-> " + outputFilePath);
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case FolderType.Playlists: {
|
||||||
|
foreach (var playlist in Directory.GetDirectories(inputDir.Path)) {
|
||||||
|
var tracks = Directory.EnumerateFiles(playlist, "*.*", SearchOption.AllDirectories).Where(IsAllowed).OrderBy(s => s, new AlphanumComparator());
|
||||||
|
|
||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
uint i = 1;
|
||||||
|
var trackCount = tracks.Count();
|
||||||
|
var playlistName = Path.GetFileName(playlist);
|
||||||
|
|
||||||
var type = args[0] == "albums" ? FolderType.Albums : FolderType.Playlists;
|
foreach (var track in tracks) {
|
||||||
|
|
||||||
var inputDir = new Folder(args[1], type);
|
|
||||||
var outputDir = args[2];
|
|
||||||
|
|
||||||
switch (inputDir.Type) {
|
|
||||||
case FolderType.Albums: {
|
|
||||||
foreach (var track in Directory.EnumerateFiles(inputDir.Path, "*.*", SearchOption.AllDirectories)
|
|
||||||
.Where(IsAllowed)) {
|
|
||||||
Console.WriteLine("<- " + track);
|
Console.WriteLine("<- " + track);
|
||||||
var tagFile = TagFile.Create(track);
|
var tagFile = TagFile.Create(track);
|
||||||
if (tagFile.Tag.AlbumArtists.Length == 0)
|
var outputFileDirectory = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName));
|
||||||
tagFile.Tag.AlbumArtists = new[] {tagFile.Tag.Performers[0]};
|
|
||||||
var outputFileDirectory = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]),
|
|
||||||
CleanFileName(tagFile.Tag.Album));
|
|
||||||
Directory.CreateDirectory(outputFileDirectory);
|
Directory.CreateDirectory(outputFileDirectory);
|
||||||
var outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]),
|
|
||||||
CleanFileName(tagFile.Tag.Album),
|
|
||||||
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)}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var outputFilePath = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName),
|
||||||
|
CleanFileName(tagFile.Tag.Performers.Length == 0
|
||||||
|
? $"{i}. {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.Track = i++;
|
||||||
|
newTagFile.Tag.TrackCount = (uint)trackCount;
|
||||||
|
newTagFile.Tag.AlbumArtists = new[] { "Various Artists" };
|
||||||
|
|
||||||
|
if (newTagFile.Tag.Performers.Length == 0)
|
||||||
|
newTagFile.Tag.Performers = new[] { "Various Artists" };
|
||||||
|
|
||||||
newTagFile.Save();
|
newTagFile.Save();
|
||||||
|
|
||||||
Console.WriteLine("-> " + outputFilePath);
|
Console.WriteLine("-> " + outputFilePath);
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case FolderType.Playlists: {
|
|
||||||
foreach (var playlist in Directory.GetDirectories(inputDir.Path)) {
|
|
||||||
var tracks = Directory.EnumerateFiles(playlist, "*.*", SearchOption.AllDirectories)
|
|
||||||
.Where(IsAllowed)
|
|
||||||
.OrderBy(s => s, new AlphanumComparator());
|
|
||||||
|
|
||||||
uint i = 1;
|
break;
|
||||||
var trackCount = tracks.Count();
|
|
||||||
var playlistName = Path.GetFileName(playlist);
|
|
||||||
|
|
||||||
foreach (var track in tracks) {
|
|
||||||
Console.WriteLine("<- " + track);
|
|
||||||
var tagFile = TagFile.Create(track);
|
|
||||||
var outputFileDirectory =
|
|
||||||
Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName));
|
|
||||||
Directory.CreateDirectory(outputFileDirectory);
|
|
||||||
|
|
||||||
var outputFilePath = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName),
|
|
||||||
CleanFileName(tagFile.Tag.Performers.Length == 0
|
|
||||||
? $"{i}. {tagFile.Tag.Title}{Path.GetExtension(track)}"
|
|
||||||
: $"{i}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}"));
|
|
||||||
File.Copy(track, outputFilePath, true);
|
|
||||||
var newTagFile = TagFile.Create(outputFilePath);
|
|
||||||
newTagFile.Tag.Comment = null;
|
|
||||||
newTagFile.Tag.Genres = null;
|
|
||||||
newTagFile.Tag.Album = playlistName;
|
|
||||||
newTagFile.Tag.Track = i++;
|
|
||||||
newTagFile.Tag.TrackCount = (uint) trackCount;
|
|
||||||
newTagFile.Tag.AlbumArtists = new[] {"Various Artists"};
|
|
||||||
|
|
||||||
if (newTagFile.Tag.Performers.Length == 0)
|
|
||||||
newTagFile.Tag.Performers = new[] {"Various Artists"};
|
|
||||||
|
|
||||||
newTagFile.Save();
|
|
||||||
Console.WriteLine("-> " + outputFilePath);
|
|
||||||
Console.WriteLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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;
|
||||||
|
|
||||||
public Folder(string path, FolderType type) {
|
public Folder(string path, FolderType type) {
|
||||||
Path = path;
|
Path = path;
|
||||||
Type = type;
|
Type = type;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal enum FolderType {
|
internal enum FolderType {
|
||||||
Albums,
|
Albums,
|
||||||
Playlists
|
Playlists
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Helpers {
|
||||||
|
private static readonly List<string> AllowedFileTypes = new() { ".flac", ".opus", ".mp3", ".m4a" };
|
||||||
|
|
||||||
|
internal static bool IsAllowed(string filename) => AllowedFileTypes.Any(filename.EndsWith);
|
||||||
|
|
||||||
|
internal static string CleanFileName(string fileName) {
|
||||||
|
return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty)).Replace(":", " -").Replace("\\", " ");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
internal static class Helpers {
|
|
||||||
private static readonly List<string> AllowedFileTypes = new List<string> {".flac", ".opus", ".mp3", ".m4a"};
|
|
||||||
|
|
||||||
internal static bool IsAllowed(string filename) => AllowedFileTypes.Any(filename.EndsWith);
|
|
||||||
|
|
||||||
internal static string CleanFileName(string fileName) {
|
|
||||||
return Path.GetInvalidFileNameChars()
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue