Archived
1
0

Seek slider fixes

Related Work Items: #235, #237
This commit is contained in:
Michael Gordeev
2018-12-30 23:58:16 +03:00
parent f797b4f851
commit ead4f76ded
3 changed files with 93 additions and 181 deletions
+1 -1
View File
@@ -191,7 +191,7 @@ namespace FoxTube
catch (ArgumentNullException) { } catch (ArgumentNullException) { }
} }
public static async void SaveData() public static void SaveData()
{ {
storage.Values["settings"] = JsonConvert.SerializeObject(settings); storage.Values["settings"] = JsonConvert.SerializeObject(settings);
ExportSettings(); ExportSettings();
+80 -175
View File
@@ -25,6 +25,11 @@ using YoutubeExplode.Models.ClosedCaptions;
using System.Globalization; using System.Globalization;
using FoxTube.Controls; using FoxTube.Controls;
using Windows.System; using Windows.System;
using Windows.Media.Core;
using Windows.Media.MediaProperties;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Media.Editing;
namespace FoxTube namespace FoxTube
{ {
@@ -55,10 +60,6 @@ namespace FoxTube
public event ObjectEventHandler NextClicked; public event ObjectEventHandler NextClicked;
public Button Next => next; public Button Next => next;
bool isMuxed = false;
bool audioReady = false;
bool videoReady = false;
CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor; CoreCursor cursorBackup = Window.Current.CoreWindow.PointerCursor;
Point cursorPositionBackup; Point cursorPositionBackup;
@@ -91,14 +92,14 @@ namespace FoxTube
{ {
Interval = TimeSpan.FromSeconds(1) Interval = TimeSpan.FromSeconds(1)
}; };
DispatcherTimer ctrlsFadeTimer; DispatcherTimer ctrlsFadeTimer = null;
public VideoPlayer() public VideoPlayer()
{ {
InitializeComponent(); InitializeComponent();
} }
public async void Initialize(Video meta, string channelAvatar) public void Initialize(Video meta, string channelAvatar)
{ {
try try
{ {
@@ -138,46 +139,6 @@ namespace FoxTube
else else
LoadUpcoming(); 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<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().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; Visibility = Visibility.Visible;
} }
catch (Exception e) catch (Exception e)
@@ -221,6 +182,7 @@ namespace FoxTube
title.Text = item.Snippet.Title; title.Text = item.Snippet.Title;
channelName.Text = item.Snippet.ChannelTitle; channelName.Text = item.Snippet.ChannelTitle;
ctrlsFadeTimer = new DispatcherTimer();
ctrlsFadeTimer.Interval = TimeSpan.FromSeconds(5); ctrlsFadeTimer.Interval = TimeSpan.FromSeconds(5);
ctrlsFadeTimer.Tick += Elapsed; ctrlsFadeTimer.Tick += Elapsed;
} }
@@ -263,11 +225,12 @@ namespace FoxTube
//TODO: Set up a stream //TODO: Set up a stream
} }
public void LoadVideo() public async void LoadVideo()
{ {
InitializeContols(); InitializeContols();
captions = grid.Children[2] as LiveCaptions; captions = grid.Children[2] as LiveCaptions;
timer.Tick += UpdateSeek; timer.Tick += UpdateSeek;
timer.Start();
total = XmlConvert.ToTimeSpan(item.ContentDetails.Duration); total = XmlConvert.ToTimeSpan(item.ContentDetails.Duration);
seek.Maximum = total.TotalSeconds; seek.Maximum = total.TotalSeconds;
@@ -276,8 +239,40 @@ namespace FoxTube
elapsed = TimeSpan.FromSeconds(seek.Value); elapsed = TimeSpan.FromSeconds(seek.Value);
remaining = total.Subtract(elapsed); remaining = total.Subtract(elapsed);
elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed.Hours}:00:" : "" + $"{elapsed:mm\\:ss}"; elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed:hh\\:mm\\:ss}" : $"{elapsed:mm\\:ss}";
remainingTime.Text = remaining.Hours > 0 ? $"{remaining.Hours}:00:" : "" + $"{remaining: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<VideoQuality> 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) public void UpdateCountdown(object sender, object e)
@@ -333,7 +328,7 @@ namespace FoxTube
if (pointerCaptured) if (pointerCaptured)
Window.Current.CoreWindow.PointerCursor = null; Window.Current.CoreWindow.PointerCursor = null;
seekIndicator.Visibility = Visibility.Collapsed; seekIndicator.Visibility = Visibility.Collapsed;
ctrlsFadeTimer.Stop(); ctrlsFadeTimer?.Stop();
} }
public void UpdateSize() public void UpdateSize()
@@ -374,7 +369,7 @@ namespace FoxTube
private void UserControl_Tapped(object sender, TappedRoutedEventArgs e) 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; touchCentral.Visibility = Visibility.Visible;
if (ctrlsFadeTimer.IsEnabled) if (ctrlsFadeTimer.IsEnabled)
@@ -386,6 +381,9 @@ namespace FoxTube
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e) private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{ {
if (ctrlsFadeTimer == null)
return;
if (cursorPositionBackup == null) if (cursorPositionBackup == null)
cursorPositionBackup = Window.Current.CoreWindow.PointerPosition; cursorPositionBackup = Window.Current.CoreWindow.PointerPosition;
else if (cursorPositionBackup == Window.Current.CoreWindow.PointerPosition) else if (cursorPositionBackup == Window.Current.CoreWindow.PointerPosition)
@@ -410,135 +408,48 @@ namespace FoxTube
void ShowControls() void ShowControls()
{ {
if (ctrlsFadeTimer == null)
return;
controls.Visibility = Visibility.Visible; controls.Visibility = Visibility.Visible;
if (MiniView) if (MiniView)
seekIndicator.Visibility = Visibility.Visible; seekIndicator.Visibility = Visibility.Visible;
Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0); Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Arrow, 0);
ctrlsFadeTimer.Stop(); ctrlsFadeTimer?.Stop();
ctrlsFadeTimer.Start(); 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(); videoSource.Pause();
audioSource.Source = null;
timecodeBackup = videoSource.Position.TotalSeconds; timecodeBackup = videoSource.Position.TotalSeconds;
audioReady = false; if(streamInfo.Muxed.ToList().Exists(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content.ToString()))
videoReady = false; videoSource.Source = streamInfo.Muxed.Find(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string).Url.ToUri();
else
{
VideoStreamInfo videoInfo = streamInfo.Video.Find(i => i.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content.ToString());
AudioStreamInfo audioInfo = streamInfo.Audio.First();
settings.Values["rememberedQuality"] = (quality.SelectedItem as ComboBoxItem).Content as string; MediaComposition muxedStream = new MediaComposition();
if(streamInfo.Muxed.ToList().Exists(x => x.VideoQualityLabel == (quality.SelectedItem as ComboBoxItem).Content as string)) BackgroundAudioTrack audioTrack = await BackgroundAudioTrack.CreateFromFileAsync(await StorageFile.GetFileFromPathAsync(audioInfo.Url));
{ MediaClip videoTrack = await MediaClip.CreateFromFileAsync(await StorageFile.GetFileFromApplicationUriAsync(videoInfo.Url.ToUri()));
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) muxedStream.BackgroundAudioTracks.Add(audioTrack);
{ muxedStream.Clips.Add(videoTrack);
case "2160p":
if(streamInfo.Muxed.First(x => x.VideoQuality.))
{
isMuxed = true;
videoSource.SetMediaStreamSource(muxedStream.GenerateMediaStreamSource());
} }
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; needUpdateTimecode = true;
videoSource.Play(); videoSource.Play();
} }
catch //catch
{ {
} }
@@ -564,7 +475,7 @@ namespace FoxTube
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url); captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
} }
else else
captions.Close(); captions?.Close();
} }
private void fullscreen_Click(object sender, RoutedEventArgs e) private void fullscreen_Click(object sender, RoutedEventArgs e)
@@ -592,7 +503,6 @@ namespace FoxTube
if (videoSource.CurrentState == MediaElementState.Playing) if (videoSource.CurrentState == MediaElementState.Playing)
videoSource.Pause(); videoSource.Pause();
else if (videoSource.CurrentState == MediaElementState.Paused) else if (videoSource.CurrentState == MediaElementState.Paused)
if((audioReady && videoReady) || isMuxed)
videoSource.Play(); videoSource.Play();
} }
@@ -613,8 +523,6 @@ namespace FoxTube
switch(videoSource.CurrentState) switch(videoSource.CurrentState)
{ {
case MediaElementState.Buffering: case MediaElementState.Buffering:
audioSource.Position = videoSource.Position;
audioSource.Pause();
bufferingBar.Visibility = Visibility.Visible; bufferingBar.Visibility = Visibility.Visible;
seek.IsEnabled = false; seek.IsEnabled = false;
@@ -628,8 +536,6 @@ namespace FoxTube
break; break;
case MediaElementState.Paused: case MediaElementState.Paused:
if(audioSource.CurrentState != MediaElementState.Buffering)
audioSource.Pause();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
seek.IsEnabled = true; seek.IsEnabled = true;
@@ -643,7 +549,6 @@ namespace FoxTube
break; break;
case MediaElementState.Playing: case MediaElementState.Playing:
audioSource.Play();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
seek.IsEnabled = true; seek.IsEnabled = true;
@@ -659,7 +564,6 @@ namespace FoxTube
break; break;
default: default:
audioSource.Pause();
bufferingBar.Visibility = Visibility.Collapsed; bufferingBar.Visibility = Visibility.Collapsed;
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed; systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
break; break;
@@ -723,8 +627,8 @@ namespace FoxTube
elapsed = TimeSpan.FromSeconds(seek.Value); elapsed = TimeSpan.FromSeconds(seek.Value);
remaining = total.Subtract(elapsed); remaining = total.Subtract(elapsed);
elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed.Hours}:00:" : "" + $"{elapsed:mm\\:ss}"; elapsedTime.Text = elapsed.Hours > 0 ? $"{elapsed:hh\\:mm\\:ss}" : $"{elapsed:mm\\:ss}";
remainingTime.Text = remaining.Hours > 0 ? $"{remaining.Hours}:00:" : "" + $"{remaining:mm\\:ss}"; remainingTime.Text = remaining.Hours > 0 ? $"{remaining:hh\\:mm\\:ss}" : $"{remaining:mm\\:ss}";
} }
private void seek_PointerCaptureLost(object sender, PointerRoutedEventArgs e) private void seek_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
@@ -752,9 +656,10 @@ namespace FoxTube
private void matureDismiss_Click(object sender, RoutedEventArgs e) private void matureDismiss_Click(object sender, RoutedEventArgs e)
{ {
if ((bool)matureDisable.IsChecked) if ((bool)matureDisable.IsChecked)
settings.Values.Add("showMature", false); SettingsStorage.Mature = MatureState.Allowed;
matureBlock.Visibility = Visibility.Collapsed; else
Initialize(item, avatar); SettingsStorage.Mature = MatureState.AllowedOnce;
Methods.MainPage.GoToVideo(videoId, Methods.MainPage.GetPlaylist());
} }
private void signin_Click(object sender, RoutedEventArgs e) private void signin_Click(object sender, RoutedEventArgs e)
@@ -800,7 +705,7 @@ namespace FoxTube
{ {
systemControls.IsEnabled = false; systemControls.IsEnabled = false;
pointerCaptured = false; pointerCaptured = false;
Elapsed(); Elapsed(this, null);
Methods.MainPage.CloseVideo(); Methods.MainPage.CloseVideo();
} }
@@ -893,7 +798,7 @@ namespace FoxTube
private void videoSource_BufferingProgressChanged(object sender, RoutedEventArgs e) 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) private void GotoLive_Click(object sender, RoutedEventArgs e)
+9 -2
View File
@@ -115,6 +115,9 @@
<Compile Include="Controls\ChannelCard.xaml.cs"> <Compile Include="Controls\ChannelCard.xaml.cs">
<DependentUpon>ChannelCard.xaml</DependentUpon> <DependentUpon>ChannelCard.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\Chat.xaml.cs">
<DependentUpon>Chat.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\CommentCard.xaml.cs"> <Compile Include="Controls\CommentCard.xaml.cs">
<DependentUpon>CommentCard.xaml</DependentUpon> <DependentUpon>CommentCard.xaml</DependentUpon>
</Compile> </Compile>
@@ -284,6 +287,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\Chat.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\CommentCard.xaml"> <Page Include="Controls\CommentCard.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@@ -403,7 +410,7 @@
<Version>6.1.9</Version> <Version>6.1.9</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications"> <PackageReference Include="Microsoft.Toolkit.Uwp.Notifications">
<Version>4.0.0</Version> <Version>5.0.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls"> <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls">
<Version>4.0.0</Version> <Version>4.0.0</Version>
@@ -412,7 +419,7 @@
<Version>4.3.2</Version> <Version>4.3.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="YoutubeExplode"> <PackageReference Include="YoutubeExplode">
<Version>4.5.1</Version> <Version>4.6.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="YoutubeExtractor"> <PackageReference Include="YoutubeExtractor">
<Version>0.10.11</Version> <Version>0.10.11</Version>