switch to new FFME control

This commit is contained in:
Paddy Xu
2017-07-29 22:29:06 +03:00
parent 882078cd60
commit 6c64aa7c3d
12 changed files with 6700 additions and 6692 deletions

View File

@@ -35,7 +35,7 @@ namespace QuickLook.Plugin.ImageViewer
".orf", ".pef", ".ptx", ".pxn", ".r3d", ".raf", ".raw", ".rwl", ".rw2", ".rwz", ".sr2", ".srf", ".srw", ".orf", ".pef", ".ptx", ".pxn", ".r3d", ".raf", ".raw", ".rwl", ".rw2", ".rwz", ".sr2", ".srf", ".srw",
".tif", ".x3f", ".tif", ".x3f",
// normal // normal
".bmp", ".gif", ".ico", ".icon", ".jpg", ".jpeg", ".png", ".psd", ".svg", ".wdp", ".tiff", ".tga", ".webp" ".bmp", ".ggg", ".ico", ".icon", ".jpg", ".jpeg", ".png", ".psd", ".svg", ".wdp", ".tiff", ".tga", ".webp"
}; };
private Size _imageSize; private Size _imageSize;
private ImagePanel _ip; private ImagePanel _ip;
@@ -67,10 +67,15 @@ namespace QuickLook.Plugin.ImageViewer
context.SetPreferredSizeFit(_imageSize, 0.8); context.SetPreferredSizeFit(_imageSize, 0.8);
else else
context.PreferredSize = new Size(1024, 768); context.PreferredSize = new Size(1024, 768);
Directory.SetCurrentDirectory(App.AppPath);
} }
public void View(string path, ContextObject context) public void View(string path, ContextObject context)
{ {
// set dcraw.exe for Magick.NET
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
_ip = new ImagePanel(); _ip = new ImagePanel();
context.ViewerContent = _ip; context.ViewerContent = _ip;
@@ -81,11 +86,12 @@ namespace QuickLook.Plugin.ImageViewer
LoadImage(_ip, path); LoadImage(_ip, path);
context.IsBusy = false; context.IsBusy = false;
Directory.SetCurrentDirectory(App.AppPath);
} }
public void Cleanup() public void Cleanup()
{ {
Directory.SetCurrentDirectory(App.AppPath);
_ip = null; _ip = null;
} }

View File

@@ -58,6 +58,24 @@ namespace QuickLook.Plugin.VideoViewer
} }
} }
public sealed class BooleanToVisibilityVisibleConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Visible;
var v = (bool) value;
return v ? Visibility.Visible : Visibility.Hidden;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public sealed class BooleanToVisibilityHiddenConverter : DependencyObject, IValueConverter public sealed class BooleanToVisibilityHiddenConverter : DependencyObject, IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
@@ -78,8 +96,7 @@ namespace QuickLook.Plugin.VideoViewer
public class TimeSpanToSecondsConverter : IValueConverter public class TimeSpanToSecondsConverter : IValueConverter
{ {
public object Convert(object value, Type targetType, public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
object parameter, CultureInfo culture)
{ {
if (value is TimeSpan) return ((TimeSpan) value).TotalSeconds; if (value is TimeSpan) return ((TimeSpan) value).TotalSeconds;
if (value is Duration) if (value is Duration)
@@ -88,15 +105,29 @@ namespace QuickLook.Plugin.VideoViewer
return 0d; return 0d;
} }
public object ConvertBack(object value, Type targetType, public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
object parameter, CultureInfo culture)
{ {
var result = TimeSpan.FromTicks((long) Math.Round(TimeSpan.TicksPerSecond * (double) value, 0)); var result = TimeSpan.FromTicks((long) Math.Round(TimeSpan.TicksPerSecond * (double) value, 0));
// Do the conversion from visibility to bool
if (targetType == typeof(TimeSpan)) return result; if (targetType == typeof(TimeSpan)) return result;
if (targetType == typeof(Duration)) return new Duration(result); if (targetType == typeof(Duration)) return new Duration(result);
return Activator.CreateInstance(targetType); return Activator.CreateInstance(targetType);
} }
} }
public class DurationToTimeSpanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = (Duration) value;
return val.HasTimeSpan ? val.TimeSpan : TimeSpan.Zero;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
} }

