Add chapters display, gray out fixed tracks, spacebar preview
This commit is contained in:
+8
-1
@@ -233,6 +233,12 @@
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource AccentFillColorSecondaryBrush}"/>
|
||||
</Trigger>
|
||||
<DataTrigger Binding="{Binding Type}" Value="video">
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Type}" Value="chapters">
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
@@ -259,13 +265,14 @@
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<CheckBox IsChecked="{Binding Copy, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsEnabled="{Binding IsEditable}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn Header="ID"
|
||||
Binding="{Binding Id}" Width="45" IsReadOnly="True"/>
|
||||
Binding="{Binding IdDisplay}" Width="45" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="Codec"
|
||||
Binding="{Binding Codec}" Width="185" IsReadOnly="True"/>
|
||||
<DataGridTextColumn Header="Language"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
@@ -357,6 +358,13 @@ public partial class MainWindow : FluentWindow
|
||||
/// </summary>
|
||||
private void FileQueueList_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Space)
|
||||
{
|
||||
OpenSelectedFileInDefaultPlayer();
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Key != System.Windows.Input.Key.Delete) return;
|
||||
|
||||
var selected = FileQueueList.SelectedItems.Cast<QueuedFileItem>().ToList();
|
||||
@@ -371,6 +379,25 @@ public partial class MainWindow : FluentWindow
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the currently-selected queue item with whatever application
|
||||
/// Windows has associated with .mkv files (typically the default video
|
||||
/// player), so the user can quickly preview a file without leaving the app.
|
||||
/// </summary>
|
||||
private void OpenSelectedFileInDefaultPlayer()
|
||||
{
|
||||
if (FileQueueList.SelectedItem is not QueuedFileItem item) return;
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(item.FilePath) { UseShellExecute = true });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusText.Text = $"Couldn't open {item.FileName}: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearQueueButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
foreach (var item in _fileQueue)
|
||||
|
||||
@@ -13,6 +13,15 @@ public class MkvIdentifyResult
|
||||
|
||||
[JsonPropertyName("tracks")]
|
||||
public List<MkvTrack> Tracks { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("chapters")]
|
||||
public List<MkvChapters> Chapters { get; set; } = new();
|
||||
}
|
||||
|
||||
public class MkvChapters
|
||||
{
|
||||
[JsonPropertyName("num_entries")]
|
||||
public int NumEntries { get; set; }
|
||||
}
|
||||
|
||||
public class MkvTrack
|
||||
|
||||
@@ -44,6 +44,20 @@ public class TrackItem : INotifyPropertyChanged
|
||||
/// </summary>
|
||||
public string DisplayName => Type == "subtitles" ? $"{Codec}/{Name}" : Name;
|
||||
|
||||
/// <summary>
|
||||
/// Video is always kept, and chapters (a synthetic pseudo-track, not a
|
||||
/// real mkvmerge track) are always kept too — neither is user-selectable,
|
||||
/// so their Copy checkbox is shown checked but disabled.
|
||||
/// </summary>
|
||||
public bool IsEditable => Type is "audio" or "subtitles";
|
||||
|
||||
/// <summary>
|
||||
/// Chapters aren't a real track and have no track ID; show a dash
|
||||
/// instead of a meaningless number.
|
||||
/// </summary>
|
||||
public string IdDisplay => Type == "chapters" ? "—" : Id.ToString();
|
||||
|
||||
|
||||
public bool Copy
|
||||
{
|
||||
get => _copy;
|
||||
|
||||
+17
-1
@@ -110,7 +110,7 @@ public class MkvService
|
||||
MkvTrack? preferredAudio = eligibleAudio.FirstOrDefault(t => t.Properties?.AudioChannels == 2)
|
||||
?? eligibleAudio.FirstOrDefault();
|
||||
|
||||
return info.Tracks.Select(t =>
|
||||
var items = info.Tracks.Select(t =>
|
||||
{
|
||||
bool copy = t.Type switch
|
||||
{
|
||||
@@ -136,6 +136,22 @@ public class MkvService
|
||||
Copy = copy,
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
int chapterCount = info.Chapters.Sum(c => c.NumEntries);
|
||||
if (chapterCount > 0)
|
||||
{
|
||||
items.Add(new TrackItem
|
||||
{
|
||||
Id = -1,
|
||||
Type = "chapters",
|
||||
Codec = string.Empty,
|
||||
Language = string.Empty,
|
||||
Name = $"Chapters ({chapterCount})",
|
||||
Copy = true,
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user