Skip to content

Commit

Permalink
支持调用外部播放器 (#509)
Browse files Browse the repository at this point in the history
* 支持外部播放器播放

* add placeholder
  • Loading branch information
Richasy authored Sep 9, 2024
1 parent 20bb020 commit bf3db18
Show file tree
Hide file tree
Showing 33 changed files with 688 additions and 48 deletions.
19 changes: 19 additions & 0 deletions src/Desktop/BiliCopilot.UI.Models/Constants/ExternalPlayerType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Bili Copilot. All rights reserved.

namespace BiliCopilot.UI.Models.Constants;

/// <summary>
/// 外部播放器类型.
/// </summary>
public enum ExternalPlayerType
{
/// <summary>
/// MPV 播放器.
/// </summary>
Mpv,

/// <summary>
/// MPV.NET 播放器.
/// </summary>
MpvNet,
}
5 changes: 5 additions & 0 deletions src/Desktop/BiliCopilot.UI.Models/Constants/PlayerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ public enum PlayerType
/// MPV 播放器.
/// </summary>
Mpv,

/// <summary>
/// 外部播放器.
/// </summary>
External,
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,5 @@ public enum SettingNames
SelectedWebDavConfigId,
LastMomentSectionIsVideo,
LastUserSpaceSectionIsVideo,
ExternalPlayer,
}
4 changes: 4 additions & 0 deletions src/Desktop/BiliCopilot.UI/BiliCopilot.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<None Remove="Controls\Components\UserCardControl\UserCardControl.xaml" />
<None Remove="Controls\Core\Player\BiliPlayer.xaml" />
<None Remove="Controls\Core\Player\PlayerPresenter.xaml" />
<None Remove="Controls\Core\TransportControl\ExternalTransportControl.xaml" />
<None Remove="Controls\Danmaku\DanmakuBox.xaml" />
<None Remove="Controls\Danmaku\DanmakuDisplayOptions.xaml" />
<None Remove="Controls\Danmaku\DanmakuSendOptions.xaml" />
Expand Down Expand Up @@ -1232,6 +1233,9 @@
<None Update="Assets\ffmpeg\ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Page Update="Controls\Core\TransportControl\ExternalTransportControl.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Controls\WebDav\WebDavPlayerSideBody.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
Expand Down
3 changes: 3 additions & 0 deletions src/Desktop/BiliCopilot.UI/BiliCopilot.UI.csproj.user
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<None Update="App.xaml">
<SubType>Designer</SubType>
</None>
<Page Update="Controls\Core\TransportControl\ExternalTransportControl.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Controls\WebDav\WebDavPlayerSideBody.xaml">
<SubType>Designer</SubType>
</Page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void ArrangeSubtitleSize()

private void CheckTransportControlVisibility(PointerRoutedEventArgs args)
{
if (TransportControls is null || ViewModel.IsPlayerDataLoading || ViewModel.IsPlayerInitializing)
if (TransportControls is null || ViewModel.IsPlayerDataLoading || ViewModel.IsPlayerInitializing || ViewModel.IsExternalPlayer)
{
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Desktop/BiliCopilot.UI/Controls/Core/Player/BiliPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private void OnRequestCancelNotification(object? sender, EventArgs e)
}

private void OnCoreTapped(object sender, TappedRoutedEventArgs e)
=> ViewModel?.TogglePlayPauseCommand.Execute(default);
=> ViewModel?.TogglePlayPauseCommand.Execute(default);

private void OnCoreDoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
Expand Down Expand Up @@ -207,7 +207,7 @@ private void OnViewModelPropertyChanged(DependencyObject sender, DependencyPrope

private void OnViewModelInnerPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(MpvPlayerViewModel.IsPaused) && TransportControls is not null)
if (e.PropertyName == nameof(MpvPlayerViewModel.IsPaused) && TransportControls is not null && !ViewModel.IsExternalPlayer)
{
TransportControls.Visibility = ViewModel.IsPaused ? Visibility.Visible : Visibility.Collapsed;
}
Expand Down
34 changes: 32 additions & 2 deletions src/Desktop/BiliCopilot.UI/Controls/Core/Player/BiliPlayer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@
</Setter>
</Style>

<Style TargetType="local:ExternalPlayer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ExternalPlayer">
<ScrollView
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
Style="{StaticResource PageScrollViewStyle}"
VerticalScrollBarVisibility="Hidden">
<Grid Padding="12">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}"
Text="{ext:Locale Name=WatchOnExternalPlayer}"
TextAlignment="Center"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LogMessage, Converter={StaticResource ObjectToVisibilityReverseConverter}}" />
<TextBlock
LineHeight="24"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LogMessage}"
TextWrapping="Wrap"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.LogMessage, Converter={StaticResource ObjectToVisibilityConverter}}" />
</Grid>
</ScrollView>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style TargetType="local:NativePlayer">
<Setter Property="Template">
<Setter.Value>
Expand Down Expand Up @@ -158,7 +186,8 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding DanmakuControls}"
Style="{StaticResource AppContentControlStyle}" />
Style="{StaticResource AppContentControlStyle}"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.IsExternalPlayer, Converter={StaticResource BoolToVisibilityReverseConverter}}" />
<ProgressBar
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Expand All @@ -172,7 +201,8 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHoldingEnabled="True">
IsHoldingEnabled="True"
Visibility="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ViewModel.IsExternalPlayer, Converter={StaticResource BoolToVisibilityReverseConverter}}">
<Rectangle.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem
Expand Down
13 changes: 13 additions & 0 deletions src/Desktop/BiliCopilot.UI/Controls/Core/Player/ExternalPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Bili Copilot. All rights reserved.