View File

@@ -18,6 +18,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text;
using System.Windows; using System.Windows;
using System.Xml.XPath; using System.Xml.XPath;
@@ -47,6 +48,7 @@ namespace QuickLook.Plugin.VideoViewer.FFmpeg
p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = _probePath; p.StartInfo.FileName = _probePath;
p.StartInfo.Arguments = $"-v quiet -print_format xml -show_streams -show_format \"{media}\""; p.StartInfo.Arguments = $"-v quiet -print_format xml -show_streams -show_format \"{media}\"";
p.StartInfo.StandardOutputEncoding = Encoding.UTF8;
p.Start(); p.Start();
p.WaitForExit(); p.WaitForExit();
@@ -67,7 +69,7 @@ namespace QuickLook.Plugin.VideoViewer.FFmpeg
public bool CanDecode() public bool CanDecode()
{ {
var info = infoNavigator.SelectSingleNode("/ffprobe/streams"); var info = infoNavigator.SelectSingleNode("/ffprobe/format");
return info != null; return info != null;
} }

View File

@@ -15,6 +15,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@@ -26,6 +28,7 @@ namespace QuickLook.Plugin.VideoViewer
{ {
public class Plugin : IViewer public class Plugin : IViewer
{ {
private Size _mediaSize;
private ViewerPanel _vp; private ViewerPanel _vp;
public int Priority => int.MaxValue; public int Priority => int.MaxValue;
@@ -43,25 +46,28 @@ namespace QuickLook.Plugin.VideoViewer
if (Directory.Exists(path)) if (Directory.Exists(path))
return false; return false;
var formats = new[] var blacklist = new[]
{ {
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv", ".txt", ".jpg", ".bmp"
".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv"
}; };
if (formats.Contains(Path.GetExtension(path).ToLower())) if (blacklist.Contains(Path.GetExtension(path).ToLower()))
return true; return false;
return false; return new FFprobe(path).CanDecode();
} }
public void Prepare(string path, ContextObject context) public void Prepare(string path, ContextObject context)
{ {
var def = new Size(1024, 768); var def = new Size(450, 450);
var real = new FFprobe(path).GetViewSize(); _mediaSize = new FFprobe(path).GetViewSize();
context.SetPreferredSizeFit(real == Size.Empty ? def : real, 0.6); var windowSize = _mediaSize == Size.Empty ? def : _mediaSize;
windowSize.Width = Math.Max(def.Width, windowSize.Width);
windowSize.Height = Math.Max(def.Height, windowSize.Height);
context.SetPreferredSizeFit(windowSize, 0.6);
} }
public void View(string path, ContextObject context) public void View(string path, ContextObject context)
@@ -70,11 +76,16 @@ namespace QuickLook.Plugin.VideoViewer
context.ViewerContent = _vp; context.ViewerContent = _vp;
Debug.WriteLine("ViewerContent done");
_vp.LoadAndPlay(path); _vp.LoadAndPlay(path);
Debug.WriteLine("LoadAndPlay done");
_vp.mediaElement.MediaOpened += (sender, e) => context.IsBusy = false;
var info = _mediaSize == Size.Empty ? "Audio" : $"{_mediaSize.Width}×{_mediaSize.Height}";
context.Title = context.Title =
$"{Path.GetFileName(path)} ({_vp.mediaElement.NaturalVideoWidth}×{_vp.mediaElement.NaturalVideoHeight})"; $"{Path.GetFileName(path)} ({info})";
context.IsBusy = false;
} }
public void Cleanup() public void Cleanup()

View File

