add volume

This commit is contained in:
Oleksandr Bezdieniezhnykh
2024-05-26 15:11:16 +03:00
parent f179a5f0ca
commit e317ce2310
6 changed files with 167 additions and 20 deletions
+1
View File
@@ -11,6 +11,7 @@ public class FormState
public Size CurrentVideoSize { get; set; } public Size CurrentVideoSize { get; set; }
public string VideoName => Path.GetFileNameWithoutExtension(CurrentFile).Replace(" ", ""); public string VideoName => Path.GetFileNameWithoutExtension(CurrentFile).Replace(" ", "");
public TimeSpan CurrentVideoLength { get; set; } public TimeSpan CurrentVideoLength { get; set; }
public int CurrentVolume { get; set; } = 100;
public string GetTimeName(TimeSpan ts) => $"{VideoName}_{ts:hmmssf}"; public string GetTimeName(TimeSpan ts) => $"{VideoName}_{ts:hmmssf}";
} }
+5
View File
@@ -13,3 +13,8 @@ public class PlaybackControlEvent(PlaybackControlEnum playbackControlEnum) : INo
{ {
public PlaybackControlEnum PlaybackControl { get; set; } = playbackControlEnum; public PlaybackControlEnum PlaybackControl { get; set; } = playbackControlEnum;
} }
public class VolumeChangedEvent(int volume) : INotification
{
public int Volume { get; set; } = volume;
}
+3 -1
View File
@@ -10,5 +10,7 @@ public enum PlaybackControlEnum
NextFrame = 5, NextFrame = 5,
SaveAnnotations = 6, SaveAnnotations = 6,
RemoveSelectedAnns = 7, RemoveSelectedAnns = 7,
RemoveAllAnns = 8 RemoveAllAnns = 8,
TurnOffVolume = 9,
TurnOnVolume = 10
} }
+91 -10
View File
@@ -5,7 +5,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF" xmlns:controls="clr-namespace:Azaion.Annotator.Controls" xmlns:wpf="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF" xmlns:controls="clr-namespace:Azaion.Annotator.Controls"
mc:Ignorable="d" mc:Ignorable="d"
Title="Azaion Annotator" Height="450" Width="1100"> Title="Azaion Annotator" Height="450" Width="1100"
>
<Window.Resources> <Window.Resources>
<Style x:Key="DataGridCellStyle1" TargetType="{x:Type DataGridCell}"> <Style x:Key="DataGridCellStyle1" TargetType="{x:Type DataGridCell}">
@@ -121,6 +122,10 @@
Grid.Column="0" Grid.Column="0"
Grid.Row="3" Grid.Row="3"
Background="Black" Background="Black"
RowBackground="#252525"
Foreground="White"
RowHeaderWidth="0"
Padding="2 0 0 0"
AutoGenerateColumns="False" AutoGenerateColumns="False"
SelectionMode="Single" SelectionMode="Single"
CellStyle="{DynamicResource DataGridCellStyle1}" CellStyle="{DynamicResource DataGridCellStyle1}"
@@ -132,6 +137,11 @@
Width="60" Width="60"
Header="Клавіша" Header="Клавіша"
CanUserSort="False"> CanUserSort="False">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="#252525"></Setter>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border Background="{Binding Path=ColorBrush}"> <Border Background="{Binding Path=ColorBrush}">
@@ -144,7 +154,13 @@
Width="*" Width="*"
Header="Назва" Header="Назва"
Binding="{Binding Path=Name}" Binding="{Binding Path=Name}"
CanUserSort="False"/> CanUserSort="False">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="#252525"></Setter>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<GridSplitter <GridSplitter
@@ -163,10 +179,12 @@
x:Name="VideoView"> x:Name="VideoView">
<controls:CanvasEditor x:Name="Editor" Background="#01000000" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" /> <controls:CanvasEditor x:Name="Editor" Background="#01000000" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</wpf:VideoView> </wpf:VideoView>
<controls:UpdatableProgressBar x:Name="videoSlider" <controls:UpdatableProgressBar x:Name="VideoSlider"
Grid.Column="0" Grid.Column="0"
Grid.Row="4" Grid.Row="4"
Grid.ColumnSpan="3"> Grid.ColumnSpan="3"
Background="#252525"
Foreground="LightBlue">
</controls:UpdatableProgressBar> </controls:UpdatableProgressBar>
<Grid <Grid
@@ -183,6 +201,7 @@
<ColumnDefinition Width="28"/> <ColumnDefinition Width="28"/>
<ColumnDefinition Width="28"/> <ColumnDefinition Width="28"/>
<ColumnDefinition Width="28"/> <ColumnDefinition Width="28"/>
<ColumnDefinition Width="28"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button Grid.Column="0" Padding="5" ToolTip="Включити програвання" Background="Black" BorderBrush="Black" <Button Grid.Column="0" Padding="5" ToolTip="Включити програвання" Background="Black" BorderBrush="Black"
Click="PlayClick"> Click="PlayClick">
@@ -303,10 +322,59 @@
</Image.Source> </Image.Source>
</Image> </Image>
</Button> </Button>
<Button
x:Name="TurnOffVolumeBtn"
Visibility="Visible"
Grid.Column="8" Padding="2" Width="25"
Height="25"
ToolTip="Виключити звук. Клавіша: [M]" Background="Black" BorderBrush="Black"
Click="TurnOffVolume">
<Path Stretch="Fill" Fill="LightGray" Data="m9.383 3.07602c.18269.07574.33881.20395.44863.36842.10983.16447.16837.35781.16837
.55558v11.99998c-.00004.1978-.05871.3911-.1686.5555-.10988.1644-.26605.2925-.44875.3682s-.38373.0955-.57768.0569-.37212-.1338-.51197-.2736l-3.707
-3.707h-2.586c-.26522 0-.51957-.1053-.70711-.2929-.18753-.1875-.29289-.4419-.29289-.7071v-3.99998c0-.26522.10536-.51957.29289-.70711.18754-.18754
.44189-.29289.70711-.29289h2.586l3.707-3.707c.13985-.13994.31805-.23524.51208-.27387.19402-.03863.39515-.01884.57792.05687zm5.274-.147c.1875-.18747
.4418-.29279.707-.29279s.5195.10532.707.29279c.9298.92765 1.6672 2.02985 2.1699 3.24331.5026 1.21345.7606 2.51425.7591 3.82767.0015 1.3135-.2565
2.6143-.7591 3.8277-.5027 1.2135-1.2401 2.3157-2.1699 3.2433-.1886.1822-.4412.283-.7034.2807s-.513-.1075-.6984-.2929-.2906-.4362-.2929-.6984
.0985-.5148.2807-.7034c.7441-.7419 1.3342-1.6237 1.7363-2.5945.4022-.9709.6083-2.0117.6067-3.0625 0-2.20998-.894-4.20798-2.343-5.65698-.1875
-.18753-.2928-.44184-.2928-.707 0-.26517.1053-.51948.2928-.707zm-2.829 2.828c.0929-.09298.2032-.16674.3246-.21706.1214-.05033.2515-.07623.3829
-.07623s.2615.0259.3829.07623c.1214.05032.2317.12408.3246.21706.5579.55666 1.0003 1.21806 1.3018 1.94621.3015.72814.4562 1.50868.4552 2.29677.001
.7881-.1537 1.5686-.4553 2.2968-.3015.7281-.7439 1.3895-1.3017 1.9462-.1876.1877-.4421.2931-.7075.2931s-.5199-.1054-.7075-.2931c-.1876-.1876
-.2931-.4421-.2931-.7075 0-.2653.1055-.5198.2931-.7075.3722-.3708.6673-.8116.8685-1.2969.2011-.4854.3043-1.0057.3035-1.5311.0008-.52537-.1023
-1.04572-.3035-1.53107-.2011-.48536-.4963-.92612-.8685-1.29691-.093-.09288-.1667-.20316-.2171-.32456-.0503-.1214-.0762-.25153-.0762-.38294
0-.13142.0259-.26155.0762-.38294.0504-.1214.1241-.23169.2171-.32456z" />
</Button>
<Button
x:Name="TurnOnVolumeBtn"
Visibility="Collapsed"
Grid.Column="8" Padding="2" Width="25"
Height="25"
ToolTip="Включити звук. Клавіша: [M]" Background="Black" BorderBrush="Black"
Click="TurnOnVolume">
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V320 H320 V0 H0 Z">
<GeometryDrawing Brush="LightGray" Geometry="m9.38268 3.07615c.37368.15478.61732.51942.61732.92388v11.99997c0
.4045-.24364.7691-.61732.9239-.37367.1548-.80379.0692-1.08979-.2168l-3.7071-3.7071h-2.58579c-.55228
0-1-.4477-1-1v-3.99997c0-.55229.44772-1 1-1h2.58579l3.7071-3.70711c.286-.286.71612-.37155 1.08979-.21677z" />
<GeometryDrawing Brush="LightGray" Geometry="m12.2929 7.29289c.3905-.39052 1.0237-.39052 1.4142 0l1.2929
1.2929 1.2929-1.2929c.3905-.39052 1.0237-.39052 1.4142 0 .3905.39053.3905 1.02369 0 1.41422l-1.2929 1.29289
1.2929 1.2929c.3905.3905.3905 1.0237 0 1.4142s-1.0237.3905-1.4142 0l-1.2929-1.2929-1.2929
1.2929c-.3905.3905-1.0237.3905-1.4142 0s-.3905-1.0237 0-1.4142l1.2929-1.2929-1.2929-1.29289c-.3905-.39053-.3905-1.02369
0-1.41422z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Button>
</Grid> </Grid>
<StatusBar <StatusBar
Grid.Row="5" Grid.Row="5"
Grid.Column="2" Grid.Column="2"
Background="#252525"
Foreground="White"
> >
<StatusBar.ItemsPanel> <StatusBar.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
@@ -314,7 +382,8 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
@@ -324,14 +393,26 @@
</Grid> </Grid>
</ItemsPanelTemplate> </ItemsPanelTemplate>
</StatusBar.ItemsPanel> </StatusBar.ItemsPanel>
<StatusBarItem Grid.Column="0"> <StatusBarItem Grid.Column="0" Background="Black">
<controls:UpdatableProgressBar x:Name="Volume"
Width="70"
Height="15"
HorizontalAlignment="Stretch"
Background="#252525"
BorderBrush="#252525"
Foreground="LightBlue"
Maximum="100"
Minimum="0">
</controls:UpdatableProgressBar>
</StatusBarItem>
<StatusBarItem Grid.Column="1">
<TextBlock Margin="3 0 0 0" x:Name="StatusClock" FontSize="16" Text="00:00 / 00:00"></TextBlock> <TextBlock Margin="3 0 0 0" x:Name="StatusClock" FontSize="16" Text="00:00 / 00:00"></TextBlock>
</StatusBarItem> </StatusBarItem>
<Separator Grid.Column="1" /> <Separator Grid.Column="2" />
<StatusBarItem Grid.Column="2">
<TextBlock Margin="3 0 0 0" x:Name="StatusHelp" FontSize="14" Foreground="DarkBlue" ></TextBlock>
</StatusBarItem>
<StatusBarItem Grid.Column="3"> <StatusBarItem Grid.Column="3">
<TextBlock Margin="3 0 0 0" x:Name="StatusHelp" FontSize="12" ></TextBlock>
</StatusBarItem>
<StatusBarItem Grid.Column="4">
<TextBlock x:Name="Status"></TextBlock> <TextBlock x:Name="Status"></TextBlock>
</StatusBarItem> </StatusBarItem>
</StatusBar> </StatusBar>
+9 -5
View File
@@ -74,7 +74,7 @@ public partial class MainWindow
_helpWindow.Show(); _helpWindow.Show();
} }
public void BlinkHelp(string helpText, int times = 3) public void BlinkHelp(string helpText, int times = 2)
{ {
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
@@ -112,7 +112,7 @@ public partial class MainWindow
_mediaPlayer.PositionChanged += (o, args) => _mediaPlayer.PositionChanged += (o, args) =>
{ {
Dispatcher.Invoke(() => videoSlider.Value = _mediaPlayer.Position * videoSlider.Maximum); Dispatcher.Invoke(() => VideoSlider.Value = _mediaPlayer.Position * VideoSlider.Maximum);
Dispatcher.Invoke(() => StatusClock.Text = $"{TimeSpan.FromMilliseconds(_mediaPlayer.Time):mm\\:ss} / {_formState.CurrentVideoLength:mm\\:ss}"); Dispatcher.Invoke(() => StatusClock.Text = $"{TimeSpan.FromMilliseconds(_mediaPlayer.Time):mm\\:ss} / {_formState.CurrentVideoLength:mm\\:ss}");
var curTime = _formState.GetTimeName(TimeSpan.FromMilliseconds(_mediaPlayer.Time)); var curTime = _formState.GetTimeName(TimeSpan.FromMilliseconds(_mediaPlayer.Time));
@@ -149,10 +149,12 @@ public partial class MainWindow
}; };
videoSlider.ValueChanged += (value, newValue) => VideoSlider.ValueChanged += (value, newValue) =>
_mediaPlayer.Position = (float)(newValue / videoSlider.Maximum); _mediaPlayer.Position = (float)(newValue / VideoSlider.Maximum);
videoSlider.KeyDown += (sender, args) => _mediator.Publish(new KeyEvent(sender, args)); VideoSlider.KeyDown += (sender, args) => _mediator.Publish(new KeyEvent(sender, args));
Volume.ValueChanged += (_, newValue) => _mediator.Publish(new VolumeChangedEvent((int)newValue));
SizeChanged += (sender, args) => SizeChanged += (sender, args) =>
{ {
@@ -257,6 +259,8 @@ public partial class MainWindow
private void RemoveSelectedClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveSelectedAnns)); private void RemoveSelectedClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveSelectedAnns));
private void RemoveAllClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveAllAnns)); private void RemoveAllClick(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.RemoveAllAnns));
private void TurnOffVolume(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.TurnOffVolume));
private void TurnOnVolume(object sender, RoutedEventArgs e) => _mediator.Publish(new PlaybackControlEvent(PlaybackControlEnum.TurnOnVolume));
private void OpenHelpWindowClick(object sender, RoutedEventArgs e) private void OpenHelpWindowClick(object sender, RoutedEventArgs e)
{ {
+55 -1
View File
@@ -1,4 +1,5 @@
using System.IO; using System.IO;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Azaion.Annotator.DTO; using Azaion.Annotator.DTO;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
@@ -9,7 +10,8 @@ namespace Azaion.Annotator;
public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWindow mainWindow, FormState formState, Config config) : public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWindow mainWindow, FormState formState, Config config) :
INotificationHandler<KeyEvent>, INotificationHandler<KeyEvent>,
INotificationHandler<AnnClassSelectedEvent>, INotificationHandler<AnnClassSelectedEvent>,
INotificationHandler<PlaybackControlEvent> INotificationHandler<PlaybackControlEvent>,
INotificationHandler<VolumeChangedEvent>
{ {
private const int STEP = 20; private const int STEP = 20;
private const int LARGE_STEP = 5000; private const int LARGE_STEP = 5000;
@@ -58,6 +60,33 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
if (KeysControlEnumDict.TryGetValue(key, out var value)) if (KeysControlEnumDict.TryGetValue(key, out var value))
await ControlPlayback(value); await ControlPlayback(value);
await VolumeControl(key);
}
private async Task VolumeControl(Key key)
{
switch (key)
{
case Key.VolumeMute when mediaPlayer.Volume == 0:
await ControlPlayback(PlaybackControlEnum.TurnOnVolume);
break;
case Key.VolumeMute:
await ControlPlayback(PlaybackControlEnum.TurnOffVolume);
break;
case Key.Up:
case Key.VolumeUp:
var vUp = Math.Min(100, mediaPlayer.Volume + 5);
ChangeVolume(vUp);
mainWindow.Volume.Value = vUp;
break;
case Key.Down:
case Key.VolumeDown:
var vDown = Math.Max(0, mediaPlayer.Volume - 5);
ChangeVolume(vDown);
mainWindow.Volume.Value = vDown;
break;
}
} }
public async Task Handle(PlaybackControlEvent notification, CancellationToken cancellationToken) public async Task Handle(PlaybackControlEvent notification, CancellationToken cancellationToken)
@@ -87,10 +116,12 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
case PlaybackControlEnum.PreviousFrame: case PlaybackControlEnum.PreviousFrame:
mediaPlayer.SetPause(true); mediaPlayer.SetPause(true);
mediaPlayer.Time -= step; mediaPlayer.Time -= step;
mainWindow.VideoSlider.Value = mediaPlayer.Position * 100;
break; break;
case PlaybackControlEnum.NextFrame: case PlaybackControlEnum.NextFrame:
mediaPlayer.SetPause(true); mediaPlayer.SetPause(true);
mediaPlayer.Time += step; mediaPlayer.Time += step;
mainWindow.VideoSlider.Value = mediaPlayer.Position * 100;
break; break;
case PlaybackControlEnum.SaveAnnotations: case PlaybackControlEnum.SaveAnnotations:
await SaveAnnotations(); await SaveAnnotations();
@@ -101,6 +132,17 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
case PlaybackControlEnum.RemoveAllAnns: case PlaybackControlEnum.RemoveAllAnns:
mainWindow.Editor.RemoveAllAnns(); mainWindow.Editor.RemoveAllAnns();
break; break;
case PlaybackControlEnum.TurnOnVolume:
mainWindow.TurnOnVolumeBtn.Visibility = Visibility.Collapsed;
mainWindow.TurnOffVolumeBtn.Visibility = Visibility.Visible;
mediaPlayer.Volume = formState.CurrentVolume;
break;
case PlaybackControlEnum.TurnOffVolume:
mainWindow.TurnOffVolumeBtn.Visibility = Visibility.Collapsed;
mainWindow.TurnOnVolumeBtn.Visibility = Visibility.Visible;
formState.CurrentVolume = mediaPlayer.Volume;
mediaPlayer.Volume = 0;
break;
case PlaybackControlEnum.None: case PlaybackControlEnum.None:
break; break;
default: default:
@@ -108,6 +150,18 @@ public class PlayerControlHandler(LibVLC libVLC, MediaPlayer mediaPlayer, MainWi
} }
} }
public async Task Handle(VolumeChangedEvent notification, CancellationToken cancellationToken)
{
ChangeVolume(notification.Volume);
await Task.CompletedTask;
}
private void ChangeVolume(int volume)
{
formState.CurrentVolume = volume;
mediaPlayer.Volume = volume;
}
private void Play() private void Play()
{ {
if (mainWindow.LvFiles.SelectedItem == null) if (mainWindow.LvFiles.SelectedItem == null)