Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions AudioCuesheetEditor/AudioCuesheetEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
<Content Remove="Resources\Localization\ModalExportdialog\en.json" />
<Content Remove="Resources\Localization\OptionsDialog\de.json" />
<Content Remove="Resources\Localization\OptionsDialog\en.json" />
<Content Remove="Resources\Localization\RecordControl\de.json" />
<Content Remove="Resources\Localization\RecordControl\en.json" />
<Content Remove="Resources\Localization\EditRecordOptions\de.json" />
<Content Remove="Resources\Localization\EditRecordOptions\en.json" />
<Content Remove="Resources\Localization\TracksTable\de.json" />
<Content Remove="Resources\Localization\TracksTable\en.json" />
<Content Remove="Resources\Localization\CultureSelector\de.json" />
Expand Down Expand Up @@ -78,6 +82,10 @@
<EmbeddedResource Include="Resources\Localization\ModalExportdialog\en.json" />
<EmbeddedResource Include="Resources\Localization\OptionsDialog\de.json" />
<EmbeddedResource Include="Resources\Localization\OptionsDialog\en.json" />
<EmbeddedResource Include="Resources\Localization\RecordControl\de.json" />
<EmbeddedResource Include="Resources\Localization\RecordControl\en.json" />
<EmbeddedResource Include="Resources\Localization\EditRecordOptions\de.json" />
<EmbeddedResource Include="Resources\Localization\EditRecordOptions\en.json" />
<EmbeddedResource Include="Resources\Localization\TracksTable\de.json" />
<EmbeddedResource Include="Resources\Localization\TracksTable\en.json" />
<EmbeddedResource Include="Resources\Localization\CultureSelector\de.json" />
Expand All @@ -103,6 +111,7 @@

<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.5.3" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.5.3" />
<PackageReference Include="MetaBrainz.MusicBrainz" Version="6.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" PrivateAssets="all" />
Expand Down
68 changes: 50 additions & 18 deletions AudioCuesheetEditor/Data/Options/LocalStorageOptionsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,25 @@
//You should have received a copy of the GNU General Public License
//along with Foobar. If not, see
//<http: //www.gnu.org/licenses />.
using AudioCuesheetEditor.Model.Entity;
using AudioCuesheetEditor.Model.Options;
using Microsoft.JSInterop;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json;

namespace AudioCuesheetEditor.Data.Options
{
public class LocalStorageOptionsProvider
public class LocalStorageOptionsProvider(IJSRuntime jsRuntime)
{
public event EventHandler<IOptions>? OptionSaved;

private readonly IJSRuntime _jsRuntime;
private readonly IJSRuntime _jsRuntime = jsRuntime;

public LocalStorageOptionsProvider(IJSRuntime jsRuntime)
private readonly JsonSerializerOptions SerializerOptions = new()
{
if (jsRuntime is null)
{
throw new ArgumentNullException(nameof(jsRuntime));
}

_jsRuntime = jsRuntime;
}
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};

public async Task<T> GetOptions<T>() where T : IOptions
{
Expand Down Expand Up @@ -65,17 +63,51 @@ public async Task<T> GetOptions<T>() where T : IOptions

public async Task SaveOptions(IOptions options)
{
if (options == null)
var optionsJson = JsonSerializer.Serialize<object>(options, SerializerOptions);
await _jsRuntime.InvokeVoidAsync(String.Format("{0}.set", options.GetType().Name), optionsJson);
OptionSaved?.Invoke(this, options);
}

public async Task SaveOptionsValue<T>(Expression<Func<T, object>> propertyExpression, object value) where T : class, IOptions, new()
{
var options = await GetOptions<T>();
if (propertyExpression.Body is MemberExpression memberExpression)
{
throw new ArgumentNullException(nameof(options));
var propertyInfo = memberExpression.Member as PropertyInfo;
if (propertyInfo != null)
{
propertyInfo.SetValue(options, Convert.ChangeType(value, propertyInfo.PropertyType));
}
else
{
throw new ArgumentException("The provided expression does not reference a valid property.");
}
}
var serializerOptions = new JsonSerializerOptions
else if (propertyExpression.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression unaryMemberExpression)
{
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};
var optionsJson = JsonSerializer.Serialize<object>(options, serializerOptions);
await _jsRuntime.InvokeVoidAsync(String.Format("{0}.set", options.GetType().Name), optionsJson);
OptionSaved?.Invoke(this, options);
var propertyInfo = unaryMemberExpression.Member as PropertyInfo;
if (propertyInfo != null)
{
propertyInfo.SetValue(options, Convert.ChangeType(value, propertyInfo.PropertyType));
}
else
{
throw new ArgumentException("The provided expression does not reference a valid property.");
}
}
else
{
throw new ArgumentException("The provided expression does not reference a valid property.");
}
Boolean saveOptions = true;
if (options is IValidateable<T> validateable)
{
saveOptions = validateable.Validate(propertyExpression).Status != ValidationStatus.Error;
}
if (saveOptions)
{
await SaveOptions(options);
}
}
}
}
15 changes: 8 additions & 7 deletions AudioCuesheetEditor/Model/AudioCuesheet/Cuesheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,22 @@ public void RemoveSection(CuesheetSection section)
return previousLinkedTrack;
}