@@ -62,6 +62,7 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xaml"> <Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework> <RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference> </Reference>
@@ -105,8 +106,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="ffme\ffme.dll" /> <Content Include="ffme\ffme.dll" />
<Resource Include="Resources\compact-disc.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
<Resource Include="ffme\ffme.xml" /> <Resource Include="ffme\ffme.xml" />
<Content Include="ffme\ffme.pdb" />
<Content Include="ffme\ffmpeg.dll" /> <Content Include="ffme\ffmpeg.dll" />
<Content Include="ffme\ffmpeg.pdb" />
<Content Include="FFmpeg\x64\avcodec-57.dll"> <Content Include="FFmpeg\x64\avcodec-57.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -4,8 +4,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ControlButtonStyle" TargetType="Grid"> <Style x:Key="ControlButtonStyle" TargetType="Grid">
<Setter Property="Height" Value="50" /> <Setter Property="Height" Value="35" />
<Setter Property="Width" Value="50" /> <Setter Property="Width" Value="35" />
<Setter Property="Cursor" Value="Hand" /> <Setter Property="Cursor" Value="Hand" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />

View File

@@ -7,26 +7,45 @@
xmlns:local="clr-namespace:QuickLook.Plugin.VideoViewer" xmlns:local="clr-namespace:QuickLook.Plugin.VideoViewer"
xmlns:ffmpeg="clr-namespace:Unosquare.FFME;assembly=ffme" xmlns:ffmpeg="clr-namespace:Unosquare.FFME;assembly=ffme"
mc:Ignorable="d" mc:Ignorable="d"
Background="#B2454545" x:Name="userControl"
d:DesignHeight="449.167" d:DesignWidth="767"> Background="#CC4E4E4E"
d:DesignHeight="450" d:DesignWidth="450">
<Grid> <Grid>
<Grid.Resources> <Grid.Resources>
<ResourceDictionary> <ResourceDictionary>
<local:TimeSpanToSecondsConverter x:Key="TimeSpanToSecondsConverter" /> <local:TimeSpanToSecondsConverter x:Key="TimeSpanToSecondsConverter" />
<local:BooleanToVisibilityVisibleConverter x:Key="BooleanToVisibilityVisibleConverter" />
<local:BooleanToVisibilityHiddenConverter x:Key="BooleanToVisibilityHiddenConverter" /> <local:BooleanToVisibilityHiddenConverter x:Key="BooleanToVisibilityHiddenConverter" />
<local:DurationToTimeSpanConverter x:Key="DurationToTimeSpanConverter" />
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml" /> <ResourceDictionary Source="Styles.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>
</Grid.Resources> </Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="7*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<ffmpeg:MediaElement Grid.RowSpan="255" x:Name="mediaElement" /> <ffmpeg:MediaElement x:Name="mediaElement" />
<Grid Grid.Row="1"> <Image Margin="50" Source="Resources/compact-disc.png">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsOpen, ElementName=mediaElement}" Value="True" />
<Condition Binding="{Binding HasVideo, ElementName=mediaElement}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Visibility" Value="Visible" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="100"
Visibility="{Binding NaturalDuration.HasTimeSpan, ElementName=mediaElement, Converter={StaticResource BooleanToVisibilityVisibleConverter}}">
<Grid.Background> <Grid.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Offset="0.0" Color="#00000000" /> <GradientStop Offset="0.0" Color="#00000000" />
@@ -42,22 +61,30 @@
<Grid.Style> <Grid.Style>
<Style TargetType="{x:Type Grid}"> <Style TargetType="{x:Type Grid}">
<Style.Triggers> <Style.Triggers>
<Trigger Property="IsMouseOver" Value="True"> <MultiDataTrigger>
<Trigger.EnterActions> <MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Self}}"
Value="True" />
<Condition Binding="{Binding IsOpen, ElementName=mediaElement}" Value="True" />
<Condition Binding="{Binding HasVideo, ElementName=mediaElement}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.2" /> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1"
Duration="0:0:0.2" />
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</Trigger.EnterActions> </MultiDataTrigger.EnterActions>
<Trigger.ExitActions> <MultiDataTrigger.ExitActions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.2" /> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0"
Duration="0:0:0.2" />
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</Trigger.ExitActions> </MultiDataTrigger.ExitActions>
</Trigger> </MultiDataTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</Grid.Style> </Grid.Style>
@@ -72,13 +99,13 @@
<Grid Grid.Row="2"> <Grid Grid.Row="2">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="149" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" <StackPanel Grid.Column="0" VerticalAlignment="Center"
Orientation="Horizontal" Margin="20,0,0,0"> Orientation="Horizontal" Margin="10,0,0,0">
<Grid x:Name="buttonMute" Style="{StaticResource ControlButtonStyle}"> <Grid x:Name="buttonMute" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Height="30" Width="30" Foreground="#FFEFEFEF"> <fa:ImageAwesome Height="23" Width="23" Foreground="#FFEFEFEF">
<fa:ImageAwesome.Style> <fa:ImageAwesome.Style>
<Style TargetType="fa:ImageAwesome"> <Style TargetType="fa:ImageAwesome">
<Setter Property="Icon" Value="VolumeOff" /> <Setter Property="Icon" Value="VolumeOff" />
@@ -92,17 +119,18 @@
</fa:ImageAwesome.Style> </fa:ImageAwesome.Style>
</fa:ImageAwesome> </fa:ImageAwesome>
</Grid> </Grid>
<Slider Style="{StaticResource CustomSliderStyle}" Width="80" Maximum="1" <Slider Style="{StaticResource CustomSliderStyle}" MaxWidth="75" Maximum="1"
Value="{Binding Volume, ElementName=mediaElement}" Value="{Binding Volume, ElementName=mediaElement}"
Visibility="{Binding IsMuted, ElementName=mediaElement, Converter={StaticResource BooleanToVisibilityHiddenConverter}}" /> Visibility="{Binding IsMuted, ElementName=mediaElement, Converter={StaticResource BooleanToVisibilityHiddenConverter}}"
BorderThickness="0,0,5,0" />
</StackPanel> </StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Grid x:Name="buttonBackward" Style="{StaticResource ControlButtonStyle}"> <Grid x:Name="buttonBackward" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Backward" Height="27" Width="27" Foreground="#FFEFEFEF" /> <fa:ImageAwesome Icon="Backward" Height="23" Width="23" Foreground="#FFEFEFEF" />
</Grid> </Grid>
<Grid Width="7" /> <Grid Width="3" />
<Grid x:Name="buttonPlayPause" Style="{StaticResource ControlButtonStyle}"> <Grid x:Name="buttonPlayPause" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Height="30" Width="30" Foreground="#FFEFEFEF"> <fa:ImageAwesome Height="23" Width="23" Foreground="#FFEFEFEF">
<fa:ImageAwesome.Style> <fa:ImageAwesome.Style>
<Style> <Style>
<Setter Property="fa:ImageAwesome.Icon" Value="Pause" /> <Setter Property="fa:ImageAwesome.Icon" Value="Pause" />
@@ -116,22 +144,22 @@
</fa:ImageAwesome.Style> </fa:ImageAwesome.Style>
</fa:ImageAwesome> </fa:ImageAwesome>
</Grid> </Grid>
<Grid Width="7" /> <Grid Width="3" />
<Grid x:Name="buttonStop" Style="{StaticResource ControlButtonStyle}"> <Grid x:Name="buttonStop" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Stop" Height="27" Width="27" Foreground="#FFEFEFEF" /> <fa:ImageAwesome Icon="Stop" Height="21" Width="21" Foreground="#FFEFEFEF" />
</Grid> </Grid>
<Grid Width="7" /> <Grid Width="3" />
<Grid x:Name="buttonForward" Style="{StaticResource ControlButtonStyle}"> <Grid x:Name="buttonForward" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Forward" Height="27" Width="27" Foreground="#FFEFEFEF" /> <fa:ImageAwesome Icon="Forward" Height="23" Width="23" Foreground="#FFEFEFEF" />
</Grid> </Grid>
</StackPanel> </StackPanel>
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" <StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center"
Orientation="Horizontal" Margin="0,0,20,0"> Orientation="Horizontal" Margin="0,0,10,0">
<TextBlock FontSize="16" Foreground="#FFEFEFEF" <TextBlock FontSize="14" Foreground="#FFEFEFEF"
Text="{Binding Position, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement}" /> Text="{Binding Position, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement}" />
<TextBlock FontSize="16" Text=" / " Foreground="#FFEFEFEF" /> <TextBlock FontSize="14" Text=" / " Foreground="#FFEFEFEF" />
<TextBlock FontSize="16" Foreground="#FFEFEFEF" <TextBlock FontSize="14" Foreground="#FFEFEFEF"
Text="{Binding NaturalDuration.TimeSpan, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement}" /> Text="{Binding NaturalDuration, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement, Converter={StaticResource DurationToTimeSpanConverter}}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>