using BiliCopilot.UI.ViewModels.Core;
using Richasy.WinUI.Share.Base;

namespace BiliCopilot.UI.Controls.Core;

/// <summary>
/// 外部播放器.
/// </summary>
public sealed class ExternalPlayer : LayoutControlBase<ExternalPlayerViewModel>
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
<DataTemplate x:Key="NativeTemplate" x:DataType="core:NativePlayerViewModel">
<local:NativePlayer ViewModel="{x:Bind Mode=OneWay}" />
</DataTemplate>
<DataTemplate x:Key="ExternalTemplate" x:DataType="core:ExternalPlayerViewModel">
<local:ExternalPlayer ViewModel="{x:Bind Mode=OneWay}" />
</DataTemplate>
<ext:PlayerTemplateSelector
x:Key="PlayerTemplateSelector"
ExternalTemplate="{StaticResource ExternalTemplate}"
MpvTemplate="{StaticResource MpvTemplate}"
NativeTemplate="{StaticResource NativeTemplate}" />
</UserControl.Resources>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8" ?>
<local:PlayerControlBase
x:Class="BiliCopilot.UI.Controls.Core.ExternalTransportControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ext="using:BiliCopilot.UI.Extensions"
xmlns:ic="using:FluentIcons.WinUI"
xmlns:local="using:BiliCopilot.UI.Controls.Core"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid
Margin="12,0"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
CornerRadius="{StaticResource ControlCornerRadius}">
<Grid Padding="12,8">
<Grid ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid>
<ProgressRing
Width="38"
Height="38"
VerticalAlignment="Center"
IsActive="{x:Bind ViewModel.IsBuffering, Mode=OneWay}"
Visibility="{x:Bind ViewModel.IsBuffering, Mode=OneWay}" />
<Grid
Width="36"
Height="36"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
BorderThickness="2"
CornerRadius="18">
<Grid>
<ic:SymbolIcon
FontSize="14"
IconVariant="Filled"
Symbol="Play"
Visibility="{x:Bind ViewModel.IsPaused, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" />
<ic:SymbolIcon
FontSize="14"
IconVariant="Filled"
Symbol="Pause"
Visibility="{x:Bind ViewModel.IsPaused, Converter={StaticResource BoolToVisibilityReverseConverter}, Mode=OneWay}" />
</Grid>
</Grid>
</Grid>

<ContentControl
x:Name="LeftPanel"
Grid.Column="1"
Content="{x:Bind LeftContent, Mode=OneWay}"
Style="{StaticResource AppContentControlStyle}" />
<TextBlock
Grid.Column="2"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Run FontWeight="Bold" Text="{x:Bind ViewModel.Position, Converter={StaticResource DurationConverter}, Mode=OneWay}" />
<Run Text="/" />
<Run Text="{x:Bind ViewModel.Duration, Converter={StaticResource DurationConverter}, Mode=OneWay}" />
</TextBlock>
<Button
Grid.Column="3"
VerticalAlignment="Center"
Command="{x:Bind ViewModel.ReloadCommand, Mode=OneWay}"
Style="{StaticResource CircleIconButtonStyle}"
ToolTipService.ToolTip="{ext:Locale Name=Reload}">
<ic:SymbolIcon FontSize="14" Symbol="ArrowSync" />
</Button>
<ContentControl
x:Name="RightPanel"
Grid.Column="4"
Content="{x:Bind RightContent, Mode=OneWay}"
Style="{StaticResource AppContentControlStyle}" />
</Grid>
</Grid>
</Grid>
</local:PlayerControlBase>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Bili Copilot. All rights reserved.

