mirror of
https://github.com/sphildreth/roadie
synced 2024-11-22 12:13:10 +00:00
Scan work
This commit is contained in:
parent
e03f01ecb1
commit
304c808acd
16 changed files with 548 additions and 143 deletions
370
Roadie.Library.Tests/ID3TagsHelperTests.cs
Normal file
370
Roadie.Library.Tests/ID3TagsHelperTests.cs
Normal file
|
@ -0,0 +1,370 @@
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Roadie.Library.Caching;
|
||||||
|
using Roadie.Library.Configuration;
|
||||||
|
using Roadie.Library.MetaData.ID3Tags;
|
||||||
|
using Roadie.Library.Processors;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Tests
|
||||||
|
{
|
||||||
|
public class ID3TagsHelperTests
|
||||||
|
{
|
||||||
|
private IEventMessageLogger MessageLogger { get; }
|
||||||
|
private ILogger Logger
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.MessageLogger as ILogger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ID3TagsHelper TagsHelper { get; }
|
||||||
|
|
||||||
|
private IRoadieSettings Configuration { get; }
|
||||||
|
public DictionaryCacheManager CacheManager { get; }
|
||||||
|
|
||||||
|
public ID3TagsHelperTests()
|
||||||
|
{
|
||||||
|
this.MessageLogger = new EventMessageLogger();
|
||||||
|
this.MessageLogger.Messages += MessageLogger_Messages;
|
||||||
|
|
||||||
|
var settings = new RoadieSettings();
|
||||||
|
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
|
||||||
|
configurationBuilder.AddJsonFile("appsettings.test.json");
|
||||||
|
IConfiguration configuration = configurationBuilder.Build();
|
||||||
|
configuration.GetSection("RoadieSettings").Bind(settings);
|
||||||
|
settings.ConnectionString = configuration.GetConnectionString("RoadieDatabaseConnection");
|
||||||
|
this.Configuration = settings;
|
||||||
|
this.CacheManager = new DictionaryCacheManager(this.Logger, new CachePolicy(TimeSpan.FromHours(4)));
|
||||||
|
this.TagsHelper = new ID3TagsHelper(this.Configuration, this.CacheManager, this.Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MessageLogger_Messages(object sender, EventMessage e)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Log Level [{ e.Level }] Log Message [{ e.Message }] ");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileWithTrackArtists()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"E:\Roadie_Test_Files\13-anna_kendrick-true_colors-a57e270d\01-justin_timberlake-hair_up-ef53c026.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.TrackArtist);
|
||||||
|
Assert.NotEqual(metaData.Artist, metaData.TrackArtist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(@"N:\Rita Ora - Phoenix (Deluxe) (2018) Mp3 (320kbps) [Hunter]\Rita Ora - Phoenix (Deluxe) (2018)")]
|
||||||
|
[InlineData(@"N:\Travis Scott - ASTROWORLD (2018) Mp3 (320kbps) [Hunter]")]
|
||||||
|
[InlineData(@"N:\Lil Wayne - Tha Carter V (2018) Mp3 (320kbps) [Hunter]")]
|
||||||
|
[InlineData(@"N:\Beyonce & JAY-Z - EVERYTHING IS LOVE (2018) Mp3 (320kbps) [Hunter]")]
|
||||||
|
public void ReadFolderTestAllFiles(string folderName)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(folderName))
|
||||||
|
{
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var folderFiles = Directory.GetFiles(folderName, "*.mp3", SearchOption.AllDirectories);
|
||||||
|
foreach(var file in folderFiles)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileSoundtrackInTitleNotSoundtrack()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"E:\Roadie_Test_Files\01 01 Angel Of Death.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.False(metaData.IsSoundTrack);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileIsSoundtrack()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"E:\Roadie_Test_Files\06 You'Re Sensational.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.IsSoundTrack);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileWithAlbumNoTrackSet()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\inbound\MEGAPACK ---METAL-DEATH-BLACK---\ebony_tears-evil_as_hell-2001-ss\01-deviation-ss.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.TrackArtist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Read_File_Test_Is_valid()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\unknown\2eec19bd-3575-4b7f-84dd-db2a0ec3e2f3~[2009] Dolly - Disc 1 Of 4~06 Nobody But You (Previously Unissued).mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.Null(metaData.TrackArtist);
|
||||||
|
Assert.False(metaData.TrackArtists.Any());
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Read_File_Test_Is_valid2()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\library_old\Perverse\[2014] Champion Dub\01 Champion Dub (Original Mix).mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.Null(metaData.TrackArtist);
|
||||||
|
Assert.False(metaData.TrackArtists.Any());
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileWithTrackAndArtistTheSame()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\library\Blind Melon\[1992] Blind Melon\01. Blind Melon - Soak The Sin.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.Null(metaData.TrackArtist);
|
||||||
|
Assert.False(metaData.TrackArtists.Any());
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFileWithArtistAndTrackArtist()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"E:\Roadie_Test_Files\Test.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.TrackArtist);
|
||||||
|
Assert.Equal("Da Album Artist", metaData.Artist);
|
||||||
|
Assert.Equal("Da Artist", metaData.TrackArtist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.NotNull(metaData.Genres);
|
||||||
|
Assert.NotNull(metaData.Genres.First());
|
||||||
|
Assert.Equal(2011, metaData.Year);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.Equal(6, metaData.TrackNumber.Value);
|
||||||
|
Assert.Equal(64, metaData.TotalTrackNumbers);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFile2()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\library\Denver, John\[1972] Aerie\10 Readjustment Blues.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.Equal(metaData.TrackNumber.Value, 10);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFile3()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"E:\Roadie_Test_Files\01. What's Yesterday.mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.Equal(1, metaData.TrackNumber.Value);
|
||||||
|
Assert.Equal(10, metaData.TotalTrackNumbers.Value);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadID3TagsFromFile4()
|
||||||
|
{
|
||||||
|
var file = new FileInfo(@"Z:\library\Ac Dc\[1975] T.N.T\01 It'S A Long Way To The Top (If You Wanna Rock 'N' Roll).mp3");
|
||||||
|
if (file.Exists)
|
||||||
|
{
|
||||||
|
var tagLib = this.TagsHelper.MetaDataForFile(file.FullName);
|
||||||
|
Assert.True(tagLib.IsSuccess);
|
||||||
|
var metaData = tagLib.Data;
|
||||||
|
Assert.NotNull(metaData.Artist);
|
||||||
|
Assert.NotNull(metaData.Release);
|
||||||
|
Assert.NotNull(metaData.Title);
|
||||||
|
Assert.True(metaData.Year > 0);
|
||||||
|
Assert.NotNull(metaData.TrackNumber);
|
||||||
|
Assert.Equal(metaData.TrackNumber.Value, 10);
|
||||||
|
Assert.True(metaData.TotalSeconds > 0);
|
||||||
|
Assert.True(metaData.ValidWeight > 30);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"skipping { file}");
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,38 +3,28 @@
|
||||||
"SiteName": "Roadie",
|
"SiteName": "Roadie",
|
||||||
"DefaultTimeZone": "US/Central",
|
"DefaultTimeZone": "US/Central",
|
||||||
"DiagnosticsPassword": "RoadieDiagPassword",
|
"DiagnosticsPassword": "RoadieDiagPassword",
|
||||||
"InboundFolder": "Z:/incoming/",
|
"InboundFolder": "C:\\roadie_dev_root\\inbound",
|
||||||
"LibraryFolder": "Z:/library/",
|
"LibraryFolder": "C:\\\\roadie_dev_root\\\\library",
|
||||||
"ThumbnailImageSize": {
|
"Thumbnails": {
|
||||||
"Height": 80,
|
"Height": 80,
|
||||||
"Width": 80
|
"Width": 80
|
||||||
},
|
},
|
||||||
"SmallImageSize": {
|
"MediumThumbnails": {
|
||||||
"Height": 160,
|
"Height": 160,
|
||||||
"Width": 160
|
"Width": 160
|
||||||
},
|
},
|
||||||
"MediumImageSize": {
|
"LargeThumbnails": {
|
||||||
"Height": 320,
|
"Height": 320,
|
||||||
"Width": 320
|
"Width": 320
|
||||||
},
|
},
|
||||||
"LargeImageSize": {
|
|
||||||
"Height": 500,
|
|
||||||
"Width": 500
|
|
||||||
},
|
|
||||||
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
|
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
|
||||||
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
|
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
|
||||||
"RecordNoResultSearches": true,
|
"RecordNoResultSearches": true,
|
||||||
"SingleArtistHoldingFolder": "Z:/single_holding/",
|
"SingleArtistHoldingFolder": "C:\\roadie_dev_root\\single_holding",
|
||||||
"ArtistNameReplace": {
|
"ArtistNameReplace": {
|
||||||
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],
|
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],
|
||||||
"Love/Hate": [ "Love; Hate", "Love;Hate", "Love/ Hate", "Love Hate" ]
|
"Love/Hate": [ "Love; Hate", "Love;Hate", "Love/ Hate", "Love Hate" ]
|
||||||
},
|
},
|
||||||
"Converting": {
|
|
||||||
"DoDeleteAfter": true,
|
|
||||||
"M4AConvertCommand": "ffmpeg -i \"{0}\" -acodec libmp3lame -q:a 0 \"{1}\"",
|
|
||||||
"OGGConvertCommand": "ffmpeg -i \"{0}\" -acodec libmp3lame -q:a 0 \"{1}\"\"",
|
|
||||||
"APEConvertCommand": "ffmpeg -i \"{0}\" \"{1}\""
|
|
||||||
},
|
|
||||||
"Integrations": {
|
"Integrations": {
|
||||||
"ITunesProviderEnabled": true,
|
"ITunesProviderEnabled": true,
|
||||||
"MusicBrainzProviderEnabled": true,
|
"MusicBrainzProviderEnabled": true,
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Roadie.Api.Controllers
|
||||||
[Authorize("Admin")]
|
[Authorize("Admin")]
|
||||||
public async Task<IActionResult> Scan()
|
public async Task<IActionResult> Scan()
|
||||||
{
|
{
|
||||||
var result = await this.AdminService.ScanInboundFolder(await this.UserManager.GetUserAsync(User));
|
var result = await this.AdminService.ScanInboundFolder(await this.UserManager.GetUserAsync(User), true);
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
{
|
{
|
||||||
return StatusCode((int)HttpStatusCode.InternalServerError);
|
return StatusCode((int)HttpStatusCode.InternalServerError);
|
||||||
|
|
|
@ -31,6 +31,16 @@ namespace Roadie.Api.Services
|
||||||
{
|
{
|
||||||
public class AdminService : ServiceBase, IAdminService
|
public class AdminService : ServiceBase, IAdminService
|
||||||
{
|
{
|
||||||
|
private IEventMessageLogger EventMessageLogger { get; }
|
||||||
|
|
||||||
|
private ILogger MessageLogger
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.EventMessageLogger as ILogger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected IHubContext<ScanActivityHub> ScanActivityHub { get; }
|
protected IHubContext<ScanActivityHub> ScanActivityHub { get; }
|
||||||
|
|
||||||
public AdminService(IRoadieSettings configuration,
|
public AdminService(IRoadieSettings configuration,
|
||||||
|
@ -44,6 +54,13 @@ namespace Roadie.Api.Services
|
||||||
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
||||||
{
|
{
|
||||||
this.ScanActivityHub = scanActivityHub;
|
this.ScanActivityHub = scanActivityHub;
|
||||||
|
this.EventMessageLogger = new EventMessageLogger();
|
||||||
|
this.EventMessageLogger.Messages += EventMessageLogger_Messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EventMessageLogger_Messages(object sender, EventMessage e)
|
||||||
|
{
|
||||||
|
Task.WaitAll(this.LogAndPublish(e.Message, e.Level));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false)
|
public async Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false)
|
||||||
|
@ -58,7 +75,7 @@ namespace Roadie.Api.Services
|
||||||
await this.LogAndPublish($"** Processing Folder: [{d.FullName}]");
|
await this.LogAndPublish($"** Processing Folder: [{d.FullName}]");
|
||||||
|
|
||||||
long processedFolders = 0;
|
long processedFolders = 0;
|
||||||
var folderProcessor = new FolderProcessor(this.Configuration, this.HttpEncoder, this.Configuration.LibraryFolder, this.DbContext, this.CacheManager, this.Logger);
|
var folderProcessor = new FolderProcessor(this.Configuration, this.HttpEncoder, this.Configuration.LibraryFolder, this.DbContext, this.CacheManager, this.MessageLogger);
|
||||||
foreach (var folder in Directory.EnumerateDirectories(d.FullName).ToArray())
|
foreach (var folder in Directory.EnumerateDirectories(d.FullName).ToArray())
|
||||||
{
|
{
|
||||||
await folderProcessor.Process(new DirectoryInfo(folder), isReadOnly);
|
await folderProcessor.Process(new DirectoryInfo(folder), isReadOnly);
|
||||||
|
@ -78,6 +95,8 @@ namespace Roadie.Api.Services
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private async Task LogAndPublish(string message, LogLevel level = LogLevel.Trace)
|
private async Task LogAndPublish(string message, LogLevel level = LogLevel.Trace)
|
||||||
{
|
{
|
||||||
switch (level)
|
switch (level)
|
||||||
|
|
14
RoadieLibrary/EventMessage.cs
Normal file
14
RoadieLibrary/EventMessage.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Roadie.Library
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class EventMessage
|
||||||
|
{
|
||||||
|
public Microsoft.Extensions.Logging.LogLevel Level { get; set; } = Microsoft.Extensions.Logging.LogLevel.Trace;
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,5 +15,14 @@ namespace Roadie.Library.Extensions
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TimeSpan? ToTimeSpan(this decimal? value)
|
||||||
|
{
|
||||||
|
if(!value.HasValue)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return TimeSpan.FromSeconds((double)value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1042,7 +1042,7 @@ namespace Roadie.Library.Factories
|
||||||
getParams.Add(new MySqlParameter("@sinAlt", string.Format("%|{0}|%", specialSearchName)));
|
getParams.Add(new MySqlParameter("@sinAlt", string.Format("%|{0}|%", specialSearchName)));
|
||||||
getParams.Add(new MySqlParameter("@sendAlt", string.Format("%|{0}", specialSearchName)));
|
getParams.Add(new MySqlParameter("@sendAlt", string.Format("%|{0}", specialSearchName)));
|
||||||
return this.DbContext.Artists.FromSql(@"SELECT *
|
return this.DbContext.Artists.FromSql(@"SELECT *
|
||||||
FROM `Artist`
|
FROM `artist`
|
||||||
WHERE LCASE(name) = @isName
|
WHERE LCASE(name) = @isName
|
||||||
OR LCASE(sortName) = @isName
|
OR LCASE(sortName) = @isName
|
||||||
OR LCASE(sortName) = @isSortName
|
OR LCASE(sortName) = @isSortName
|
||||||
|
@ -1053,7 +1053,7 @@ namespace Roadie.Library.Factories
|
||||||
OR alternatenames like @sinAlt
|
OR alternatenames like @sinAlt
|
||||||
OR (alternatenames like @endAlt
|
OR (alternatenames like @endAlt
|
||||||
OR alternatenames like @sendAlt)
|
OR alternatenames like @sendAlt)
|
||||||
LIMIT 1;", getParams.ToArray()).FirstOrDefault();
|
LIMIT 1", getParams.ToArray()).FirstOrDefault();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
34
RoadieLibrary/Processors/EventMessageLogger.cs
Normal file
34
RoadieLibrary/Processors/EventMessageLogger.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Processors
|
||||||
|
{
|
||||||
|
public class EventMessageLogger : ILogger, IEventMessageLogger
|
||||||
|
{
|
||||||
|
public event EventHandler<EventMessage> Messages;
|
||||||
|
|
||||||
|
public IDisposable BeginScope<TState>(TState state)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
|
{
|
||||||
|
Messages?.Invoke(this, new EventMessage { Level = logLevel, Message = formatter(state, exception) });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEventMessage(EventMessage message)
|
||||||
|
{
|
||||||
|
Messages?.Invoke(this, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,13 +36,14 @@ namespace Roadie.Library.Processors
|
||||||
{
|
{
|
||||||
if (t.GetInterface("IFilePlugin") != null && !t.IsAbstract && !t.IsInterface)
|
if (t.GetInterface("IFilePlugin") != null && !t.IsAbstract && !t.IsInterface)
|
||||||
{
|
{
|
||||||
IFilePlugin plugin = Activator.CreateInstance(t, new object[] { this.ArtistFactory, this.ReleaseFactory, this.ImageFactory, this.CacheManager, this.Logger }) as IFilePlugin;
|
IFilePlugin plugin = Activator.CreateInstance(t, new object[] { this.Configuration, this.HttpEncoder, this.ArtistFactory, this.ReleaseFactory, this.ImageFactory, this.CacheManager, this.Logger }) as IFilePlugin;
|
||||||
plugins.Add(plugin);
|
plugins.Add(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
this.Logger.LogError(ex);
|
||||||
}
|
}
|
||||||
this._plugins = plugins.ToArray();
|
this._plugins = plugins.ToArray();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,16 +49,18 @@ namespace Roadie.Library.Processors
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OperationResult<bool>> Process(DirectoryInfo inboundFolder, bool doJustInfo, int? submissionId = null)
|
public async Task<OperationResult<bool>> Process(DirectoryInfo folder, bool doJustInfo, int? submissionId = null)
|
||||||
{
|
{
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
this.PrePrecessFolder(inboundFolder, doJustInfo);
|
await this.PreProcessFolder(folder, doJustInfo);
|
||||||
int processedFiles = 0;
|
int processedFiles = 0;
|
||||||
var pluginResultInfos = new List<PluginResultInfo>();
|
var pluginResultInfos = new List<PluginResultInfo>();
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
|
|
||||||
this.FileProcessor.SubmissionId = submissionId;
|
this.FileProcessor.SubmissionId = submissionId;
|
||||||
foreach (var file in Directory.EnumerateFiles(inboundFolder.FullName, "*.*", SearchOption.AllDirectories).ToArray())
|
|
||||||
|
foreach (var file in Directory.EnumerateFiles(folder.FullName, "*.*", SearchOption.AllDirectories).ToArray())
|
||||||
{
|
{
|
||||||
var operation = await this.FileProcessor.Process(file, doJustInfo);
|
var operation = await this.FileProcessor.Process(file, doJustInfo);
|
||||||
if (operation != null && operation.AdditionalData != null && operation.AdditionalData.ContainsKey(PluginResultInfo.AdditionalDataKeyPluginResultInfo))
|
if (operation != null && operation.AdditionalData != null && operation.AdditionalData.ContainsKey(PluginResultInfo.AdditionalDataKeyPluginResultInfo))
|
||||||
|
@ -67,7 +69,7 @@ namespace Roadie.Library.Processors
|
||||||
}
|
}
|
||||||
if (operation == null)
|
if (operation == null)
|
||||||
{
|
{
|
||||||
var fileExtensionsToDelete = this.Configuration.FileExtensionsToDelete;
|
var fileExtensionsToDelete = this.Configuration.FileExtensionsToDelete ?? new string[0];
|
||||||
if (fileExtensionsToDelete.Any(x => x.Equals(Path.GetExtension(file), StringComparison.OrdinalIgnoreCase)))
|
if (fileExtensionsToDelete.Any(x => x.Equals(Path.GetExtension(file), StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
if (!doJustInfo)
|
if (!doJustInfo)
|
||||||
|
@ -86,9 +88,9 @@ namespace Roadie.Library.Processors
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.PostProcessFolder(inboundFolder, pluginResultInfos, doJustInfo);
|
await this.PostProcessFolder(folder, pluginResultInfos, doJustInfo);
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
this.Logger.LogInformation("** Completed! Processed Folder [{0}]: Processed Files [{1}] : Elapsed Time [{2}]", inboundFolder.FullName.ToString(), processedFiles, sw.Elapsed);
|
this.Logger.LogInformation("** Completed! Processed Folder [{0}]: Processed Files [{1}] : Elapsed Time [{2}]", folder.FullName.ToString(), processedFiles, sw.Elapsed);
|
||||||
return new OperationResult<bool>
|
return new OperationResult<bool>
|
||||||
{
|
{
|
||||||
IsSuccess = !errors.Any(),
|
IsSuccess = !errors.Any(),
|
||||||
|
@ -98,7 +100,6 @@ namespace Roadie.Library.Processors
|
||||||
{ "newReleases", this.ReleaseFactory.AddedReleaseIds.Count() },
|
{ "newReleases", this.ReleaseFactory.AddedReleaseIds.Count() },
|
||||||
{ "newTracks", this.ReleaseFactory.AddedTrackIds.Count() }
|
{ "newTracks", this.ReleaseFactory.AddedTrackIds.Count() }
|
||||||
},
|
},
|
||||||
|
|
||||||
OperationTime = sw.ElapsedMilliseconds
|
OperationTime = sw.ElapsedMilliseconds
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -131,29 +132,8 @@ namespace Roadie.Library.Processors
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform any operations to the given folder before processing
|
/// Perform any operations to the given folder before processing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool PrePrecessFolder(DirectoryInfo inboundFolder, bool doJustInfo = false)
|
private async Task<bool> PreProcessFolder(DirectoryInfo inboundFolder, bool doJustInfo = false)
|
||||||
{
|
{
|
||||||
// If Folder name starts with "~" then remove the tilde and set all files in the folder artist to the folder name
|
|
||||||
if (this.Configuration.Processing.DoFolderArtistNameSet && inboundFolder.Name.StartsWith("~"))
|
|
||||||
{
|
|
||||||
var artist = inboundFolder.Name.Replace("~", "");
|
|
||||||
this.Logger.LogInformation("Setting Folder File Tags To [{0}]", artist);
|
|
||||||
if (!doJustInfo)
|
|
||||||
{
|
|
||||||
foreach (var file in inboundFolder.GetFiles("*.*", SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
var extension = file.Extension.ToLower();
|
|
||||||
if (extension.Equals(".mp3") || extension.Equals(".flac"))
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
//var tagFile = TagLib.File.Create(file.FullName);
|
|
||||||
//tagFile.Tag.Performers = null;
|
|
||||||
//tagFile.Tag.Performers = new[] { artist };
|
|
||||||
//tagFile.Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
RoadieLibrary/Processors/IEventMessageLogger.cs
Normal file
14
RoadieLibrary/Processors/IEventMessageLogger.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Roadie.Library.Processors
|
||||||
|
{
|
||||||
|
public interface IEventMessageLogger
|
||||||
|
{
|
||||||
|
event EventHandler<EventMessage> Messages;
|
||||||
|
|
||||||
|
IDisposable BeginScope<TState>(TState state);
|
||||||
|
bool IsEnabled(LogLevel logLevel);
|
||||||
|
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,8 @@
|
||||||
<PackageReference Include="CsvHelper" Version="12.0.1" />
|
<PackageReference Include="CsvHelper" Version="12.0.1" />
|
||||||
<PackageReference Include="FluentFTP" Version="19.2.2" />
|
<PackageReference Include="FluentFTP" Version="19.2.2" />
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.8.10" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.8.10" />
|
||||||
<PackageReference Include="ID3" Version="0.5.0-beta.1" />
|
<PackageReference Include="IdSharp.Common" Version="1.0.1" />
|
||||||
<PackageReference Include="ID3Tag.Core" Version="0.1.3" />
|
<PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" />
|
||||||
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
|
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
|
||||||
<PackageReference Include="Mapster" Version="3.2.0" />
|
<PackageReference Include="Mapster" Version="3.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.6" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.6" />
|
||||||
|
@ -30,8 +30,13 @@
|
||||||
<Folder Include="Factories\" />
|
<Folder Include="Factories\" />
|
||||||
<Folder Include="FilePlugins\" />
|
<Folder Include="FilePlugins\" />
|
||||||
<Folder Include="Models\Subsonic\" />
|
<Folder Include="Models\Subsonic\" />
|
||||||
<Folder Include="Processors\" />
|
|
||||||
<Folder Include="SearchEngines\MetaData\Audio\" />
|
<Folder Include="SearchEngines\MetaData\Audio\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="IdSharp.AudioInfo-core">
|
||||||
|
<HintPath>..\libraries\IdSharp.AudioInfo-core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -9,6 +9,11 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using IdSharp.AudioInfo;
|
||||||
|
using IdSharp.Common.Utils;
|
||||||
|
using IdSharp.Tagging.ID3v1;
|
||||||
|
using IdSharp.Tagging.ID3v2;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Roadie.Library.MetaData.ID3Tags
|
namespace Roadie.Library.MetaData.ID3Tags
|
||||||
{
|
{
|
||||||
|
@ -21,12 +26,7 @@ namespace Roadie.Library.MetaData.ID3Tags
|
||||||
|
|
||||||
public OperationResult<AudioMetaData> MetaDataForFile(string fileName)
|
public OperationResult<AudioMetaData> MetaDataForFile(string fileName)
|
||||||
{
|
{
|
||||||
var result = this.MetaDataForFileFromTagLib(fileName);
|
var result = this.MetaDataForFileFromIdSharp(fileName);
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = this.MetaDataForFileFromNTagLite(fileName);
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
@ -39,19 +39,11 @@ namespace Roadie.Library.MetaData.ID3Tags
|
||||||
var result = new List<AudioMetaData>();
|
var result = new List<AudioMetaData>();
|
||||||
foreach (var fileName in fileNames)
|
foreach (var fileName in fileNames)
|
||||||
{
|
{
|
||||||
var r = this.MetaDataForFileFromTagLib(fileName);
|
var r = this.MetaDataForFileFromIdSharp(fileName);
|
||||||
if (r.IsSuccess)
|
if (r.IsSuccess)
|
||||||
{
|
{
|
||||||
result.Add(r.Data);
|
result.Add(r.Data);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
r = this.MetaDataForFileFromNTagLite(fileName);
|
|
||||||
if (r.IsSuccess)
|
|
||||||
{
|
|
||||||
result.Add(r.Data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new OperationResult<IEnumerable<AudioMetaData>>
|
return new OperationResult<IEnumerable<AudioMetaData>>
|
||||||
{
|
{
|
||||||
|
@ -102,7 +94,8 @@ namespace Roadie.Library.MetaData.ID3Tags
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResult<AudioMetaData> MetaDataForFileFromNTagLite(string fileName)
|
|
||||||
|
private OperationResult<AudioMetaData> MetaDataForFileFromIdSharp(string fileName)
|
||||||
{
|
{
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
|
@ -110,81 +103,57 @@ namespace Roadie.Library.MetaData.ID3Tags
|
||||||
var isSuccess = false;
|
var isSuccess = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO
|
IAudioFile audioFile = AudioFile.Create(fileName, true);
|
||||||
|
if (ID3v2Tag.DoesTagExist(fileName))
|
||||||
|
{
|
||||||
|
IID3v2Tag id3v2 = new ID3v2Tag(fileName);
|
||||||
|
result.Release = id3v2.Album;
|
||||||
|
result.Artist = id3v2.AlbumArtist ?? id3v2.Artist;
|
||||||
|
result.ArtistRaw = id3v2.AlbumArtist ?? id3v2.Artist;
|
||||||
|
result.Genres = id3v2.Genre?.Split(new char[] { ',', '\\' });
|
||||||
|
result.TrackArtist = id3v2.OriginalArtist ?? id3v2.Artist ?? id3v2.AlbumArtist;
|
||||||
|
result.TrackArtistRaw = id3v2.OriginalArtist;
|
||||||
|
result.AudioBitrate = (int?)audioFile.Bitrate;
|
||||||
|
result.AudioChannels = audioFile.Channels;
|
||||||
|
result.AudioSampleRate = (int)audioFile.Bitrate;
|
||||||
|
result.Disk = SafeParser.ToNumber<int?>(id3v2.DiscNumber);
|
||||||
|
result.Images = id3v2.PictureList?.Select(x => new AudioMetaDataImage
|
||||||
|
{
|
||||||
|
Data = x.PictureData,
|
||||||
|
Description = x.Description,
|
||||||
|
MimeType = x.MimeType,
|
||||||
|
Type = (AudioMetaDataImageType)x.PictureType
|
||||||
|
}).ToArray();
|
||||||
|
result.Time = (int)audioFile.TotalSeconds > 0 ? ((decimal?)audioFile.TotalSeconds).ToTimeSpan() : null;
|
||||||
|
result.Title = id3v2.Title.ToTitleCase(false);
|
||||||
|
|
||||||
//var file = LiteFile.LoadFromFile(fileName);
|
var trackparts = id3v2.TrackNumber?.Split('/');
|
||||||
//var tpos = file.Tag.FindFirstFrameById(FrameId.TPOS);
|
result.TrackNumber = SafeParser.ToNumber<short?>(trackparts[0]);
|
||||||
//Picture[] pics = file.Tag.FindFramesById(FrameId.APIC).Select(f => f.GetPicture()).ToArray();
|
result.TotalTrackNumbers = trackparts.Length > 1 ? SafeParser.ToNumber<short?>(trackparts[1]) : 0;
|
||||||
//result.Release = file.Tag.Album;
|
result.Year = SafeParser.ToNumber<int?>(id3v2.Year);
|
||||||
//result.Artist = file.Tag.Artist;
|
|
||||||
//result.ArtistRaw = file.Tag.Artist;
|
|
||||||
//result.Genres = (file.Tag.Genre ?? string.Empty).Split(';');
|
|
||||||
//result.TrackArtist = file.Tag.OriginalArtist;
|
|
||||||
//result.TrackArtistRaw = file.Tag.OriginalArtist;
|
|
||||||
//result.AudioBitrate = file.Bitrate;
|
|
||||||
//result.AudioChannels = file.AudioMode.HasValue ? (int?)file.AudioMode.Value : null;
|
|
||||||
//result.AudioSampleRate = file.Frequency;
|
|
||||||
//result.Disk = tpos != null ? SafeParser.ToNumber<int?>(tpos.Text) : null;
|
|
||||||
//result.Images = pics.Select(x => new AudioMetaDataImage
|
|
||||||
//{
|
|
||||||
// Data = x.Data,
|
|
||||||
// Description = x.Description,
|
|
||||||
// MimeType = x.MimeType,
|
|
||||||
// Type = (AudioMetaDataImageType)x.PictureType
|
|
||||||
//}).ToArray();
|
|
||||||
//result.Time = file.Duration;
|
|
||||||
//result.Title = file.Tag.Title.ToTitleCase(false);
|
|
||||||
//result.TotalTrackNumbers = file.Tag.TrackCount;
|
|
||||||
//result.TrackNumber = file.Tag.TrackNumber;
|
|
||||||
//result.Year = file.Tag.Year;
|
|
||||||
isSuccess = true;
|
isSuccess = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
if (!isSuccess)
|
||||||
{
|
{
|
||||||
this.Logger.LogError(ex, "MetaDataForFileFromTagLib Filename [" + fileName + "] Error [" + ex.Serialize() + "]");
|
if (ID3v1Tag.DoesTagExist(fileName))
|
||||||
|
{
|
||||||
|
IID3v1Tag id3v1 = new ID3v1Tag(fileName);
|
||||||
|
result.Release = id3v1.Album;
|
||||||
|
result.Artist = id3v1.Artist;
|
||||||
|
result.ArtistRaw = id3v1.Artist;
|
||||||
|
result.AudioBitrate = (int?)audioFile.Bitrate;
|
||||||
|
result.AudioChannels = audioFile.Channels;
|
||||||
|
result.AudioSampleRate = (int)audioFile.Bitrate;
|
||||||
|
result.Time = (int)audioFile.TotalSeconds > 0 ? ((decimal?)audioFile.TotalSeconds).ToTimeSpan() : null;
|
||||||
|
result.Title = id3v1.Title.ToTitleCase(false);
|
||||||
|
|
||||||
|
result.TrackNumber = (short?)id3v1.TrackNumber;
|
||||||
|
result.Year = SafeParser.ToNumber<int?>(id3v1.Year);
|
||||||
|
isSuccess = true;
|
||||||
}
|
}
|
||||||
sw.Stop();
|
|
||||||
return new OperationResult<AudioMetaData>
|
|
||||||
{
|
|
||||||
IsSuccess = isSuccess,
|
|
||||||
OperationTime = sw.ElapsedMilliseconds,
|
|
||||||
Data = result
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResult<AudioMetaData> MetaDataForFileFromTagLib(string fileName)
|
|
||||||
{
|
|
||||||
var sw = new Stopwatch();
|
|
||||||
sw.Start();
|
|
||||||
AudioMetaData result = new AudioMetaData();
|
|
||||||
var isSuccess = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
//var tagFile = TagLib.File.Create(fileName);
|
|
||||||
//result.Release = tagFile.Tag.Album;
|
|
||||||
//result.Artist = !string.IsNullOrEmpty(tagFile.Tag.JoinedAlbumArtists) ? tagFile.Tag.JoinedAlbumArtists : tagFile.Tag.JoinedPerformers;
|
|
||||||
//result.ArtistRaw = !string.IsNullOrEmpty(tagFile.Tag.JoinedAlbumArtists) ? tagFile.Tag.JoinedAlbumArtists : tagFile.Tag.JoinedPerformers;
|
|
||||||
//result.Genres = tagFile.Tag.Genres != null ? tagFile.Tag.Genres : new string[0];
|
|
||||||
//result.TrackArtist = tagFile.Tag.JoinedPerformers;
|
|
||||||
//result.TrackArtistRaw = tagFile.Tag.JoinedPerformers;
|
|
||||||
//result.AudioBitrate = (tagFile.Properties.AudioBitrate > 0 ? (int?)tagFile.Properties.AudioBitrate : null);
|
|
||||||
//result.AudioChannels = (tagFile.Properties.AudioChannels > 0 ? (int?)tagFile.Properties.AudioChannels : null);
|
|
||||||
//result.AudioSampleRate = (tagFile.Properties.AudioSampleRate > 0 ? (int?)tagFile.Properties.AudioSampleRate : null);
|
|
||||||
//result.Disk = (tagFile.Tag.Disc > 0 ? (int?)tagFile.Tag.Disc : null);
|
|
||||||
//result.Images = (tagFile.Tag.Pictures != null ? tagFile.Tag.Pictures.Select(x => new AudioMetaDataImage
|
|
||||||
//{
|
|
||||||
// Data = x.Data.Data,
|
|
||||||
// Description = x.Description,
|
|
||||||
// MimeType = x.MimeType,
|
|
||||||
// Type = (AudioMetaDataImageType)x.Type
|
|
||||||
//}).ToArray() : null);
|
|
||||||
//result.Time = (tagFile.Properties.Duration.TotalMinutes > 0 ? (TimeSpan?)tagFile.Properties.Duration : null);
|
|
||||||
//result.Title = tagFile.Tag.Title.ToTitleCase(false);
|
|
||||||
//result.TotalTrackNumbers = (tagFile.Tag.TrackCount > 0 ? (int?)tagFile.Tag.TrackCount : null);
|
|
||||||
//result.TrackNumber = (tagFile.Tag.Track > 0 ? (short?)tagFile.Tag.Track : null);
|
|
||||||
//result.Year = (tagFile.Tag.Year > 0 ? (int?)tagFile.Tag.Year : null);
|
|
||||||
isSuccess = true;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
BIN
libraries/IdSharp.AudioInfo-core.dll
Normal file
BIN
libraries/IdSharp.AudioInfo-core.dll
Normal file
Binary file not shown.
BIN
libraries/IdSharp.Common-core.dll
Normal file
BIN
libraries/IdSharp.Common-core.dll
Normal file
Binary file not shown.
BIN
libraries/IdSharp.Tagging-core.dll
Normal file
BIN
libraries/IdSharp.Tagging-core.dll
Normal file
Binary file not shown.
Loading…
Reference in a new issue