#224: Fixed
This commit is contained in:
+1
-10
@@ -1,6 +1,4 @@
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Newtonsoft.Json;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -9,13 +7,11 @@ using System.Linq;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.ApplicationModel.Background;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Globalization;
|
||||
using Windows.Storage;
|
||||
using Windows.System;
|
||||
using Windows.System.Power;
|
||||
using Windows.UI.Notifications;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
@@ -81,11 +77,6 @@ namespace FoxTube
|
||||
|
||||
rootFrame.NavigationFailed += OnNavigationFailed;
|
||||
|
||||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
|
||||
{
|
||||
//TODO: Load state from previously suspended application
|
||||
}
|
||||
|
||||
// Place the frame in the current Window
|
||||
Window.Current.Content = rootFrame;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Name="progressPanel" Grid.Column="4" Margin="10">
|
||||
<TextBlock Name="status" Text="Initializing..." HorizontalAlignment="Left"/>
|
||||
<TextBlock Name="status" Text="Downloading..." HorizontalAlignment="Left"/>
|
||||
<ProgressBar Name="progressBar" Width="200" Maximum="1" IsIndeterminate="True" Foreground="Red"/>
|
||||
<TextBlock Name="perc" Text="--%"/>
|
||||
<Button Content="Cancel" Name="cancel" Click="CancelPrompt" HorizontalAlignment="Right"/>
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace FoxTube.Controls
|
||||
Progress<double> progress = new Progress<double>();
|
||||
NotificationData data = new NotificationData();
|
||||
|
||||
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
|
||||
double percentage;
|
||||
|
||||
public DownloadItem(MediaStreamInfo info, Video meta, string q)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -71,24 +74,27 @@ namespace FoxTube.Controls
|
||||
donePanel.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
async Task Download(MediaStreamInfo info, Video meta, string q)
|
||||
async void Download(MediaStreamInfo info, Video meta, string q)
|
||||
{
|
||||
InProgress = true;
|
||||
Container = new DownloadItemContainer();
|
||||
|
||||
token = cts.Token;
|
||||
progress.ProgressChanged += UpdateInfo;
|
||||
|
||||
file = await DownloadAgent.Downloads.CreateFileAsync($"{meta.Snippet.Title.ReplaceInvalidChars('_')}.{info.Container.GetFileExtension()}", CreationCollisionOption.GenerateUniqueName);
|
||||
Container.Name = file.Name;
|
||||
|
||||
ToastContent toastContent = new ToastContent()
|
||||
try
|
||||
{
|
||||
Visual = new ToastVisual()
|
||||
InProgress = true;
|
||||
Container = new DownloadItemContainer();
|
||||
|
||||
token = cts.Token;
|
||||
progress.ProgressChanged += (s, e) => percentage = e;
|
||||
timer.Tick += (s, e) => UpdateInfo(percentage);
|
||||
|
||||
file = await DownloadAgent.Downloads.CreateFileAsync($"{meta.Snippet.Title.ReplaceInvalidChars('_')}.{info.Container.GetFileExtension()}", CreationCollisionOption.GenerateUniqueName);
|
||||
Container.Name = file.Name;
|
||||
|
||||
ToastContent toastContent = new ToastContent()
|
||||
{
|
||||
BindingGeneric = new ToastBindingGeneric()
|
||||
Visual = new ToastVisual()
|
||||
{
|
||||
Children =
|
||||
BindingGeneric = new ToastBindingGeneric()
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new AdaptiveText() { Text = "Downloading a video" },
|
||||
new AdaptiveProgressBar()
|
||||
@@ -98,59 +104,62 @@ namespace FoxTube.Controls
|
||||
Value = new BindableProgressBarValue("value")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
Actions = new ToastActionsCustom()
|
||||
{
|
||||
Buttons =
|
||||
Actions = new ToastActionsCustom()
|
||||
{
|
||||
Buttons =
|
||||
{
|
||||
new ToastButton("Cancel", $"dcancel|{Container.Id}")
|
||||
{
|
||||
ActivationType = ToastActivationType.Background
|
||||
}
|
||||
}
|
||||
},
|
||||
Launch = "download",
|
||||
ActivationType = ToastActivationType.Foreground
|
||||
};
|
||||
},
|
||||
Launch = "download",
|
||||
ActivationType = ToastActivationType.Foreground
|
||||
};
|
||||
|
||||
data.Values["value"] = "0";
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastContent.GetXml()) { Tag = $"download|{meta.Id}", Data = data });
|
||||
data.Values["value"] = "0";
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastContent.GetXml()) { Tag = $"download|{meta.Id}", Data = data });
|
||||
|
||||
Container.Channel = meta.Snippet.ChannelTitle;
|
||||
Container.Duration = XmlConvert.ToTimeSpan(meta.ContentDetails.Duration);
|
||||
Container.Id = meta.Id;
|
||||
Container.Quality = q;
|
||||
Container.Thumbnail = meta.Snippet.Thumbnails.Medium.Url.ToUri();
|
||||
Container.Title = meta.Snippet.Title;
|
||||
Container.Extension = info.Container.GetFileExtension();
|
||||
Container.Channel = meta.Snippet.ChannelTitle;
|
||||
Container.Duration = XmlConvert.ToTimeSpan(meta.ContentDetails.Duration);
|
||||
Container.Id = meta.Id;
|
||||
Container.Quality = q;
|
||||
Container.Thumbnail = meta.Snippet.Thumbnails.Medium.Url.ToUri();
|
||||
Container.Title = meta.Snippet.Title;
|
||||
Container.Extension = info.Container.GetFileExtension();
|
||||
|
||||
thumbnail.Source = new BitmapImage(new Uri(meta.Snippet.Thumbnails.Medium.Url));
|
||||
title.Text = meta.Snippet.Title;
|
||||
ext.Text = $"Extension: {info.Container.GetFileExtension()}";
|
||||
quality.Text = $"Quality: {q}";
|
||||
duration.Text = $"Duration: {XmlConvert.ToTimeSpan(meta.ContentDetails.Duration)}";
|
||||
channel.Text = $"Author: {meta.Snippet.ChannelTitle}";
|
||||
path.Text = file.Name;
|
||||
thumbnail.Source = new BitmapImage(new Uri(meta.Snippet.Thumbnails.Medium.Url));
|
||||
title.Text = meta.Snippet.Title;
|
||||
ext.Text = $"Extension: {info.Container.GetFileExtension()}";
|
||||
quality.Text = $"Quality: {q}";
|
||||
duration.Text = $"Duration: {XmlConvert.ToTimeSpan(meta.ContentDetails.Duration)}";
|
||||
channel.Text = $"Author: {meta.Snippet.ChannelTitle}";
|
||||
path.Text = file.Name;
|
||||
|
||||
progressPanel.Visibility = Visibility.Visible;
|
||||
donePanel.Visibility = Visibility.Collapsed;
|
||||
progressPanel.Visibility = Visibility.Visible;
|
||||
donePanel.Visibility = Visibility.Collapsed;
|
||||
|
||||
await client.DownloadMediaStreamAsync(info, await file.OpenStreamForWriteAsync(), progress, token);
|
||||
timer.Start();
|
||||
|
||||
progressPanel.Visibility = Visibility.Collapsed;
|
||||
donePanel.Visibility = Visibility.Visible;
|
||||
await client.DownloadMediaStreamAsync(info, await file.OpenStreamForWriteAsync(), progress, token);
|
||||
|
||||
InProgress = false;
|
||||
progressPanel.Visibility = Visibility.Collapsed;
|
||||
donePanel.Visibility = Visibility.Visible;
|
||||
|
||||
if(!cts.IsCancellationRequested)
|
||||
DownloadCompleted();
|
||||
InProgress = false;
|
||||
|
||||
if (!cts.IsCancellationRequested)
|
||||
DownloadCompleted();
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
}
|
||||
|
||||
private void UpdateInfo(object sender, double e)
|
||||
private void UpdateInfo(double e)
|
||||
{
|
||||
status.Text = "Downloading";
|
||||
progressBar.Value = e;
|
||||
perc.Text = $"{(int)e * 100}%";
|
||||
|
||||
|
||||
@@ -168,5 +168,13 @@
|
||||
<Button Name="signin" Click="signin_Click" Content="Sign in now" Foreground="White" Background="Gray" HorizontalAlignment="Right" Grid.Column="1" Margin="0,0,10,0"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Background="#E5000000" Visibility="Collapsed">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Name="errorPlate">
|
||||
<TextBlock Text="Something went wrong..." HorizontalAlignment="Center" FontSize="20"/>
|
||||
<TextBlock Text="Video ID: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||
<TextBlock Text="Error type: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||
<TextBlock Text="Message: " HorizontalAlignment="Center" IsTextSelectionEnabled="True" FontSize="20"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -113,101 +113,116 @@ namespace FoxTube
|
||||
|
||||
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().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)
|
||||
try
|
||||
{
|
||||
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
|
||||
item = meta;
|
||||
avatar = channelAvatar;
|
||||
videoId = item.Id;
|
||||
|
||||
if (item.ContentDetails.ContentRating != null)
|
||||
#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
|
||||
|
||||
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;
|
||||
|
||||
//SecretsVault.HistoryAdd(videoId, elapsed, total);
|
||||
|
||||
t.Start();
|
||||
|
||||
Visibility = Visibility.Visible;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
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;
|
||||
}
|
||||
RaiseError(e);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//SecretsVault.HistoryAdd(videoId, elapsed, total);
|
||||
|
||||
t.Start();
|
||||
|
||||
Visibility = Visibility.Visible;
|
||||
public void RaiseError(Exception e)
|
||||
{
|
||||
((TextBlock)errorPlate.Children[1]).Text = $"Video ID: {videoId}";
|
||||
((TextBlock)errorPlate.Children[2]).Text = $"Error type: {e.GetType()}";
|
||||
((TextBlock)errorPlate.Children[3]).Text = $"Message: {e.Message}";
|
||||
((Grid)errorPlate.Parent).Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
||||
|
||||
@@ -243,25 +243,32 @@ namespace FoxTube.Pages
|
||||
|
||||
async void LoadDownloads()
|
||||
{
|
||||
MediaStreamInfoSet infoSet = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
|
||||
foreach(MuxedStreamInfo i in infoSet.Muxed)
|
||||
try
|
||||
{
|
||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||
MediaStreamInfoSet infoSet = await new YoutubeClient().GetVideoMediaStreamInfosAsync(videoId);
|
||||
foreach (MuxedStreamInfo i in infoSet.Muxed)
|
||||
{
|
||||
Text = i.VideoQualityLabel,
|
||||
Tag = new object[] { i, i.VideoQualityLabel }
|
||||
};
|
||||
menuItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(menuItem);
|
||||
}
|
||||
MenuFlyoutItem menuItem = new MenuFlyoutItem()
|
||||
{
|
||||
Text = i.VideoQualityLabel,
|
||||
Tag = new object[] { i, i.VideoQualityLabel }
|
||||
};
|
||||
menuItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(menuItem);
|
||||
}
|
||||
|
||||
MenuFlyoutItem audioItem = new MenuFlyoutItem()
|
||||
MenuFlyoutItem audioItem = new MenuFlyoutItem()
|
||||
{
|
||||
Text = "Audio track",
|
||||
Tag = new object[] { infoSet.Audio[0], "Audio only" }
|
||||
};
|
||||
audioItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(audioItem);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Text = "Audio track",
|
||||
Tag = new object[] { infoSet.Audio[0], "Audio only" }
|
||||
};
|
||||
audioItem.Click += downloadItemSelected;
|
||||
downloadSelector.Items.Add(audioItem);
|
||||
loading.Error(e.GetType().ToString(), e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadItemSelected(object sender, RoutedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user