public void AddTrack(Track track, ApplicationOptions? applicationOptions = null)
public void AddTrack(Track track, ApplicationOptions? applicationOptions = null, RecordOptions? recordOptions = null)
{
if (track.IsCloned)
{
throw new ArgumentException("Cloned tracks may not be added!");
}
var previousValue = new List<Track>(tracks);
track.IsLinkedToPreviousTrackChanged += Track_IsLinkedToPreviousTrackChanged;
if (IsRecording && recordingStart.HasValue)
{
ArgumentNullException.ThrowIfNull(recordOptions);
track.Begin = CalculateTimeSpanWithSensitivity(DateTime.UtcNow - recordingStart.Value, recordOptions.RecordTimeSensitivity);
}
//When no applications are available (because of used by import for example) we don't try to calculate properties
if (applicationOptions != null)
{
if (IsRecording && (recordingStart.HasValue))
{
track.Begin = CalculateTimeSpanWithSensitivity(DateTime.UtcNow - recordingStart.Value, applicationOptions.RecordTimeSensitivity);
}
track.IsLinkedToPreviousTrack = applicationOptions.LinkTracksWithPreviousOne;
}
tracks.Add(track);
Expand Down Expand Up @@ -418,13 +419,13 @@ public void StartRecording()
recordingStart = DateTime.UtcNow;
}

public void StopRecording(ApplicationOptions applicationOptions)
public void StopRecording(RecordOptions recordOptions)
{
//Set end of last track
var lastTrack = Tracks.LastOrDefault();
if ((lastTrack != null) && (recordingStart.HasValue))
{
lastTrack.End = CalculateTimeSpanWithSensitivity(DateTime.UtcNow - recordingStart.Value, applicationOptions.RecordTimeSensitivity);
lastTrack.End = CalculateTimeSpanWithSensitivity(DateTime.UtcNow - recordingStart.Value, recordOptions.RecordTimeSensitivity);
}
recordingStart = null;
}
Expand Down
16 changes: 11 additions & 5 deletions AudioCuesheetEditor/Model/Entity/Validateable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
//You should have received a copy of the GNU General Public License
//along with Foobar. If not, see
//<http: //www.gnu.org/licenses />.
using AudioCuesheetEditor.Model.AudioCuesheet;
using System.Linq.Expressions;
using System.Reflection;

Expand All @@ -25,11 +24,18 @@ public abstract class Validateable<T> : IValidateable<T>

public ValidationResult Validate<TProperty>(Expression<Func<T, TProperty>> expression)
{
if (expression.Body is not MemberExpression body)
if (expression.Body is MemberExpression memberExpression)
{
throw new ArgumentException("'expression' should be a member expression");
return Validate(memberExpression.Member.Name);
}
else if (expression.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression unaryMemberExpression)
{
return Validate(unaryMemberExpression.Member.Name);
}
else
{
throw new ArgumentException("The provided expression does not reference a valid property.");
}
return Validate(body.Member.Name);
}

