f637c18e22
- Closed captions fixes - Merged to YoutubeExplode instead of MyToolkit for video sources - Video playback fixes - Internal links support - Subscription button fixed - Comments threads fixes and improvements (highlighting author's and user's names) - General bug fixes
864 lines
33 KiB
C#
864 lines
33 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Timers;
|
|
using Windows.Foundation;
|
|
using Windows.Storage;
|
|
using Windows.UI.Core;
|
|
using Windows.UI.Xaml;
|
|
using Windows.UI.Xaml.Controls;
|
|
using Windows.UI.Xaml.Controls.Primitives;
|
|
using Windows.UI.Xaml.Input;
|
|
using Windows.UI.Xaml.Media;
|
|
using Google.Apis.YouTube.v3.Data;
|
|
using Windows.UI.Xaml.Media.Imaging;
|
|
using System.Diagnostics;
|
|
using Windows.Media;
|
|
using Windows.Storage.Streams;
|
|
using Windows.UI.ViewManagement;
|
|
using System.Xml;
|
|
using Windows.ApplicationModel.Core;
|
|
using Windows.UI;
|
|
using Windows.Media.Casting;
|
|
using YoutubeExplode.Models.MediaStreams;
|
|
using YoutubeExplode;
|
|
using YoutubeExplode.Models.ClosedCaptions;
|
|
using System.Globalization;
|
|
using FoxTube.Controls;
|
|
using Windows.System;
|
|
|
|
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
|
|
|
namespace FoxTube
|
|
{
|
|
public sealed partial class VideoPlayer : UserControl
|
|
{
|
|
public string videoId;
|
|
|
|
private bool miniview = false;
|
|
public bool MiniView
|
|
{
|
|
get { return miniview; }
|
|
set
|
|
{
|
|
miniview = value;
|
|
if (value)
|
|
captions.Hide();
|
|
else
|
|
captions.Show();
|
|
}
|
|
}
|
|
private bool fullScreen = false;
|
|
public bool pointerCaptured = false;
|
|
|
|
public event ObjectEventHandler SetFullSize;
|
|
public event ObjectEventHandler NextClicked;
|
|
|
|
bool isMuxed = false;
|
|
bool audioReady = false;
|
|
bool videoReady = false;
|
|
|
|
CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor;
|
|
Point cursorPositionBackup;
|
|
|
|
public TimeSpan elapsed;
|
|
TimeSpan remaining;
|
|
TimeSpan total;
|
|
|
|
Video item;
|
|
string avatar;
|
|
double timecodeBackup = 0;
|
|
bool needUpdateTimecode = false;
|
|
|
|
SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView();
|
|
LiveCaptions captions;
|
|
|
|
IReadOnlyList<ClosedCaptionTrackInfo> ccInfo;
|
|
MediaStreamInfoSet streamInfo;
|
|
|
|
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
|
Timer t = new Timer()
|
|
{
|
|
Interval = 5000,
|
|
Enabled = false
|
|
};
|
|
Timer seekTimer = new Timer()
|
|
{
|
|
Interval = 1000,
|
|
Enabled = true
|
|
};
|
|
|
|
public VideoPlayer()
|
|
{
|
|
this.InitializeComponent();
|
|
Visibility = Visibility.Collapsed;
|
|
if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
|
|
miniViewBtn.Visibility = Visibility.Collapsed;
|
|
|
|
captions = grid.Children[2] as LiveCaptions;
|
|
|
|
volume.Value = Convert.ToDouble(settings.Values["volume"]);
|
|
videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"];
|
|
|
|
videoSource.MediaEnded += (s, arg) =>
|
|
{
|
|
seek.Value = seek.Maximum;
|
|
seekIndicator.Value = seekIndicator.Maximum;
|
|
seekTimer.Stop();
|
|
};
|
|
audioSource.CurrentStateChanged += AudioSource_CurrentStateChanged;
|
|
t.Elapsed += T_Elapsed;
|
|
seekTimer.Elapsed += SeekTimer_Elapsed;
|
|
}
|
|
|
|
public async void Initialize(Video meta, string channelAvatar)
|
|
{
|
|
item = meta;
|
|
avatar = channelAvatar;
|
|
videoId = item.Id;
|
|
|
|
#region Retrieving info for CC and Media streams
|
|
//Loading streams
|
|
streamInfo = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
|
|
streamInfo.Audio.ToList().ForEach(x => Debug.WriteLine($"{x.AudioEncoding} {x.Bitrate}"));
|
|
|
|
List<VideoQuality> q = streamInfo.GetAllVideoQualities().ToList();
|
|
q.Sort();
|
|
q.Reverse();
|
|
foreach (VideoQuality i in q)
|
|
quality.Items.Add(new ComboBoxItem() { Content = i.GetVideoQualityLabel() });
|
|
|
|
string s;
|
|
if ((string)settings.Values["quality"] == "remember")
|
|
s = (string)settings.Values["rememberedQuality"];
|
|
else
|
|
s = (string)settings.Values["quality"];
|
|
|
|
if (quality.Items.ToList().Find(x => (x as ComboBoxItem).Content as string == s) != null)
|
|
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Content as string == s);
|
|
else
|
|
quality.SelectedItem = quality.Items.First();
|
|
|
|
//Loading captions
|
|
ccInfo = await new YoutubeClient().GetVideoClosedCaptionTrackInfosAsync(item.Id);
|
|
foreach (ClosedCaptionTrackInfo cc in ccInfo)
|
|
{
|
|
subsLang.Items.Add(new ComboBoxItem()
|
|
{
|
|
Content = string.Format("{0}{1}", CultureInfo.GetCultureInfo(cc.Language.Code).DisplayName, cc.IsAutoGenerated ? " (Auto-generated)" : ""),
|
|
Tag = cc
|
|
});
|
|
}
|
|
if(ccInfo.Count > 0)
|
|
subsLang.SelectedIndex = 0;
|
|
else
|
|
captionsBtn.Visibility = Visibility.Collapsed;
|
|
#endregion
|
|
|
|
if (item.ContentDetails.ContentRating != null)
|
|
{
|
|
if(SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
|
|
{
|
|
Visibility = Visibility.Visible;
|
|
proceedMature.Visibility = Visibility.Visible;
|
|
matureBlock.Visibility = Visibility.Visible;
|
|
return;
|
|
}
|
|
else if(!SecretsVault.IsAuthorized)
|
|
{
|
|
Visibility = Visibility.Visible;
|
|
signReq.Visibility = Visibility.Visible;
|
|
matureBlock.Visibility = Visibility.Visible;
|
|
return;
|
|
}
|
|
}
|
|
|
|
try { videoSource.PosterSource = new BitmapImage(new Uri(item.Snippet.Thumbnails.Maxres.Url)); }
|
|
catch { }
|
|
title.Text = item.Snippet.Title;
|
|
channelName.Text = item.Snippet.ChannelTitle;
|
|
|
|
quality_SelectionChanged(this, null);
|
|
|
|
total = XmlConvert.ToTimeSpan(item.ContentDetails.Duration);
|
|
seek.Maximum = total.TotalSeconds;
|
|
seekIndicator.Maximum = total.TotalSeconds;
|
|
|
|
elapsed = TimeSpan.FromSeconds(seek.Value);
|
|
remaining = total.Subtract(elapsed);
|
|
|
|
elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed.Hours}:00:" : "" + $"{elapsed:mm\\:ss}";
|
|
remainingTime.Text = remaining.Hours > 0 ? $"{remaining.Hours}:00:" : "" + $"{remaining:mm\\:ss}";
|
|
|
|
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;
|
|
systemControls.IsEnabled = true;
|
|
|
|
t.Start();
|
|
|
|
Visibility = Visibility.Visible;
|
|
}
|
|
|
|
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
|
{
|
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
|
{
|
|
switch (args.Button)
|
|
{
|
|
case SystemMediaTransportControlsButton.Pause:
|
|
videoSource.Pause();
|
|
break;
|
|
|
|
case SystemMediaTransportControlsButton.Play:
|
|
videoSource.Play();
|
|
break;
|
|
|
|
case SystemMediaTransportControlsButton.Next:
|
|
NextClicked.Invoke(this, null);
|
|
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)
|
|
{
|
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Elapsed);
|
|
}
|
|
|
|
void SeekElapsed()
|
|
{
|
|
seek.Value = videoSource.Position.TotalSeconds;
|
|
seekIndicator.Value = seek.Value;
|
|
/*if (Math.Round(videoSource.Position.TotalSeconds, 1) != Math.Round(audioSource.Position.TotalSeconds, 1))
|
|
{
|
|
Debug.WriteLine($"Correcting tracks synchronization (Video track position: {videoSource.Position}; Audio track position: {audioSource.Position})");
|
|
audioSource.Position = videoSource.Position;
|
|
}*/
|
|
}
|
|
|
|
void Elapsed()
|
|
{
|
|
controls.Visibility = Visibility.Collapsed;
|
|
if (!MiniView)
|
|
touchCentral.Visibility = Visibility.Collapsed;
|
|
if (pointerCaptured)
|
|
{
|
|
cursorPositionBackup = Window.Current.CoreWindow.PointerPosition;
|
|
Window.Current.CoreWindow.PointerCursor = null;
|
|
}
|
|
seekIndicator.Visibility = Visibility.Collapsed;
|
|
t.Stop();
|
|
}
|
|
|
|
public void UpdateSize()
|
|
{
|
|
if(MiniView)
|
|
{
|
|
Height = Window.Current.Bounds.Height;
|
|
Debug.WriteLine("Video player aspect ratio has been corrected.");
|
|
}
|
|
}
|
|
|
|
private void volume_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
|
{
|
|
double v = volume.Value;
|
|
if (v == 0)
|
|
muteBtn.Content = openVolume.Content = "\xE74F";
|
|
else if (v <= 25 && v > 0)
|
|
muteBtn.Content = openVolume.Content = "\xE992";
|
|
else if (v <= 50 && v > 25)
|
|
muteBtn.Content = openVolume.Content = "\xE993";
|
|
else if (v <= 75 && v > 50)
|
|
muteBtn.Content = openVolume.Content = "\xE994";
|
|
else if (v > 75)
|
|
muteBtn.Content = openVolume.Content = "\xE995";
|
|
|
|
settings.Values["volume"] = volume.Value;
|
|
|
|
audioSource.Volume = videoSource.Volume = volume.Value * 0.01;
|
|
}
|
|
|
|
private void muteBtn_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if(volume.Value != 0)
|
|
{
|
|
double v = (double)settings.Values["volume"];
|
|
volume.Value = 0;
|
|
settings.Values["volume"] = v;
|
|
}
|
|
else volume.Value = (double)settings.Values["volume"];
|
|
}
|
|
|
|
private void UserControl_Tapped(object sender, TappedRoutedEventArgs e)
|
|
{
|
|
if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch)
|
|
{
|
|
touchCentral.Visibility = Visibility.Visible;
|
|
if (t.Enabled)
|
|
Elapsed();
|
|
else
|
|
ShowControls();
|
|
}
|
|
}
|
|
|
|
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
if (cursorPositionBackup == null)
|
|
cursorPositionBackup = Window.Current.CoreWindow.PointerPosition;
|
|
else if (cursorPositionBackup == Window.Current.CoreWindow.PointerPosition)
|
|
return;
|
|
ShowControls();
|
|
}
|
|
|
|
void ShowControls()
|
|
{
|
|
controls.Visibility = Visibility.Visible;
|
|
if (MiniView)
|
|
seekIndicator.Visibility = Visibility.Visible;
|
|
if (pointerCaptured)
|
|
Window.Current.CoreWindow.PointerCursor = cursorBackup;
|
|
t.Stop();
|
|
t.Start();
|
|
}
|
|
|
|
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
videoSource.Pause();
|
|
audioSource.Source = null;
|
|
timecodeBackup = videoSource.Position.TotalSeconds;
|
|
|
|
audioReady = false;
|
|
videoReady = false;
|
|
|
|
settings.Values["rememberedQuality"] = (quality.SelectedItem as ComboBoxItem).Content as string;
|
|
|
|
if(streamInfo.Muxed.ToList().Find(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string) != null)
|
|
{
|
|
isMuxed = true;
|
|
videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
|
|
}
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
videoSource.Source = streamInfo.Video.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
|
|
audioSource.Source = streamInfo.Audio.First().Url.ToUri();
|
|
}
|
|
|
|
/*switch((quality.SelectedItem as ComboBoxItem).Content)
|
|
{
|
|
case "2160p":
|
|
if(streamInfo.Muxed.First(x => x.VideoQuality.))
|
|
{
|
|
isMuxed = true;
|
|
|
|
}
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality2160P).Uri;
|
|
break;
|
|
case "1080p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).Uri;
|
|
break;
|
|
case "720p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityHigh && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).Uri;
|
|
break;
|
|
case "480p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).Uri;
|
|
break;
|
|
case "360p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityMedium && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).Uri;
|
|
break;
|
|
case "240p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).Uri;
|
|
break;
|
|
case "144p":
|
|
if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).HasAudio)
|
|
isMuxed = true;
|
|
else
|
|
{
|
|
isMuxed = false;
|
|
audioSource.Source = (streamInfo.Find(x => x.AudioQuality == YouTubeQuality.QualityLow && !x.HasVideo) ??
|
|
streamInfo.Find(x => x.HasAudio && !x.HasVideo)).Uri;
|
|
}
|
|
videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).Uri;
|
|
break;
|
|
}*/
|
|
|
|
needUpdateTimecode = true;
|
|
videoSource.Play();
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
private void subsSwitch_Toggled(object sender, RoutedEventArgs e)
|
|
{
|
|
if (subsSwitch.IsOn)
|
|
subsLang.Visibility = Visibility.Visible;
|
|
else
|
|
subsLang.Visibility = Visibility.Collapsed;
|
|
|
|
LoadTrack();
|
|
}
|
|
|
|
void LoadTrack()
|
|
{
|
|
if (subsSwitch.IsOn)
|
|
{
|
|
if (ccInfo[subsLang.SelectedIndex].IsAutoGenerated)
|
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url.Replace("format=3", "format=0"), true);
|
|
else
|
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
|
|
}
|
|
else
|
|
captions.Close();
|
|
}
|
|
|
|
private void fullscreen_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
fullScreen = !fullScreen;
|
|
SetFullSize.Invoke(this, fullScreen);
|
|
Methods.MainPage.Fullscreen(fullScreen);
|
|
|
|
if(fullScreen)
|
|
{
|
|
ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
|
|
fullscreen.Content = "\xE1D8";
|
|
Height = Methods.MainPage.Height;
|
|
}
|
|
else
|
|
{
|
|
ApplicationView.GetForCurrentView().ExitFullScreenMode();
|
|
fullscreen.Content = "\xE1D9";
|
|
Height = double.NaN;
|
|
}
|
|
}
|
|
|
|
private void play_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (videoSource.CurrentState == MediaElementState.Playing)
|
|
videoSource.Pause();
|
|
else if (videoSource.CurrentState == MediaElementState.Paused)
|
|
if((audioReady && videoReady) || isMuxed)
|
|
videoSource.Play();
|
|
}
|
|
|
|
private void AudioSource_CurrentStateChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
switch (audioSource.CurrentState)
|
|
{
|
|
case MediaElementState.Buffering:
|
|
if(videoSource.CurrentState != MediaElementState.Buffering)
|
|
videoSource.Pause();
|
|
break;
|
|
|
|
case MediaElementState.Playing:
|
|
if (videoSource.CurrentState == MediaElementState.Paused)
|
|
videoSource.Play();
|
|
else if (videoSource.CurrentState == MediaElementState.Buffering)
|
|
audioSource.Pause();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void videoSource_Opened(object sender, RoutedEventArgs arg)
|
|
{
|
|
if(!isMuxed)
|
|
{
|
|
if(sender == videoSource)
|
|
{
|
|
videoReady = true;
|
|
if (audioReady && ((timecodeBackup == 0 && (bool)settings.Values["videoAutoplay"]) || timecodeBackup > 0))
|
|
play_Click(this, null);
|
|
}
|
|
else if(sender == audioSource)
|
|
{
|
|
audioReady = true;
|
|
if (videoReady && ((timecodeBackup == 0 && (bool)settings.Values["videoAutoplay"]) || timecodeBackup > 0))
|
|
play_Click(this, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
if(videoSource.CurrentState == MediaElementState.Playing && needUpdateTimecode)
|
|
{
|
|
videoSource.Position = TimeSpan.FromSeconds(timecodeBackup);
|
|
needUpdateTimecode = false;
|
|
}
|
|
|
|
switch(videoSource.CurrentState)
|
|
{
|
|
case MediaElementState.Buffering:
|
|
audioSource.Position = videoSource.Position;
|
|
audioSource.Pause();
|
|
bufferingBar.Visibility = Visibility.Visible;
|
|
|
|
seek.IsEnabled = false;
|
|
play.IsEnabled = false;
|
|
touchPlay.IsEnabled = false;
|
|
|
|
play.Content = "\xE102";
|
|
touchPlay.Content = "\xE102";
|
|
|
|
systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
|
|
break;
|
|
|
|
case MediaElementState.Paused:
|
|
if(audioSource.CurrentState != MediaElementState.Buffering)
|
|
audioSource.Pause();
|
|
bufferingBar.Visibility = Visibility.Collapsed;
|
|
|
|
seek.IsEnabled = true;
|
|
play.IsEnabled = true;
|
|
touchPlay.IsEnabled = true;
|
|
|
|
play.Content = "\xE102";
|
|
touchPlay.Content = "\xE102";
|
|
|
|
systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
|
|
break;
|
|
|
|
case MediaElementState.Playing:
|
|
audioSource.Play();
|
|
bufferingBar.Visibility = Visibility.Collapsed;
|
|
|
|
seek.IsEnabled = true;
|
|
play.IsEnabled = true;
|
|
touchPlay.IsEnabled = true;
|
|
|
|
seekTimer.Start();
|
|
|
|
play.Content = "\xE103";
|
|
touchPlay.Content = "\xE103";
|
|
|
|
systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
|
|
break;
|
|
|
|
default:
|
|
audioSource.Pause();
|
|
bufferingBar.Visibility = Visibility.Collapsed;
|
|
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private async void miniView_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
|
MiniView = !MiniView;
|
|
SetFullSize(this, MiniView);
|
|
|
|
if (MiniView)
|
|
{
|
|
if (fullScreen)
|
|
{
|
|
fullscreen.Content = "\xE740";
|
|
fullScreen = false;
|
|
}
|
|
|
|
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);
|
|
pointerCaptured = false;
|
|
|
|
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
|
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
|
|
|
CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
|
|
coreTitleBar.ExtendViewIntoTitleBar = true;
|
|
|
|
mainControls.Visibility = Visibility.Collapsed;
|
|
header.Visibility = Visibility.Collapsed;
|
|
|
|
touchCentral.Visibility = Visibility.Visible;
|
|
miniViewExit.Visibility = Visibility.Visible;
|
|
|
|
touchBack10.FontSize = touchFwd30.FontSize = 20;
|
|
touchPlay.FontSize = 50;
|
|
Methods.MainPage.Fullscreen(true);
|
|
}
|
|
else
|
|
{
|
|
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);
|
|
|
|
//Methods.MainPage.SetTitleBar();
|
|
|
|
mainControls.Visibility = Visibility.Visible;
|
|
header.Visibility = Visibility.Visible;
|
|
|
|
touchCentral.Visibility = Visibility.Collapsed;
|
|
miniViewExit.Visibility = Visibility.Collapsed;
|
|
|
|
touchBack10.FontSize = touchFwd30.FontSize = 40;
|
|
touchPlay.FontSize = 100;
|
|
Methods.MainPage.Fullscreen(false);
|
|
|
|
Height = double.NaN;
|
|
}
|
|
}
|
|
|
|
private void seek_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
|
{
|
|
elapsed = TimeSpan.FromSeconds(seek.Value);
|
|
remaining = total.Subtract(elapsed);
|
|
|
|
elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed.Hours}:00:" : "" + $"{elapsed:mm\\:ss}";
|
|
remainingTime.Text = remaining.Hours > 0 ? $"{remaining.Hours}:00:" : "" + $"{remaining:mm\\:ss}";
|
|
}
|
|
|
|
private void seek_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
videoSource.Position = elapsed;
|
|
}
|
|
|
|
private void fwd30_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if(remaining.TotalSeconds >= 30)
|
|
videoSource.Position = elapsed.Add(TimeSpan.FromSeconds(30));
|
|
}
|
|
|
|
private void back10_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (elapsed.TotalSeconds >= 10)
|
|
videoSource.Position = elapsed.Subtract(TimeSpan.FromSeconds(10));
|
|
}
|
|
|
|
private void UserControl_PointerExited(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
if (t.Enabled && e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
|
|
{
|
|
pointerCaptured = false;
|
|
Elapsed();
|
|
}
|
|
}
|
|
|
|
private void UserControl_PointerEntered(object sender, PointerRoutedEventArgs e)
|
|
{
|
|
if (e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
|
|
pointerCaptured = true;
|
|
}
|
|
|
|
private void next_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
NextClicked.Invoke(this, null);
|
|
}
|
|
|
|
private void matureDismiss_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if ((bool)matureDisable.IsChecked)
|
|
settings.Values.Add("showMature", false);
|
|
matureBlock.Visibility = Visibility.Collapsed;
|
|
Initialize(item, avatar);
|
|
}
|
|
|
|
private void signin_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
SecretsVault.Authorize();
|
|
}
|
|
|
|
public void Pause()
|
|
{
|
|
videoSource.Pause();
|
|
}
|
|
|
|
public void minimize_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if(fullScreen)
|
|
{
|
|
ApplicationView.GetForCurrentView().ExitFullScreenMode();
|
|
fullscreen.Content = "\xE740";
|
|
fullScreen = false;
|
|
Methods.MainPage.Fullscreen(false);
|
|
}
|
|
else
|
|
SetFullSize.Invoke(this, true);
|
|
|
|
Width = 432;
|
|
Height = 243;
|
|
|
|
MiniView = true;
|
|
Methods.MainPage.MinimizeVideo();
|
|
|
|
mainControls.Visibility = Visibility.Collapsed;
|
|
header.Visibility = Visibility.Collapsed;
|
|
|
|
touchCentral.Visibility = Visibility.Visible;
|
|
maximize.Visibility = Visibility.Visible;
|
|
close.Visibility = Visibility.Visible;
|
|
|
|
touchBack10.FontSize = touchFwd30.FontSize = 20;
|
|
touchPlay.FontSize = 50;
|
|
}
|
|
|
|
private void close_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
systemControls.IsEnabled = false;
|
|
pointerCaptured = false;
|
|
Elapsed();
|
|
Methods.MainPage.CloseVideo();
|
|
}
|
|
|
|
private void maximize_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
SetFullSize.Invoke(this, false);
|
|
|
|
Width = double.NaN;
|
|
Height = double.NaN;
|
|
|
|
MiniView = false;
|
|
Methods.MainPage.MaximizeVideo();
|
|
|
|
mainControls.Visibility = Visibility.Visible;
|
|
header.Visibility = Visibility.Visible;
|
|
|
|
touchCentral.Visibility = Visibility.Collapsed;
|
|
maximize.Visibility = Visibility.Collapsed;
|
|
close.Visibility = Visibility.Collapsed;
|
|
|
|
touchBack10.FontSize = touchFwd30.FontSize = 40;
|
|
touchPlay.FontSize = 100;
|
|
}
|
|
|
|
private void cast_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if(videoSource.Source != null)
|
|
{
|
|
if (videoSource.CurrentState != MediaElementState.Paused)
|
|
videoSource.Pause();
|
|
CastingDevicePicker picker = new CastingDevicePicker();
|
|
picker.Filter.SupportsVideo = true;
|
|
picker.CastingDeviceSelected += Picker_CastingDeviceSelected;
|
|
|
|
Point positinon = cast.TransformToVisual(Window.Current.Content).TransformPoint(new Point(0, 0));
|
|
|
|
picker.Show(new Rect(positinon.X, positinon.Y, cast.ActualWidth, cast.ActualHeight), Windows.UI.Popups.Placement.Below);
|
|
}
|
|
}
|
|
|
|
private async void Picker_CastingDeviceSelected(CastingDevicePicker sender, CastingDeviceSelectedEventArgs args)
|
|
{
|
|
CastingConnection connection = args.SelectedCastingDevice.CreateCastingConnection();
|
|
await connection.RequestStartCastingAsync(videoSource.GetAsCastingSource());
|
|
}
|
|
|
|
private void playPauseArea_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
|
{
|
|
if (MiniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.CompactOverlay)
|
|
miniView_Click(this, null);
|
|
else if (MiniView && ApplicationView.GetForCurrentView().ViewMode == ApplicationViewMode.Default)
|
|
maximize_Click(this, null);
|
|
else if (fullScreen)
|
|
fullscreen_Click(this, null);
|
|
else if (!MiniView && !fullScreen)
|
|
fullscreen_Click(this, null);
|
|
}
|
|
|
|
private void playPauseArea_Tapped(object sender, TappedRoutedEventArgs e)
|
|
{
|
|
if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse && !MiniView)
|
|
play_Click(this, null);
|
|
}
|
|
|
|
public void KeyUpPressed(object sender, KeyRoutedEventArgs e)
|
|
{
|
|
switch(e.Key)
|
|
{
|
|
case VirtualKey.Escape:
|
|
case VirtualKey.F11:
|
|
if (fullScreen)
|
|
fullscreen_Click(this, null);
|
|
break;
|
|
case VirtualKey.Space:
|
|
play_Click(this, null);
|
|
break;
|
|
case VirtualKey.Left:
|
|
back10_Click(this, null);
|
|
break;
|
|
case VirtualKey.Right:
|
|
fwd30_Click(this, null);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void subsLang_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
LoadTrack();
|
|
}
|
|
|
|
private void videoSource_BufferingProgressChanged(object sender, RoutedEventArgs e)
|
|
{
|
|
bufferingLevel.Value = (audioSource.Source != null && videoSource.BufferingProgress > audioSource.BufferingProgress ? audioSource.BufferingProgress : videoSource.BufferingProgress) * 100;
|
|
}
|
|
}
|
|
}
|