namespace BiliCopilot.UI.Controls.Core;

/// <summary>
/// 外部播放器控件.
/// </summary>
public sealed partial class ExternalTransportControl : PlayerControlBase
{
/// <summary>
/// <see cref="LeftContent"/> 的依赖属性.
/// </summary>
public static readonly DependencyProperty LeftContentProperty =
DependencyProperty.Register(nameof(LeftContent), typeof(object), typeof(VideoTransportControl), new PropertyMetadata(default));

/// <summary>
/// <see cref="RightContent"/> 的依赖属性.
/// </summary>
public static readonly DependencyProperty RightContentProperty =
DependencyProperty.Register(nameof(RightContent), typeof(object), typeof(VideoTransportControl), new PropertyMetadata(default));

/// <summary>
/// Initializes a new instance of the <see cref="ExternalTransportControl"/> class.
/// </summary>
public ExternalTransportControl() => InitializeComponent();

/// <summary>
/// 左侧内容.
/// </summary>
public object LeftContent
{
get => (object)GetValue(LeftContentProperty);
set => SetValue(LeftContentProperty, value);
}

/// <summary>
/// 右侧内容.
/// </summary>
public object RightContent
{
get => (object)GetValue(RightContentProperty);
set => SetValue(RightContentProperty, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<UserControl.Resources>
<converters:PreferQualityTypeConverter x:Key="PreferQualityConverter" />
<converters:PlayerTypeConverter x:Key="PlayerTypeConverter" />
<converters:ExternalPlayerTypeConverter x:Key="ExternalPlayerTypeConverter" />
<converters:DisplayModeConverter x:Key="DisplayModeConverter" />
</UserControl.Resources>

Expand All @@ -35,6 +36,21 @@
</ComboBox.ItemTemplate>
</ComboBox>
</community:SettingsCard>
<community:SettingsCard
Description="{ext:Locale Name=ExternalPlayerTypeDescription}"
Header="{ext:Locale Name=ExternalPlayerType}"
Visibility="{x:Bind ViewModel.IsExternalPlayerType, Mode=OneWay}">
<ComboBox
MinWidth="120"
ItemsSource="{x:Bind ViewModel.ExternalPlayerTypeCollection, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.ExternalPlayerType, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="constants:ExternalPlayerType">
<TextBlock Text="{x:Bind Converter={StaticResource ExternalPlayerTypeConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</community:SettingsCard>
<community:SettingsCard Header="{ext:Locale Name=PreferQuality}">
<ComboBox
MinWidth="120"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Bili Copilot. All rights reserved.

using BiliCopilot.UI.Models.Constants;
using Microsoft.UI.Xaml.Data;

namespace BiliCopilot.UI.Converters;

internal sealed class ExternalPlayerTypeConverter : IValueConverter
{
/// <inheritdoc/>
public object Convert(object value, Type targetType, object parameter, string language)
{
var result = string.Empty;
if (value is ExternalPlayerType type)
{
switch (type)
{
case ExternalPlayerType.Mpv:
result = "MPV";
break;
case ExternalPlayerType.MpvNet:
result = "MPV.NET";
break;
default:
break;
}
}

return result;
}

/// <inheritdoc/>
public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException();
}
3 changes: 3 additions & 0 deletions src/Desktop/BiliCopilot.UI/Converters/PlayerTypeConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ public object Convert(object value, Type targetType, object parameter, string la
case PlayerType.Native:
result = ResourceToolkit.GetLocalizedString(StringNames.Native);
break;
case PlayerType.External:
result = ResourceToolkit.GetLocalizedString(StringNames.ExternalPlayer);
break;
default:
result = "MPV";
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ internal sealed class PlayerTemplateSelector : DataTemplateSelector

public DataTemplate NativeTemplate { get; set; }

public DataTemplate ExternalTemplate { get; set; }

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item is MpvPlayerViewModel)
Expand All @@ -20,6 +22,10 @@ protected override DataTemplate SelectTemplateCore(object item, DependencyObject
{
return NativeTemplate;
}
else if (item is ExternalPlayerViewModel)
{
return ExternalTemplate;
}

return default;
}
Expand Down
Loading

0 comments on commit bf3db18

Please sign in to comment.