public ValidationResult Validate()
Expand All @@ -40,7 +46,7 @@ public ValidationResult Validate()
var result = Validate(property.Name);
if (result.ValidationMessages != null)
{
validationResult.ValidationMessages ??= new();
validationResult.ValidationMessages ??= [];
validationResult.ValidationMessages.AddRange(result.ValidationMessages);
}
switch (validationResult.Status)
Expand Down
43 changes: 0 additions & 43 deletions AudioCuesheetEditor/Model/Options/ApplicationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using AudioCuesheetEditor.Model.AudioCuesheet;
using AudioCuesheetEditor.Model.Entity;
using AudioCuesheetEditor.Model.IO;
using AudioCuesheetEditor.Model.IO.Audio;
using AudioCuesheetEditor.Model.IO.Export;
using AudioCuesheetEditor.Model.Utility;
using System.Globalization;
Expand Down Expand Up @@ -91,27 +90,8 @@ public String? ViewModename
}
}
}
public String RecordedAudiofilename { get; set; } = Audiofile.RecordingFileName;
public Boolean LinkTracksWithPreviousOne { get; set; } = true;
public String? ProjectFilename { get; set; } = Projectfile.DefaultFilename;
public uint RecordCountdownTimer { get; set; } = 5;
[JsonIgnore]
public TimeSensitivityMode RecordTimeSensitivity { get; set; }
public String? RecordTimeSensitivityname
{
get { return Enum.GetName(typeof(TimeSensitivityMode), RecordTimeSensitivity); }
set
{
if (value != null)
{
RecordTimeSensitivity = (TimeSensitivityMode)Enum.Parse(typeof(TimeSensitivityMode), value);
}
else
{
throw new ArgumentNullException(nameof(value));
}
}
}
public TimeSpanFormat? TimeSpanFormat { get; set; }

protected override ValidationResult Validate(string property)
Expand Down Expand Up @@ -143,29 +123,6 @@ protected override ValidationResult Validate(string property)
}
}
break;
case nameof(RecordedAudiofilename):
validationStatus = ValidationStatus.Success;
if (String.IsNullOrEmpty(RecordedAudiofilename))
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(RecordedAudiofilename)));
}
else
{
var extension = Path.GetExtension(RecordedAudiofilename);
if (extension.Equals(Audiofile.AudioCodecWEBM.FileExtension, StringComparison.OrdinalIgnoreCase) == false)
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} must end with '{1}'!", nameof(RecordedAudiofilename), Audiofile.AudioCodecWEBM.FileExtension));
}
var filename = Path.GetFileNameWithoutExtension(RecordedAudiofilename);
if (String.IsNullOrEmpty(filename))
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} must have a filename!", nameof(RecordedAudiofilename)));
}
}
break;
case nameof(ProjectFilename):
validationStatus = ValidationStatus.Success;
if (String.IsNullOrEmpty(ProjectFilename))
Expand Down
76 changes: 76 additions & 0 deletions AudioCuesheetEditor/Model/Options/RecordOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//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
//<http: //www.gnu.org/licenses />.
using AudioCuesheetEditor.Model.Entity;
using AudioCuesheetEditor.Model.IO.Audio;
using System.Text.Json.Serialization;

namespace AudioCuesheetEditor.Model.Options
{
public class RecordOptions : Validateable<RecordOptions>, IOptions
{
public String RecordedAudiofilename { get; set; } = Audiofile.RecordingFileName;
[JsonIgnore]
public TimeSensitivityMode RecordTimeSensitivity { get; set; }
public uint RecordCountdownTimer { get; set; } = 5;
public String? RecordTimeSensitivityname
{
get { return Enum.GetName(typeof(TimeSensitivityMode), RecordTimeSensitivity); }
set
{
if (value != null)
{
RecordTimeSensitivity = (TimeSensitivityMode)Enum.Parse(typeof(TimeSensitivityMode), value);
}
else
{
throw new ArgumentNullException(nameof(value));
}
}
}
protected override ValidationResult Validate(string property)
{
ValidationStatus validationStatus = ValidationStatus.NoValidation;
List<ValidationMessage>? validationMessages = null;
switch (property)
{
case nameof(RecordedAudiofilename):
validationStatus = ValidationStatus.Success;
if (String.IsNullOrEmpty(RecordedAudiofilename))
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} has no value!", nameof(RecordedAudiofilename)));
}
else
{
var extension = Path.GetExtension(RecordedAudiofilename);
if (extension.Equals(Audiofile.AudioCodecWEBM.FileExtension, StringComparison.OrdinalIgnoreCase) == false)
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} must end with '{1}'!", nameof(RecordedAudiofilename), Audiofile.AudioCodecWEBM.FileExtension));
}
var filename = Path.GetFileNameWithoutExtension(RecordedAudiofilename);
if (String.IsNullOrEmpty(filename))
{
validationMessages ??= [];
validationMessages.Add(new ValidationMessage("{0} must have a filename!", nameof(RecordedAudiofilename)));
}
}
break;
}
return ValidationResult.Create(validationStatus, validationMessages);
}
}
}
Loading