diff --git a/AudioCuesheetEditorTests/AudioCuesheetEditorTests.csproj b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj similarity index 97% rename from AudioCuesheetEditorTests/AudioCuesheetEditorTests.csproj rename to AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj index ce05d25f..da02ce7b 100644 --- a/AudioCuesheetEditorTests/AudioCuesheetEditorTests.csproj +++ b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj @@ -7,10 +7,10 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/AudioCuesheetEditorTests/Extensions/SessionStateContainerTests.cs b/AudioCuesheetEditor.Tests/Extensions/SessionStateContainerTests.cs similarity index 98% rename from AudioCuesheetEditorTests/Extensions/SessionStateContainerTests.cs rename to AudioCuesheetEditor.Tests/Extensions/SessionStateContainerTests.cs index 885fe83e..07641a59 100644 --- a/AudioCuesheetEditorTests/Extensions/SessionStateContainerTests.cs +++ b/AudioCuesheetEditor.Tests/Extensions/SessionStateContainerTests.cs @@ -15,7 +15,7 @@ //. using AudioCuesheetEditor.Model.AudioCuesheet; using AudioCuesheetEditor.Model.UI; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace AudioCuesheetEditor.Extensions.Tests diff --git a/AudioCuesheetEditorTests/Model/AudioCuesheet/CataloguenumberTests.cs b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/CataloguenumberTests.cs similarity index 67% rename from AudioCuesheetEditorTests/Model/AudioCuesheet/CataloguenumberTests.cs rename to AudioCuesheetEditor.Tests/Model/AudioCuesheet/CataloguenumberTests.cs index aa7a8198..4488015a 100644 --- a/AudioCuesheetEditorTests/Model/AudioCuesheet/CataloguenumberTests.cs +++ b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/CataloguenumberTests.cs @@ -13,16 +13,11 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. -using Microsoft.VisualStudio.TestTools.UnitTesting; using AudioCuesheetEditor.Model.AudioCuesheet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Model.Entity; +using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace AudioCuesheetEditor.Model.AudioCuesheet.Tests +namespace AudioCuesheetEditor.Tests.Model.AudioCuesheet { [TestClass()] public class CataloguenumberTests @@ -31,13 +26,13 @@ public class CataloguenumberTests public void CatalogueNumberTest() { var catalogueNumber = new Cataloguenumber(); - Assert.AreEqual(Entity.ValidationStatus.NoValidation, catalogueNumber.Validate().Status); + Assert.AreEqual(ValidationStatus.NoValidation, catalogueNumber.Validate().Status); catalogueNumber.Value = "Testvalue"; - Assert.AreEqual(Entity.ValidationStatus.Error, catalogueNumber.Validate().Status); + Assert.AreEqual(ValidationStatus.Error, catalogueNumber.Validate().Status); catalogueNumber.Value = "01234567891234567890"; - Assert.AreEqual(Entity.ValidationStatus.Error, catalogueNumber.Validate().Status); + Assert.AreEqual(ValidationStatus.Error, catalogueNumber.Validate().Status); catalogueNumber.Value = "1234567890123"; - Assert.AreEqual(Entity.ValidationStatus.Success, catalogueNumber.Validate().Status); + Assert.AreEqual(ValidationStatus.Success, catalogueNumber.Validate().Status); } } } \ No newline at end of file diff --git a/AudioCuesheetEditorTests/Model/AudioCuesheet/CuesheetTests.cs b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/CuesheetTests.cs similarity index 97% rename from AudioCuesheetEditorTests/Model/AudioCuesheet/CuesheetTests.cs rename to AudioCuesheetEditor.Tests/Model/AudioCuesheet/CuesheetTests.cs index 00373876..d524a6d7 100644 --- a/AudioCuesheetEditorTests/Model/AudioCuesheet/CuesheetTests.cs +++ b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/CuesheetTests.cs @@ -15,23 +15,25 @@ //. using AudioCuesheetEditor.Data.Options; using AudioCuesheetEditor.Extensions; +using AudioCuesheetEditor.Model.AudioCuesheet; using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO.Audio; using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Model.Options; using AudioCuesheetEditor.Model.UI; using AudioCuesheetEditor.Services.IO; -using AudioCuesheetEditorTests.Properties; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Tests.Properties; +using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; -namespace AudioCuesheetEditor.Model.AudioCuesheet.Tests +namespace AudioCuesheetEditor.Tests.Model.AudioCuesheet { [TestClass()] public class CuesheetTests @@ -41,15 +43,12 @@ public void AddTrackTest() { var testHelper = new TestHelper(); var cuesheet = new Cuesheet(); - var trackAddedFired = false; - cuesheet.TrackAdded += delegate - { - trackAddedFired = true; - }; + AutoResetEvent tracksAddedEvent = new(false); + cuesheet.TracksAdded += (object? sender, TracksAddedRemovedEventArgs args) => tracksAddedEvent.Set(); Assert.AreEqual(cuesheet.Tracks.Count, 0); cuesheet.AddTrack(new Track(), testHelper.ApplicationOptions); Assert.AreEqual(cuesheet.Tracks.Count, 1); - Assert.IsTrue(trackAddedFired); + Assert.IsTrue(tracksAddedEvent.WaitOne(1000)); } [TestMethod()] @@ -221,7 +220,7 @@ public void MoveAndDeleteTrackTest() public async Task ImportTestAsync() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist - CuesheetTitle c:\\tmp\\Testfile.mp3", "Sample Artist 1 - Sample Title 1 00:05:00", @@ -271,7 +270,7 @@ public async Task ImportTestCalculateEndCorrectlyAsync() // Arrange var textImportMemoryStream = new MemoryStream(Resources.Textimport_Bug_54); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -320,11 +319,11 @@ public void RecordTest() cuesheet = new Cuesheet(); cuesheet.StartRecording(); track = new Track(); - testHelper.RecordOptions.RecordTimeSensitivity = Options.TimeSensitivityMode.Seconds; + testHelper.RecordOptions.RecordTimeSensitivity = TimeSensitivityMode.Seconds; cuesheet.AddTrack(track, testHelper.ApplicationOptions, testHelper.RecordOptions); Assert.AreEqual(TimeSpan.Zero, track.Begin); Assert.IsNull(track.End); - System.Threading.Thread.Sleep(3000); + Thread.Sleep(3000); track2 = new Track(); cuesheet.AddTrack(track2, testHelper.ApplicationOptions, testHelper.RecordOptions); Assert.IsNotNull(track.End); @@ -427,7 +426,9 @@ public void RemoveTrackTest() { var testHelper = new TestHelper(); testHelper.ApplicationOptions.LinkTracksWithPreviousOne = true; + AutoResetEvent tracksRemovedEvent = new(false); var cuesheet = new Cuesheet(); + cuesheet.TracksRemoved += (sender, trackAddRemoveEventArgs) => tracksRemovedEvent.Set(); var track1 = new Track() { Artist = "1", Title = "1" }; var track2 = new Track() { Artist = "2", Title = "2" }; var track3 = new Track() { Artist = "3", Title = "3" }; @@ -445,12 +446,14 @@ public void RemoveTrackTest() track5.End = new TimeSpan(0, 25, 0); Assert.AreEqual(5, cuesheet.Tracks.Count); cuesheet.RemoveTrack(track2); + Assert.AreEqual(true, tracksRemovedEvent.WaitOne(1000)); Assert.AreEqual((uint)2, track3.Position); Assert.AreEqual((uint)3, track4.Position); Assert.AreEqual((uint)4, track5.Position); testHelper = new TestHelper(); testHelper.ApplicationOptions.LinkTracksWithPreviousOne = true; cuesheet = new Cuesheet(); + cuesheet.TracksRemoved += (sender, trackAddRemoveEventArgs) => tracksRemovedEvent.Set(); track1 = new Track { Artist = "Track 1", @@ -487,6 +490,7 @@ public void RemoveTrackTest() cuesheet.AddTrack(track5, testHelper.ApplicationOptions); var list = new List() { track2, track4 }; cuesheet.RemoveTracks(list.AsReadOnly()); + Assert.AreEqual(true, tracksRemovedEvent.WaitOne(1000)); Assert.AreEqual(3, cuesheet.Tracks.Count); Assert.AreEqual(new TimeSpan(0, 5, 0), track3.Begin); Assert.AreEqual(new TimeSpan(0, 15, 0), track5.Begin); diff --git a/AudioCuesheetEditorTests/Model/AudioCuesheet/TrackTests.cs b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/TrackTests.cs similarity index 98% rename from AudioCuesheetEditorTests/Model/AudioCuesheet/TrackTests.cs rename to AudioCuesheetEditor.Tests/Model/AudioCuesheet/TrackTests.cs index 957430e5..2d3becf5 100644 --- a/AudioCuesheetEditorTests/Model/AudioCuesheet/TrackTests.cs +++ b/AudioCuesheetEditor.Tests/Model/AudioCuesheet/TrackTests.cs @@ -13,14 +13,15 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. +using AudioCuesheetEditor.Model.AudioCuesheet; using AudioCuesheetEditor.Model.Entity; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.Linq; -namespace AudioCuesheetEditor.Model.AudioCuesheet.Tests +namespace AudioCuesheetEditor.Tests.Model.AudioCuesheet { [TestClass()] public class TrackTests @@ -84,7 +85,7 @@ public void LinkTrackTest() Position = 2 }; Assert.IsFalse(track2.IsLinkedToPreviousTrack); - Boolean eventFired = false; + bool eventFired = false; track2.IsLinkedToPreviousTrackChanged += delegate { eventFired = true; diff --git a/AudioCuesheetEditorTests/Model/Entity/ValidateableTests.cs b/AudioCuesheetEditor.Tests/Model/Entity/ValidateableTests.cs similarity index 87% rename from AudioCuesheetEditorTests/Model/Entity/ValidateableTests.cs rename to AudioCuesheetEditor.Tests/Model/Entity/ValidateableTests.cs index 1488cc14..75913b47 100644 --- a/AudioCuesheetEditorTests/Model/Entity/ValidateableTests.cs +++ b/AudioCuesheetEditor.Tests/Model/Entity/ValidateableTests.cs @@ -13,19 +13,18 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Model.Entity; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; using System.Collections.Generic; -namespace AudioCuesheetEditor.Model.Entity.Tests +namespace AudioCuesheetEditor.Tests.Model.Entity { public class ValidateableTestClass : Validateable { - private String? testProperty; + private string? testProperty; private int? testProperty2; - public String? TestProperty + public string? TestProperty { get => testProperty; set @@ -34,7 +33,7 @@ public String? TestProperty OnValidateablePropertyChanged(); } } - public int? TestProperty2 + public int? TestProperty2 { get => testProperty2; set @@ -51,9 +50,9 @@ protected override ValidationResult Validate(string property) { case nameof(TestProperty): validationStatus = ValidationStatus.Success; - if (String.IsNullOrEmpty(TestProperty)) + if (string.IsNullOrEmpty(TestProperty)) { - validationMessages ??= new(); + validationMessages ??= []; validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(TestProperty))); } break; @@ -69,7 +68,7 @@ public void ValidateTest() { var testObject = new ValidateableTestClass { - TestProperty = String.Empty + TestProperty = string.Empty }; Assert.AreEqual(ValidationStatus.Error, testObject.Validate().Status); Assert.IsNotNull(testObject.Validate().ValidationMessages); diff --git a/AudioCuesheetEditorTests/Model/Entity/ValidationResultTests.cs b/AudioCuesheetEditor.Tests/Model/Entity/ValidationResultTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/Entity/ValidationResultTests.cs rename to AudioCuesheetEditor.Tests/Model/Entity/ValidationResultTests.cs diff --git a/AudioCuesheetEditorTests/Model/IO/Audio/AudiofileTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/IO/Audio/AudiofileTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs diff --git a/AudioCuesheetEditorTests/Model/IO/Export/CuesheetSectionTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Export/CuesheetSectionTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/IO/Export/CuesheetSectionTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/Export/CuesheetSectionTests.cs diff --git a/AudioCuesheetEditorTests/Model/IO/Export/ExportfileGeneratorTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Export/ExportfileGeneratorTests.cs similarity index 87% rename from AudioCuesheetEditorTests/Model/IO/Export/ExportfileGeneratorTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/Export/ExportfileGeneratorTests.cs index 97653e63..fbebfaf5 100644 --- a/AudioCuesheetEditorTests/Model/IO/Export/ExportfileGeneratorTests.cs +++ b/AudioCuesheetEditor.Tests/Model/IO/Export/ExportfileGeneratorTests.cs @@ -13,21 +13,17 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. -using Microsoft.VisualStudio.TestTools.UnitTesting; -using AudioCuesheetEditor.Model.IO.Export; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AudioCuesheetEditorTests.Utility; using AudioCuesheetEditor.Model.AudioCuesheet; +using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO.Audio; +using AudioCuesheetEditor.Model.IO.Export; +using AudioCuesheetEditor.Tests.Utility; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; using System.IO; -using AudioCuesheetEditor.Model.Entity; -using System.Diagnostics.Metrics; +using System.Linq; -namespace AudioCuesheetEditor.Model.IO.Export.Tests +namespace AudioCuesheetEditor.Tests.Model.IO.Export { [TestClass()] public class ExportfileGeneratorTests @@ -48,8 +44,8 @@ public void GenerateCuesheetFilesTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -65,20 +61,20 @@ public void GenerateCuesheetFilesTest() var fileName = Path.GetTempFileName(); File.WriteAllBytes(fileName, content); var fileContent = File.ReadAllLines(fileName); - Assert.AreEqual(fileContent[0], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); - Assert.AreEqual(fileContent[1], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); - Assert.AreEqual(fileContent[2], String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); + Assert.AreEqual(fileContent[0], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); + Assert.AreEqual(fileContent[1], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); + Assert.AreEqual(fileContent[2], string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); var position = 1; for (int i = 3; i < fileContent.Length; i += 4) { var track = cuesheet.Tracks.Single(x => x.Position == position); position++; - Assert.AreEqual(fileContent[i], String.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio)); - Assert.AreEqual(fileContent[i + 1], String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title)); - Assert.AreEqual(fileContent[i + 2], String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist)); + Assert.AreEqual(fileContent[i], string.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio)); + Assert.AreEqual(fileContent[i + 1], string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title)); + Assert.AreEqual(fileContent[i + 2], string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist)); var trackBegin = track.Begin; Assert.IsNotNull(trackBegin); - Assert.AreEqual(fileContent[i + 3], String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75)); + Assert.AreEqual(fileContent[i + 3], string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75)); } File.Delete(fileName); cuesheet.CDTextfile = new CDTextfile("Testfile.cdt"); @@ -90,8 +86,8 @@ public void GenerateCuesheetFilesTest() fileName = Path.GetTempFileName(); File.WriteAllBytes(fileName, content); fileContent = File.ReadAllLines(fileName); - Assert.AreEqual(fileContent[0], String.Format("{0} {1}", CuesheetConstants.CuesheetCatalogueNumber, cuesheet.Cataloguenumber.Value)); - Assert.AreEqual(fileContent[1], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetCDTextfile, cuesheet.CDTextfile.Name)); + Assert.AreEqual(fileContent[0], string.Format("{0} {1}", CuesheetConstants.CuesheetCatalogueNumber, cuesheet.Cataloguenumber.Value)); + Assert.AreEqual(fileContent[1], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetCDTextfile, cuesheet.CDTextfile.Name)); File.Delete(fileName); cuesheet.CDTextfile = new CDTextfile("Testfile.cdt"); cuesheet.Cataloguenumber.Value = "Testvalue"; @@ -115,8 +111,8 @@ public void GenerateCuesheetFilesWithPreGapAndPostGapTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -139,27 +135,27 @@ public void GenerateCuesheetFilesWithPreGapAndPostGapTest() var fileName = Path.GetTempFileName(); File.WriteAllBytes(fileName, content); var fileContent = File.ReadAllLines(fileName); - Assert.AreEqual(fileContent[0], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); - Assert.AreEqual(fileContent[1], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); - Assert.AreEqual(fileContent[2], String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); + Assert.AreEqual(fileContent[0], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); + Assert.AreEqual(fileContent[1], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); + Assert.AreEqual(fileContent[2], string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); var position = 1; for (int i = 3; i < fileContent.Length; i += 7) { var track = cuesheet.Tracks.Single(x => x.Position == position); position++; - Assert.AreEqual(String.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); - Assert.AreEqual(String.Format("{0}{1}{2} {3}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackFlags, String.Join(" ", track.Flags.Select(x => x.CuesheetLabel))), fileContent[i + 3]); + Assert.AreEqual(string.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); + Assert.AreEqual(string.Format("{0}{1}{2} {3}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackFlags, string.Join(" ", track.Flags.Select(x => x.CuesheetLabel))), fileContent[i + 3]); var preGap = track.PreGap; var trackBegin = track.Begin; var postGap = track.PostGap; Assert.IsNotNull(preGap); Assert.IsNotNull(trackBegin); Assert.IsNotNull(postGap); - Assert.AreEqual(String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackPreGap, Math.Floor(preGap.Value.TotalMinutes), preGap.Value.Seconds, preGap.Value.Milliseconds / 75), fileContent[i + 4]); - Assert.AreEqual(String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 5]); - Assert.AreEqual(String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackPostGap, Math.Floor(postGap.Value.TotalMinutes), postGap.Value.Seconds, postGap.Value.Milliseconds / 75), fileContent[i + 6]); + Assert.AreEqual(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackPreGap, Math.Floor(preGap.Value.TotalMinutes), preGap.Value.Seconds, preGap.Value.Milliseconds / 75), fileContent[i + 4]); + Assert.AreEqual(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 5]); + Assert.AreEqual(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackPostGap, Math.Floor(postGap.Value.TotalMinutes), postGap.Value.Seconds, postGap.Value.Milliseconds / 75), fileContent[i + 6]); } File.Delete(fileName); } @@ -179,8 +175,8 @@ public void GenerateCuesheetFilesWithTrackFlagsTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -201,21 +197,21 @@ public void GenerateCuesheetFilesWithTrackFlagsTest() var fileName = Path.GetTempFileName(); File.WriteAllBytes(fileName, content); var fileContent = File.ReadAllLines(fileName); - Assert.AreEqual(fileContent[0], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); - Assert.AreEqual(fileContent[1], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); - Assert.AreEqual(fileContent[2], String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); + Assert.AreEqual(fileContent[0], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); + Assert.AreEqual(fileContent[1], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); + Assert.AreEqual(fileContent[2], string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); var position = 1; for (int i = 3; i < fileContent.Length; i += 5) { var track = cuesheet.Tracks.Single(x => x.Position == position); position++; - Assert.AreEqual(fileContent[i], String.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio)); - Assert.AreEqual(fileContent[i + 1], String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title)); - Assert.AreEqual(fileContent[i + 2], String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist)); - Assert.AreEqual(fileContent[i + 3], String.Format("{0}{1}{2} {3}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackFlags, String.Join(" ", track.Flags.Select(x => x.CuesheetLabel)))); + Assert.AreEqual(fileContent[i], string.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position, CuesheetConstants.CuesheetTrackAudio)); + Assert.AreEqual(fileContent[i + 1], string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title)); + Assert.AreEqual(fileContent[i + 2], string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist)); + Assert.AreEqual(fileContent[i + 3], string.Format("{0}{1}{2} {3}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackFlags, string.Join(" ", track.Flags.Select(x => x.CuesheetLabel)))); var trackBegin = track.Begin; Assert.IsNotNull(trackBegin); - Assert.AreEqual(fileContent[i + 4], String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75)); + Assert.AreEqual(fileContent[i + 4], string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75)); } File.Delete(fileName); } @@ -236,8 +232,8 @@ public void GenerateCuesheetFilesWithIncorrectTrackPositionsTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin, Position = (uint)(i + random.Next(1, 10)) }; @@ -261,19 +257,19 @@ public void GenerateCuesheetFilesWithIncorrectTrackPositionsTest() var fileName = Path.GetTempFileName(); File.WriteAllBytes(fileName, content); var fileContent = File.ReadAllLines(fileName); - Assert.AreEqual(fileContent[0], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); - Assert.AreEqual(fileContent[1], String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); - Assert.AreEqual(fileContent[2], String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); + Assert.AreEqual(fileContent[0], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title)); + Assert.AreEqual(fileContent[1], string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist)); + Assert.AreEqual(fileContent[2], string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheet.Audiofile.Name, cuesheet.Audiofile.AudioFileType)); var position = 1; for (int i = 3; i < fileContent.Length; i += 4) { var track = cuesheet.Tracks.ElementAt(position - 1); - Assert.AreEqual(String.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, position, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); + Assert.AreEqual(string.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, position, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); var trackBegin = track.Begin; Assert.IsNotNull(trackBegin); - Assert.AreEqual(String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 3]); + Assert.AreEqual(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 3]); position++; } File.Delete(fileName); @@ -294,8 +290,8 @@ public void GenerateCuesheetFilesWithSectionsTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -338,7 +334,7 @@ public void GenerateCuesheetFilesWithSectionsTest() Assert.AreEqual(new TimeSpan(2, 0, 0), generatedFiles.Last().End); foreach (var generatedFile in generatedFiles) { - Assert.AreEqual(String.Format("Unit test({0}).cue", counter), generatedFile.Name); + Assert.AreEqual(string.Format("Unit test({0}).cue", counter), generatedFile.Name); counter++; var content = generatedFile.Content; Assert.IsNotNull(content); @@ -351,25 +347,25 @@ public void GenerateCuesheetFilesWithSectionsTest() var sectionForThisFile = cuesheet.Sections.FirstOrDefault(x => x.Begin == generatedFile.Begin); if (sectionForThisFile != null) { - Assert.AreEqual(String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, sectionForThisFile.Title), fileContent.First()); - Assert.AreEqual(String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, sectionForThisFile.Artist), fileContent[1]); - Assert.AreEqual(String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, sectionForThisFile.AudiofileName, cuesheet.Audiofile?.AudioFileType), fileContent[2]); + Assert.AreEqual(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, sectionForThisFile.Title), fileContent.First()); + Assert.AreEqual(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, sectionForThisFile.Artist), fileContent[1]); + Assert.AreEqual(string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, sectionForThisFile.AudiofileName, cuesheet.Audiofile?.AudioFileType), fileContent[2]); } else { - Assert.AreEqual(String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title), fileContent.First()); - Assert.AreEqual(String.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist), fileContent[1]); - var cuesheetFileName = String.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(cuesheet.Audiofile?.Name), counter - 1, Path.GetExtension(cuesheet.Audiofile?.Name)); - Assert.AreEqual(String.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheetFileName, cuesheet.Audiofile?.AudioFileType), fileContent[2]); + Assert.AreEqual(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, cuesheet.Title), fileContent.First()); + Assert.AreEqual(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, cuesheet.Artist), fileContent[1]); + var cuesheetFileName = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(cuesheet.Audiofile?.Name), counter - 1, Path.GetExtension(cuesheet.Audiofile?.Name)); + Assert.AreEqual(string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, cuesheetFileName, cuesheet.Audiofile?.AudioFileType), fileContent[2]); } //Check for start from position 1 and begin = 00:00:00 for (int i = 3; i < fileContent.Length; i += 4) { var track = cuesheet.Tracks.Single(x => x.Position == position); position++; - Assert.AreEqual(String.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position + positionDifference, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); - Assert.AreEqual(String.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); + Assert.AreEqual(string.Format("{0}{1} {2:00} {3}", CuesheetConstants.Tab, CuesheetConstants.CuesheetTrack, track.Position + positionDifference, CuesheetConstants.CuesheetTrackAudio), fileContent[i]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackTitle, track.Title), fileContent[i + 1]); + Assert.AreEqual(string.Format("{0}{1}{2} \"{3}\"", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackArtist, track.Artist), fileContent[i + 2]); var trackBegin = track.Begin; if (generatedFile.Begin != null) { @@ -383,7 +379,7 @@ public void GenerateCuesheetFilesWithSectionsTest() } } Assert.IsNotNull(trackBegin); - Assert.AreEqual(String.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 3]); + Assert.AreEqual(string.Format("{0}{1}{2} {3:00}:{4:00}:{5:00}", CuesheetConstants.Tab, CuesheetConstants.Tab, CuesheetConstants.TrackIndex01, Math.Floor(trackBegin.Value.TotalMinutes), trackBegin.Value.Seconds, trackBegin.Value.Milliseconds / 75), fileContent[i + 3]); } position--; } @@ -405,8 +401,8 @@ public void GenerateExportfilesTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -446,7 +442,7 @@ public void GenerateExportfilesTest() Assert.AreEqual("Demo Artist;Demo Title;0123456789123;Testfile.cdt", content[0]); for (int i = 1; i < content.Length - 1; i++) { - Assert.IsFalse(String.IsNullOrEmpty(content[i])); + Assert.IsFalse(string.IsNullOrEmpty(content[i])); Assert.AreNotEqual(content[i], ";;;;;"); Assert.IsTrue(content[i].StartsWith(cuesheet.Tracks.ToList()[i - 1].Position + ";")); } @@ -463,7 +459,7 @@ public void GenerateExportfilesTest() exportProfile = new Exportprofile { SchemeHead = "%Cuesheet.Artist%;%Cuesheet.Title%", - SchemeTracks = String.Format("%Track.Position%{0}%Track.Artist%{1}%Track.Title%;%Track.Begin%;%Track.End%;%Track.Length%", Environment.NewLine, Environment.NewLine), + SchemeTracks = string.Format("%Track.Position%{0}%Track.Artist%{1}%Track.Title%;%Track.Begin%;%Track.End%;%Track.Length%", Environment.NewLine, Environment.NewLine), SchemeFooter = "Exported %Cuesheet.Title% from %Cuesheet.Artist% using AudioCuesheetEditor" }; Assert.AreEqual(ValidationStatus.Success, exportProfile.Validate().Status); @@ -480,7 +476,7 @@ public void GenerateExportfilesTest() var trackPosition = 0; for (int i = 1; i < content.Length - 1; i += 3) { - Assert.IsFalse(String.IsNullOrEmpty(content[i])); + Assert.IsFalse(string.IsNullOrEmpty(content[i])); Assert.AreNotEqual(content[i], ";;;;;"); var track = cuesheet.Tracks.ToList()[trackPosition]; Assert.IsNotNull(track.Position); @@ -513,13 +509,13 @@ public void GenerateExportfilesTest() Assert.AreEqual("Demo Artist;Demo Title;0123456789123;Testfile.cdt", content[0]); for (int i = 1; i < content.Length - 1; i++) { - Assert.IsFalse(String.IsNullOrEmpty(content[i])); + Assert.IsFalse(string.IsNullOrEmpty(content[i])); Assert.AreNotEqual(content[i], ";;;;;"); Assert.IsTrue(content[i].StartsWith(cuesheet.Tracks.ToList()[i - 1].Position + ";")); if (cuesheet.Tracks.ElementAt(i - 1).Flags.Count > 0) { var flags = cuesheet.Tracks.ElementAt(i - 1).Flags; - Assert.IsTrue(content[i].Contains(String.Join(" ", flags.Select(x => x.CuesheetLabel)))); + Assert.IsTrue(content[i].Contains(string.Join(" ", flags.Select(x => x.CuesheetLabel)))); } } Assert.AreEqual(content[^1], "Exported Demo Title from Demo Artist using AudioCuesheetEditor"); @@ -542,8 +538,8 @@ public void GenerateExportfilesWithPregapAndPostgapTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin, PostGap = new TimeSpan(0, 0, 1), PreGap = new TimeSpan(0, 0, 3) @@ -584,11 +580,11 @@ public void GenerateExportfilesWithPregapAndPostgapTest() Assert.AreEqual("Demo Artist;Demo Title;0123456789123;Testfile.cdt", content[0]); for (int i = 1; i < content.Length - 1; i++) { - Assert.IsFalse(String.IsNullOrEmpty(content[i])); + Assert.IsFalse(string.IsNullOrEmpty(content[i])); Assert.AreNotEqual(content[i], ";;;;;"); Assert.IsTrue(content[i].StartsWith(cuesheet.Tracks.ToList()[i - 1].Position + ";")); } - Assert.AreEqual(content[^1], String.Format("Exported Demo Title from Demo Artist using AudioCuesheetEditor at {0}", DateTime.Now.ToShortDateString())); + Assert.AreEqual(content[^1], string.Format("Exported Demo Title from Demo Artist using AudioCuesheetEditor at {0}", DateTime.Now.ToShortDateString())); File.Delete(tempFile); } @@ -608,8 +604,8 @@ public void GenerateExportfilesWithSectionsTest() { var track = new Track { - Artist = String.Format("Demo Track Artist {0}", i), - Title = String.Format("Demo Track Title {0}", i), + Artist = string.Format("Demo Track Artist {0}", i), + Title = string.Format("Demo Track Title {0}", i), Begin = begin }; begin = begin.Add(new TimeSpan(0, i, i)); @@ -671,7 +667,7 @@ public void GenerateExportfilesWithSectionsTest() var position = 1; foreach (var generatedFile in generatedFiles) { - Assert.AreEqual(String.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(exportProfile.Filename), counter, Path.GetExtension(exportProfile.Filename)), generatedFile.Name); + Assert.AreEqual(string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(exportProfile.Filename), counter, Path.GetExtension(exportProfile.Filename)), generatedFile.Name); counter++; var content = generatedFile.Content; Assert.IsNotNull(content); @@ -684,12 +680,12 @@ public void GenerateExportfilesWithSectionsTest() var sectionForThisFile = cuesheet.Sections.FirstOrDefault(x => x.Begin == generatedFile.Begin); if (sectionForThisFile != null) { - Assert.AreEqual(String.Format("{0};{1};{2};0123456789123;Testfile.cdt", sectionForThisFile.Artist, sectionForThisFile.Title, sectionForThisFile.AudiofileName), fileContent[0]); + Assert.AreEqual(string.Format("{0};{1};{2};0123456789123;Testfile.cdt", sectionForThisFile.Artist, sectionForThisFile.Title, sectionForThisFile.AudiofileName), fileContent[0]); } else { - var audiofileName = String.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(cuesheet.Audiofile?.Name), counter - 1, Path.GetExtension(cuesheet.Audiofile?.Name)); - Assert.AreEqual(String.Format("{0};{1};{2};0123456789123;Testfile.cdt", cuesheet.Artist, cuesheet.Title, audiofileName), fileContent[0]); + var audiofileName = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(cuesheet.Audiofile?.Name), counter - 1, Path.GetExtension(cuesheet.Audiofile?.Name)); + Assert.AreEqual(string.Format("{0};{1};{2};0123456789123;Testfile.cdt", cuesheet.Artist, cuesheet.Title, audiofileName), fileContent[0]); } //Check for start from position 1 and begin = 00:00:00 for (int i = 1; i < fileContent.Length - 1; i++) @@ -710,15 +706,15 @@ public void GenerateExportfilesWithSectionsTest() } trackEnd = track.End - generatedFile.Begin; } - Assert.AreEqual(String.Format("{0};{1};{2};{3};{4};{5}", track.Position + positionDifference, track.Artist, track.Title, trackBegin, trackEnd, trackEnd - trackBegin), fileContent[i]); + Assert.AreEqual(string.Format("{0};{1};{2};{3};{4};{5}", track.Position + positionDifference, track.Artist, track.Title, trackBegin, trackEnd, trackEnd - trackBegin), fileContent[i]); } if (sectionForThisFile != null) { - Assert.AreEqual(String.Format("Exported {0} from {1} using AudioCuesheetEditor", sectionForThisFile.Title, sectionForThisFile.Artist), fileContent.Last()); + Assert.AreEqual(string.Format("Exported {0} from {1} using AudioCuesheetEditor", sectionForThisFile.Title, sectionForThisFile.Artist), fileContent.Last()); } else { - Assert.AreEqual(String.Format("Exported {0} from {1} using AudioCuesheetEditor", cuesheet.Title, cuesheet.Artist), fileContent.Last()); + Assert.AreEqual(string.Format("Exported {0} from {1} using AudioCuesheetEditor", cuesheet.Title, cuesheet.Artist), fileContent.Last()); } position--; } diff --git a/AudioCuesheetEditorTests/Model/IO/Export/ExportprofileTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Export/ExportprofileTests.cs similarity index 87% rename from AudioCuesheetEditorTests/Model/IO/Export/ExportprofileTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/Export/ExportprofileTests.cs index c78f6a37..b976c7c0 100644 --- a/AudioCuesheetEditorTests/Model/IO/Export/ExportprofileTests.cs +++ b/AudioCuesheetEditor.Tests/Model/IO/Export/ExportprofileTests.cs @@ -1,4 +1,3 @@ -using AudioCuesheetEditor.Model.IO.Export; //This file is part of AudioCuesheetEditor. //AudioCuesheetEditor is free software: you can redistribute it and/or modify @@ -14,19 +13,12 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. +using AudioCuesheetEditor.Model.Entity; +using AudioCuesheetEditor.Model.IO.Export; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using AudioCuesheetEditorTests.Utility; -using AudioCuesheetEditor.Model.AudioCuesheet; -using System.IO; -using AudioCuesheetEditor.Model.IO.Audio; -using AudioCuesheetEditor.Model.Entity; -namespace AudioCuesheetEditor.Model.IO.Export.Tests +namespace AudioCuesheetEditor.Tests.Model.IO.Export { [TestClass()] public class ExportprofileTests @@ -36,7 +28,7 @@ public void ValidateTest() { var exportprofile = new Exportprofile { - Filename = String.Empty + Filename = string.Empty }; Assert.AreEqual(ValidationStatus.Error, exportprofile.Validate(x => x.Filename).Status); exportprofile.Filename = "Test123"; diff --git a/AudioCuesheetEditorTests/Model/IO/Import/TextImportSchemeTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Import/TextImportSchemeTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/IO/Import/TextImportSchemeTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/Import/TextImportSchemeTests.cs diff --git a/AudioCuesheetEditorTests/Model/IO/ProjectfileTests.cs b/AudioCuesheetEditor.Tests/Model/IO/ProjectfileTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/IO/ProjectfileTests.cs rename to AudioCuesheetEditor.Tests/Model/IO/ProjectfileTests.cs diff --git a/AudioCuesheetEditorTests/Model/Options/ExportOptionsTest.cs b/AudioCuesheetEditor.Tests/Model/Options/ExportOptionsTest.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/Options/ExportOptionsTest.cs rename to AudioCuesheetEditor.Tests/Model/Options/ExportOptionsTest.cs diff --git a/AudioCuesheetEditorTests/Model/UI/TraceChangeManagerTests.cs b/AudioCuesheetEditor.Tests/Model/UI/TraceChangeManagerTests.cs similarity index 97% rename from AudioCuesheetEditorTests/Model/UI/TraceChangeManagerTests.cs rename to AudioCuesheetEditor.Tests/Model/UI/TraceChangeManagerTests.cs index fe31187a..c083c37c 100644 --- a/AudioCuesheetEditorTests/Model/UI/TraceChangeManagerTests.cs +++ b/AudioCuesheetEditor.Tests/Model/UI/TraceChangeManagerTests.cs @@ -19,9 +19,10 @@ using AudioCuesheetEditor.Model.Entity; using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Model.Options; +using AudioCuesheetEditor.Model.UI; using AudioCuesheetEditor.Services.IO; -using AudioCuesheetEditorTests.Properties; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Tests.Properties; +using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System; @@ -30,7 +31,7 @@ using System.Linq; using System.Threading.Tasks; -namespace AudioCuesheetEditor.Model.UI.Tests +namespace AudioCuesheetEditor.Tests.Model.UI { [TestClass()] public class TraceChangeManagerTests @@ -174,7 +175,7 @@ public async Task Import_ValidTextfile_IsUndoable() var sessionStateContainer = new SessionStateContainer(traceChangeManager); var textImportMemoryStream = new MemoryStream(Resources.Textimport_with_Cuesheetdata); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -187,8 +188,8 @@ public async Task Import_ValidTextfile_IsUndoable() localStorageOptionsProviderMock.Setup(x => x.GetOptions()).ReturnsAsync(importOptions); var textImportService = new TextImportService(); var importManager = new ImportManager(sessionStateContainer, localStorageOptionsProviderMock.Object, textImportService, traceChangeManager); - Boolean eventFired = false; - sessionStateContainer.Cuesheet.TrackAdded += delegate + bool eventFired = false; + sessionStateContainer.Cuesheet.TracksAdded += delegate { eventFired = true; }; @@ -213,7 +214,7 @@ public async Task UndoImport_ValidTextfile_ResetsToEmptyCuesheet() var sessionStateContainer = new SessionStateContainer(traceChangeManager); var textImportMemoryStream = new MemoryStream(Resources.Textimport_with_Cuesheetdata); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -226,8 +227,8 @@ public async Task UndoImport_ValidTextfile_ResetsToEmptyCuesheet() localStorageOptionsProviderMock.Setup(x => x.GetOptions()).ReturnsAsync(importOptions); var textImportService = new TextImportService(); var importManager = new ImportManager(sessionStateContainer, localStorageOptionsProviderMock.Object, textImportService, traceChangeManager); - Boolean eventFired = false; - sessionStateContainer.Cuesheet.TrackAdded += delegate + bool eventFired = false; + sessionStateContainer.Cuesheet.TracksAdded += delegate { eventFired = true; }; @@ -237,8 +238,8 @@ public async Task UndoImport_ValidTextfile_ResetsToEmptyCuesheet() traceChangeManager.Undo(); // Assert Assert.AreEqual(0, sessionStateContainer.Cuesheet.Tracks.Count); - Assert.IsTrue(String.IsNullOrEmpty(sessionStateContainer.Cuesheet.Artist)); - Assert.IsTrue(String.IsNullOrEmpty(sessionStateContainer.Cuesheet.Cataloguenumber.Value)); + Assert.IsTrue(string.IsNullOrEmpty(sessionStateContainer.Cuesheet.Artist)); + Assert.IsTrue(string.IsNullOrEmpty(sessionStateContainer.Cuesheet.Cataloguenumber.Value)); Assert.IsFalse(traceChangeManager.CanUndo); Assert.IsTrue(traceChangeManager.CanRedo); Assert.IsFalse(eventFired); @@ -253,7 +254,7 @@ public async Task UndoAndRedoImport_ValidTextfile_ResetsTextfileValues() var sessionStateContainer = new SessionStateContainer(traceChangeManager); var textImportMemoryStream = new MemoryStream(Resources.Textimport_with_Cuesheetdata); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -266,8 +267,8 @@ public async Task UndoAndRedoImport_ValidTextfile_ResetsTextfileValues() localStorageOptionsProviderMock.Setup(x => x.GetOptions()).ReturnsAsync(importOptions); var textImportService = new TextImportService(); var importManager = new ImportManager(sessionStateContainer, localStorageOptionsProviderMock.Object, textImportService, traceChangeManager); - Boolean eventFired = false; - sessionStateContainer.Cuesheet.TrackAdded += delegate + bool eventFired = false; + sessionStateContainer.Cuesheet.TracksAdded += delegate { eventFired = true; }; diff --git a/AudioCuesheetEditorTests/Model/Utility/TimeSpanUtilityTests.cs b/AudioCuesheetEditor.Tests/Model/Utility/TimeSpanUtilityTests.cs similarity index 100% rename from AudioCuesheetEditorTests/Model/Utility/TimeSpanUtilityTests.cs rename to AudioCuesheetEditor.Tests/Model/Utility/TimeSpanUtilityTests.cs diff --git a/AudioCuesheetEditorTests/Properties/Resources.Designer.cs b/AudioCuesheetEditor.Tests/Properties/Resources.Designer.cs similarity index 97% rename from AudioCuesheetEditorTests/Properties/Resources.Designer.cs rename to AudioCuesheetEditor.Tests/Properties/Resources.Designer.cs index 379b79fc..20d2a794 100644 --- a/AudioCuesheetEditorTests/Properties/Resources.Designer.cs +++ b/AudioCuesheetEditor.Tests/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace AudioCuesheetEditorTests.Properties { +namespace AudioCuesheetEditor.Tests.Properties { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AudioCuesheetEditorTests.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AudioCuesheetEditor.Tests.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/AudioCuesheetEditorTests/Properties/Resources.resx b/AudioCuesheetEditor.Tests/Properties/Resources.resx similarity index 100% rename from AudioCuesheetEditorTests/Properties/Resources.resx rename to AudioCuesheetEditor.Tests/Properties/Resources.resx diff --git a/AudioCuesheetEditorTests/Resources/Playlist-#36-Frames.cue b/AudioCuesheetEditor.Tests/Resources/Playlist-#36-Frames.cue similarity index 100% rename from AudioCuesheetEditorTests/Resources/Playlist-#36-Frames.cue rename to AudioCuesheetEditor.Tests/Resources/Playlist-#36-Frames.cue diff --git a/AudioCuesheetEditorTests/Resources/Playlist-Bug#30.cue b/AudioCuesheetEditor.Tests/Resources/Playlist-Bug#30.cue similarity index 100% rename from AudioCuesheetEditorTests/Resources/Playlist-Bug#30.cue rename to AudioCuesheetEditor.Tests/Resources/Playlist-Bug#30.cue diff --git a/AudioCuesheetEditorTests/Resources/Playlist-Bug#57.cue b/AudioCuesheetEditor.Tests/Resources/Playlist-Bug#57.cue similarity index 100% rename from AudioCuesheetEditorTests/Resources/Playlist-Bug#57.cue rename to AudioCuesheetEditor.Tests/Resources/Playlist-Bug#57.cue diff --git a/AudioCuesheetEditorTests/Resources/Textimport with Cuesheetdata.txt b/AudioCuesheetEditor.Tests/Resources/Textimport with Cuesheetdata.txt similarity index 100% rename from AudioCuesheetEditorTests/Resources/Textimport with Cuesheetdata.txt rename to AudioCuesheetEditor.Tests/Resources/Textimport with Cuesheetdata.txt diff --git a/AudioCuesheetEditorTests/Resources/Textimport-Bug-#54.txt b/AudioCuesheetEditor.Tests/Resources/Textimport-Bug-#54.txt similarity index 100% rename from AudioCuesheetEditorTests/Resources/Textimport-Bug-#54.txt rename to AudioCuesheetEditor.Tests/Resources/Textimport-Bug-#54.txt diff --git a/AudioCuesheetEditorTests/Resources/Textimport_Bug_#233.txt b/AudioCuesheetEditor.Tests/Resources/Textimport_Bug_#233.txt similarity index 100% rename from AudioCuesheetEditorTests/Resources/Textimport_Bug_#233.txt rename to AudioCuesheetEditor.Tests/Resources/Textimport_Bug_#233.txt diff --git a/AudioCuesheetEditorTests/Resources/Textimport_Bug_213.txt b/AudioCuesheetEditor.Tests/Resources/Textimport_Bug_213.txt similarity index 100% rename from AudioCuesheetEditorTests/Resources/Textimport_Bug_213.txt rename to AudioCuesheetEditor.Tests/Resources/Textimport_Bug_213.txt diff --git a/AudioCuesheetEditorTests/Services/IO/CuesheetImportServiceTests.cs b/AudioCuesheetEditor.Tests/Services/IO/CuesheetImportServiceTests.cs similarity index 90% rename from AudioCuesheetEditorTests/Services/IO/CuesheetImportServiceTests.cs rename to AudioCuesheetEditor.Tests/Services/IO/CuesheetImportServiceTests.cs index 4bbcc7bb..a31aa3eb 100644 --- a/AudioCuesheetEditorTests/Services/IO/CuesheetImportServiceTests.cs +++ b/AudioCuesheetEditor.Tests/Services/IO/CuesheetImportServiceTests.cs @@ -14,14 +14,15 @@ //along with Foobar. If not, see //. using AudioCuesheetEditor.Model.AudioCuesheet; -using AudioCuesheetEditorTests.Properties; +using AudioCuesheetEditor.Services.IO; +using AudioCuesheetEditor.Tests.Properties; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.IO; using System.Linq; -namespace AudioCuesheetEditor.Services.IO.Tests +namespace AudioCuesheetEditor.Tests.Services.IO { [TestClass()] public class CuesheetImportServiceTests @@ -30,7 +31,7 @@ public class CuesheetImportServiceTests public void Analyse_WithSampleCuesheet_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "PERFORMER \"Sample CD Artist\"", "TITLE \"Sample CD Title\"", @@ -77,15 +78,15 @@ public void Analyse_WithSampleCuesheet_CreatesValidCuesheet() Assert.IsNull(importFile.AnalyseException); Assert.IsNotNull(importFile.AnalysedCuesheet); Assert.AreEqual(8, importFile.AnalysedCuesheet.Tracks.Count); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "PERFORMER \"Sample CD Artist\""), importFile.FileContentRecognized?.ElementAt(0)); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "TITLE \"Sample CD Title\""), importFile.FileContentRecognized?.ElementAt(1)); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "FILE \"AC DC - TNT.mp3\" MP3"), importFile.FileContentRecognized?.ElementAt(2)); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "CDTEXTFILE \"Testfile.cdt\""), importFile.FileContentRecognized?.ElementAt(3)); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "CATALOG 0123456789012"), importFile.FileContentRecognized?.ElementAt(4)); - Assert.AreEqual(String.Format(CuesheetConstants.RecognizedMarkHTML, "TRACK 01 AUDIO"), importFile.FileContentRecognized?.ElementAt(5)); - Assert.AreEqual(String.Format(" {0}", String.Format(CuesheetConstants.RecognizedMarkHTML, "PERFORMER \"Sample Artist 1\"")), importFile.FileContentRecognized?.ElementAt(6)); - Assert.AreEqual(String.Format(" {0}", String.Format(CuesheetConstants.RecognizedMarkHTML, "TITLE \"Sample Title 1\"")), importFile.FileContentRecognized?.ElementAt(7)); - Assert.AreEqual(String.Format(" {0}", String.Format(CuesheetConstants.RecognizedMarkHTML, "INDEX 01 00:00:00")), importFile.FileContentRecognized?.ElementAt(8)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "PERFORMER \"Sample CD Artist\""), importFile.FileContentRecognized?.ElementAt(0)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "TITLE \"Sample CD Title\""), importFile.FileContentRecognized?.ElementAt(1)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "FILE \"AC DC - TNT.mp3\" MP3"), importFile.FileContentRecognized?.ElementAt(2)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "CDTEXTFILE \"Testfile.cdt\""), importFile.FileContentRecognized?.ElementAt(3)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "CATALOG 0123456789012"), importFile.FileContentRecognized?.ElementAt(4)); + Assert.AreEqual(string.Format(CuesheetConstants.RecognizedMarkHTML, "TRACK 01 AUDIO"), importFile.FileContentRecognized?.ElementAt(5)); + Assert.AreEqual(string.Format(" {0}", string.Format(CuesheetConstants.RecognizedMarkHTML, "PERFORMER \"Sample Artist 1\"")), importFile.FileContentRecognized?.ElementAt(6)); + Assert.AreEqual(string.Format(" {0}", string.Format(CuesheetConstants.RecognizedMarkHTML, "TITLE \"Sample Title 1\"")), importFile.FileContentRecognized?.ElementAt(7)); + Assert.AreEqual(string.Format(" {0}", string.Format(CuesheetConstants.RecognizedMarkHTML, "INDEX 01 00:00:00")), importFile.FileContentRecognized?.ElementAt(8)); } [TestMethod()] @@ -94,7 +95,7 @@ public void Analyse_WithCuesheetBug30_CreatesValidCuesheet() //Arrange var textImportMemoryStream = new MemoryStream(Resources.Playlist_Bug_30); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -113,7 +114,7 @@ public void Analyse_WithCuesheetBug57_CreatesValidCuesheet() //Arrange var textImportMemoryStream = new MemoryStream(Resources.Playlist_Bug_57); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -134,7 +135,7 @@ public void Analyse_WithCuesheetBug36_CreatesValidCuesheet() //Arrange var textImportMemoryStream = new MemoryStream(Resources.Playlist__36_Frames); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -153,7 +154,7 @@ public void Analyse_WithCuesheetBug36_CreatesValidCuesheet() public void Analyse_WithCDTextFileCatalogueNumberAndPreAndPostGap_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "PERFORMER \"Sample CD Artist\"", "TITLE \"Sample CD Title\"", @@ -202,8 +203,8 @@ public void Analyse_WithCDTextFileCatalogueNumberAndPreAndPostGap_CreatesValidCu // Assert Assert.IsNull(importFile.AnalyseException); Assert.IsNotNull(importFile.AnalysedCuesheet); - Assert.AreEqual(String.Format(" {0}", String.Format(CuesheetConstants.RecognizedMarkHTML, "FLAGS 4CH DCP PRE SCMS")), importFile.FileContentRecognized?.ElementAt(8)); - Assert.AreEqual(String.Format(" {0}", String.Format(CuesheetConstants.RecognizedMarkHTML, "PREGAP 00:04:00")), importFile.FileContentRecognized?.ElementAt(35)); + Assert.AreEqual(string.Format(" {0}", string.Format(CuesheetConstants.RecognizedMarkHTML, "FLAGS 4CH DCP PRE SCMS")), importFile.FileContentRecognized?.ElementAt(8)); + Assert.AreEqual(string.Format(" {0}", string.Format(CuesheetConstants.RecognizedMarkHTML, "PREGAP 00:04:00")), importFile.FileContentRecognized?.ElementAt(35)); Assert.AreEqual(8, importFile.AnalysedCuesheet.Tracks.Count); Assert.IsNotNull(importFile.AnalysedCuesheet.CDTextfile); Assert.AreEqual(4, importFile.AnalysedCuesheet.Tracks.ElementAt(0).Flags.Count); diff --git a/AudioCuesheetEditorTests/Services/IO/ImportManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs similarity index 99% rename from AudioCuesheetEditorTests/Services/IO/ImportManagerTests.cs rename to AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs index bd98e833..76382dd6 100644 --- a/AudioCuesheetEditorTests/Services/IO/ImportManagerTests.cs +++ b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs @@ -19,7 +19,7 @@ using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Model.Options; using AudioCuesheetEditor.Model.UI; -using AudioCuesheetEditorTests.Utility; +using AudioCuesheetEditor.Tests.Utility; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System; diff --git a/AudioCuesheetEditorTests/Services/IO/TextImportServiceTests.cs b/AudioCuesheetEditor.Tests/Services/IO/TextImportServiceTests.cs similarity index 92% rename from AudioCuesheetEditorTests/Services/IO/TextImportServiceTests.cs rename to AudioCuesheetEditor.Tests/Services/IO/TextImportServiceTests.cs index 305c580e..06ef45b5 100644 --- a/AudioCuesheetEditorTests/Services/IO/TextImportServiceTests.cs +++ b/AudioCuesheetEditor.Tests/Services/IO/TextImportServiceTests.cs @@ -17,15 +17,15 @@ using AudioCuesheetEditor.Model.IO.Import; using AudioCuesheetEditor.Model.Options; using AudioCuesheetEditor.Model.Utility; -using AudioCuesheetEditorTests.Properties; +using AudioCuesheetEditor.Services.IO; +using AudioCuesheetEditor.Tests.Properties; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -namespace AudioCuesheetEditor.Services.IO.Tests +namespace AudioCuesheetEditor.Tests.Services.IO { [TestClass()] public class TextImportServiceTests @@ -34,7 +34,7 @@ public class TextImportServiceTests public void Analyse_SampleCuesheet_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist - CuesheetTitle c:\\tmp\\Testfile.mp3", "Sample Artist 1 - Sample Title 1 00:05:00", @@ -73,7 +73,7 @@ public void Analyse_SampleCuesheet_CreatesValidCuesheet() public void Analyse_InvalidSchemeTracks_CreatesAnalyseException() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist|CuesheetTitle c:\\tmp\\TestTextFile.cdt", "1|Sample Artist 1 - Sample Title 1 00:05:00", @@ -104,7 +104,7 @@ public void Analyse_InvalidSchemeTracks_CreatesAnalyseException() public void Analyse_InputfileWithExtraSeperator_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist|CuesheetTitle c:\\tmp\\TestTextFile.cdt", "1|Sample Artist 1 - Sample Title 1 00:05:00", @@ -144,7 +144,7 @@ public void Analyse_InputfileWithExtraSeperator_CreatesValidCuesheet() public void Analyse_InvalidScheme_CreatesAnalyseException() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist|CuesheetTitle c:\\tmp\\TestTextFile.cdt A83412346734", "1|Sample Artist 1 - Sample Title 1 00:05:00", @@ -155,14 +155,14 @@ public void Analyse_InvalidScheme_CreatesAnalyseException() "6|Sample Artist 6 - Sample Title 6 00:31:54", "7|Sample Artist 7 - Sample Title 7 00:45:54", "8|Sample Artist 8 - Sample Title 8 01:15:54", - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty }; var importService = new TextImportService(); var importOptions = new ImportOptions @@ -183,7 +183,7 @@ public void Analyse_InvalidScheme_CreatesAnalyseException() public void Analyse_CuesheetWithTextfileAndCatalogueNumber_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist|CuesheetTitle c:\\tmp\\TestTextFile.cdt A83412346734", "1|Sample Artist 1 - Sample Title 1 00:05:00", @@ -194,14 +194,14 @@ public void Analyse_CuesheetWithTextfileAndCatalogueNumber_CreatesValidCuesheet( "6|Sample Artist 6 - Sample Title 6 00:31:54", "7|Sample Artist 7 - Sample Title 7 00:45:54", "8|Sample Artist 8 - Sample Title 8 01:15:54", - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty, - String.Empty + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty }; var importService = new TextImportService(); var importOptions = new ImportOptions @@ -232,7 +232,7 @@ public void Analyse_CuesheetWithTextfileAndCatalogueNumber_CreatesValidCuesheet( public void Analyse_CuesheeTracksOnly_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "Sample Artist 1 - Sample Title 1 00:05:00", "Sample Artist 2 - Sample Title 2 00:09:23", @@ -270,15 +270,15 @@ public void Analyse_CuesheetBug213_CreatesValidCuesheet() // Arrange var textImportMemoryStream = new MemoryStream(Resources.Textimport_Bug_213); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); } var fileContent = lines.AsReadOnly(); var importService = new TextImportService(); - var importOptions = new ImportOptions() - { + var importOptions = new ImportOptions() + { TimeSpanFormat = new TimeSpanFormat() { Scheme = "(?'TimeSpanFormat.Minutes'\\d{1,})[:](?'TimeSpanFormat.Seconds'\\d{1,})" }, TextImportScheme = new TextImportScheme() { @@ -299,7 +299,7 @@ public void Analyse_CuesheetBug213_CreatesValidCuesheet() public void Analyse_CuesheetWithFlags_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "Sample Artist 1 - Sample Title 1 00:05:00 DCP", "Sample Artist 2 - Sample Title 2 00:09:23", @@ -342,7 +342,7 @@ public void Analyse_CuesheetWithFlags_CreatesValidCuesheet() public void Analyse_CuesheetWithPreGapAndPostGap_CreatesValidCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "Sample Artist 1 - Sample Title 1 00:00:02 00:05:00 00:00:00", "Sample Artist 2 - Sample Title 2 00:00:04 00:09:23 00:00:00", @@ -390,7 +390,7 @@ public void Analyse_CuesheetWithPreGapAndPostGap_CreatesValidCuesheet() public void Analyse_SchemeCuesheetOnly_CreatesFileContentRecognizedOnlyForCuesheet() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist - CuesheetTitle c:\\tmp\\Testfile.mp3", "Sample Artist 1 - Sample Title 1 00:05:00", @@ -417,10 +417,10 @@ public void Analyse_SchemeCuesheetOnly_CreatesFileContentRecognizedOnlyForCueshe Assert.IsNull(importfile.AnalyseException); Assert.IsNotNull(importfile.AnalysedCuesheet); Assert.IsNotNull(importfile.FileContentRecognized); - Assert.AreEqual(String.Format("{0} - {1} {2}", - String.Format(CuesheetConstants.RecognizedMarkHTML, "CuesheetArtist"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "CuesheetTitle"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "c:\\tmp\\Testfile.mp3")), importfile.FileContentRecognized.First()); + Assert.AreEqual(string.Format("{0} - {1} {2}", + string.Format(CuesheetConstants.RecognizedMarkHTML, "CuesheetArtist"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "CuesheetTitle"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "c:\\tmp\\Testfile.mp3")), importfile.FileContentRecognized.First()); Assert.AreEqual("CuesheetArtist", importfile.AnalysedCuesheet.Artist); Assert.AreEqual("CuesheetTitle", importfile.AnalysedCuesheet.Title); Assert.AreEqual("c:\\tmp\\Testfile.mp3", importfile.AnalysedCuesheet.Audiofile); @@ -439,7 +439,7 @@ public void Analyse_SchemeCuesheetOnly_CreatesFileContentRecognizedOnlyForCueshe public void Analyse_CuesheetWithoutTracks_CreatesValidFileContentRecognized() { // Arrange - var fileContent = new List + var fileContent = new List { "CuesheetArtist - CuesheetTitle c:\\tmp\\Testfile.mp3", "Sample Artist 1 - Sample Title 1 00:05:00", @@ -470,10 +470,10 @@ public void Analyse_CuesheetWithoutTracks_CreatesValidFileContentRecognized() Assert.AreEqual("Sample Artist 1", importfile.AnalysedCuesheet.Tracks.ElementAt(0).Artist); Assert.AreEqual("Sample Title 1", importfile.AnalysedCuesheet.Tracks.ElementAt(0).Title); Assert.AreEqual(new TimeSpan(0, 5, 0), importfile.AnalysedCuesheet.Tracks.ElementAt(0).End); - Assert.AreEqual(String.Format("{0} - {1} {2}", - String.Format(CuesheetConstants.RecognizedMarkHTML, "Sample Artist 8"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "Sample Title 8"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "01:15:54")), importfile.FileContentRecognized.Last()); + Assert.AreEqual(string.Format("{0} - {1} {2}", + string.Format(CuesheetConstants.RecognizedMarkHTML, "Sample Artist 8"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "Sample Title 8"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "01:15:54")), importfile.FileContentRecognized.Last()); } [TestMethod()] @@ -482,7 +482,7 @@ public void Analyse_TextfileBug233_CreatesValidFileContentRecognized() // Arrange var textImportMemoryStream = new MemoryStream(Resources.Textimport_Bug__233); using var reader = new StreamReader(textImportMemoryStream); - List lines = []; + List lines = []; while (reader.EndOfStream == false) { lines.Add(reader.ReadLine()); @@ -503,10 +503,10 @@ public void Analyse_TextfileBug233_CreatesValidFileContentRecognized() Assert.IsNull(importfile.AnalyseException); Assert.IsNotNull(importfile.AnalysedCuesheet); Assert.IsNotNull(importfile.FileContentRecognized); - Assert.AreEqual(String.Format("{0} - {1}\t\t\t\t\t\t\t\t{2}", - String.Format(CuesheetConstants.RecognizedMarkHTML, "Age Of Love"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "The Age Of Love (Charlotte De Witte & Enrico Sangiuliano Remix)"), - String.Format(CuesheetConstants.RecognizedMarkHTML, "04:29:28")), importfile.FileContentRecognized.ElementAt(53)); + Assert.AreEqual(string.Format("{0} - {1}\t\t\t\t\t\t\t\t{2}", + string.Format(CuesheetConstants.RecognizedMarkHTML, "Age Of Love"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "The Age Of Love (Charlotte De Witte & Enrico Sangiuliano Remix)"), + string.Format(CuesheetConstants.RecognizedMarkHTML, "04:29:28")), importfile.FileContentRecognized.ElementAt(53)); } } } \ No newline at end of file diff --git a/AudioCuesheetEditorTests/Utility/TestHelper.cs b/AudioCuesheetEditor.Tests/Utility/TestHelper.cs similarity index 91% rename from AudioCuesheetEditorTests/Utility/TestHelper.cs rename to AudioCuesheetEditor.Tests/Utility/TestHelper.cs index 9e303b2d..3b382b6c 100644 --- a/AudioCuesheetEditorTests/Utility/TestHelper.cs +++ b/AudioCuesheetEditor.Tests/Utility/TestHelper.cs @@ -13,15 +13,12 @@ //You should have received a copy of the GNU General Public License //along with Foobar. If not, see //. -using AudioCuesheetEditor.Model.Entity; -using AudioCuesheetEditor.Model.IO.Audio; using AudioCuesheetEditor.Model.Options; -using Blazorise.Localization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; -namespace AudioCuesheetEditorTests.Utility +namespace AudioCuesheetEditor.Tests.Utility { internal class TestHelper { diff --git a/AudioCuesheetEditor.sln b/AudioCuesheetEditor.sln index 9b561cc3..bbea4d79 100644 --- a/AudioCuesheetEditor.sln +++ b/AudioCuesheetEditor.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudioCuesheetEditor", "AudioCuesheetEditor\AudioCuesheetEditor.csproj", "{099AE4DF-4847-460F-BBF2-207B9A35B58D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudioCuesheetEditorTests", "AudioCuesheetEditorTests\AudioCuesheetEditorTests.csproj", "{12CA5D1F-D758-4016-85D0-A045AC06CFE6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AudioCuesheetEditor.Tests", "AudioCuesheetEditor.Tests\AudioCuesheetEditor.Tests.csproj", "{12CA5D1F-D758-4016-85D0-A045AC06CFE6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj index ff8fb902..d07c440b 100644 --- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj +++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj @@ -41,8 +41,6 @@ - - @@ -51,6 +49,16 @@ + + + + + + + + + + @@ -88,8 +96,14 @@ - - + + + + + + + + @@ -98,6 +112,8 @@ + + @@ -114,20 +130,20 @@ - - + + - - - - + + + + - + diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs index 755f4d14..b41356c4 100644 --- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs +++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs @@ -28,9 +28,9 @@ public enum MoveDirection Down } - public class TrackAddRemoveEventArgs(Track track) : EventArgs + public class TracksAddedRemovedEventArgs(IEnumerable tracks) : EventArgs { - public Track Track { get; } = track; + public IEnumerable Tracks { get; } = tracks; } public class CuesheetSectionAddRemoveEventArgs(CuesheetSection section) : EventArgs @@ -54,8 +54,8 @@ public class Cuesheet(TraceChangeManager? traceChangeManager = null) : Validatea public event EventHandler? AudioFileChanged; public event EventHandler? TraceablePropertyChanged; - public event EventHandler? TrackAdded; - public event EventHandler? TrackRemoved; + public event EventHandler? TracksAdded; + public event EventHandler? TracksRemoved; public event EventHandler? SectionAdded; public event EventHandler? SectionRemoved; @@ -212,7 +212,7 @@ public void RemoveSection(CuesheetSection section) public CuesheetSection? GetSectionAtTrack(Track track) { - return Sections?.FirstOrDefault(x => track.Begin < x.Begin && track.End >= x.Begin); + return Sections?.FirstOrDefault(x => track.Begin <= x.Begin && track.End >= x.Begin); } /// @@ -259,7 +259,7 @@ public void AddTrack(Track track, ApplicationOptions? applicationOptions = null, OnTraceablePropertyChanged(previousValue, nameof(Tracks)); if (IsImporting == false) { - TrackAdded?.Invoke(this, new TrackAddRemoveEventArgs(track)); + TracksAdded?.Invoke(this, new TracksAddedRemovedEventArgs([track])); } } @@ -299,7 +299,7 @@ public void RemoveTrack(Track track) } RecalculateLastTrackEnd(); OnTraceablePropertyChanged(previousValue, nameof(Tracks)); - TrackRemoved?.Invoke(this, new TrackAddRemoveEventArgs(track)); + TracksRemoved?.Invoke(this, new TracksAddedRemovedEventArgs([track])); } /// @@ -333,6 +333,7 @@ public void RemoveTracks(IReadOnlyCollection tracksToRemove) tracks.ForEach(x => x.IsLinkedToPreviousTrackChanged += Track_IsLinkedToPreviousTrackChanged); RecalculateLastTrackEnd(); OnTraceablePropertyChanged(previousValue, nameof(Tracks)); + TracksRemoved?.Invoke(this, new TracksAddedRemovedEventArgs(intersection)); } public Boolean MoveTrackPossible(Track track, MoveDirection moveDirection) diff --git a/AudioCuesheetEditor/Pages/EditSections.razor b/AudioCuesheetEditor/Pages/EditSections.razor index ebeb8d8a..24c721cb 100644 --- a/AudioCuesheetEditor/Pages/EditSections.razor +++ b/AudioCuesheetEditor/Pages/EditSections.razor @@ -180,8 +180,8 @@ along with Foobar. If not, see { track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; } - Cuesheet.TrackAdded -= Cuesheet_TrackAdded; - Cuesheet.TrackRemoved -= Cuesheet_TrackRemoved; + Cuesheet.TracksAdded -= Cuesheet_TracksAdded; + Cuesheet.TracksRemoved -= Cuesheet_TracksRemoved; } _traceChangeManager.UndoDone -= TraceChangeManager_UndoDone; _traceChangeManager.RedoDone -= TraceChangeManager_RedoDone; @@ -195,8 +195,8 @@ along with Foobar. If not, see _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; if (Cuesheet != null) { - Cuesheet.TrackAdded += Cuesheet_TrackAdded; - Cuesheet.TrackRemoved += Cuesheet_TrackRemoved; + Cuesheet.TracksAdded += Cuesheet_TracksAdded; + Cuesheet.TracksRemoved += Cuesheet_TracksRemoved; } _traceChangeManager.UndoDone += TraceChangeManager_UndoDone; _traceChangeManager.RedoDone += TraceChangeManager_RedoDone; @@ -230,15 +230,21 @@ along with Foobar. If not, see return Task.CompletedTask; } - void Cuesheet_TrackAdded(object? sender, TrackAddRemoveEventArgs args) + void Cuesheet_TracksAdded(object? sender, TracksAddedRemovedEventArgs args) { - args.Track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; + foreach (var track in args.Tracks) + { + track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; + } validations?.ValidateAll().GetAwaiter().GetResult(); } - void Cuesheet_TrackRemoved(object? sender, TrackAddRemoveEventArgs args) + void Cuesheet_TracksRemoved(object? sender, TracksAddedRemovedEventArgs args) { - args.Track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + foreach (var track in args.Tracks) + { + track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + } validations?.ValidateAll().GetAwaiter().GetResult(); } diff --git a/AudioCuesheetEditor/Pages/Index.razor b/AudioCuesheetEditor/Pages/Index.razor index b9d76fc5..5b897946 100644 --- a/AudioCuesheetEditor/Pages/Index.razor +++ b/AudioCuesheetEditor/Pages/Index.razor @@ -59,7 +59,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + @@ -100,8 +100,10 @@ along with Foobar. If not, see ModalDialog? modalDialog; AudioPlayer? audioPlayer; - protected override async Task OnInitializedAsync() + protected override void OnInitialized() { + base.OnInitialized(); + _logger.LogDebug("OnInitializedAsync"); _logger.LogInformation("CultureInfo.CurrentCulture = {0}", CultureInfo.CurrentCulture); @@ -113,18 +115,12 @@ along with Foobar. If not, see .Add(ModKey.Ctrl, Key.y, () => _traceChangeManager.Redo()); _sessionStateContainer.CurrentViewModeChanged += CurrentViewModeChanged; - - var dotNetReference = DotNetObjectReference.Create(this); - await _jsRuntime.InvokeVoidAsync("GLOBAL.SetIndexReference", dotNetReference); } - protected override async Task OnParametersSetAsync() + protected override void OnParametersSet() { - await base.OnParametersSetAsync(); - if (mainLayout != null) - { - mainLayout.SetDisplayMenuBar(true); - } + base.OnParametersSet(); + mainLayout?.SetDisplayMenuBar(true); } async ValueTask OnEnterKeyDown() diff --git a/AudioCuesheetEditor/Pages/ViewModeImport.razor b/AudioCuesheetEditor/Pages/ViewModeImport.razor index 05cf22ba..8f302f3c 100644 --- a/AudioCuesheetEditor/Pages/ViewModeImport.razor +++ b/AudioCuesheetEditor/Pages/ViewModeImport.razor @@ -135,7 +135,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + diff --git a/AudioCuesheetEditor/Pages/ViewModeRecord.razor b/AudioCuesheetEditor/Pages/ViewModeRecord.razor index b4508cc9..30c402bd 100644 --- a/AudioCuesheetEditor/Pages/ViewModeRecord.razor +++ b/AudioCuesheetEditor/Pages/ViewModeRecord.razor @@ -108,7 +108,7 @@ along with Foobar. If not, see @_localizer["Tracks"] - + diff --git a/AudioCuesheetEditor/Program.cs b/AudioCuesheetEditor/Program.cs index ca84b218..e03f3db7 100644 --- a/AudioCuesheetEditor/Program.cs +++ b/AudioCuesheetEditor/Program.cs @@ -18,7 +18,6 @@ using AudioCuesheetEditor.Data.Services; using AudioCuesheetEditor.Extensions; using AudioCuesheetEditor.Model.UI; -using AudioCuesheetEditor.Model.Utility; using AudioCuesheetEditor.Services.IO; using AudioCuesheetEditor.Services.UI; using BlazorDownloadFile; diff --git a/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json new file mode 100644 index 00000000..5c21be15 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/de.json @@ -0,0 +1,7 @@ +{ + "culture": "de", + "translations": { + "Unlink this track from previous track": "Diesen Titel vom vorherigen Titel abkoppeln", + "Link this track with previous track": "Diesen Titel an den vorherigen Titel koppeln" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json new file mode 100644 index 00000000..5effbf15 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackLinkControl/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "translations": { + "Unlink this track from previous track": "Unlink this track from previous track", + "Link this track with previous track": "Link this track with previous track" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackList/de.json b/AudioCuesheetEditor/Resources/Localization/TrackList/de.json new file mode 100644 index 00000000..1407eb91 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackList/de.json @@ -0,0 +1,25 @@ +{ + "culture": "de", + "translations": { + "Add new track": "Neuen Titel hinzufügen", + "Display selection of tracks": "Auswahl einblenden", + "Selection": "Auswahl", + "Select all": "Wählen Sie alle Spuren für Mehrfachspuroperationen aus", + "Delete selected tracks": "Ausgewählte löschen", + "Hide selection of tracks": "Auswahl ausblenden", + "Delete all tracks": "Alle Titel löschen", + "Controls": "Steuerung", + "Artist": "Künstler", + "Title": "Titel", + "Begin": "Beginn", + "End": "Ende", + "Length": "Länge", + "Position": "Position", + "Abort": "Abbrechen", + "Save changes": "Änderungen speichern", + "Confirmation required": "Bestätigung erforderlich", + "Do you really want to delete all tracks?": "Möchten Sie wirklich alle Titel löschen?", + "Edit selected tracks": "Ausgewählte Titel bearbeiten", + "Validation errors": "Validierungsfehler" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackList/en.json b/AudioCuesheetEditor/Resources/Localization/TrackList/en.json new file mode 100644 index 00000000..16d63fb6 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackList/en.json @@ -0,0 +1,25 @@ +{ + "culture": "en", + "translations": { + "Add new track": "Add new track", + "Display selection of tracks": "Display selection", + "Selection": "Selection", + "Select all": "Select all track for multiple track operations", + "Delete selected tracks": "Delete selected", + "Hide selection of tracks": "Hide selection", + "Delete all tracks": "Delete all tracks", + "Controls": "Controls", + "Artist": "Artist", + "Title": "Title", + "Begin": "Begin", + "End": "End", + "Length": "Length", + "Position": "Position", + "Abort": "Abort", + "Save changes": "Save changes", + "Confirmation required": "Confirmation required", + "Do you really want to delete all tracks?": "Do you really want to delete all tracks?", + "Edit selected tracks": "Edit selected tracks", + "Validation errors": "Validation errors" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackListItem/de.json b/AudioCuesheetEditor/Resources/Localization/TrackListItem/de.json new file mode 100644 index 00000000..f7bdaaf0 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackListItem/de.json @@ -0,0 +1,7 @@ +{ + "culture": "de", + "translations": { + "Current track is played": "Dieser Track wird aktuell wiedergegeben", + "A split point is currently set at the time of this track": "Ein Aufteilungspunkt ist aktuell in dem Zeitfenster dieses Titels gesetzt" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackListItem/en.json b/AudioCuesheetEditor/Resources/Localization/TrackListItem/en.json new file mode 100644 index 00000000..b8f6bf35 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackListItem/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "translations": { + "Current track is played": "Current track is played", + "A split point is currently set at the time of this track": "A split point is currently set at the time of this track" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/de.json b/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/de.json new file mode 100644 index 00000000..04281f60 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/de.json @@ -0,0 +1,11 @@ +{ + "culture": "de", + "translations": { + "Edit track tooltip": "Titeldetails in einem Dialog bearbeiten", + "Copy track tooltip": "Kopiere diesen Titel mit allen Werten und füge ihn anschließend zum Cuesheet hinzu.", + "Start playback this track": "Diesen Titel wiedergeben", + "Move track up tooltip": "Diesen Titel eine Position nach oben schieben", + "Delete track tooltip": "Diesen Titel löschen", + "Move track down tooltip": "Diesen Titel eine Position nach unten schieben" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/en.json b/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/en.json new file mode 100644 index 00000000..144c6602 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackListItemControlColumn/en.json @@ -0,0 +1,11 @@ +{ + "culture": "en", + "translations": { + "Edit track tooltip": "Edit track details in a dialog", + "Copy track tooltip": "Copy this track with all values and attach it to the cuesheet.", + "Start playback this track": "Start playing this track", + "Move track up tooltip": "Move this track one position up", + "Delete track tooltip": "Delete this track", + "Move track down tooltip": "Move this track one position down" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackSelection/de.json b/AudioCuesheetEditor/Resources/Localization/TrackSelection/de.json new file mode 100644 index 00000000..7d261e5e --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackSelection/de.json @@ -0,0 +1,6 @@ +{ + "culture": "de", + "translations": { + "Select this track for multiple track operations": "Diesen Titel in Mehrfachauswahl übernehmen" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TrackSelection/en.json b/AudioCuesheetEditor/Resources/Localization/TrackSelection/en.json new file mode 100644 index 00000000..a61c2a09 --- /dev/null +++ b/AudioCuesheetEditor/Resources/Localization/TrackSelection/en.json @@ -0,0 +1,6 @@ +{ + "culture": "en", + "translations": { + "Select this track for multiple track operations": "Select this track for multiple track operations" + } +} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TracksTable/de.json b/AudioCuesheetEditor/Resources/Localization/TracksTable/de.json deleted file mode 100644 index 3a738f1a..00000000 --- a/AudioCuesheetEditor/Resources/Localization/TracksTable/de.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "culture": "de", - "translations": { - "Add new track": "Neuen Titel hinzufügen", - "Display selection of tracks": "Auswahl einblenden", - "Selection": "Auswahl", - "Select this track for multiple track operations": "Diesen Titel in Mehrfachauswahl übernehmen", - "Select all": "Wählen Sie alle Spuren für Mehrfachspuroperationen aus", - "Delete selected tracks": "Ausgewählte löschen", - "Hide selection of tracks": "Auswahl ausblenden", - "Delete all tracks": "Alle Titel löschen", - "Controls": "Steuerung", - "Artist": "Künstler", - "Title": "Titel", - "Begin": "Beginn", - "End": "Ende", - "Length": "Länge", - "Unlink this track from previous track": "Diesen Titel vom vorherigen Titel abkoppeln", - "Link this track with previous track": "Diesen Titel an den vorherigen Titel koppeln", - "Current track is played": "Dieser Track wird aktuell wiedergegeben", - "Edit track tooltip": "Titeldetails in einem Dialog bearbeiten", - "Copy track tooltip": "Kopiere diesen Titel mit allen Werten und füge ihn anschließend zum Cuesheet hinzu.", - "Start playback this track": "Diesen Titel wiedergeben", - "Move track up tooltip": "Diesen Titel eine Position nach oben schieben", - "Delete track tooltip": "Diesen Titel löschen", - "Move track down tooltip": "Diesen Titel eine Position nach unten schieben", - "Position": "Position", - "Abort": "Abbrechen", - "Save changes": "Änderungen speichern", - "Confirmation required": "Bestätigung erforderlich", - "Do you really want to delete all tracks?": "Möchten Sie wirklich alle Titel löschen?", - "Edit selected tracks": "Ausgewählte Titel bearbeiten", - "Validation errors": "Validierungsfehler", - "A split point is currently set at the time of this track": "Ein Aufteilungspunkt ist aktuell in dem Zeitfenster dieses Titels gesetzt" - } -} \ No newline at end of file diff --git a/AudioCuesheetEditor/Resources/Localization/TracksTable/en.json b/AudioCuesheetEditor/Resources/Localization/TracksTable/en.json deleted file mode 100644 index 819ccbf3..00000000 --- a/AudioCuesheetEditor/Resources/Localization/TracksTable/en.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "culture": "en", - "translations": { - "Add new track": "Add new track", - "Display selection of tracks": "Display selection", - "Selection": "Selection", - "Select this track for multiple track operations": "Select this track for multiple track operations", - "Select all": "Select all track for multiple track operations", - "Delete selected tracks": "Delete selected", - "Hide selection of tracks": "Hide selection", - "Delete all tracks": "Delete all tracks", - "Controls": "Controls", - "Artist": "Artist", - "Title": "Title", - "Begin": "Begin", - "End": "End", - "Length": "Length", - "Unlink this track from previous track": "Unlink this track from previous track", - "Link this track with previous track": "Link this track with previous track", - "Current track is played": "Current track is played", - "Edit track tooltip": "Edit track details in a dialog", - "Copy track tooltip": "Copy this track with all values and attach it to the cuesheet.", - "Start playback this track": "Start playing this track", - "Move track up tooltip": "Move this track one position up", - "Delete track tooltip": "Delete this track", - "Move track down tooltip": "Move this track one position down", - "Position": "Position", - "Abort": "Abort", - "Save changes": "Save changes", - "Confirmation required": "Confirmation required", - "Do you really want to delete all tracks?": "Do you really want to delete all tracks?", - "Edit selected tracks": "Edit selected tracks", - "Validation errors": "Validation errors", - "A split point is currently set at the time of this track": "A split point is currently set at the time of this track" - } -} \ No newline at end of file diff --git a/AudioCuesheetEditor/Shared/MainLayout.razor b/AudioCuesheetEditor/Shared/MainLayout.razor index ea35a241..b1b270f1 100644 --- a/AudioCuesheetEditor/Shared/MainLayout.razor +++ b/AudioCuesheetEditor/Shared/MainLayout.razor @@ -280,138 +280,141 @@ along with Foobar. If not, see - - @_localizer["Select exportprofile"] - - - - - @_localizer["Add new exportprofile"] - @_localizer["Delete selected exportprofile"] - - - - @_localizer["Name"] - - - - - - - - - - - - @_localizer["Filename"] - - - - - - - - - - - - - - @_localizer["Exportprofilescheme head"] - - - - - - - - - - - - - - - @_localizer["Select placeholder"] - - - @foreach (var availableScheme in Exportprofile.AvailableCuesheetSchemes) - { - @_localizer[availableScheme.Key] - } - - - - - - - - - - - - @_localizer["Exportprofilescheme track"] - - - - - - - - - - - - - - - @_localizer["Select placeholder"] - - - @foreach (var availableScheme in Exportprofile.AvailableTrackSchemes) - { - @_localizer[availableScheme.Key] - } - - - - - - - - - - - - @_localizer["Exportprofilescheme footer"] - - + @if (exportOptions != null) + { + + @_localizer["Select exportprofile"] - - - - - - - - - - - - @_localizer["Select placeholder"] - - - @foreach (var availableScheme in Exportprofile.AvailableCuesheetSchemes) - { - @_localizer[availableScheme.Key] - } - - - - + - + @_localizer["Add new exportprofile"] + @_localizer["Delete selected exportprofile"] + + + + @_localizer["Name"] + + + + + + + + + + + + @_localizer["Filename"] + + + + + + + + + + + + + + @_localizer["Exportprofilescheme head"] + + + + + + + + + + + + + + + @_localizer["Select placeholder"] + + + @foreach (var availableScheme in Exportprofile.AvailableCuesheetSchemes) + { + @_localizer[availableScheme.Key] + } + + + + + + + + + + + + @_localizer["Exportprofilescheme track"] + + + + + + + + + + + + + + + @_localizer["Select placeholder"] + + + @foreach (var availableScheme in Exportprofile.AvailableTrackSchemes) + { + @_localizer[availableScheme.Key] + } + + + + + + + + + + + + @_localizer["Exportprofilescheme footer"] + + + + + + + + + + + + + + + @_localizer["Select placeholder"] + + + @foreach (var availableScheme in Exportprofile.AvailableCuesheetSchemes) + { + @_localizer[availableScheme.Key] + } + + + + + + + + } diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor b/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor new file mode 100644 index 00000000..40260a05 --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackLinkControl.razor @@ -0,0 +1,98 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject ITextLocalizerService _localizationService +@inject SessionStateContainer _sessionStateContainer + +@if ((TrackReference != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) +{ + + + @if (TrackReference?.IsLinkedToPreviousTrack == true) + { + + + + + @_localizer["Unlink this track from previous track"] + + } + else + { + + + + + @_localizer["Link this track with previous track"] + + } + + +} + +@code { + [Parameter, EditorRequired] + public Boolean TrackSelectionVisible { get; set; } + + [Parameter, EditorRequired] + public Track? TrackReference { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + } + + void SetLink(Boolean linkState) + { + if (TrackReference != null) + { + TrackReference.IsLinkedToPreviousTrack = linkState; + } + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackList.razor b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor new file mode 100644 index 00000000..88e92d6a --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackList.razor @@ -0,0 +1,474 @@ + + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject SessionStateContainer _sessionStateContainer +@inject ILocalStorageOptionsProvider _localStorageOptionsProvider +@inject TraceChangeManager _traceChangeManager +@inject ILogger _logger +@inject ITextLocalizerService _localizationService +@inject ITextLocalizer _validationMessageLocalizer + + + @if (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) + { + var validationResult = Cuesheet?.Validate(x => x.Tracks); + + + @_localizer["Validation errors"] + + @if (validationResult?.ValidationMessages != null) + { + @foreach(var message in validationResult.ValidationMessages) + { + @message.GetMessageLocalized(_validationMessageLocalizer) + } + } + + + + + + + + + + + @_localizer["Add new track"] + + + + + + @if (TrackSelectionVisible == false) + { + + + + + + + + @_localizer["Display selection of tracks"] + + + + } + else + { + + + + + + + + @_localizer["Hide selection of tracks"] + + + + } + + + + + + + + + + @_localizer["Edit selected tracks"] + + + + + + + + + + @_localizer["Delete selected tracks"] + + + + + + + + + + @_localizer["Delete all tracks"] + + + + + + + } + + + + + @if ((_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) && (TrackSelectionVisible)) + { + + + @if (Cuesheet?.Tracks.Count > 0) + { + + + + } + @_localizer["Selection"] + + + } + @switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + @_localizer["Controls"] + break; + case ViewMode.ViewModeRecord: + @_localizer["Controls"] + break; + } + # + @_localizer["Artist"] + @_localizer["Title"] + @_localizer["Begin"] + @_localizer["End"] + @_localizer["Length"] + + + + + + + + + + + +@code { + ModalDialog? modalDialog; + EditTrackModal? modalTrackEdit; + List selectedTracks = new(); + Boolean _trackSelectionVisible = false; + Validations? validations; + Boolean revalidate = false; + List TracksAttachedToValidateablePropertyChanged = new(); + + [Parameter] + public AudioPlayer? AudioPlayer { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + public Boolean TrackSelectionVisible + { + get => _trackSelectionVisible; + set + { + _trackSelectionVisible = value; + selectedTracks = new(); + } + } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + _sessionStateContainer.CuesheetChanged -= SessionStateContainer_CuesheetChanged; + _sessionStateContainer.ImportCuesheetChanged -= SessionStateContainer_ImportCuesheetChanged; + _sessionStateContainer.Cuesheet.TracksRemoved -= Cuesheet_TracksRemoved; + _sessionStateContainer.Cuesheet.TracksAdded -= Cuesheet_TracksAdded; + DetachTrackFromValidateablePropertyChanged(); + DetachCuesheetFromSplitPointsAddedRemoved(); + } + + protected override void OnInitialized() + { + base.OnInitialized(); + + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + + _sessionStateContainer.CuesheetChanged += SessionStateContainer_CuesheetChanged; + _sessionStateContainer.ImportCuesheetChanged += SessionStateContainer_ImportCuesheetChanged; + + _sessionStateContainer.Cuesheet.TracksAdded += Cuesheet_TracksAdded; + _sessionStateContainer.Cuesheet.TracksRemoved += Cuesheet_TracksRemoved; + + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + _logger.LogDebug("OnAfterRenderAsync({firstRender})", firstRender); + if ((revalidate) && (validations != null)) + { + await validations.ValidateAll(); + revalidate = false; + } + } + + async Task OnAddTrackClicked() + { + var applicationOptions = await _localStorageOptionsProvider.GetOptions(); + var newTrack = new Track(); + Cuesheet?.AddTrack(newTrack, applicationOptions); + _traceChangeManager.TraceChanges(newTrack); + } + + async Task EditSelectedTracksClicked() + { + if (modalTrackEdit != null) + { + modalTrackEdit.TracksToEdit = selectedTracks; + await modalTrackEdit.Show(); + } + } + + private void DeleteSelectedTracksClicked() + { + Cuesheet?.RemoveTracks(selectedTracks.AsReadOnly()); + selectedTracks.Clear(); + } + + async Task OnDeleteAllTracksClicked() + { + _logger.LogInformation("OnDeleteAllTracksClicked"); + //Display a confirm warning + if (modalDialog != null) + { + modalDialog.Title = _localizer["Confirmation required"]; + modalDialog.Text = _localizer["Do you really want to delete all tracks?"]; + modalDialog.ModalSize = ModalSize.Small; + modalDialog.Mode = ModalDialog.DialogMode.Confirm; + void deleteTracksDelegate(object? sender, EventArgs args) + { + _logger.LogInformation("deleteTracksDelegate"); + Cuesheet?.RemoveTracks(Cuesheet.Tracks); + selectedTracks.Clear(); + modalDialog.Confirmed -= deleteTracksDelegate; + StateHasChanged(); + }; + modalDialog.Confirmed += deleteTracksDelegate; + await modalDialog.ShowModal(); + } + } + + private String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) + { + if (expressionToCheck == true) + { + return _localizer[localizedStringName]; + } + else + { + return null; + } + } + + bool SelectAllIndeterminate + { + get => selectedTracks.Count > 0 && selectedTracks.Count < Cuesheet?.Tracks.Count; + } + + private void OnSelectAllTracks(bool select) + { + if (select) + { + if (Cuesheet != null) + { + foreach (var track in Cuesheet.Tracks) + { + if (!selectedTracks.Contains(track)) + { + selectedTracks.Add(track); + } + } + } + } + else + { + selectedTracks.Clear(); + } + } + + bool AllTracksSelected + { + get => selectedTracks.Count > 0 && selectedTracks.Count == Cuesheet?.Tracks.Count; + } + + private void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + validations?.ValidateAll(); + } + + private MarkupString GetMarkupString(String? stringValue) + { + MarkupString result = new MarkupString(String.Empty); + if (stringValue != null) + { + result = new MarkupString(stringValue); + } + return result; + } + + private void SessionStateContainer_CuesheetChanged(object? sender, EventArgs args) + { + DetachTrackFromValidateablePropertyChanged(); + DetachCuesheetFromSplitPointsAddedRemoved(); + selectedTracks.Clear(); + StateHasChanged(); + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + } + + private void SessionStateContainer_ImportCuesheetChanged(object? sender, EventArgs args) + { + // Unsubscribe to previous attached events + DetachCuesheetFromSplitPointsAddedRemoved(); + var tracks = TracksAttachedToValidateablePropertyChanged.Except(_sessionStateContainer.Cuesheet.Tracks); + for (int i = tracks.Count() - 1; i >= 0; i--) + { + var track = tracks.ElementAt(i); + DetachTrackFromValidateablePropertyChanged(track); + TracksAttachedToValidateablePropertyChanged.Remove(track); + } + // Reattach if needed + AttachTracksToValidateablePropertyChanged(); + AttachCuesheetToSplitPointsAddedRemoved(); + revalidate = true; + StateHasChanged(); + } + + void Cuesheet_TracksAdded(object? sender, TracksAddedRemovedEventArgs args) + { + StateHasChanged(); + AttachTracksToValidateablePropertyChanged(); + revalidate = true; + } + + void Cuesheet_TracksRemoved(object? sender, TracksAddedRemovedEventArgs args) + { + foreach(var track in args.Tracks) + { + DetachTrackFromValidateablePropertyChanged(track); + } + revalidate = true; + } + + void AttachTracksToValidateablePropertyChanged() + { + if (Cuesheet != null) + { + foreach (var track in Cuesheet.Tracks) + { + if (TracksAttachedToValidateablePropertyChanged.Contains(track) == false) + { + track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; + TracksAttachedToValidateablePropertyChanged.Add(track); + } + } + } + } + + void DetachTrackFromValidateablePropertyChanged(Track? track = null) + { + if (track == null) + { + foreach (var trackCurrentlyAttached in TracksAttachedToValidateablePropertyChanged) + { + trackCurrentlyAttached.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + } + } + else + { + track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; + } + } + + void Track_ValidateablePropertyChanged(object? sender, string property) + { + if (validations != null) + { + validations.ValidateAll().GetAwaiter().GetResult(); + } + StateHasChanged(); + } + + void AttachCuesheetToSplitPointsAddedRemoved() + { + if (Cuesheet != null) + { + Cuesheet.SectionAdded += Cuesheet_SectionAdded; + Cuesheet.SectionRemoved += Cuesheet_SectionRemoved; + } + } + + void DetachCuesheetFromSplitPointsAddedRemoved() + { + if (Cuesheet != null) + { + Cuesheet.SectionAdded -= Cuesheet_SectionAdded; + Cuesheet.SectionRemoved -= Cuesheet_SectionRemoved; + } + } + + void Cuesheet_SectionAdded(object? sender, CuesheetSectionAddRemoveEventArgs args) + { + args.Section.ValidateablePropertyChanged += Section_ValidateablePropertyChanged; + } + + void Cuesheet_SectionRemoved(object? sender, CuesheetSectionAddRemoveEventArgs args) + { + args.Section.ValidateablePropertyChanged -= Section_ValidateablePropertyChanged; + } + + void Section_ValidateablePropertyChanged(object? sender, string property) + { + switch (property) + { + case nameof(CuesheetSection.Begin): + case nameof(CuesheetSection.End): + StateHasChanged(); + break; + } + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor new file mode 100644 index 00000000..b111092f --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItem.razor @@ -0,0 +1,301 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject SessionStateContainer _sessionStateContainer +@inject ITextLocalizer _validationMessageLocalizer +@inject TraceChangeManager _traceChangeManager +@inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser +@inject MusicBrainzDataProvider _musicBrainzDataProvider +@inject ITextLocalizerService _localizationService +@inject ILocalStorageOptionsProvider _localStorageOptionsProvider +@inject ILogger _logger + + + @if (Cuesheet != null) + { + + + + + + + + + + @if (context.Item.Disambiguation != null) + { + @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) + } + else + { + @context.Text + } + + + + + + + + + @if (context.Item.Disambiguation != null) + { + @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) + } + else + { + @context.Text + } + + + + + @switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeRecord: + @track.Begin + @track.End + @track.Length + break; + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + + + @if (Cuesheet?.GetSectionAtTrack(track) != null) + { + + + + + + + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + break; + } + + + } + + + + +@code { + EditTrackModal? modalTrackEdit; + Validations? validations; + IEnumerable? autocompleteTrackArtists; + IEnumerable? autocompleteTrackTitles; + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + _traceChangeManager.UndoDone -= TraceChangeManager_UndoDone; + _traceChangeManager.RedoDone -= TraceChangeManager_RedoDone; + } + + [Parameter, EditorRequired] + public Boolean TrackSelectionVisible { get; set; } + + [Parameter, EditorRequired] + public IReadOnlyCollection? SelectedTracks { get; set; } + + [Parameter] + public EventCallback> SelectedTracksChanged { get; set; } + + [Parameter, EditorRequired] + public AudioPlayer? AudioPlayer { get; set; } + + public Cuesheet? Cuesheet + { + get + { + Cuesheet? cuesheet; + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeImport: + cuesheet = _sessionStateContainer.ImportCuesheet; + break; + default: + cuesheet = _sessionStateContainer.Cuesheet; + break; + } + return cuesheet; + } + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + _traceChangeManager.UndoDone += TraceChangeManager_UndoDone; + _traceChangeManager.RedoDone += TraceChangeManager_RedoDone; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + validations?.ValidateAll(); + } + + String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) + { + if (expressionToCheck == true) + { + return _localizer[localizedStringName]; + } + else + { + return null; + } + } + + async Task EditTrackModal(Track trackToEdit) + { + if (modalTrackEdit != null) + { + modalTrackEdit.TracksToEdit = new List() { trackToEdit }; + await modalTrackEdit.Show(); + } + } + + async Task CopyTrackClicked(Track trackToCopy) + { + var copy = new Track(trackToCopy); + var applicationOptions = await _localStorageOptionsProvider.GetOptions(); + Cuesheet?.AddTrack(copy, applicationOptions); + _traceChangeManager.TraceChanges(copy); + await EditTrackModal(copy); + } + + void SelectedTrackChanged(Track track, bool selected) + { + var selectedTracks = new List(); + if (SelectedTracks != null) + { + selectedTracks.AddRange(SelectedTracks); + } + if (selected) + { + selectedTracks.Add(track); + } + else + { + selectedTracks.Remove(track); + } + SelectedTracksChanged.InvokeAsync(selectedTracks); + } + + async Task OnReadDataAutocompleteTrackArtist(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs) + { + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + var artists = await _musicBrainzDataProvider.SearchArtistAsync(autocompleteReadDataEventArgs.SearchValue); + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + autocompleteTrackArtists = artists; + } + } + } + + async Task OnReadDataAutocompleteTrackTitle(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs, Track track) + { + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + var titles = await _musicBrainzDataProvider.SearchTitleAsync(autocompleteReadDataEventArgs.SearchValue, track.Artist); + if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) + { + autocompleteTrackTitles = titles; + } + } + } + + async Task OnSelectedValueChangedTrackTitle(Guid selectedValue, Track track) + { + switch (_sessionStateContainer.CurrentViewMode) + { + case ViewMode.ViewModeFull: + case ViewMode.ViewModeImport: + var trackDetails = await _musicBrainzDataProvider.GetDetailsAsync(selectedValue); + if (trackDetails != null) + { + track.Length = trackDetails.Length; + if (String.IsNullOrEmpty(track.Artist)) + { + track.Artist = trackDetails.Artist; + } + } + break; + } + } + + void TrackDeleted(Track track) + { + var selectedTracks = new List(); + if (SelectedTracks != null) + { + selectedTracks.AddRange(SelectedTracks); + } + selectedTracks.Remove(track); + SelectedTracksChanged.InvokeAsync(selectedTracks); + } + + void TraceChangeManager_UndoDone(object? sender, EventArgs args) + { + StateHasChanged(); + } + + void TraceChangeManager_RedoDone(object? sender, EventArgs args) + { + StateHasChanged(); + } +} diff --git a/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor b/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor new file mode 100644 index 00000000..59c0418d --- /dev/null +++ b/AudioCuesheetEditor/Shared/TrackList/TrackListItemControlColumn.razor @@ -0,0 +1,210 @@ + +@implements IDisposable + +@inject ITextLocalizer _localizer +@inject ITextLocalizerService _localizationService + +@if (Visible) +{ + + + + + +} + +@code { + [Parameter, EditorRequired] + public Boolean Visible { get; set; } + + [Parameter, EditorRequired] + public bool Selected { get; set; } + + [Parameter, EditorRequired] + public EventCallback SelectedChanged { get; set; } + + public void Dispose() + { + _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; + } + + protected override void OnInitialized() + { + base.OnInitialized(); + _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; + } + + void LocalizationService_LocalizationChanged(object? sender, EventArgs args) + { + StateHasChanged(); + } +} diff --git a/AudioCuesheetEditor/Shared/TracksTable.razor b/AudioCuesheetEditor/Shared/TracksTable.razor deleted file mode 100644 index 61947058..00000000 --- a/AudioCuesheetEditor/Shared/TracksTable.razor +++ /dev/null @@ -1,805 +0,0 @@ - - -@implements IDisposable - -@inject ITextLocalizer _localizer -@inject SessionStateContainer _sessionStateContainer -@inject ILocalStorageOptionsProvider _localStorageOptionsProvider -@inject TraceChangeManager _traceChangeManager -@inject ILogger _logger -@inject ITextLocalizerService _localizationService -@inject MusicBrainzDataProvider _musicBrainzDataProvider -@inject ITextLocalizer _validationMessageLocalizer -@inject ApplicationOptionsTimeSpanParser _applicationOptionsTimeSpanParser - - - @if (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) - { - var validationResult = Cuesheet?.Validate(x => x.Tracks); - - - @_localizer["Validation errors"] - - @if (validationResult?.ValidationMessages != null) - { - @foreach(var message in validationResult.ValidationMessages) - { - @message.GetMessageLocalized(_validationMessageLocalizer) - } - } - - - - - - - - - - - @_localizer["Add new track"] - - - - - - @if (TrackSelectionVisible == false) - { - - - - - - - - @_localizer["Display selection of tracks"] - - - - } - else - { - - - - - - - - @_localizer["Hide selection of tracks"] - - - - } - - - - - - - - - - @_localizer["Edit selected tracks"] - - - - - - - - - - @_localizer["Delete selected tracks"] - - - - - - - - - - @_localizer["Delete all tracks"] - - - - - - - } - - - - - @if ((_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull) && (TrackSelectionVisible)) - { - - - @if (Cuesheet?.Tracks.Count > 0) - { - - - - } - @_localizer["Selection"] - - - } - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - @_localizer["Controls"] - break; - case ViewMode.ViewModeRecord: - @_localizer["Controls"] - break; - } - # - @_localizer["Artist"] - @_localizer["Title"] - @_localizer["Begin"] - @_localizer["End"] - @_localizer["Length"] - - - - @if (Cuesheet != null) - { - - @if ((track != Cuesheet?.Tracks.FirstOrDefault()) && (_sessionStateContainer.CurrentViewMode == ViewMode.ViewModeFull)) - { - - - @if (track.IsLinkedToPreviousTrack) - { - - - - - @_localizer["Unlink this track from previous track"] - - } - else - { - - - - - @_localizer["Link this track with previous track"] - - } - - - } - - @if (TrackSelectionVisible) - { - - - - - - } - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeRecord: - - - - - - - - @track.Position - break; - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - break; - } - - - - - @if (context.Item.Disambiguation != null) - { - @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) - } - else - { - @context.Text - } - - - - - - - - - @if (context.Item.Disambiguation != null) - { - @String.Format("{0} ({1})", context.Text, context.Item.Disambiguation) - } - else - { - @context.Text - } - - - - - @switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeRecord: - @track.Begin - @track.End - @track.Length - break; - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - - - @if (Cuesheet?.GetSectionAtTrack(track) != null) - { - - - - - - - - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - break; - } - - - } - - - - - - - -@code { - ModalDialog? modalDialog; - EditTrackModal? modalTrackEdit; - List selectedTracks = new(); - IEnumerable? autocompleteTrackArtists; - IEnumerable? autocompleteTrackTitles; - Boolean _trackSelectionVisible = false; - //Saved locally because of performance (do not load everytime something is edited) - ApplicationOptions? applicationOptions; - Validations? validations; - Boolean revalidate = false; - List TracksAttachedToValidateablePropertyChanged = new(); - - [Parameter] - public AudioPlayer? AudioPlayer { get; set; } - - public Cuesheet? Cuesheet - { - get - { - Cuesheet? cuesheet; - switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeImport: - cuesheet = _sessionStateContainer.ImportCuesheet; - break; - default: - cuesheet = _sessionStateContainer.Cuesheet; - break; - } - return cuesheet; - } - } - - public Boolean TrackSelectionVisible - { - get => _trackSelectionVisible; - set - { - _trackSelectionVisible = value; - selectedTracks = new(); - } - } - - public void Dispose() - { - _localizationService.LocalizationChanged -= LocalizationService_LocalizationChanged; - _localStorageOptionsProvider.OptionSaved -= LocalStorageOptionsProvider_OptionSaved; - _sessionStateContainer.CuesheetChanged -= SessionStateContainer_CuesheetChanged; - _sessionStateContainer.ImportCuesheetChanged -= SessionStateContainer_ImportCuesheetChanged; - _traceChangeManager.UndoDone -= TraceChangeManager_UndoDone; - _traceChangeManager.RedoDone -= TraceChangeManager_RedoDone; - _sessionStateContainer.Cuesheet.TrackRemoved -= Cuesheet_TrackRemoved; - _sessionStateContainer.Cuesheet.TrackAdded -= Cuesheet_TrackAdded; - DetachTrackFromValidateablePropertyChanged(); - DetachCuesheetFromSplitPointsAddedRemoved(); - } - - protected override async Task OnInitializedAsync() - { - _logger.LogDebug("OnInitializedAsync"); - - _localizationService.LocalizationChanged += LocalizationService_LocalizationChanged; - - applicationOptions = await _localStorageOptionsProvider.GetOptions(); - _localStorageOptionsProvider.OptionSaved += LocalStorageOptionsProvider_OptionSaved; - - _sessionStateContainer.CuesheetChanged += SessionStateContainer_CuesheetChanged; - _sessionStateContainer.ImportCuesheetChanged += SessionStateContainer_ImportCuesheetChanged; - - _traceChangeManager.UndoDone += TraceChangeManager_UndoDone; - _traceChangeManager.RedoDone += TraceChangeManager_RedoDone; - - _sessionStateContainer.Cuesheet.TrackAdded += Cuesheet_TrackAdded; - _sessionStateContainer.Cuesheet.TrackRemoved += Cuesheet_TrackRemoved; - - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - _logger.LogDebug("OnAfterRenderAsync({firstRender})", firstRender); - if ((revalidate) && (validations != null)) - { - await validations.ValidateAll(); - revalidate = false; - } - } - - Task OnAddTrackClicked() - { - var newTrack = new Track(); - Cuesheet?.AddTrack(newTrack, applicationOptions); - _traceChangeManager.TraceChanges(newTrack); - return Task.CompletedTask; - } - - void OnDeleteTrackClicked(Track track) - { - Cuesheet?.RemoveTrack(track); - selectedTracks.Remove(track); - } - - async Task EditSelectedTracksClicked() - { - if (modalTrackEdit != null) - { - modalTrackEdit.TracksToEdit = selectedTracks; - await modalTrackEdit.Show(); - } - } - - private void DeleteSelectedTracksClicked() - { - Cuesheet?.RemoveTracks(selectedTracks.AsReadOnly()); - selectedTracks.Clear(); - } - - async Task OnDeleteAllTracksClicked() - { - _logger.LogInformation("OnDeleteAllTracksClicked"); - //Display a confirm warning - if (modalDialog != null) - { - modalDialog.Title = _localizer["Confirmation required"]; - modalDialog.Text = _localizer["Do you really want to delete all tracks?"]; - modalDialog.ModalSize = ModalSize.Small; - modalDialog.Mode = ModalDialog.DialogMode.Confirm; - void deleteTracksDelegate(object? sender, EventArgs args) - { - _logger.LogInformation("deleteTracksDelegate"); - Cuesheet?.RemoveTracks(Cuesheet.Tracks); - selectedTracks.Clear(); - modalDialog.Confirmed -= deleteTracksDelegate; - StateHasChanged(); - }; - modalDialog.Confirmed += deleteTracksDelegate; - await modalDialog.ShowModal(); - } - } - - async Task EditTrackModal(Track trackToEdit) - { - if (modalTrackEdit != null) - { - modalTrackEdit.TracksToEdit = new List() { trackToEdit }; - await modalTrackEdit.Show(); - } - } - - private String? GetLocalizedString(Boolean expressionToCheck, String localizedStringName) - { - if (expressionToCheck == true) - { - return _localizer[localizedStringName]; - } - else - { - return null; - } - } - - bool SelectAllIndeterminate - { - get => selectedTracks.Count > 0 && selectedTracks.Count < Cuesheet?.Tracks.Count; - } - - private void SelectedTrackChanged(Track track, bool selected) - { - if (selected) - { - selectedTracks.Add(track); - } - else - { - selectedTracks.Remove(track); - } - } - - private void OnSelectAllTracks(bool select) - { - if (select) - { - if (Cuesheet != null) - { - foreach (var track in Cuesheet.Tracks) - { - if (!selectedTracks.Contains(track)) - { - selectedTracks.Add(track); - } - } - } - } - else - { - selectedTracks.Clear(); - } - } - - bool AllTracksSelected - { - get => selectedTracks.Count > 0 && selectedTracks.Count == Cuesheet?.Tracks.Count; - } - - async Task CopyTrackClicked(Track trackToCopy) - { - var copy = new Track(trackToCopy); - Cuesheet?.AddTrack(copy, applicationOptions); - _traceChangeManager.TraceChanges(copy); - await EditTrackModal(copy); - } - - private async Task OnPlayTrackClicked(Track track) - { - if (AudioPlayer != null) - { - await AudioPlayer.OnPlayTrackClicked(track); - } - } - - private void LocalizationService_LocalizationChanged(object? sender, EventArgs args) - { - StateHasChanged(); - validations?.ValidateAll(); - } - - private MarkupString GetMarkupString(String? stringValue) - { - MarkupString result = new MarkupString(String.Empty); - if (stringValue != null) - { - result = new MarkupString(stringValue); - } - return result; - } - - private void SessionStateContainer_CuesheetChanged(object? sender, EventArgs args) - { - DetachTrackFromValidateablePropertyChanged(); - DetachCuesheetFromSplitPointsAddedRemoved(); - selectedTracks.Clear(); - StateHasChanged(); - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - } - - private void SessionStateContainer_ImportCuesheetChanged(object? sender, EventArgs args) - { - // Unsubscribe to previous attached events - DetachCuesheetFromSplitPointsAddedRemoved(); - var tracks = TracksAttachedToValidateablePropertyChanged.Except(_sessionStateContainer.Cuesheet.Tracks); - for (int i = tracks.Count() - 1; i >= 0; i--) - { - var track = tracks.ElementAt(i); - DetachTrackFromValidateablePropertyChanged(track); - TracksAttachedToValidateablePropertyChanged.Remove(track); - } - // Reattach if needed - AttachTracksToValidateablePropertyChanged(); - AttachCuesheetToSplitPointsAddedRemoved(); - revalidate = true; - StateHasChanged(); - } - - private void TraceChangeManager_UndoDone(object? sender, EventArgs args) - { - StateHasChanged(); - } - - private void TraceChangeManager_RedoDone(object? sender, EventArgs args) - { - StateHasChanged(); - } - - void Cuesheet_TrackAdded(object? sender, TrackAddRemoveEventArgs args) - { - StateHasChanged(); - AttachTracksToValidateablePropertyChanged(); - revalidate = true; - } - - void Cuesheet_TrackRemoved(object? sender, TrackAddRemoveEventArgs args) - { - DetachTrackFromValidateablePropertyChanged(args.Track); - revalidate = true; - } - - async Task OnReadDataAutocompleteTrackArtist(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs) - { - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - var artists = await _musicBrainzDataProvider.SearchArtistAsync(autocompleteReadDataEventArgs.SearchValue); - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - autocompleteTrackArtists = artists; - } - } - } - - async Task OnReadDataAutocompleteTrackTitle(AutocompleteReadDataEventArgs autocompleteReadDataEventArgs, Track track) - { - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - var titles = await _musicBrainzDataProvider.SearchTitleAsync(autocompleteReadDataEventArgs.SearchValue, track.Artist); - if (!autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested) - { - autocompleteTrackTitles = titles; - } - } - } - - async Task OnSelectedValueChangedTrackTitle(Guid selectedValue, Track track) - { - switch (_sessionStateContainer.CurrentViewMode) - { - case ViewMode.ViewModeFull: - case ViewMode.ViewModeImport: - var trackDetails = await _musicBrainzDataProvider.GetDetailsAsync(selectedValue); - if (trackDetails != null) - { - track.Length = trackDetails.Length; - if (String.IsNullOrEmpty(track.Artist)) - { - track.Artist = trackDetails.Artist; - } - } - break; - } - } - - void LocalStorageOptionsProvider_OptionSaved(object? sender, IOptions options) - { - if (options is ApplicationOptions) - { - applicationOptions = (ApplicationOptions)options; - } - } - - void AttachTracksToValidateablePropertyChanged() - { - if (Cuesheet != null) - { - foreach (var track in Cuesheet.Tracks) - { - if (TracksAttachedToValidateablePropertyChanged.Contains(track) == false) - { - track.ValidateablePropertyChanged += Track_ValidateablePropertyChanged; - TracksAttachedToValidateablePropertyChanged.Add(track); - } - } - } - } - - void DetachTrackFromValidateablePropertyChanged(Track? track = null) - { - if (track == null) - { - foreach (var trackCurrentlyAttached in TracksAttachedToValidateablePropertyChanged) - { - trackCurrentlyAttached.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; - } - } - else - { - track.ValidateablePropertyChanged -= Track_ValidateablePropertyChanged; - } - } - - void Track_ValidateablePropertyChanged(object? sender, string property) - { - if (validations != null) - { - validations.ValidateAll().GetAwaiter().GetResult(); - } - StateHasChanged(); - } - - void AttachCuesheetToSplitPointsAddedRemoved() - { - if (Cuesheet != null) - { - Cuesheet.SectionAdded += Cuesheet_SectionAdded; - Cuesheet.SectionRemoved += Cuesheet_SectionRemoved; - } - } - - void DetachCuesheetFromSplitPointsAddedRemoved() - { - if (Cuesheet != null) - { - Cuesheet.SectionAdded -= Cuesheet_SectionAdded; - Cuesheet.SectionRemoved -= Cuesheet_SectionRemoved; - } - } - - void Cuesheet_SectionAdded(object? sender, CuesheetSectionAddRemoveEventArgs args) - { - args.Section.ValidateablePropertyChanged += Section_ValidateablePropertyChanged; - } - - void Cuesheet_SectionRemoved(object? sender, CuesheetSectionAddRemoveEventArgs args) - { - args.Section.ValidateablePropertyChanged -= Section_ValidateablePropertyChanged; - } - - void Section_ValidateablePropertyChanged(object? sender, string property) - { - switch (property) - { - case nameof(CuesheetSection.Begin): - case nameof(CuesheetSection.End): - StateHasChanged(); - break; - } - } -} diff --git a/AudioCuesheetEditor/_Imports.razor b/AudioCuesheetEditor/_Imports.razor index b86c652b..61538055 100644 --- a/AudioCuesheetEditor/_Imports.razor +++ b/AudioCuesheetEditor/_Imports.razor @@ -12,6 +12,7 @@ @using AudioCuesheetEditor @using AudioCuesheetEditor.Pages @using AudioCuesheetEditor.Shared +@using AudioCuesheetEditor.Shared.TrackList @using AudioCuesheetEditor.Model.AudioCuesheet @using AudioCuesheetEditor.Model.IO @using AudioCuesheetEditor.Model.IO.Export diff --git a/AudioCuesheetEditor/wwwroot/index.html b/AudioCuesheetEditor/wwwroot/index.html index 6679a1ac..4aded2df 100644 --- a/AudioCuesheetEditor/wwwroot/index.html +++ b/AudioCuesheetEditor/wwwroot/index.html @@ -21,28 +21,28 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +