From 27102353e2dd36f8fd0f25bc808736df12303729 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Thu, 12 Mar 2026 09:27:42 +0100
Subject: [PATCH 01/12] Update AudioCuesheetEditor.csproj
---
AudioCuesheetEditor/AudioCuesheetEditor.csproj | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
index 9dd43125..26315d86 100644
--- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj
+++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
@@ -7,7 +7,7 @@
enable
https://github.com/NeoCoderMatrix86/AudioCuesheetEditor
3.0
- 11.0.0
+ 11.1.0
false
true
true
@@ -22,13 +22,13 @@
-
-
+
+
-
-
-
+
+
+
From 27173104b5f0a05c4f3184def7076fe1df790d86 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Thu, 12 Mar 2026 11:19:42 +0100
Subject: [PATCH 02/12] remove sections
---
.../Model/AudioCuesheet/Cuesheet.cs | 38 ---
.../Model/IO/Export/CuesheetSection.cs | 217 ------------------
.../Model/Options/ExportOptions.cs | 2 +-
.../Services/IO/CuesheetExportService.cs | 88 +++----
.../Services/IO/ExportfileGenerator.cs | 92 +++-----
.../Services/IO/ImportManager.cs | 7 -
AudioCuesheetEditor/Services/Result.cs | 117 ++++++++++
.../Shared/Cuesheet/EditSections.de.resx | 150 ------------
.../Shared/Cuesheet/EditSections.razor | 154 -------------
.../Shared/Cuesheet/EditSections.resx | 150 ------------
.../Dialogs/GenerateCuesheetDialog.razor | 37 +--
.../Dialogs/GenerateExportDialog.de.resx | 16 +-
.../Shared/Dialogs/GenerateExportDialog.razor | 65 ++----
.../Shared/Dialogs/GenerateExportDialog.resx | 16 +-
.../Shared/TrackList/TrackList.de.resx | 6 -
.../Shared/TrackList/TrackList.razor | 6 -
.../Shared/TrackList/TrackList.resx | 6 -
.../Shared/ViewModes/ViewModeFull.de.resx | 3 -
.../Shared/ViewModes/ViewModeFull.razor | 9 -
.../Shared/ViewModes/ViewModeFull.resx | 3 -
20 files changed, 223 insertions(+), 959 deletions(-)
delete mode 100644 AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs
create mode 100644 AudioCuesheetEditor/Services/Result.cs
delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.de.resx
delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.razor
delete mode 100644 AudioCuesheetEditor/Shared/Cuesheet/EditSections.resx
diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
index c0501fdf..d4c73211 100644
--- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
+++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
@@ -15,7 +15,6 @@
//.
using AudioCuesheetEditor.Model.Entity;
using AudioCuesheetEditor.Model.IO.Audio;
-using AudioCuesheetEditor.Model.IO.Export;
using AudioCuesheetEditor.Model.UI;
using System.Text.Json.Serialization;
@@ -43,7 +42,6 @@ public class Cuesheet() : Validateable, ITraceable, ICuesheet
private CDTextfile? cDTextfile;
private String? catalogueNumber;
private readonly List> currentlyHandlingLinkedTrackPropertyChange = [];
- private List sections = [];
public event EventHandler? TraceablePropertyChanged;
public event EventHandler? IsRecordingChanged;
@@ -151,42 +149,6 @@ public IEnumerable IsRecordingPossible
[JsonIgnore]
public Boolean IsImporting { get; set; }
-
- [JsonInclude]
- public IReadOnlyCollection Sections
- {
- get => sections;
- private set
- {
- foreach(var section in value.Where(x => x.Cuesheet != this))
- {
- section.Cuesheet = this;
- }
- sections = [.. value];
- }
- }
-
- public CuesheetSection AddSection()
- {
- var previousValue = new List(sections);
- var section = new CuesheetSection(this);
- sections.Add(section);
- OnTraceablePropertyChanged(previousValue, nameof(Sections));
- return section;
- }
-
- public void RemoveSections(IEnumerable sectionsToRemove)
- {
- var previousValue = new List(sections);
- var intersection = sections.Intersect(sectionsToRemove);
- sections = [.. sections.Except(intersection)];
- OnTraceablePropertyChanged(previousValue, nameof(Sections));
- }
-
- public CuesheetSection? GetSection(Track track)
- {
- return Sections?.FirstOrDefault(x => track.Begin <= x.Begin && track.End >= x.Begin);
- }
///
/// Get the previous linked track of a track object
diff --git a/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs b/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs
deleted file mode 100644
index 534b65d3..00000000
--- a/AudioCuesheetEditor/Model/IO/Export/CuesheetSection.cs
+++ /dev/null
@@ -1,217 +0,0 @@
-//This file is part of AudioCuesheetEditor.
-
-//AudioCuesheetEditor is free software: you can redistribute it and/or modify
-//it under the terms of the GNU General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//AudioCuesheetEditor is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-
-//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 AudioCuesheetEditor.Model.UI;
-using System.Text.Json.Serialization;
-
-namespace AudioCuesheetEditor.Model.IO.Export
-{
- public class CuesheetSection : Validateable, ITraceable
- {
- private Cuesheet? cuesheet;
- private TimeSpan? begin;
- private TimeSpan? end;
- private String? artist;
- private String? title;
- private String? audiofileName;
-
- public event EventHandler? TraceablePropertyChanged;
-
- public CuesheetSection(Cuesheet cuesheet)
- {
- Cuesheet = cuesheet;
- artist = Cuesheet.Artist;
- title = Cuesheet.Title;
- audiofileName = Cuesheet.Audiofile?.Name;
- //Try to set begin
- begin = Cuesheet.Sections?.LastOrDefault()?.End;
- if (Begin.HasValue == false)
- {
- begin = Cuesheet.Tracks.Min(x => x.Begin);
- }
- end = Cuesheet.Tracks.Max(x => x.End);
- }
-
- [JsonConstructor]
- public CuesheetSection() { }
- public Cuesheet? Cuesheet
- {
- get => cuesheet;
- set
- {
- if (cuesheet == null)
- {
- cuesheet = value;
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
- }
-
- public String? Artist
- {
- get => artist;
- set
- {
- var previousValue = artist;
- artist = value;
- OnValidateablePropertyChanged(nameof(Artist));
- OnTraceablePropertyChanged(previousValue, nameof(Artist));
- }
- }
-
- public String? Title
- {
- get => title;
- set
- {
- var previousValue = title;
- title = value;
- OnValidateablePropertyChanged(nameof(Title));
- OnTraceablePropertyChanged(previousValue, nameof(Title));
- }
- }
-
- public TimeSpan? Begin
- {
- get => begin;
- set
- {
- var previousValue = begin;
- begin = value;
- OnValidateablePropertyChanged(nameof(Begin));
- OnTraceablePropertyChanged(previousValue, nameof(Begin));
- }
- }
-
- public TimeSpan? End
- {
- get => end;
- set
- {
- var previousValue = end;
- end = value;
- OnValidateablePropertyChanged(nameof(End));
- OnTraceablePropertyChanged(previousValue, nameof(End));
- }
- }
-
- public String? AudiofileName
- {
- get => audiofileName;
- set
- {
- var previousValue = audiofileName;
- audiofileName = value;
- OnValidateablePropertyChanged(nameof(AudiofileName));
- OnTraceablePropertyChanged(previousValue, nameof(AudiofileName));
- }
- }
-
- public void CopyValues(CuesheetSection splitPoint)
- {
- Artist = splitPoint.Artist;
- Title = splitPoint.Title;
- Begin = splitPoint.Begin;
- }
-
- public override ValidationResult Validate(string property)
- {
- ValidationStatus validationStatus = ValidationStatus.NoValidation;
- List? validationMessages = null;
- switch (property)
- {
- case nameof(Begin):
- validationStatus = ValidationStatus.Success;
- if (Begin == null)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Begin)));
- }
- else
- {
- var minBegin = Cuesheet?.Tracks.Min(x => x.Begin);
- if (Begin < minBegin)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} should be greater than or equal '{1}'!", nameof(Begin), minBegin));
- }
- if (Begin > End)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} should be less than or equal '{1}'!", nameof(Begin), End));
- }
- }
- break;
- case nameof(End):
- validationStatus = ValidationStatus.Success;
- if (End == null)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(End)));
- }
- else
- {
- var maxEnd = Cuesheet?.Tracks.Max(x => x.End);
- if (End > maxEnd)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} should be less than or equal '{1}'!", nameof(End), maxEnd));
- }
- if (End < Begin)
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} should be greater than or equal '{1}'!", nameof(End), Begin));
- }
- }
- break;
- case nameof(Artist):
- validationStatus = ValidationStatus.Success;
- if (String.IsNullOrEmpty(Artist))
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Artist)));
- }
- break;
- case nameof(Title):
- validationStatus = ValidationStatus.Success;
- if (String.IsNullOrEmpty(Title))
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(Title)));
- }
- break;
- case nameof(AudiofileName):
- validationStatus = ValidationStatus.Success;
- if (String.IsNullOrEmpty(AudiofileName))
- {
- validationMessages ??= [];
- validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(AudiofileName)));
- }
- break;
- }
- return ValidationResult.Create(validationStatus, validationMessages);
- }
-
- private void OnTraceablePropertyChanged(object? previousValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
- {
- TraceablePropertyChanged?.Invoke(this, new TraceablePropertiesChangedEventArgs(new TraceableChange(previousValue, propertyName)));
- }
- }
-}
diff --git a/AudioCuesheetEditor/Model/Options/ExportOptions.cs b/AudioCuesheetEditor/Model/Options/ExportOptions.cs
index dfa267a2..3f8457ac 100644
--- a/AudioCuesheetEditor/Model/Options/ExportOptions.cs
+++ b/AudioCuesheetEditor/Model/Options/ExportOptions.cs
@@ -60,7 +60,7 @@ public ExportOptions()
public ExportOptions(ICollection exportProfiles, Guid? selectedProfileId = null)
{
ExportProfiles = exportProfiles;
- SelectedProfileId = selectedProfileId ?? ExportProfiles.First().Id;
+ SelectedProfileId = selectedProfileId ?? ExportProfiles.FirstOrDefault()?.Id;
}
public ICollection ExportProfiles { get; set; }
[JsonIgnore]
diff --git a/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs b/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs
index 835cad77..eefeac07 100644
--- a/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs
+++ b/AudioCuesheetEditor/Services/IO/CuesheetExportService.cs
@@ -17,16 +17,19 @@
using AudioCuesheetEditor.Model.Entity;
using AudioCuesheetEditor.Model.IO;
using AudioCuesheetEditor.Model.IO.Export;
+using AudioCuesheetEditor.Model.IO.Import;
using AudioCuesheetEditor.Services.UI;
+using Microsoft.Extensions.Localization;
using System.Text;
namespace AudioCuesheetEditor.Services.IO
{
- public class CuesheetExportService(ISessionStateContainer sessionStateContainer)
+ public class CuesheetExportService(ISessionStateContainer sessionStateContainer, IStringLocalizer localizer)
{
private readonly ISessionStateContainer _sessionStateContainer = sessionStateContainer;
+ private readonly IStringLocalizer _localizer = localizer;
- public IEnumerable CanGenerateExportfiles(string? filename)
+ public Result CanGenerateExportfile(string? filename)
{
List validationMessages = [];
var extension = Path.GetExtension(filename);
@@ -37,52 +40,36 @@ public IEnumerable CanGenerateExportfiles(string? filename)
}
validationMessages.AddRange(_sessionStateContainer.Cuesheet.Validate().ValidationMessages);
validationMessages.AddRange(_sessionStateContainer.Cuesheet.Tracks.Select(x => x.Validate()).SelectMany(x => x.ValidationMessages));
- return validationMessages;
+ if (validationMessages.Count != 0)
+ {
+ return Result.Failure(new Error(ErrorType.ValidationFailed, string.Join(Environment.NewLine, validationMessages.Select(x => x.GetMessageLocalized(_localizer)))));
+ }
+ return Result.Success();
}
- public IReadOnlyCollection GenerateExportfiles(string? filename)
+ public Result GenerateExportfile(string? filename)
{
- List exportfiles = [];
- if (!CanGenerateExportfiles(filename).Any())
+ var validationResult = CanGenerateExportfile(filename);
+ if (validationResult.IsSuccess == false)
{
- if (_sessionStateContainer.Cuesheet.Sections.Count != 0)
- {
- var counter = 1;
- string? content = null;
- string? audioFileName = null;
- foreach (var section in _sessionStateContainer.Cuesheet.Sections.OrderBy(x => x.Begin))
- {
- audioFileName = section.AudiofileName;
- if (section.Validate().Status == ValidationStatus.Success)
- {
- content = WriteCuesheet(audioFileName, section);
- var name = string.Format("{0}({1}){2}", Path.GetFileNameWithoutExtension(filename), counter, FileExtensions.Cuesheet);
- exportfiles.Add(new Exportfile() { Name = name, Content = content, Begin = section.Begin, End = section.End });
- counter++;
- }
- }
- }
- else
- {
- string? content = null;
- var extension = Path.GetExtension(filename);
- if (extension?.Equals(FileExtensions.Cuesheet, StringComparison.OrdinalIgnoreCase) == false)
- {
- filename = $"{filename}{FileExtensions.Cuesheet}";
- }
- if (_sessionStateContainer.Cuesheet.Audiofile != null)
- {
- content = WriteCuesheet(_sessionStateContainer.Cuesheet.Audiofile.Name);
- }
- var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin);
- var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End);
- exportfiles.Add(new Exportfile() { Name = filename!, Content = content, Begin = begin, End = end });
- }
+ return Result.Failure(new Error(ErrorType.ValidationFailed, validationResult.Error!.Message));
+ }
+ string? content = null;
+ var extension = Path.GetExtension(filename);
+ if (extension?.Equals(FileExtensions.Cuesheet, StringComparison.OrdinalIgnoreCase) == false)
+ {
+ filename = $"{filename}{FileExtensions.Cuesheet}";
+ }
+ if (_sessionStateContainer.Cuesheet.Audiofile != null)
+ {
+ content = WriteCuesheet(_sessionStateContainer.Cuesheet.Audiofile.Name);
}
- return exportfiles;
+ var begin = _sessionStateContainer.Cuesheet.Tracks.Min(x => x.Begin);
+ var end = _sessionStateContainer.Cuesheet.Tracks.Max(x => x.End);
+ return Result.Success(new Exportfile() { Name = filename!, Content = content, Begin = begin, End = end });
}
- private string WriteCuesheet(string? audiofileName, CuesheetSection? section = null)
+ private string WriteCuesheet(string? audiofileName)
{
var builder = new StringBuilder();
if (string.IsNullOrEmpty(_sessionStateContainer.Cuesheet.Cataloguenumber) == false)
@@ -93,14 +80,10 @@ private string WriteCuesheet(string? audiofileName, CuesheetSection? section = n
{
builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetCDTextfile, _sessionStateContainer.Cuesheet.CDTextfile.Name));
}
- builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, section != null ? section.Title : _sessionStateContainer.Cuesheet.Title));
- builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, section != null ? section.Artist : _sessionStateContainer.Cuesheet.Artist));
+ builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetTitle, _sessionStateContainer.Cuesheet.Title));
+ builder.AppendLine(string.Format("{0} \"{1}\"", CuesheetConstants.CuesheetArtist, _sessionStateContainer.Cuesheet.Artist));
builder.AppendLine(string.Format("{0} \"{1}\" {2}", CuesheetConstants.CuesheetFileName, audiofileName, _sessionStateContainer.Cuesheet.Audiofile?.AudioFileType));
IEnumerable
diff --git a/AudioCuesheetEditor/Extensions/InterfaceConverter.cs b/AudioCuesheetEditor/Extensions/InterfaceConverter.cs
deleted file mode 100644
index f5ab2bfb..00000000
--- a/AudioCuesheetEditor/Extensions/InterfaceConverter.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-//This file is part of AudioCuesheetEditor.
-
-//AudioCuesheetEditor is free software: you can redistribute it and/or modify
-//it under the terms of the GNU General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//AudioCuesheetEditor is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-
-//You should have received a copy of the GNU General Public License
-//along with Foobar. If not, see
-//.
-using System.Text.Json.Serialization;
-using System.Text.Json;
-
-namespace AudioCuesheetEditor.Extensions
-{
- public class InterfaceConverter : JsonConverter where TImplementation : TInterface
- {
- public override TInterface? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- return JsonSerializer.Deserialize(ref reader, options);
- }
-
- public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
- {
- if (value != null)
- {
- JsonSerializer.Serialize(writer, (TImplementation)value, options);
- }
- else
- {
- writer.WriteNullValue();
- }
- }
- }
-}
diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
index d4c73211..f6b49bd7 100644
--- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
+++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
@@ -38,7 +38,7 @@ public class Cuesheet() : Validateable, ITraceable, ICuesheet
private List tracks = [];
private String? artist;
private String? title;
- private IAudiofile? audiofile;
+ private Audiofile? audiofile;
private CDTextfile? cDTextfile;
private String? catalogueNumber;
private readonly List> currentlyHandlingLinkedTrackPropertyChange = [];
@@ -89,7 +89,7 @@ public String? Title
FireEvents(previousValue, propertyName: nameof(Title));
}
}
- public IAudiofile? Audiofile
+ public Audiofile? Audiofile
{
get => audiofile;
set
diff --git a/AudioCuesheetEditor/Model/IO/Audio/Audiofile.cs b/AudioCuesheetEditor/Model/IO/Audio/Audiofile.cs
index c61e7a63..ebee7f8d 100644
--- a/AudioCuesheetEditor/Model/IO/Audio/Audiofile.cs
+++ b/AudioCuesheetEditor/Model/IO/Audio/Audiofile.cs
@@ -18,7 +18,7 @@
namespace AudioCuesheetEditor.Model.IO.Audio
{
[method: JsonConstructor]
- public class Audiofile(String name) : IDisposable, IAudiofile
+ public class Audiofile(String name)
{
public static readonly AudioCodec AudioCodecWEBM = new("audio/webm", ".webm", "AudioCodec WEBM");
@@ -35,13 +35,9 @@ public class Audiofile(String name) : IDisposable, IAudiofile
];
private AudioCodec? audioCodec;
- private Stream? contentStream;
private String name = name;
- private bool disposedValue;
- public event EventHandler? ContentStreamLoaded;
-
- public Audiofile(String name, String objectURL, AudioCodec? audioCodec) : this(name)
+ public Audiofile(String name, String objectURL, AudioCodec? audioCodec, TimeSpan? duration = null) : this(name)
{
if (String.IsNullOrEmpty(objectURL))
{
@@ -49,6 +45,7 @@ public Audiofile(String name, String objectURL, AudioCodec? audioCodec) : this(n
}
ObjectURL = objectURL;
AudioCodec = audioCodec;
+ Duration = duration;
}
public String Name
@@ -71,32 +68,6 @@ public String Name
[JsonIgnore]
public String? ObjectURL { get; private set; }
///
- /// Boolean indicating if the stream has fully been loaded
- ///
- [JsonIgnore]
- public Boolean IsContentStreamLoaded
- {
- get { return ContentStream != null; }
- }
- ///
- /// File content stream. Be carefully, this stream is loaded asynchronously. Connect to the StreamLoaded for checking if loading has already been done!
- ///
- [JsonIgnore]
- public Stream? ContentStream
- {
- get => contentStream;
- set
- {
- contentStream = value;
- if ((ContentStream != null) && (AudioCodec != null))
- {
- var track = new ATL.Track(ContentStream, AudioCodec.MimeType);
- Duration = new TimeSpan(0, 0, track.Duration);
- ContentStreamLoaded?.Invoke(this, EventArgs.Empty);
- }
- }
- }
- ///
/// Duration of the audio file
///
public TimeSpan? Duration { get; private set; }
@@ -144,30 +115,5 @@ public Boolean PlaybackPossible
return playbackPossible;
}
}
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- if (ContentStream != null)
- {
- ContentStream.Close();
- ContentStream.Dispose();
- ContentStream = null;
- }
- }
-
- disposedValue = true;
- }
- }
-
- public void Dispose()
- {
- // Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in der Methode "Dispose(bool disposing)" ein.
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
}
}
diff --git a/AudioCuesheetEditor/Model/IO/Audio/IAudiofile.cs b/AudioCuesheetEditor/Model/IO/Audio/IAudiofile.cs
deleted file mode 100644
index 456fd475..00000000
--- a/AudioCuesheetEditor/Model/IO/Audio/IAudiofile.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-//This file is part of AudioCuesheetEditor.
-
-//AudioCuesheetEditor is free software: you can redistribute it and/or modify
-//it under the terms of the GNU General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//AudioCuesheetEditor is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-
-//You should have received a copy of the GNU General Public License
-//along with Foobar. If not, see
-//.
-namespace AudioCuesheetEditor.Model.IO.Audio
-{
- public interface IAudiofile
- {
- AudioCodec? AudioCodec { get; }
- string? AudioFileType { get; }
- Stream? ContentStream { get; set; }
- TimeSpan? Duration { get; }
- bool IsContentStreamLoaded { get; }
- string Name { get; set; }
- string? ObjectURL { get; }
- bool PlaybackPossible { get; }
-
- event EventHandler? ContentStreamLoaded;
- }
-}
\ No newline at end of file
diff --git a/AudioCuesheetEditor/Model/IO/Projectfile.cs b/AudioCuesheetEditor/Model/IO/Projectfile.cs
index c54dace0..c6d2617e 100644
--- a/AudioCuesheetEditor/Model/IO/Projectfile.cs
+++ b/AudioCuesheetEditor/Model/IO/Projectfile.cs
@@ -13,9 +13,7 @@
//You should have received a copy of the GNU General Public License
//along with Foobar. If not, see
//.
-using AudioCuesheetEditor.Extensions;
using AudioCuesheetEditor.Model.AudioCuesheet;
-using AudioCuesheetEditor.Model.IO.Audio;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -32,8 +30,7 @@ public class Projectfile(Cuesheet cuesheet)
ReferenceHandler = ReferenceHandler.IgnoreCycles,
Converters =
{
- new JsonStringEnumConverter(),
- new InterfaceConverter() // Add a custom converter for IAudiofile
+ new JsonStringEnumConverter()
}
};
diff --git a/AudioCuesheetEditor/Services/Audio/PlaybackService.cs b/AudioCuesheetEditor/Services/Audio/PlaybackService.cs
index 89f90592..b451800e 100644
--- a/AudioCuesheetEditor/Services/Audio/PlaybackService.cs
+++ b/AudioCuesheetEditor/Services/Audio/PlaybackService.cs
@@ -26,7 +26,7 @@ public class PlaybackService : IDisposable
private readonly IHowl _howl;
private int? soundId;
- private IAudiofile? currentlyPlayingAudiofile;
+ private Audiofile? currentlyPlayingAudiofile;
private Timer? updateTimer;
private bool disposedValue;
private readonly Lock timerLock = new();
@@ -71,7 +71,7 @@ public PlaybackService(ISessionStateContainer sessionStateContainer, IHowl howl)
public async Task PlayOrPauseAsync()
{
//Reset if the last played audiofile is not the current one
- if (currentlyPlayingAudiofile !=cuesheet.Audiofile)
+ if (currentlyPlayingAudiofile != cuesheet.Audiofile)
{
soundId = null;
}
diff --git a/AudioCuesheetEditor/Services/IO/FileInputManager.cs b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
index 61cef4db..8d18dd69 100644
--- a/AudioCuesheetEditor/Services/IO/FileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
@@ -92,22 +92,13 @@ public bool CheckFileMimeType(string? fileContentType, string fileName, string m
var codec = GetAudioCodec(fileUpload.ContentType, fileUpload.Name);
if (codec != null)
{
- audiofile = new Audiofile(fileUpload.Name, fileUpload.ObjectUrl, codec);
+ TimeSpan? duration = null;
if (String.IsNullOrEmpty(fileUpload.ObjectUrl) == false)
{
- var request = new HttpRequestMessage(HttpMethod.Get, fileUpload.ObjectUrl);
- //TODO: Enable when https://github.com/NeoCoderMatrix86/AudioCuesheetEditor/issues/524 gets done
- request.SetBrowserRequestStreamingEnabled(false);
-
- var response = await _httpClient.SendAsync(request);
- var loadContentStreamTask = response.Content.ReadAsStreamAsync()
- .ContinueWith(x => audiofile.ContentStream = x.Result);
- if (afterContentStreamLoaded != null)
- {
- _ = loadContentStreamTask
- .ContinueWith(afterContentStreamLoaded);
- }
+ var durationSeconds = await _jsRuntime.InvokeAsync("getAudioDurationFromFile", fileUpload.ObjectUrl);
+ duration = TimeSpan.FromSeconds(durationSeconds);
}
+ audiofile = new Audiofile(fileUpload.Name, fileUpload.ObjectUrl, codec, duration);
}
else
{
diff --git a/AudioCuesheetEditor/wwwroot/scripts/library.js b/AudioCuesheetEditor/wwwroot/scripts/library.js
index a3e73692..aa44cab8 100644
--- a/AudioCuesheetEditor/wwwroot/scripts/library.js
+++ b/AudioCuesheetEditor/wwwroot/scripts/library.js
@@ -39,4 +39,21 @@ function beforeunload(e) {
function removeBeforeunload() {
window.removeEventListener('beforeunload', beforeunload);
+}
+
+function getAudioDurationFromFile(url) {
+ return new Promise((resolve, reject) => {
+ const audio = new Audio();
+
+ audio.preload = "metadata";
+ audio.src = url;
+
+ audio.onloadedmetadata = () => {
+ resolve(audio.duration);
+ };
+
+ audio.onerror = (e) => {
+ reject(e);
+ };
+ });
}
\ No newline at end of file
From 36f95ad9318117deb9136f24e7848d8a09c918d3 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 14:48:04 +0100
Subject: [PATCH 06/12] update libraries
---
.../AudioCuesheetEditor.Tests.csproj | 2 +-
AudioCuesheetEditor/AudioCuesheetEditor.csproj | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj
index dc6ac4ec..0651db7f 100644
--- a/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj
+++ b/AudioCuesheetEditor.Tests/AudioCuesheetEditor.Tests.csproj
@@ -12,7 +12,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
index 8b2501b6..aa58202b 100644
--- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj
+++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
@@ -22,14 +22,14 @@
-
-
+
+
-
-
-
+
+
+
From 949502496a3b3037a88537e3df18f5f4b91105a5 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 15:25:02 +0100
Subject: [PATCH 07/12] Delete AudiofileTests.cs
---
.../Model/IO/Audio/AudiofileTests.cs | 46 -------------------
1 file changed, 46 deletions(-)
delete mode 100644 AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs
diff --git a/AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs b/AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs
deleted file mode 100644
index 77c5f293..00000000
--- a/AudioCuesheetEditor.Tests/Model/IO/Audio/AudiofileTests.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//This file is part of AudioCuesheetEditor.
-
-//AudioCuesheetEditor is free software: you can redistribute it and/or modify
-//it under the terms of the GNU General Public License as published by
-//the Free Software Foundation, either version 3 of the License, or
-//(at your option) any later version.
-
-//AudioCuesheetEditor is distributed in the hope that it will be useful,
-//but WITHOUT ANY WARRANTY; without even the implied warranty of
-//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-//GNU General Public License for more details.
-
-//You should have received a copy of the GNU General Public License
-//along with Foobar. If not, see
-//.
-using AudioCuesheetEditor.Model.IO.Audio;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Linq;
-
-namespace AudioCuesheetEditor.Tests.Model.IO.Audio
-{
- [TestClass()]
- public class AudiofileTests
- {
- [TestMethod()]
- public void AudioFileTest()
- {
- var audioFile = new Audiofile("test.mp3");
- Assert.IsNotNull(audioFile.Name);
- Assert.AreEqual("MP3", audioFile.AudioFileType);
- audioFile = new Audiofile("Test");
- Assert.AreEqual(audioFile.AudioFileType, string.Empty);
- Assert.IsNotNull(audioFile.Name);
- var codec = Audiofile.AudioCodecs.Single(x => x.FileExtension == ".ogg");
- audioFile = new Audiofile("test", "TestobjectURL", codec);
- Assert.IsNotNull(audioFile.Name);
- Assert.AreEqual("test.ogg", audioFile.Name);
- Assert.AreEqual("OGG", audioFile.AudioFileType);
- Assert.IsNotNull(audioFile.ObjectURL);
- Assert.IsTrue(audioFile.PlaybackPossible);
- codec = Audiofile.AudioCodecs.Single(x => x.FileExtension == ".mp3");
- var audioFile2 = new Audiofile(audioFile.Name, "TestObjectURL2", codec);
- Assert.AreEqual("test.mp3", audioFile2.Name);
- }
- }
-}
\ No newline at end of file
From 125d4619d6fb36c7b697bd906f5775ede38a8b98 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 15:38:06 +0100
Subject: [PATCH 08/12] Update Cuesheet.cs
---
AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
index f6b49bd7..65ea5d96 100644
--- a/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
+++ b/AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
@@ -446,7 +446,7 @@ public override ValidationResult Validate(string property)
private void RecalculateTrackProperties(Track trackToCalculate)
{
- if ((Audiofile != null) && (Audiofile.Duration.HasValue) && (trackToCalculate.End.HasValue == false))
+ if ((Audiofile?.Duration.HasValue == true) && (trackToCalculate.End.HasValue == false))
{
trackToCalculate.End = Audiofile.Duration;
}
From 26824c9ef0166569197cf918683750cbc50781f4 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 16:25:17 +0100
Subject: [PATCH 09/12] fix loading of duration
---
AudioCuesheetEditor/Services/IO/FileInputManager.cs | 4 ++--
AudioCuesheetEditor/Services/IO/IFileInputManager.cs | 2 +-
.../Shared/Cuesheet/CuesheetData.razor | 11 ++++-------
3 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/AudioCuesheetEditor/Services/IO/FileInputManager.cs b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
index 8d18dd69..4adba3c8 100644
--- a/AudioCuesheetEditor/Services/IO/FileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
@@ -83,7 +83,7 @@ public bool CheckFileMimeType(string? fileContentType, string fileName, string m
return fileMimeTypeMatches;
}
- public async Task CreateAudiofileAsync(FileUpload fileUpload, Action>? afterContentStreamLoaded = null)
+ public async Task CreateAudiofileAsync(FileUpload fileUpload)
{
Audiofile? audiofile = null;
if (fileUpload.ObjectUrl != null)
@@ -98,7 +98,7 @@ public bool CheckFileMimeType(string? fileContentType, string fileName, string m
var durationSeconds = await _jsRuntime.InvokeAsync("getAudioDurationFromFile", fileUpload.ObjectUrl);
duration = TimeSpan.FromSeconds(durationSeconds);
}
- audiofile = new Audiofile(fileUpload.Name, fileUpload.ObjectUrl, codec, duration);
+ audiofile = new Audiofile(fileUpload.Name, fileUpload.ObjectUrl, codec, duration);
}
else
{
diff --git a/AudioCuesheetEditor/Services/IO/IFileInputManager.cs b/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
index 026ed5d4..f79f88a0 100644
--- a/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/IFileInputManager.cs
@@ -34,7 +34,7 @@ public interface IFileInputManager
///
///
bool CheckFileMimeType(string? fileContentType, string fileName, string mimeType, IEnumerable fileExtensions);
- Task CreateAudiofileAsync(FileUpload fileUpload, Action>? afterContentStreamLoaded = null);
+ Task CreateAudiofileAsync(FileUpload fileUpload);
CDTextfile? CreateCDTextfile(string? fileContentType, string fileName);
///
/// Checks if the file can be used for the import view
diff --git a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
index 61605a5a..cc0cf4eb 100644
--- a/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
+++ b/AudioCuesheetEditor/Shared/Cuesheet/CuesheetData.razor
@@ -114,14 +114,11 @@ along with Foobar. If not, see
if (browserFile != null)
{
var fileUpload = await _fileInputManager.CreateFileUploadsAsync([browserFile], fileInputAudiofileId);
- Cuesheet.Audiofile = await _fileInputManager.CreateAudiofileAsync(fileUpload.Single(), x =>
+ Cuesheet.Audiofile = await _fileInputManager.CreateAudiofileAsync(fileUpload.Single());
+ if (Cuesheet.RecalculateLastTrackEnd())
{
- if (Cuesheet.RecalculateLastTrackEnd())
- {
- TraceChangeManager.MergeLastEditWithEdit(x => x.Changes.All(y => y.TraceableObject == Cuesheet && y.TraceableChange.PropertyName == nameof(Audiofile)));
- }
- StateHasChanged();
- });
+ TraceChangeManager.MergeLastEditWithEdit(x => x.Changes.All(y => y.TraceableObject == Cuesheet && y.TraceableChange.PropertyName == nameof(Audiofile)));
+ }
}
else
{
From 0d00bf1ab3505bea060e5339de040631afcd4cd9 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 16:26:14 +0100
Subject: [PATCH 10/12] Update ImportManagerTests.cs
---
AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
index 5b6b2ec9..875a900b 100644
--- a/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
+++ b/AudioCuesheetEditor.Tests/Services/IO/ImportManagerTests.cs
@@ -288,7 +288,7 @@ public async Task UploadFilesAsync_WithAudiofile_ImportsCorrectly()
_fileInputManagerMock.Setup(f => f.CheckFileMimeType(file.ContentType, file.Name, FileMimeTypes.Cuesheet, It.IsAny>())).Returns(false);
_fileInputManagerMock.Setup(f => f.IsValidForImportView(file.ContentType, file.Name)).Returns(false);
_fileInputManagerMock.Setup(f => f.IsValidAudiofile(file.ContentType, file.Name)).Returns(true);
- _fileInputManagerMock.Setup(f => f.CreateAudiofileAsync(It.IsAny(), It.IsAny>?>())).ReturnsAsync(new AudioCuesheetEditor.Model.IO.Audio.Audiofile(file.Name));
+ _fileInputManagerMock.Setup(f => f.CreateAudiofileAsync(It.IsAny())).ReturnsAsync(new Audiofile(file.Name));
IImportfile? sessionStateContainerImportfile = null;
_sessionStateContainerMock.SetupSet(x => x.Importfile = It.IsAny()).Callback(x => sessionStateContainerImportfile = x);
From fb476a720483eb15d7b77d2cb04061c661b97468 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Wed, 18 Mar 2026 16:33:29 +0100
Subject: [PATCH 11/12] fix tests
---
AudioCuesheetEditor.End2EndTests/Tests/Desktop/ExportTest.cs | 2 +-
.../Tests/Smartphone/ExportTestSmartphone.cs | 2 +-
AudioCuesheetEditor/Services/IO/FileInputManager.cs | 1 -
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/AudioCuesheetEditor.End2EndTests/Tests/Desktop/ExportTest.cs b/AudioCuesheetEditor.End2EndTests/Tests/Desktop/ExportTest.cs
index 7ba3dae3..8e856f81 100644
--- a/AudioCuesheetEditor.End2EndTests/Tests/Desktop/ExportTest.cs
+++ b/AudioCuesheetEditor.End2EndTests/Tests/Desktop/ExportTest.cs
@@ -68,7 +68,7 @@ public async Task DownloadProject_GeneratesProjectFile_WhenCuesheetIsValidAsync(
using var stream = await download.CreateReadStreamAsync();
using var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync(TestContext.CancellationToken);
- Assert.AreEqual("{\"Tracks\":[{\"Position\":1,\"Artist\":\"Track Artist 1\",\"Title\":\"Track Title 1\",\"Begin\":\"00:00:00\",\"End\":\"00:05:48\",\"Flags\":[],\"IsLinkedToPreviousTrack\":true}],\"Artist\":\"Cuesheet Artist 1\",\"Title\":\"Cuesheet Title 1\",\"Audiofile\":{\"Name\":\"Kalimba.mp3\",\"Duration\":\"00:05:48\",\"AudioCodec\":{\"MimeType\":\"audio/mpeg\",\"FileExtension\":\".mp3\",\"Name\":\"AudioCodec MP3\"}}}", content);
+ Assert.AreEqual("{\"Tracks\":[{\"Position\":1,\"Artist\":\"Track Artist 1\",\"Title\":\"Track Title 1\",\"Begin\":\"00:00:00\",\"End\":\"00:05:48.0608330\",\"Flags\":[],\"IsLinkedToPreviousTrack\":true}],\"Artist\":\"Cuesheet Artist 1\",\"Title\":\"Cuesheet Title 1\",\"Audiofile\":{\"Name\":\"Kalimba.mp3\",\"Duration\":\"00:05:48.0608330\",\"AudioCodec\":{\"MimeType\":\"audio/mpeg\",\"FileExtension\":\".mp3\",\"Name\":\"AudioCodec MP3\"}}}", content);
}
[TestMethod]
diff --git a/AudioCuesheetEditor.End2EndTests/Tests/Smartphone/ExportTestSmartphone.cs b/AudioCuesheetEditor.End2EndTests/Tests/Smartphone/ExportTestSmartphone.cs
index 1e3d7b5e..22865d9b 100644
--- a/AudioCuesheetEditor.End2EndTests/Tests/Smartphone/ExportTestSmartphone.cs
+++ b/AudioCuesheetEditor.End2EndTests/Tests/Smartphone/ExportTestSmartphone.cs
@@ -68,7 +68,7 @@ public async Task DownloadProject_GeneratesProjectFile_WhenCuesheetIsValidAsync(
using var stream = await download.CreateReadStreamAsync();
using var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync(TestContext.CancellationToken);
- Assert.AreEqual("{\"Tracks\":[{\"Position\":1,\"Artist\":\"Track Artist 1\",\"Title\":\"Track Title 1\",\"Begin\":\"00:00:00\",\"End\":\"00:05:48\",\"Flags\":[],\"IsLinkedToPreviousTrack\":true}],\"Artist\":\"Cuesheet Artist 1\",\"Title\":\"Cuesheet Title 1\",\"Audiofile\":{\"Name\":\"Kalimba.mp3\",\"Duration\":\"00:05:48\",\"AudioCodec\":{\"MimeType\":\"audio/mpeg\",\"FileExtension\":\".mp3\",\"Name\":\"AudioCodec MP3\"}}}", content);
+ Assert.AreEqual("{\"Tracks\":[{\"Position\":1,\"Artist\":\"Track Artist 1\",\"Title\":\"Track Title 1\",\"Begin\":\"00:00:00\",\"End\":\"00:05:48.0608330\",\"Flags\":[],\"IsLinkedToPreviousTrack\":true}],\"Artist\":\"Cuesheet Artist 1\",\"Title\":\"Cuesheet Title 1\",\"Audiofile\":{\"Name\":\"Kalimba.mp3\",\"Duration\":\"00:05:48.0608330\",\"AudioCodec\":{\"MimeType\":\"audio/mpeg\",\"FileExtension\":\".mp3\",\"Name\":\"AudioCodec MP3\"}}}", content);
}
[TestMethod]
diff --git a/AudioCuesheetEditor/Services/IO/FileInputManager.cs b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
index 4adba3c8..32836dc8 100644
--- a/AudioCuesheetEditor/Services/IO/FileInputManager.cs
+++ b/AudioCuesheetEditor/Services/IO/FileInputManager.cs
@@ -17,7 +17,6 @@
using AudioCuesheetEditor.Model.IO;
using AudioCuesheetEditor.Model.IO.Audio;
using Microsoft.AspNetCore.Components.Forms;
-using Microsoft.AspNetCore.Components.WebAssembly.Http;
using Microsoft.JSInterop;
namespace AudioCuesheetEditor.Services.IO
From 0b754712c149d12e8d0239820e552a3284d14be7 Mon Sep 17 00:00:00 2001
From: Sven <40752681+NeoCoderMatrix86@users.noreply.github.com>
Date: Fri, 20 Mar 2026 13:58:36 +0100
Subject: [PATCH 12/12] fix version
---
AudioCuesheetEditor/AudioCuesheetEditor.csproj | 2 +-
Readme.md | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/AudioCuesheetEditor/AudioCuesheetEditor.csproj b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
index aa58202b..171d7120 100644
--- a/AudioCuesheetEditor/AudioCuesheetEditor.csproj
+++ b/AudioCuesheetEditor/AudioCuesheetEditor.csproj
@@ -7,7 +7,7 @@
enable
https://github.com/NeoCoderMatrix86/AudioCuesheetEditor
3.0
- 11.1.0
+ 12.0.0
false
true
true
diff --git a/Readme.md b/Readme.md
index 2a69f968..387225d0 100644
--- a/Readme.md
+++ b/Readme.md
@@ -35,6 +35,12 @@ You can contribute to the project by opening up issues or adding feature request
This application is build using Blazor WASM Standalone and needs .NET 10 to run. Tests are running using MSTest and Playwright.
+## Guidelines
+
+### Versioning
+
+This application uses semantic versioning (https://semver.org/) set inside the visual studio project file.
+
# License
GNU GENERAL PUBLIC LICENSE Version 3