mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-11 17:59:17 +00:00
switch to new FFME control
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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()
|
||||||
|
@@ -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 |
@@ -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" />
|
||||||
|
@@ -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>
|
||||||
|
@@ -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)
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Reference in New Issue
Block a user