diff --git a/FoxTube/Controls/VideoPlayer.xaml b/FoxTube/Controls/VideoPlayer.xaml index 9dced1b..362a4b4 100644 --- a/FoxTube/Controls/VideoPlayer.xaml +++ b/FoxTube/Controls/VideoPlayer.xaml @@ -16,8 +16,8 @@ PointerEntered="UserControl_PointerEntered"> - - + + @@ -98,7 +98,10 @@ - + + + + diff --git a/FoxTube/Controls/VideoPlayer.xaml.cs b/FoxTube/Controls/VideoPlayer.xaml.cs index b2d6adc..747517c 100644 --- a/FoxTube/Controls/VideoPlayer.xaml.cs +++ b/FoxTube/Controls/VideoPlayer.xaml.cs @@ -67,6 +67,10 @@ namespace FoxTube 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; @@ -129,7 +133,11 @@ namespace FoxTube #region Retrieving info for CC and Media streams //Loading streams streamInfo = (await YouTube.GetUrisAsync(item.Id)).ToList(); - streamInfo.ForEach(x => Debug.WriteLine(x)); + foreach (YouTubeQuality q in Enum.GetValues(typeof(YouTubeQuality))) + if (streamInfo.FindAll(x => x.VideoQuality == q).Count > 1) + streamInfo.RemoveAll(x => x.VideoQuality == q && !x.HasAudio); + + streamInfo.ForEach(x => Debug.WriteLine($"{x.HasAudio}; {x.HasVideo}; {x.VideoQuality}; {x.AudioQuality}")); foreach (YouTubeUri i in streamInfo) { if (i.VideoQuality == YouTubeQuality.Quality2160P) @@ -258,11 +266,11 @@ namespace FoxTube { seek.Value = videoSource.Position.TotalSeconds; seekIndicator.Value = seek.Value; - if (Math.Round(videoSource.Position.TotalSeconds, 1) != Math.Round(audioSource.Position.TotalSeconds, 1)) + /*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() @@ -292,19 +300,19 @@ namespace FoxTube { double v = volume.Value; if (v == 0) - muteBtn.Content = openVolume.Content = ""; + muteBtn.Content = openVolume.Content = "\xE74F"; else if (v <= 25 && v > 0) - muteBtn.Content = openVolume.Content = ""; + muteBtn.Content = openVolume.Content = "\xE992"; else if (v <= 50 && v > 25) - muteBtn.Content = openVolume.Content = ""; + muteBtn.Content = openVolume.Content = "\xE993"; else if (v <= 75 && v > 50) - muteBtn.Content = openVolume.Content = ""; + muteBtn.Content = openVolume.Content = "\xE994"; else if (v > 75) - muteBtn.Content = openVolume.Content = ""; + muteBtn.Content = openVolume.Content = "\xE995"; settings.Values["volume"] = volume.Value; - audioSource.Volume = volume.Value * 0.01; + audioSource.Volume = videoSource.Volume = volume.Value * 0.01; } private void muteBtn_Click(object sender, RoutedEventArgs e) @@ -352,82 +360,108 @@ namespace FoxTube private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e) { - //try + try { videoSource.Pause(); + audioSource.Source = null; timecodeBackup = videoSource.Position.TotalSeconds; + audioReady = false; + videoReady = false; + switch((quality.SelectedItem as ComboBoxItem).Content) { case "2160p": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality2160P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } - catch + if(streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality2160P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality1080P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality720P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality480P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality360P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality240P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } + 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": - videoSource.Source = streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).Uri; - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityLow).Uri; } - catch + if (streamInfo.First(x => x.VideoQuality == YouTubeQuality.Quality144P).HasAudio) + isMuxed = true; + else { - try { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityMedium).Uri; } - catch { audioSource.Source = streamInfo.First(x => x.AudioQuality == YouTubeQuality.QualityHigh).Uri; } + 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 { } @@ -481,7 +515,8 @@ namespace FoxTube if (videoSource.CurrentState == MediaElementState.Playing) videoSource.Pause(); else if (videoSource.CurrentState == MediaElementState.Paused) - videoSource.Play(); + if((audioReady && videoReady) || isMuxed) + videoSource.Play(); } private void AudioSource_CurrentStateChanged(object sender, RoutedEventArgs e) @@ -489,16 +524,38 @@ namespace FoxTube switch (audioSource.CurrentState) { case MediaElementState.Buffering: - videoSource.Pause(); + if(videoSource.CurrentState != MediaElementState.Buffering) + videoSource.Pause(); break; case MediaElementState.Playing: - if(videoSource.CurrentState == MediaElementState.Paused) + 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) @@ -510,6 +567,7 @@ namespace FoxTube switch(videoSource.CurrentState) { case MediaElementState.Buffering: + audioSource.Position = videoSource.Position; audioSource.Pause(); bufferingBar.Visibility = Visibility.Visible; @@ -551,12 +609,6 @@ namespace FoxTube play.Content = "\xE103"; touchPlay.Content = "\xE103"; - 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; - } - systemControls.PlaybackStatus = MediaPlaybackStatus.Playing; break; @@ -796,7 +848,7 @@ namespace FoxTube case VirtualKey.Left: back10_Click(this, null); break; - case Windows.System.VirtualKey.Right: + case VirtualKey.Right: fwd30_Click(this, null); break; } @@ -806,5 +858,10 @@ namespace FoxTube { LoadTrack(); } + + private void videoSource_BufferingProgressChanged(object sender, RoutedEventArgs e) + { + bufferingLevel.Value = (audioSource.Source != null && videoSource.BufferingProgress > audioSource.BufferingProgress ? audioSource.BufferingProgress : videoSource.BufferingProgress) * 100; + } } }