Public Access
154 lines
5.0 KiB
C#
154 lines
5.0 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace MeetingAssistant.LaunchProfiles;
|
|
|
|
public interface ILaunchProfileOptionsProvider
|
|
{
|
|
LaunchProfile GetRequiredProfile(string? name);
|
|
|
|
IReadOnlyList<LaunchProfileHotkey> GetHotkeys();
|
|
}
|
|
|
|
public sealed record LaunchProfile(string Name, MeetingAssistantOptions Options);
|
|
|
|
public sealed record LaunchProfileHotkey(string ProfileName, string Toggle);
|
|
|
|
public sealed class ConfigurationLaunchProfileOptionsProvider : ILaunchProfileOptionsProvider
|
|
{
|
|
public const string DefaultProfileName = "default";
|
|
|
|
private readonly IConfiguration configuration;
|
|
|
|
public ConfigurationLaunchProfileOptionsProvider(IConfiguration configuration)
|
|
{
|
|
this.configuration = configuration;
|
|
}
|
|
|
|
public LaunchProfile GetRequiredProfile(string? name)
|
|
{
|
|
var profileName = NormalizeProfileName(name);
|
|
var options = BindDefaultOptions();
|
|
if (profileName.Equals(DefaultProfileName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return new LaunchProfile(DefaultProfileName, options);
|
|
}
|
|
|
|
var profileSection = GetProfilesSection().GetSection(profileName);
|
|
if (!profileSection.Exists())
|
|
{
|
|
throw new KeyNotFoundException($"Launch profile '{profileName}' is not configured.");
|
|
}
|
|
|
|
profileSection.Bind(options);
|
|
ApplyArrayOverrides(profileSection, options);
|
|
return new LaunchProfile(profileName, options);
|
|
}
|
|
|
|
public IReadOnlyList<LaunchProfileHotkey> GetHotkeys()
|
|
{
|
|
var hotkeys = GetProfileNames()
|
|
.Select(profileName =>
|
|
{
|
|
var profile = GetRequiredProfile(profileName);
|
|
return new LaunchProfileHotkey(profile.Name, profile.Options.Hotkey.Toggle);
|
|
})
|
|
.Where(hotkey => !string.IsNullOrWhiteSpace(hotkey.Toggle))
|
|
.ToList();
|
|
var duplicate = hotkeys
|
|
.GroupBy(hotkey => hotkey.Toggle.Trim(), StringComparer.OrdinalIgnoreCase)
|
|
.FirstOrDefault(group => group.Count() > 1);
|
|
if (duplicate is not null)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"Launch profile hotkey '{duplicate.Key}' is configured more than once for profiles {string.Join(", ", duplicate.Select(hotkey => hotkey.ProfileName))}.");
|
|
}
|
|
|
|
return hotkeys;
|
|
}
|
|
|
|
private IReadOnlyList<string> GetProfileNames()
|
|
{
|
|
return new[] { DefaultProfileName }
|
|
.Concat(GetProfilesSection()
|
|
.GetChildren()
|
|
.Select(section => section.Key)
|
|
.Where(key => !key.Equals(DefaultProfileName, StringComparison.OrdinalIgnoreCase)))
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
}
|
|
|
|
private MeetingAssistantOptions BindDefaultOptions()
|
|
{
|
|
var options = new MeetingAssistantOptions();
|
|
GetRootSection().Bind(options);
|
|
return options;
|
|
}
|
|
|
|
private IConfigurationSection GetRootSection()
|
|
{
|
|
return configuration.GetSection("MeetingAssistant");
|
|
}
|
|
|
|
private IConfigurationSection GetProfilesSection()
|
|
{
|
|
return GetRootSection().GetSection("LaunchProfiles");
|
|
}
|
|
|
|
private static string NormalizeProfileName(string? name)
|
|
{
|
|
return string.IsNullOrWhiteSpace(name) ||
|
|
name.Equals(DefaultProfileName, StringComparison.OrdinalIgnoreCase)
|
|
? DefaultProfileName
|
|
: name.Trim();
|
|
}
|
|
|
|
private static void ApplyArrayOverrides(
|
|
IConfigurationSection profileSection,
|
|
MeetingAssistantOptions options)
|
|
{
|
|
var autoDetectLanguages = ReadArrayOverride(profileSection.GetSection("AzureSpeech:AutoDetectLanguages"));
|
|
if (autoDetectLanguages is not null)
|
|
{
|
|
options.AzureSpeech.AutoDetectLanguages = autoDetectLanguages;
|
|
}
|
|
|
|
var funAsrChunkSize = ReadIntArrayOverride(profileSection.GetSection("FunAsr:ChunkSize"));
|
|
if (funAsrChunkSize is not null)
|
|
{
|
|
options.FunAsr.ChunkSize = funAsrChunkSize;
|
|
}
|
|
}
|
|
|
|
private static string[]? ReadArrayOverride(IConfigurationSection section)
|
|
{
|
|
if (!section.Exists())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return section
|
|
.GetChildren()
|
|
.OrderBy(child => int.TryParse(child.Key, out var index) ? index : int.MaxValue)
|
|
.Select(child => child.Value)
|
|
.Where(value => !string.IsNullOrWhiteSpace(value))
|
|
.Select(value => value!)
|
|
.ToArray();
|
|
}
|
|
|
|
private static int[]? ReadIntArrayOverride(IConfigurationSection section)
|
|
{
|
|
if (!section.Exists())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return section
|
|
.GetChildren()
|
|
.OrderBy(child => int.TryParse(child.Key, out var index) ? index : int.MaxValue)
|
|
.Select(child => int.TryParse(child.Value, out var value) ? value : (int?)null)
|
|
.Where(value => value.HasValue)
|
|
.Select(value => value!.Value)
|
|
.ToArray();
|
|
}
|
|
}
|