Revert attempt to ARM64 VideoViewer

This commit is contained in:
ema
2026-04-14 23:25:58 +08:00
parent f2515b1b16
commit 39feab58a3
5 changed files with 45 additions and 289 deletions
@@ -88,47 +88,3 @@ public sealed class CoverArtConverter : IValueConverter
throw new NotImplementedException();
}
}
public sealed class TimeToLongConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is long v)
return TimeSpan.FromTicks((long)v);
else
return TimeSpan.FromTicks(0L);
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is TimeSpan v)
return ((TimeSpan)v).Ticks;
else
return 0L;
}
}
public sealed class TimeToShortStringConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "00:00";
var v = (TimeSpan)value;
var s = string.Empty;
if (v.Hours > 0)
s += $"{v.Hours:D2}:";
s += $"{v.Minutes:D2}:{v.Seconds:D2}";
return s;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
@@ -22,7 +22,6 @@ using QuickLook.Common.Plugin;
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
namespace QuickLook.Plugin.VideoViewer;
@@ -32,7 +31,6 @@ public sealed class Plugin : IViewer
private static MediaInfoLib _mediaInfo;
private ViewerPanel _vp;
private static readonly bool isArm64 = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
public int Priority => -3;
@@ -40,7 +38,7 @@ public sealed class Plugin : IViewer
{
_mediaInfo = new MediaInfoLib(Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
isArm64 ? @"MediaInfo-arm64\" : Environment.Is64BitProcess ? @"MediaInfo-x64\" : @"MediaInfo-x86\"));
Environment.Is64BitProcess ? @"MediaInfo-x64\" : @"MediaInfo-x86\"));
_mediaInfo.Option("Cover_Data", "base64");
}
@@ -130,10 +128,8 @@ public sealed class Plugin : IViewer
context.ViewerContent = _vp;
context.Title = $"{Path.GetFileName(path)}";
if (isArm64)
_vp.LoadAndPlayWPF(path, _mediaInfo);
else
_vp.LoadAndPlay(path, _mediaInfo);
_vp.LoadAndPlay(path, _mediaInfo);
}
public void Cleanup()
@@ -31,7 +31,6 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
/// <summary>
/// Load and insert the GlassLayer control to the videoControlContainer.
/// </summary>
private partial void LoadAndInsertGlassLayer()
{
// Replace XAML with C# dynamic construction
@@ -116,7 +115,7 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
var blurredElementSetter = new Setter((DependencyProperty)blurredElementProperty, new Binding()
{
ElementName = isArm64 ? "mediaElementWPF" : "mediaElement"
ElementName = "mediaElement"
});
style.Setters.Add(blurredElementSetter);
@@ -132,7 +131,7 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
var dataTriggerSetter = new Setter((DependencyProperty)blurredElementProperty, new Binding()
{
ElementName = isArm64 ? "mediaElementWPF" : "mediaElement"
ElementName = "mediaElement"
});
dataTrigger.Setters.Add(dataTriggerSetter);
@@ -13,8 +13,6 @@
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<local:TimeTickToShortStringConverter x:Key="TimeTickToShortStringConverter" />
<local:TimeToShortStringConverter x:Key="TimeToShortStringConverter" />
<local:TimeToLongConverter x:Key="TimeToLongConverter" />
<local:VolumeToIconConverter x:Key="VolumeToIconConverter" />
<local:CoverArtConverter x:Key="CoverArtConverter" />
<ResourceDictionary.MergedDictionaries>
@@ -24,7 +22,6 @@
</UserControl.Resources>
<Grid MouseLeftButtonDown="Panel_MouseLeftButtonDown">
<mediakit:MediaUriElement x:Name="mediaElement" />
<MediaElement x:Name="mediaElementWPF" LoadedBehavior="Manual" Stretch="UniformToFill" Margin="0,0,0,0" />
<Grid x:Name="coverArtPersenter"
Background="{StaticResource MainWindowBackground}"
ClipToBounds="True">
@@ -207,7 +204,6 @@
</Button.Style>
</Button>
<Button x:Name="buttonTime"
Visibility="Hidden"
Width="NaN"
MinWidth="37"
DockPanel.Dock="Right"
@@ -232,50 +228,13 @@
</TextBlock.Style>
</TextBlock>
</Button>
<Button x:Name="buttonTimeWPF"
Visibility="Hidden"
Width="NaN"
MinWidth="37"
DockPanel.Dock="Right"
Style="{StaticResource ControlButtonStyle}"
Tag="Time"
ToolTip="Time Elapsed/Remaining">
<TextBlock VerticalAlignment="Center"
x:Name="textProgress"
FontFamily="{Binding ElementName=viewerPanel, Path=FontFamily}"
FontSize="11"
Foreground="{DynamicResource CaptionButtonIconForeground}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=buttonTimeWPF, Path=Tag}" Value="Time">
<Setter Property="Text" Value="{Binding ElementName=mediaElementWPF, Path=Position, Converter={StaticResource TimeToShortStringConverter}}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=buttonTimeWPF, Path=Tag}" Value="Length">
<Setter Property="Text" Value="{Binding ElementName=mediaElementWPF, Path=NaturalDuration.TimeSpan, Converter={StaticResource TimeToShortStringConverter}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Button>
<Slider x:Name="sliderProgress"
Visibility="Hidden"
Delay="1"
LargeChange="1"
Maximum="{Binding ElementName=mediaElement, Path=MediaDuration}"
SmallChange="1"
Style="{StaticResource PositionSliderStyle}"
Value="{Binding MediaPosition, ElementName=mediaElement}" />
<Slider x:Name="sliderProgressWPF"
Thumb.DragStarted="Seek_Drag_Started" Thumb.DragCompleted="Seek_Drag_Completed" ValueChanged="Seek_Value_Changed"
Visibility="Hidden"
Delay="1"
LargeChange="1"
Maximum="{Binding ElementName=mediaElementWPF, Path=NaturalDuration, Converter={StaticResource TimeToLongConverter}}"
SmallChange="1"
Style="{StaticResource PositionSliderStyle}"
Value="{Binding Position, ElementName=mediaElementWPF, Converter={StaticResource TimeToLongConverter}}" />
</DockPanel>
</Grid>
<Grid x:Name="volumeSliderLayer"
@@ -28,12 +28,10 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
@@ -47,9 +45,6 @@ namespace QuickLook.Plugin.VideoViewer;
public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChanged
{
private DispatcherTimer timer;
private bool IsSeeked;
private readonly ContextObject _context;
private BitmapSource _coverArt;
private DispatcherTimer _lyricTimer;
@@ -60,7 +55,6 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
private bool _isPlaying;
private bool _wasPlaying;
private bool _shouldLoop;
private readonly bool isArm64 = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
public ViewerPanel(ContextObject context)
{
@@ -72,41 +66,25 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
_context = context;
mediaElement.MediaUriPlayer.LAVFilterDirectory =
IntPtr.Size == 8 ? @"LAVFilters-x64\" : @"LAVFilters-x86\";
//ShowViedoControlContainer(null, null);
viewerPanel.PreviewMouseMove += ShowViedoControlContainer;
if (isArm64)
{
InitializeArm64();
} else
{
InitializeDefault();
}
ShouldLoop = SettingHelper.Get("ShouldLoop", false, "QuickLook.Plugin.VideoViewer");
buttonPlayPause.Click += TogglePlayPause;
buttonLoop.Click += ToggleShouldLoop;
buttonMute.Click += (_, _) => volumeSliderLayer.Visibility = Visibility.Visible;
volumeSliderLayer.MouseDown += (_, _) => volumeSliderLayer.Visibility = Visibility.Collapsed;
PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d);
}
private void InitializeDefault()
{
sliderProgress.Visibility = Visibility.Visible;
buttonTime.Visibility = Visibility.Visible;
mediaElement.MediaUriPlayer.LAVFilterDirectory = (IntPtr.Size == 8 ? @"LAVFilters-x64\" : @"LAVFilters-x86\");
mediaElement.MediaUriPlayer.PlayerStateChanged += PlayerStateChanged;
mediaElement.MediaOpened += MediaOpened;
mediaElement.MediaEnded += MediaEnded;
mediaElement.MediaFailed += MediaFailed;
ShouldLoop = SettingHelper.Get("ShouldLoop", false, "QuickLook.Plugin.VideoViewer");
buttonPlayPause.Click += TogglePlayPause;
buttonLoop.Click += ToggleShouldLoop;
buttonTime.Click += (_, _) => buttonTime.Tag = (string)buttonTime.Tag == "Time" ? "Length" : "Time";
buttonMute.Click += (_, _) => volumeSliderLayer.Visibility = Visibility.Visible;
volumeSliderLayer.MouseDown += (_, _) => volumeSliderLayer.Visibility = Visibility.Collapsed;
sliderProgress.PreviewMouseDown += (_, e) =>
{
_wasPlaying = mediaElement.IsPlaying;
@@ -116,66 +94,8 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
{
if (_wasPlaying) mediaElement.Play();
};
}
private void InitializeArm64()
{
sliderProgressWPF.Visibility = Visibility.Visible;
buttonTimeWPF.Visibility = Visibility.Visible;
mediaElementWPF.MediaOpened += MediaOpened;
mediaElementWPF.MediaEnded += MediaEnded;
buttonTimeWPF.Click += (_, _) => buttonTimeWPF.Tag = (string)buttonTimeWPF.Tag == "Time" ? "Length" : "Time";
timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
timer.Tick += Seek_Timer;
timer.Start();
buttonTimeWPF.Click += (_, _) => buttonTime.Tag = (string)buttonTime.Tag == "Time" ? "Length" : "Time";
sliderProgressWPF.PreviewMouseDown += (_, e) =>
{
_wasPlaying = IsPlaying;
mediaElementWPF.Pause();
};
sliderProgressWPF.PreviewMouseUp += (_, _) =>
{
if (_wasPlaying) mediaElementWPF.Play();
};
IsSeeked = false;
}
private void Seek_Timer(object sender, EventArgs e)
{
if ((mediaElementWPF.Source != null) && (mediaElementWPF.NaturalDuration.HasTimeSpan) && (!IsSeeked))
{
sliderProgressWPF.Minimum = 0;
sliderProgressWPF.Maximum = mediaElementWPF.NaturalDuration.TimeSpan.TotalSeconds;
sliderProgressWPF.Value = mediaElementWPF.Position.TotalSeconds;
}
}
private void Seek_Drag_Started(object sender, DragStartedEventArgs e)
{
IsSeeked = true;
}
private void Seek_Drag_Completed(object sender, DragCompletedEventArgs e)
{
IsSeeked = false;
mediaElementWPF.Position = TimeSpan.FromSeconds(sliderProgressWPF.Value);
}
private void Seek_Value_Changed(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if ((string)buttonTimeWPF.Tag == "Time")
textProgress.Text = TimeSpan.FromSeconds(sliderProgressWPF.Value).ToString(@"hh\:mm\:ss");
else
textProgress.Text = TimeSpan.FromSeconds(sliderProgressWPF.Maximum).ToString(@"hh\:mm\:ss");
PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d);
}
private partial void LoadAndInsertGlassLayer();
@@ -210,12 +130,6 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
if (value == _shouldLoop) return;
_shouldLoop = value;
OnPropertyChanged();
if (!IsPlaying)
{
IsPlaying = true;
if (isArm64) mediaElementWPF.Play(); else mediaElement.Play();
}
}
}
@@ -239,18 +153,15 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
try
{
if (timer!=null)
timer.Stop();
mediaElement?.Close();
mediaElementWPF?.Close();
Task.Run(() =>
{
mediaElement?.MediaUriPlayer.Dispose();
mediaElement = null;
mediaElementWPF = null;
});
} catch (Exception e)
}
catch (Exception e)
{
Debug.WriteLine(e);
}
@@ -274,21 +185,10 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
private void MediaOpened(object o, RoutedEventArgs args)
{
if (isArm64)
{
if (mediaElementWPF == null)
return;
if (mediaElement == null)
return;
HasVideo = mediaElementWPF.HasVideo;
} else
{
if (mediaElement == null)
return;
HasVideo = mediaElement.HasVideo;
}
HasVideo = mediaElement.HasVideo;
_context.IsBusy = false;
}
@@ -309,42 +209,21 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
private void MediaEnded(object sender, RoutedEventArgs e)
{
if (isArm64)
if (mediaElement == null)
return;
mediaElement.MediaPosition = 0L;
if (ShouldLoop)
{
if (mediaElementWPF == null)
return;
IsPlaying = true;
mediaElementWPF.Position = new TimeSpan(0L);
if (ShouldLoop)
{
IsPlaying = true;
mediaElementWPF.Play();
} else
{
IsPlaying = false;
mediaElementWPF.Pause();
}
} else
mediaElement.Play();
}
else
{
if (mediaElement == null)
return;
mediaElement.MediaPosition = 0L;
if (ShouldLoop)
{
IsPlaying = true;
mediaElement.Play();
} else
{
IsPlaying = false;
mediaElement.Pause();
}
IsPlaying = false;
mediaElement.Pause();
}
}
@@ -406,7 +285,8 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
var coverData = info.Get(StreamKind.General, 0, "Cover_Data");
var coverBytes = CoverDataExtractor.Extract(coverData);
CoverArt = CoverDataExtractor.Extract(coverBytes);
} catch (Exception e)
}
catch (Exception e)
{
Debug.WriteLine(e);
metaTitle.Text = Path.GetFileName(path);
@@ -461,9 +341,10 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
{
if (_lyricLines != null && _lyricLines.Length != 0)
{
var lyric = LrcHelper.GetNearestLrc(_lyricLines, new TimeSpan(isArm64 ? mediaElementWPF.Position.Ticks : mediaElement.MediaPosition));
var lyric = LrcHelper.GetNearestLrc(_lyricLines, new TimeSpan(mediaElement.MediaPosition));
metaLyric.Text = lyric?.LrcText?.Trim();
} else
}
else
{
metaLyric.Text = null;
metaLyric.Visibility = Visibility.Collapsed;
@@ -472,7 +353,8 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
_lyricTimer.Start();
metaLyric.Visibility = Visibility.Visible;
} else
}
else
{
metaLyric.Visibility = Visibility.Collapsed;
}
@@ -480,10 +362,10 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
public double LinearVolume
{
get => (isArm64 ? mediaElementWPF.Volume : mediaElement.Volume);
get => mediaElement.Volume;
set
{
if (isArm64) mediaElementWPF.Volume = value; else mediaElement.Volume = value;
mediaElement.Volume = value;
OnPropertyChanged();
}
}
@@ -495,53 +377,17 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
private void TogglePlayPause(object sender, EventArgs e)
{
if (isArm64)
{
if (IsPlaying)
{
IsPlaying = false;
mediaElementWPF.Pause();
} else
{
IsPlaying = true;
mediaElementWPF.Play();
}
} else
{
if (mediaElement.IsPlaying)
mediaElement.Pause();
else
mediaElement.Play();
}
if (mediaElement.IsPlaying)
mediaElement.Pause();
else
mediaElement.Play();
}
private void ToggleShouldLoop(object sender, EventArgs e)
{
ShouldLoop = !ShouldLoop;
}
public void LoadAndPlayWPF(string path, MediaInfoLib info)
{
// Detect whether it is other playback formats
if (!HasVideo)
{
string audioCodec = info?.Get(StreamKind.Audio, 0, "Format");
if (audioCodec?.Equals("MIDI", StringComparison.OrdinalIgnoreCase) ?? false)
{
_midiPlayer = new MidiPlayer(this, _context);
_midiPlayer.LoadAndPlay(path);
return; // Midi player will handle the playback at all
}
}
UpdateMeta(path, info);
mediaElementWPF.Source = new Uri(path);
// old plugin use an int-typed "Volume" config key ranged from 0 to 100. Let's use a new one here.
LinearVolume = SettingHelper.Get("VolumeDouble", 1d, "QuickLook.Plugin.VideoViewer");
mediaElementWPF.Play();
}
public void LoadAndPlay(string path, MediaInfoLib info)
{
// Detect whether it is other playback formats