diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d0f70ca..a78d0cc 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,26 +12,30 @@ jobs:
- name: Set version number
shell: pwsh
run: |
- $version = "0.1.0"
- echo $version
- echo "VERSION_NUMBER=$version" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
+ $versionNumber = "2.0.0"
+ $versionSuffix = "beta.1"
+ $infoVersion = "$versionNumber-$versionSuffix"
+ echo $infoVersion
+ echo "VERSION_NUMBER=$versionNumber" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
+ echo "VERSION_SUFFIX=$versionSuffix" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
+ echo "INFO_VERSION=$infoVersion" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 7.0.x
- name: Publish for win-x64
- run: dotnet publish KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj /p:Version=${{ env.VERSION_NUMBER }}.0 /p:Configuration=Release /p:RuntimeIdentifier=win-x64 /p:PublishSingleFile=true /p:PublishDir=${{ github.workspace }}/publish
+ run: dotnet publish KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj /p:VersionPrefix=${{ env.VERSION_NUMBER }} /p:VersionSuffix=${{ env.VERSION_SUFFIX }} /p:Configuration=Release /p:RuntimeIdentifier=win-x64 /p:PublishSingleFile=true /p:PublishDir=${{ github.workspace }}/publish
- name: Zip for win-x64
shell: pwsh
- run: Compress-Archive -Path ${{ github.workspace }}/publish/* -DestinationPath KaddaOKTools_win-x64_${{ env.VERSION_NUMBER }}.zip
+ run: Compress-Archive -Path ${{ github.workspace }}/publish/* -DestinationPath KaddaOKTools_win-x64_${{ env.INFO_VERSION }}.zip
- name: Upload win-x64 Artifact
uses: actions/upload-artifact@v4
with:
- name: KaddaOKTools_win-x64_${{ env.VERSION_NUMBER }}
- path: KaddaOKTools_win-x64_${{ env.VERSION_NUMBER }}.zip
+ name: KaddaOKTools_win-x64_${{ env.INFO_VERSION }}
+ path: KaddaOKTools_win-x64_${{ env.INFO_VERSION }}.zip
- name: Create Release
uses: ncipollo/release-action@v1.13.0
with:
- artifacts: "KaddaOKTools_win-x64_${{ env.VERSION_NUMBER }}.zip"
- tag: ${{ env.VERSION_NUMBER }}
+ artifacts: "KaddaOKTools_win-x64_${{ env.INFO_VERSION }}.zip"
+ tag: ${{ env.INFO_VERSION }}
diff --git a/KaddaOK.AvaloniaApp.Tests/ViewModels/EditLinesViewModelTests.cs b/KaddaOK.AvaloniaApp.Tests/ViewModels/EditLinesViewModelTests.cs
index 0970b81..d0eee17 100644
--- a/KaddaOK.AvaloniaApp.Tests/ViewModels/EditLinesViewModelTests.cs
+++ b/KaddaOK.AvaloniaApp.Tests/ViewModels/EditLinesViewModelTests.cs
@@ -1,7 +1,9 @@
using System.Collections.ObjectModel;
+using Avalonia.Input;
using FluentAvalonia.Core;
using KaddaOK.AvaloniaApp.Models;
using KaddaOK.AvaloniaApp.ViewModels;
+using KaddaOK.AvaloniaApp.Views;
using KaddaOK.Library;
using NAudio.Wave;
@@ -26,6 +28,13 @@ private static KaraokeProcess GetNewCurrentProcess() =>
}
};
+ public class DummyEditLinesView : IEditLinesView
+ {
+ public bool Focus(NavigationMethod method = NavigationMethod.Unspecified, KeyModifiers keyModifiers = KeyModifiers.None)
+ {
+ return true;
+ }
+ }
public class MoveLineToPrevious
{
[Fact]
@@ -33,7 +42,8 @@ public void ShouldMergeLines()
{
var currentProcess = GetNewCurrentProcess();
- var viewModel = new EditLinesViewModel(currentProcess, new LineSplitter(), new WordMerger(), new MinMaxFloatWaveStreamSampler());
+ var viewModel = new EditLinesViewModel(currentProcess, new LineSplitter(), new WordMerger(), new MinMaxFloatWaveStreamSampler())
+ { EditLinesView = new DummyEditLinesView() };
viewModel.MoveLineToPrevious(currentProcess.ChosenLines!.Last());
@@ -47,7 +57,8 @@ public void ShouldAddSpaceToPreviousWordWhenMergingLines()
{
var currentProcess = GetNewCurrentProcess();
- var viewModel = new EditLinesViewModel(currentProcess, new LineSplitter(), new WordMerger(), new MinMaxFloatWaveStreamSampler());
+ var viewModel = new EditLinesViewModel(currentProcess, new LineSplitter(), new WordMerger(), new MinMaxFloatWaveStreamSampler())
+ { EditLinesView = new DummyEditLinesView()};
viewModel.MoveLineToPrevious(currentProcess.ChosenLines!.Last());
diff --git a/KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj b/KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj
index 0b7a8ef..d70fcf5 100644
--- a/KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj
+++ b/KaddaOK.AvaloniaApp.Windows/KaddaOK.AvaloniaApp.Windows.csproj
@@ -12,6 +12,8 @@
true
app.manifest
KaddaOKTools
+ 0.0.0
+ dev
diff --git a/KaddaOK.AvaloniaApp/App.axaml b/KaddaOK.AvaloniaApp/App.axaml
index f484f1a..5496234 100644
--- a/KaddaOK.AvaloniaApp/App.axaml
+++ b/KaddaOK.AvaloniaApp/App.axaml
@@ -123,11 +123,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/KaddaOK.AvaloniaApp/App.axaml.cs b/KaddaOK.AvaloniaApp/App.axaml.cs
index 3eeca92..34179c5 100644
--- a/KaddaOK.AvaloniaApp/App.axaml.cs
+++ b/KaddaOK.AvaloniaApp/App.axaml.cs
@@ -25,7 +25,7 @@ public override void Initialize()
KaraokeProcess = new KaraokeProcess
{
- KaraokeSource = InitialKaraokeSource.AzureSpeechService
+ KaraokeSource = InitialKaraokeSource.NotSelected
};
services.AddSingleton(KaraokeProcess);
@@ -53,6 +53,8 @@ public override void Initialize()
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
// Build the service provider
ServiceProvider = services.BuildServiceProvider();
diff --git a/KaddaOK.AvaloniaApp/Controls/Dialogs/EditSyllableTextDialog.axaml b/KaddaOK.AvaloniaApp/Controls/Dialogs/EditSyllableTextDialog.axaml
index 166fb8e..d8ac381 100644
--- a/KaddaOK.AvaloniaApp/Controls/Dialogs/EditSyllableTextDialog.axaml
+++ b/KaddaOK.AvaloniaApp/Controls/Dialogs/EditSyllableTextDialog.axaml
@@ -12,16 +12,17 @@
- Enter the new text for this timed syllable. (You may break it up into multiple words or syllables by using space or | characters,
- and the timing dialog will open automatically for you to check the new distribution.)
+ Enter the new text for this timed syllable. (You may break it up into multiple words or syllables by using space, /, or | characters.)
- (To separate syllables, use a | (pipe) character.)
+ (To separate syllables, use a / or | character.)
diff --git a/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml b/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml
new file mode 100644
index 0000000..0074a40
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+ Shift all the starts and stops in the entire song by an offset value in seconds.
+
+
+ Positive values will move everything later relative to the music, and should
+ be applied if the scroll is happening too early.
+
+
+ Negative values will move everything earlier relative to the music, and should
+ be applied if the scroll isn't happening early enough.
+
+
+ For instance, to move everything 100ms earlier in the song to give singers more
+ time to react, enter -0.1 in the input below.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml.cs b/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml.cs
new file mode 100644
index 0000000..37f7dcd
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Controls/Dialogs/NudgeTimingsDialog.axaml.cs
@@ -0,0 +1,36 @@
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.VisualTree;
+using DialogHostAvalonia;
+
+namespace KaddaOK.AvaloniaApp.Controls.Dialogs
+{
+ public partial class NudgeTimingsDialog : UserControl
+ {
+ private DialogHost? dialogHost;
+
+ public NudgeTimingsDialog()
+ {
+ InitializeComponent();
+ }
+
+ private void TextBox_AttachedToVisualTree(object? sender, Avalonia.VisualTreeAttachmentEventArgs e)
+ {
+ (sender as TextBox)?.Focus();
+ dialogHost = this.FindAncestorOfType();
+ }
+
+ private void TextBox_KeyDown(object? sender, Avalonia.Input.KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ {
+ dialogHost?.CloseDialogCommand.Execute(((TextBox)sender).Text);
+ }
+
+ if (e.Key == Key.Escape)
+ {
+ dialogHost?.CloseDialogCommand.Execute(null);
+ }
+ }
+ }
+}
diff --git a/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml b/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml
new file mode 100644
index 0000000..95b476b
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml.cs b/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml.cs
new file mode 100644
index 0000000..b2eb164
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Controls/InitialSyncOption.axaml.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+using CommunityToolkit.Mvvm.Input;
+
+namespace KaddaOK.AvaloniaApp.Controls;
+
+public partial class InitialSyncOption : UserControl
+{
+ public InitialSyncOption()
+ {
+ InitializeComponent();
+ MoreInfoContent = new List();
+ }
+
+ public static readonly StyledProperty ChooseCommandProperty = AvaloniaProperty.Register(nameof(ChooseCommand));
+ public static readonly StyledProperty OptionTitleProperty = AvaloniaProperty.Register(nameof(OptionTitle));
+ public static readonly StyledProperty OptionSummaryProperty = AvaloniaProperty.Register(nameof(OptionSummary));
+ public static readonly StyledProperty> MoreInfoContentProperty = AvaloniaProperty.Register>(nameof(MoreInfoContent));
+ public static readonly StyledProperty IconDrawingProperty = AvaloniaProperty.Register(nameof(IconDrawing));
+ public static readonly StyledProperty MoreInfoVisibleProperty = AvaloniaProperty.Register(nameof(MoreInfoVisible));
+
+ public ICommand ChooseCommand
+ {
+ get => GetValue(ChooseCommandProperty);
+ set => SetValue(ChooseCommandProperty, value);
+ }
+
+ public string OptionTitle
+ {
+ get => GetValue(OptionTitleProperty);
+ set => SetValue(OptionTitleProperty, value);
+ }
+
+ public string OptionSummary
+ {
+ get => GetValue(OptionSummaryProperty);
+ set => SetValue(OptionSummaryProperty, value);
+ }
+
+ public IEnumerable MoreInfoContent
+ {
+ get => GetValue(MoreInfoContentProperty);
+ set => SetValue(MoreInfoContentProperty, value);
+ }
+
+ public DrawingImage IconDrawing
+ {
+ get => GetValue(IconDrawingProperty);
+ set => SetValue(IconDrawingProperty, value);
+ }
+
+ // Encapsulated properties and commands
+ public bool MoreInfoVisible
+ {
+ get => GetValue(MoreInfoVisibleProperty);
+ set => SetValue(MoreInfoVisibleProperty, value);
+ }
+
+ [RelayCommand]
+ public void HideMoreInfo(object? parameter)
+ {
+ MoreInfoVisible = false;
+ }
+ [RelayCommand]
+ public void ShowMoreInfo(object? parameter)
+ {
+ MoreInfoVisible = true;
+ }
+}
\ No newline at end of file
diff --git a/KaddaOK.AvaloniaApp/Controls/OverlayRectangle.axaml b/KaddaOK.AvaloniaApp/Controls/OverlayRectangle.axaml
index c380215..845d691 100644
--- a/KaddaOK.AvaloniaApp/Controls/OverlayRectangle.axaml
+++ b/KaddaOK.AvaloniaApp/Controls/OverlayRectangle.axaml
@@ -1,22 +1,32 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
@@ -90,33 +91,24 @@
Classes.gettingFile="{Binding GettingFile}">
-
- To use the guided process for generating karaoke files, start here and follow
- the
- instructions on each screen, pushing the "Next Step" button to go through each
- tab,
- until you are satisfied with the content on the Edit tab.
+ Margin="20,0,20,20">
+
+ Audio
+
+ To get started, select the WAV or FLAC files to work on below.
+
To get started, select the WAV or FLAC files to work on below.
+ Classes="introText">
(Separate instruments from vocals first using a tool such as
-
- or whatever you prefer.) To proceed with the automatic process, only Vocals-only
- is mandatory, but for the best experience, all 3 should be selected.
-
- Alternately, to edit a file from YTMM or KBS, click the Import... button at the
- bottom and select it.
- The app will attempt to load it and the accompanying audio files, and jump
- directly to the Edit tab.
-
+ or whatever you prefer.)
+
+ The Vocals-only version is mandatory, but for the best experience, all 3 should be selected.
+
@@ -234,11 +226,6 @@
ColumnDefinitions="*,*"
Margin="0, 15">
-
+
+
+
+
+
+
+
+
@@ -106,6 +137,9 @@
+
+
+
+
+ Edit
+
On this screen you can make direct changes to the words and lines.
Click the ⤴ button to make a line part of its preceeding line.
@@ -176,17 +213,28 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KaddaOK.AvaloniaApp/Views/StartView.axaml.cs b/KaddaOK.AvaloniaApp/Views/StartView.axaml.cs
new file mode 100644
index 0000000..ca4cb2c
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Views/StartView.axaml.cs
@@ -0,0 +1,29 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Notifications;
+using KaddaOK.AvaloniaApp.ViewModels;
+using KaddaOK.AvaloniaApp.ViewModels.DesignTime;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace KaddaOK.AvaloniaApp.Views
+{
+ public partial class StartView : UserControl
+ {
+ private StartViewModel _viewModel;
+ public StartView()
+ {
+ InitializeComponent();
+
+ _viewModel = Design.IsDesignMode
+ ? new DesignTimeStartViewModel()
+ : App.ServiceProvider.GetRequiredService();
+ DataContext = _viewModel;
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+ _viewModel.NotificationManager = new WindowNotificationManager(TopLevel.GetTopLevel(this)!);
+ }
+ }
+}
diff --git a/KaddaOK.AvaloniaApp/Views/TabIndexes.cs b/KaddaOK.AvaloniaApp/Views/TabIndexes.cs
new file mode 100644
index 0000000..6301905
--- /dev/null
+++ b/KaddaOK.AvaloniaApp/Views/TabIndexes.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KaddaOK.AvaloniaApp.Views
+{
+ public enum TabIndexes
+ {
+ Start = 0,
+ Audio = 1,
+ Lyrics = 2,
+ Recognize = 3,
+ Narrow = 4,
+ ManualAlign = 5,
+ Edit = 6,
+ Export = 7,
+ About = 8
+ }
+}
diff --git a/KaddaOK.AvaloniaApp/WaveformToPointConverter.cs b/KaddaOK.AvaloniaApp/WaveformToPointConverter.cs
index 1faa7ea..fc8eed5 100644
--- a/KaddaOK.AvaloniaApp/WaveformToPointConverter.cs
+++ b/KaddaOK.AvaloniaApp/WaveformToPointConverter.cs
@@ -12,15 +12,16 @@ public class WaveformToPointConverter : IMultiValueConverter
{
public object? Convert(IList