View File

@@ -30,6 +30,8 @@ namespace QuickLook.Plugin.VideoViewer
{ {
private readonly ContextObject _context; private readonly ContextObject _context;
private bool _wasPlaying;
public ViewerPanel(ContextObject context) public ViewerPanel(ContextObject context)
{ {
InitializeComponent(); InitializeComponent();
@@ -47,7 +49,25 @@ namespace QuickLook.Plugin.VideoViewer
buttonBackward.MouseLeftButtonUp += (sender, e) => SeekBackward(); buttonBackward.MouseLeftButtonUp += (sender, e) => SeekBackward();
buttonForward.MouseLeftButtonUp += (sender, e) => SeekForward(); buttonForward.MouseLeftButtonUp += (sender, e) => SeekForward();
sliderProgress.PreviewMouseDown += (sender, e) =>
{
_wasPlaying = mediaElement.IsPlaying;
mediaElement.Pause();
};
sliderProgress.PreviewMouseUp += (sender, e) =>
{
if (_wasPlaying) mediaElement.Play();
};
mediaElement.MediaFailed += ShowErrorNotification; mediaElement.MediaFailed += ShowErrorNotification;
mediaElement.MediaEnded += (s, e) =>
{
if (!mediaElement.NaturalDuration.HasTimeSpan)
{
mediaElement.Stop();
mediaElement.Play();
}
};
} }
public void Dispose() public void Dispose()
@@ -55,23 +75,39 @@ namespace QuickLook.Plugin.VideoViewer
mediaElement?.Stop(); mediaElement?.Stop();
mediaElement?.Dispose(); mediaElement?.Dispose();
mediaElement = null; mediaElement = null;
Debug.WriteLine("dispose done");
}
private void ResumePlaying()
{
_wasPlaying = mediaElement.IsPlaying;
} }
private void SeekBackward() private void SeekBackward()
{ {
_wasPlaying = mediaElement.IsPlaying;
mediaElement.Pause();
var pos = mediaElement.Position; var pos = mediaElement.Position;
var delta = TimeSpan.FromSeconds(15); var delta = TimeSpan.FromSeconds(15);
mediaElement.Position = pos < pos - delta ? TimeSpan.Zero : pos - delta; mediaElement.Position = pos < pos - delta ? TimeSpan.Zero : pos - delta;
if (_wasPlaying) mediaElement.Play();
} }
private void SeekForward() private void SeekForward()
{ {
_wasPlaying = mediaElement.IsPlaying;
mediaElement.Pause();
var pos = mediaElement.Position; var pos = mediaElement.Position;
var len = mediaElement.NaturalDuration.TimeSpan; var len = mediaElement.NaturalDuration.TimeSpan;
var delta = TimeSpan.FromSeconds(15); var delta = TimeSpan.FromSeconds(15);
mediaElement.Position = pos + delta > len ? len : pos + delta; mediaElement.Position = pos + delta > len ? len : pos + delta;
if (_wasPlaying) mediaElement.Play();
} }
private void TogglePlayPause(object sender, MouseButtonEventArgs e) private void TogglePlayPause(object sender, MouseButtonEventArgs e)
@@ -86,12 +122,12 @@ namespace QuickLook.Plugin.VideoViewer
private void ShowErrorNotification(object sender, ExceptionRoutedEventArgs exceptionRoutedEventArgs) private void ShowErrorNotification(object sender, ExceptionRoutedEventArgs exceptionRoutedEventArgs)
{ {
_context.ShowNotification("", "An error occurred while loading the video."); _context.ShowNotification("", "An error occurred while loading the video.");
mediaElement.Stop(); mediaElement?.Close();
Dispose(); Dispose();
throw new Exception("fallback to default viewer."); //throw new Exception("fallback to default viewer.");
} }
public void LoadAndPlay(string path) public void LoadAndPlay(string path)

File diff suppressed because it is too large Load Diff