Archived
1
0

Video player development 1

This commit is contained in:
Michael Gordeev
2018-06-16 01:07:40 +03:00
parent 4a77a9f0d5
commit 4af35951f5
2 changed files with 214 additions and 103 deletions
+52 -46
View File
@@ -5,64 +5,58 @@
xmlns:local="using:FoxTube"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d"
d:DesignHeight="1080"
d:DesignWidth="1920"
SizeChanged="UserControl_SizeChanged"
Tapped="UserControl_Tapped"
PointerMoved="UserControl_PointerMoved">
PointerMoved="UserControl_PointerMoved"
PointerExited="UserControl_PointerExited">
<Grid Background="White">
<MediaElement CurrentStateChanged="videoSource_CurrentStateChanged" AutoPlay="False" Name="videoSource" AreTransportControlsEnabled="False" PosterSource="ms-appx:///Assets/videoThumbSample.png"/>
<TextBox Name="subtitleCapture" Visibility="Collapsed" Text="This is subtitle capture" Background="#99000000" VerticalAlignment="Bottom" HorizontalAlignment="Center" Foreground="White" FontSize="24" Padding="10" Margin="0,0,0,100"/>
<Grid Name="controls" Visibility="Visible">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
<RowDefinition Height="100"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid Grid.Row="0" Name="header">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
<AcrylicBrush TintColor="Black" TintOpacity="0.795" BackgroundSource="Backdrop" AlwaysUseFallback="False" Opacity="0.8"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE099;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Minimize"/>
<TextBlock Name="title" Grid.Column="1" Text="This is Video title" Foreground="White" VerticalAlignment="Center" TextWrapping="WrapWholeWords" FontSize="20" Margin="10,0,0,0" MaxLines="1" ToolTipService.ToolTip="Title"/>
<StackPanel Orientation="Horizontal" Grid.Column="2">
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xEC15;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Cast to device"/>
<Button Name="miniView" Click="miniView_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE2B3;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Picture-in-picture mode"/>
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal">
<Button Visibility="Collapsed" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE099;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Minimize"/>
<TextBlock Name="title" Text="This is Video title" Foreground="White" VerticalAlignment="Center" TextWrapping="WrapWholeWords" FontSize="20" Margin="10,0,0,0" MaxLines="1" ToolTipService.ToolTip="Title"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Visibility="Collapsed" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xEC15;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Cast to device"/>
<Button Name="miniView" Click="miniView_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE2B3;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Compact view mode"/>
</StackPanel>
</Grid>
<Grid Grid.Row="2">
<StackPanel Name="touchCentral" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed">
<Button VerticalAlignment="Center" Content="&#xED3C;" FontFamily="Segoe MDL2 Assets" Background="Transparent" FontSize="20" Foreground="WhiteSmoke" Name="touchBack10" Click="back10_Click"/>
<Button VerticalAlignment="Center" Content="&#xE102;" FontFamily="Segoe MDL2 Assets" Background="Transparent" FontSize="50" Foreground="WhiteSmoke" Name="touchPlay" Click="play_Click"/>
<Button VerticalAlignment="Center" Content="&#xED3D;" FontFamily="Segoe MDL2 Assets" Background="Transparent" FontSize="20" Foreground="WhiteSmoke" Name="touchFwd30" Click="fwd30_Click"/>
</StackPanel>
<Button Name="skipAd" Visibility="Collapsed" Grid.Row="1" HorizontalAlignment="Right" Foreground="White" VerticalAlignment="Bottom" Padding="10" BorderBrush="Black" BorderThickness="2" Background="#7E000000">
<StackPanel Orientation="Horizontal">
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="30" Margin="0,0,10,0" Text="&#xE101;" VerticalAlignment="Center"/>
<TextBlock Text="Skip ad" FontSize="30" TextWrapping="WrapWholeWords" MaxWidth="250"/>
</StackPanel>
</Button>
<Grid Grid.Row="2" Name="mainControls">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Transparent"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
<AcrylicBrush TintColor="Black" TintOpacity="0.795" BackgroundSource="Backdrop" AlwaysUseFallback="False" Opacity="0.8"/>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ProgressBar Name="bufferingBar" VerticalAlignment="Bottom" IsIndeterminate="True" Visibility="Collapsed"/>
<Grid Grid.Row="1">
<ProgressBar Name="bufferingBar" VerticalAlignment="Top" Margin="0,-4,0,0" IsIndeterminate="True" Visibility="Visible"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="252"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<Button Click="play_Click" Name="play" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE768;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Play"/>
@@ -76,16 +70,28 @@
</StackPanel>
</Popup>
<TextBlock Name="elapsedTime" Foreground="White" Text="18:28" VerticalAlignment="Bottom" Grid.Column="1" HorizontalAlignment="Left" Margin="10,0,10,0" ToolTipService.ToolTip="Time elapsed"/>
<TextBlock Name="remainingTime" Foreground="White" Text="18:28" VerticalAlignment="Bottom" Grid.Column="1" HorizontalAlignment="Right" Margin="10,0,10,0" ToolTipService.ToolTip="Time remaining"/>
<Slider Name="seek" Grid.Column="1" VerticalAlignment="Top" Margin="10,0,10,0" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False"/>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Name="goLive" Visibility="Collapsed" Foreground="White" Background="Transparent">
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="Red" FontSize="30" VerticalAlignment="Center" FontFamily="Segoe MDL2 Assets" Text="&#xE1F5;"/>
<TextBlock Text="LIVE" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<TextBlock Grid.Column="1" Name="elapsedTime" Foreground="White" Text="18:28" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10,0,10,0" ToolTipService.ToolTip="Time elapsed"/>
<TextBlock Grid.Column="1" Name="remainingTime" Foreground="White" Text="18:28" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,0" ToolTipService.ToolTip="Time remaining"/>
<Slider Grid.Column="1" PointerCaptureLost="seek_PointerCaptureLost" ValueChanged="seek_ValueChanged" Name="seek" VerticalAlignment="Top" ToolTipService.ToolTip="Seek" IsThumbToolTipEnabled="False" HorizontalAlignment="Stretch"/>
</Grid>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button Name="back10" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xED3C;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Skip back for 10 seconds"/>
<Button Name="fwd30" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xED3D;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Skip forward for 30 seconds"/>
<Button Click="back10_Click" Name="back10" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xED3C;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Skip back for 10 seconds"/>
<Button Click="fwd30_Click" Name="fwd30" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xED3D;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Skip forward for 30 seconds"/>
<Line Stroke="White" StrokeThickness="2" Y1="5" Y2="45"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE190;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Subtitles" Name="openSubs" Click="openSubs_Click"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality" Name="openSets" Click="openSets_Click"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE740;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Full screen" Name="fullscreen" Click="fullscreen_Click"/>
+162 -57
View File
@@ -26,6 +26,7 @@ using System.Diagnostics;
using Windows.Media;
using Windows.Storage.Streams;
using Windows.UI.ViewManagement;
using System.Xml;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
@@ -38,7 +39,23 @@ namespace FoxTube
private bool miniViewed = false;
private bool fullScreen = false;
YouTubeQuality videoQuality;
TimeSpan elapsed;
TimeSpan remaining;
TimeSpan total;
SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView();
YouTubeQuality[] qualities = new YouTubeQuality[8]
{
YouTubeQuality.QualityHigh,
YouTubeQuality.Quality2160P,
YouTubeQuality.Quality1080P,
YouTubeQuality.Quality270P,
YouTubeQuality.Quality480P,
YouTubeQuality.Quality360P,
YouTubeQuality.Quality240P,
YouTubeQuality.Quality144P,
};
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
Timer t = new Timer()
@@ -46,6 +63,7 @@ namespace FoxTube
Interval = 5000,
Enabled = true
};
Timer seekTimer = new Timer() { Interval = 1000 };
public VideoPlayer(string id, string channelAvatar)
{
@@ -58,10 +76,9 @@ namespace FoxTube
if ((bool)settings.Values["moblieWarning"] && (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable))
meteredNotification.Visibility = Visibility.Visible;
quality.SelectedIndex = (int)settings.Values["quality"] +
(int)settings.Values["quality"] > 0? 1 : 0;
t.Elapsed += T_Elapsed;
seekTimer.Elapsed += SeekTimer_Elapsed;
CheckQualityAvailability(id);
Initialize(id, channelAvatar);
}
@@ -78,19 +95,78 @@ namespace FoxTube
videoSource.PosterSource = new BitmapImage(new Uri(item.Snippet.Thumbnails.Maxres.Url));
title.Text = item.Snippet.Title;
YouTubeUri url = await YouTube.GetVideoUriAsync(item.Id, videoQuality);
videoSource.Source = url.Uri;
YouTubeUri uri = await YouTube.GetVideoUriAsync(id, qualities[quality.SelectedIndex]);
videoSource.Source = uri.Uri;
SystemMediaTransportControls controls = SystemMediaTransportControls.GetForCurrentView();
controls.IsNextEnabled = true;
controls.IsPauseEnabled = true;
controls.IsPlayEnabled = true;
total = XmlConvert.ToTimeSpan(item.ContentDetails.Duration);
seek.Maximum = total.TotalSeconds;
controls.DisplayUpdater.Type = MediaPlaybackType.Video;
controls.DisplayUpdater.VideoProperties.Title = item.Snippet.Title;
controls.DisplayUpdater.VideoProperties.Subtitle = item.Snippet.ChannelTitle;
controls.DisplayUpdater.Thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri(channelAvatar));
controls.DisplayUpdater.Update();
elapsed = TimeSpan.FromSeconds(seek.Value);
remaining = total.Subtract(elapsed);
elapsedTime.Text = string.Format("{0}{1:00}:{2:00}", elapsed.Hours == 0 ? "" : elapsed.Hours + ":", elapsed.Minutes, elapsed.Seconds);
remainingTime.Text = string.Format("{0}{1:00}:{2:00}", remaining.Hours == 0 ? "" : remaining.Hours + ":", remaining.Minutes, remaining.Seconds);
systemControls.IsNextEnabled = true;
systemControls.IsPauseEnabled = true;
systemControls.IsPlayEnabled = true;
systemControls.DisplayUpdater.Type = MediaPlaybackType.Video;
systemControls.DisplayUpdater.VideoProperties.Title = item.Snippet.Title;
systemControls.DisplayUpdater.VideoProperties.Subtitle = item.Snippet.ChannelTitle;
systemControls.DisplayUpdater.Thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri(channelAvatar));
systemControls.DisplayUpdater.Update();
systemControls.ButtonPressed += SystemControls_Engaged;
}
void CheckQualityAvailability(string id)
{
for (int i = 0; i < 8; i++)
{
try
{
YouTube.GetVideoUriAsync(id, qualities[i]);
}
catch
{
(quality.Items[i] as ComboBoxItem).Visibility = Visibility.Collapsed;
}
}
int k = (int)settings.Values["quality"] +
(int)settings.Values["quality"] > 0 ? 1 : 0;
if ((quality.Items[k] as ComboBoxItem).Visibility == Visibility.Collapsed)
for (int i = 0; i < 8; i++)
{
if ((quality.Items[i] as ComboBoxItem).Visibility == Visibility.Visible)
{
quality.SelectedIndex = i;
break;
}
}
else quality.SelectedIndex = k;
}
private void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Pause:
videoSource.Pause();
break;
case SystemMediaTransportControlsButton.Play:
videoSource.Play();
break;
case SystemMediaTransportControlsButton.Next:
break;
}
}
private async void SeekTimer_Elapsed(object sender, ElapsedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, SeekElapsed);
}
private async void T_Elapsed(object sender, ElapsedEventArgs e)
@@ -98,6 +174,11 @@ namespace FoxTube
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Elapsed);
}
void SeekElapsed()
{
seek.Value = videoSource.Position.TotalSeconds;
}
async void Elapsed()
{
if(!volumePane.IsOpen && !qualityPane.IsOpen)
@@ -106,6 +187,8 @@ namespace FoxTube
volumePane.IsOpen = false;
qualityPane.IsOpen = false;
controls.Visibility = Visibility.Collapsed;
/*if(!miniViewed)
touchCentral.Visibility = Visibility.Collapsed;*/
t.Stop();
}
}
@@ -163,10 +246,15 @@ namespace FoxTube
private void UserControl_Tapped(object sender, TappedRoutedEventArgs e)
{
if (t.Enabled)
Elapsed();
else
ShowControls();
if (e.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse)
{
touchCentral.Visibility = Visibility.Visible;
if (t.Enabled)
Elapsed();
else
ShowControls();
}
//else play_Click(this, null);
}
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
@@ -187,48 +275,12 @@ namespace FoxTube
private async void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("Selected index: " + quality.SelectedIndex);
switch(quality.SelectedIndex)
{
case 0:
videoQuality = YouTubeQuality.QualityHigh;
break;
case 1:
videoQuality = YouTubeQuality.Quality2160P;
break;
case 2:
videoQuality = YouTubeQuality.Quality1080P;
break;
case 3:
videoQuality = YouTubeQuality.Quality270P;
break;
case 4:
videoQuality = YouTubeQuality.Quality480P;
break;
case 5:
videoQuality = YouTubeQuality.Quality360P;
break;
case 6:
videoQuality = YouTubeQuality.Quality240P;
break;
case 7:
videoQuality = YouTubeQuality.Quality144P;
break;
}
if(videoId != null)
{
videoSource.Pause();
TimeSpan timecode = videoSource.Position;
YouTubeUri url = await YouTube.GetVideoUriAsync(videoId, videoQuality);
YouTubeUri url = await YouTube.GetVideoUriAsync(videoId, qualities[quality.SelectedIndex]);
videoSource.Source = url.Uri;
videoSource.Position = timecode;
@@ -252,6 +304,10 @@ namespace FoxTube
fullScreen = false;
}
else fullScreen = ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
if ((string)fullscreen.Content == "")
fullscreen.Content = "";
else fullscreen.Content = "";
}
private void play_Click(object sender, RoutedEventArgs e)
@@ -270,20 +326,26 @@ namespace FoxTube
bufferingBar.Visibility = Visibility.Visible;
seek.IsEnabled = false;
play.IsEnabled = false;
seekTimer.Stop();
break;
case MediaElementState.Paused:
bufferingBar.Visibility = Visibility.Collapsed;
play.Content = "";
touchPlay.Content = "";
seekTimer.Stop();
break;
case MediaElementState.Playing:
bufferingBar.Visibility = Visibility.Collapsed;
play.Content = "";
touchPlay.Content = "";
seekTimer.Start();
break;
default:
bufferingBar.Visibility = Visibility.Collapsed;
seekTimer.Stop();
break;
}
}
@@ -299,11 +361,54 @@ namespace FoxTube
{
ApplicationView.GetForCurrentView().ExitFullScreenMode();
fullScreen = false;
fullscreen.Content = "";
}
if (!miniViewed)
{
miniViewed = await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);
else miniViewed = await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);
mainControls.Visibility = Visibility.Collapsed;
touchCentral.Visibility = Visibility.Visible;
title.Visibility = Visibility.Collapsed;
}
else
{
miniViewed = !await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);
mainControls.Visibility = Visibility.Visible;
touchCentral.Visibility = Visibility.Collapsed;
title.Visibility = Visibility.Visible;
}
}
private void seek_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
elapsed = TimeSpan.FromSeconds(seek.Value);
remaining = total.Subtract(elapsed);
elapsedTime.Text = string.Format("{0}{1:00}:{2:00}", elapsed.Hours == 0 ? "" : elapsed.Hours + ":", elapsed.Minutes, elapsed.Seconds);
remainingTime.Text = string.Format("{0}{1:00}:{2:00}", remaining.Hours == 0 ? "" : remaining.Hours + ":", remaining.Minutes, remaining.Seconds);
}
private void seek_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
videoSource.Position = elapsed;
}
private void fwd30_Click(object sender, RoutedEventArgs e)
{
videoSource.Position = elapsed.Add(TimeSpan.FromSeconds(30));
}
private void back10_Click(object sender, RoutedEventArgs e)
{
videoSource.Position = elapsed.Subtract(TimeSpan.FromSeconds(10));
}
private void UserControl_PointerExited(object sender, PointerRoutedEventArgs e)
{
if (t.Enabled)
Elapsed();
}
}
}