From ead4f76dedbf75646d28777ff93e4e0c70416a69 Mon Sep 17 00:00:00 2001 From: Michael Gordeev Date: Sun, 30 Dec 2018 23:58:16 +0300 Subject: [PATCH] Seek slider fixes Related Work Items: #235, #237 --- FoxTube/Classes/SettingsStorage.cs | 2 +- FoxTube/Controls/VideoPlayer.xaml.cs | 261 +++++++++------------------ FoxTube/FoxTube.csproj | 11 +- 3 files changed, 93 insertions(+), 181 deletions(-) diff --git a/FoxTube/Classes/SettingsStorage.cs b/FoxTube/Classes/SettingsStorage.cs index c8ed1f9..675b03f 100644 --- a/FoxTube/Classes/SettingsStorage.cs +++ b/FoxTube/Classes/SettingsStorage.cs @@ -191,7 +191,7 @@ namespace FoxTube catch (ArgumentNullException) { } } - public static async void SaveData() + public static void SaveData() { storage.Values["settings"] = JsonConvert.SerializeObject(settings); ExportSettings(); diff --git a/FoxTube/Controls/VideoPlayer.xaml.cs b/FoxTube/Controls/VideoPlayer.xaml.cs index 8cb43cc..8f1194e 100644 --- a/FoxTube/Controls/VideoPlayer.xaml.cs +++ b/FoxTube/Controls/VideoPlayer.xaml.cs @@ -25,6 +25,11 @@ using YoutubeExplode.Models.ClosedCaptions; using System.Globalization; using FoxTube.Controls; using Windows.System; +using Windows.Media.Core; +using Windows.Media.MediaProperties; +using Windows.Storage; +using Windows.Storage.FileProperties; +using Windows.Media.Editing; namespace FoxTube { @@ -55,10 +60,6 @@ namespace FoxTube public event ObjectEventHandler NextClicked; public Button Next => next; - bool isMuxed = false; - bool audioReady = false; - bool videoReady = false; - CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor; Point cursorPositionBackup; @@ -91,14 +92,14 @@ namespace FoxTube { Interval = TimeSpan.FromSeconds(1) }; - DispatcherTimer ctrlsFadeTimer; + DispatcherTimer ctrlsFadeTimer = null; public VideoPlayer() { InitializeComponent(); } - public async void Initialize(Video meta, string channelAvatar) + public void Initialize(Video meta, string channelAvatar) { try { @@ -138,46 +139,6 @@ namespace FoxTube else LoadUpcoming(); - #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 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().Exists(x => (x as ComboBoxItem).Content as string == s)) - 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 - - quality_SelectionChanged(this, null); - Visibility = Visibility.Visible; } catch (Exception e) @@ -221,6 +182,7 @@ namespace FoxTube title.Text = item.Snippet.Title; channelName.Text = item.Snippet.ChannelTitle; + ctrlsFadeTimer = new DispatcherTimer(); ctrlsFadeTimer.Interval = TimeSpan.FromSeconds(5); ctrlsFadeTimer.Tick += Elapsed; } @@ -263,11 +225,12 @@ namespace FoxTube //TODO: Set up a stream } - public void LoadVideo() + public async void LoadVideo() { InitializeContols(); captions = grid.Children[2] as LiveCaptions; timer.Tick += UpdateSeek; + timer.Start(); total = XmlConvert.ToTimeSpan(item.ContentDetails.Duration); seek.Maximum = total.TotalSeconds; @@ -276,8 +239,40 @@ namespace FoxTube 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}"; + elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed:hh\\:mm\\:ss}" : $"{elapsed:mm\\:ss}"; + remainingTime.Text = remaining.Hours > 0 ? $"{remaining:hh\\:mm\\:ss}" : $"{remaining:mm\\:ss}"; + + #region Retrieving info for CC and Media streams + //Loading streams + streamInfo = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId); + + List q = streamInfo.GetAllVideoQualities().ToList(); + q.Sort(); + q.Reverse(); + foreach (VideoQuality i in q) + quality.Items.Add(new ComboBoxItem() { Content = i.GetVideoQualityLabel() }); + + string s = SettingsStorage.VideoQuality == "remember" ? SettingsStorage.RememberedQuality : SettingsStorage.VideoQuality; + + quality.SelectedItem = quality.Items.ToList().Exists(x => (x as ComboBoxItem).Content as string == s) ? quality.Items.Find(x => (x as ComboBoxItem).Content as string == s) : quality.Items.First(); + + //Loading captions + ccInfo = await new YoutubeClient().GetVideoClosedCaptionTrackInfosAsync(videoId); + 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 + + //quality_SelectionChanged(this, null); } public void UpdateCountdown(object sender, object e) @@ -333,7 +328,7 @@ namespace FoxTube if (pointerCaptured) Window.Current.CoreWindow.PointerCursor = null; seekIndicator.Visibility = Visibility.Collapsed; - ctrlsFadeTimer.Stop(); + ctrlsFadeTimer?.Stop(); } public void UpdateSize() @@ -374,7 +369,7 @@ namespace FoxTube private void UserControl_Tapped(object sender, TappedRoutedEventArgs e) { - if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch) + if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch && ctrlsFadeTimer != null) { touchCentral.Visibility = Visibility.Visible; if (ctrlsFadeTimer.IsEnabled) @@ -386,6 +381,9 @@ namespace FoxTube private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e) { + if (ctrlsFadeTimer == null) + return; + if (cursorPositionBackup == null) cursorPositionBackup = Window.Current.CoreWindow.PointerPosition; else if (cursorPositionBackup == Window.Current.CoreWindow.PointerPosition) @@ -410,135 +408,48 @@ namespace FoxTube void ShowControls() { + if (ctrlsFadeTimer == null) + return; + controls.Visibility = Visibility.Visible; if (MiniView) seekIndicator.Visibility = Visibility.Visible; Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0); - ctrlsFadeTimer.Stop(); - ctrlsFadeTimer.Start(); + ctrlsFadeTimer?.Stop(); + ctrlsFadeTimer?.Start(); } - private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e) + private async void quality_SelectionChanged(object sender, SelectionChangedEventArgs e) { - try + //try { + SettingsStorage.RememberedQuality = ((ComboBoxItem)quality.SelectedItem).Content.ToString(); + 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().Exists(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string)) - { - isMuxed = true; - videoSource.Source = streamInfo.Muxed.First(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri(); - } + if(streamInfo.Muxed.ToList().Exists(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content.ToString())) + videoSource.Source = streamInfo.Muxed.Find(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(); + VideoStreamInfo videoInfo = streamInfo.Video.Find(i => i.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content.ToString()); + AudioStreamInfo audioInfo = streamInfo.Audio.First(); + + MediaComposition muxedStream = new MediaComposition(); + + BackgroundAudioTrack audioTrack = await BackgroundAudioTrack.CreateFromFileAsync(await StorageFile.GetFileFromPathAsync(audioInfo.Url)); + MediaClip videoTrack = await MediaClip.CreateFromFileAsync(await StorageFile.GetFileFromApplicationUriAsync(videoInfo.Url.ToUri())); + + muxedStream.BackgroundAudioTracks.Add(audioTrack); + muxedStream.Clips.Add(videoTrack); + + videoSource.SetMediaStreamSource(muxedStream.GenerateMediaStreamSource()); } - /*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 + //catch { } @@ -564,7 +475,7 @@ namespace FoxTube captions.Initialize(ccInfo[subsLang.SelectedIndex].Url); } else - captions.Close(); + captions?.Close(); } private void fullscreen_Click(object sender, RoutedEventArgs e) @@ -592,8 +503,7 @@ namespace FoxTube if (videoSource.CurrentState == MediaElementState.Playing) videoSource.Pause(); else if (videoSource.CurrentState == MediaElementState.Paused) - if((audioReady && videoReady) || isMuxed) - videoSource.Play(); + videoSource.Play(); } private void videoSource_Opened(object sender, RoutedEventArgs arg) @@ -613,8 +523,6 @@ namespace FoxTube switch(videoSource.CurrentState) { case MediaElementState.Buffering: - audioSource.Position = videoSource.Position; - audioSource.Pause(); bufferingBar.Visibility = Visibility.Visible; seek.IsEnabled = false; @@ -628,8 +536,6 @@ namespace FoxTube break; case MediaElementState.Paused: - if(audioSource.CurrentState != MediaElementState.Buffering) - audioSource.Pause(); bufferingBar.Visibility = Visibility.Collapsed; seek.IsEnabled = true; @@ -643,7 +549,6 @@ namespace FoxTube break; case MediaElementState.Playing: - audioSource.Play(); bufferingBar.Visibility = Visibility.Collapsed; seek.IsEnabled = true; @@ -659,7 +564,6 @@ namespace FoxTube break; default: - audioSource.Pause(); bufferingBar.Visibility = Visibility.Collapsed; systemControls.PlaybackStatus = MediaPlaybackStatus.Closed; break; @@ -723,8 +627,8 @@ namespace FoxTube 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}"; + elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed:hh\\:mm\\:ss}" : $"{elapsed:mm\\:ss}"; + remainingTime.Text = remaining.Hours > 0 ? $"{remaining:hh\\:mm\\:ss}" : $"{remaining:mm\\:ss}"; } private void seek_PointerCaptureLost(object sender, PointerRoutedEventArgs e) @@ -752,9 +656,10 @@ namespace FoxTube private void matureDismiss_Click(object sender, RoutedEventArgs e) { if ((bool)matureDisable.IsChecked) - settings.Values.Add("showMature", false); - matureBlock.Visibility = Visibility.Collapsed; - Initialize(item, avatar); + SettingsStorage.Mature = MatureState.Allowed; + else + SettingsStorage.Mature = MatureState.AllowedOnce; + Methods.MainPage.GoToVideo(videoId, Methods.MainPage.GetPlaylist()); } private void signin_Click(object sender, RoutedEventArgs e) @@ -800,7 +705,7 @@ namespace FoxTube { systemControls.IsEnabled = false; pointerCaptured = false; - Elapsed(); + Elapsed(this, null); Methods.MainPage.CloseVideo(); } @@ -893,7 +798,7 @@ namespace FoxTube private void videoSource_BufferingProgressChanged(object sender, RoutedEventArgs e) { - bufferingLevel.Value = (audioSource.Source != null && videoSource.BufferingProgress > audioSource.BufferingProgress ? audioSource.BufferingProgress : videoSource.BufferingProgress) * 100; + bufferingLevel.Value = videoSource.BufferingProgress * 100; } private void GotoLive_Click(object sender, RoutedEventArgs e) diff --git a/FoxTube/FoxTube.csproj b/FoxTube/FoxTube.csproj index 771f8d3..f20fbe7 100644 --- a/FoxTube/FoxTube.csproj +++ b/FoxTube/FoxTube.csproj @@ -115,6 +115,9 @@ ChannelCard.xaml + + Chat.xaml + CommentCard.xaml @@ -284,6 +287,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -403,7 +410,7 @@ 6.1.9 - 4.0.0 + 5.0.0 4.0.0 @@ -412,7 +419,7 @@ 4.3.2 - 4.5.1 + 4.6.1 0.10.11