Closed captions
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FoxTube.Classes
|
||||||
|
{
|
||||||
|
public class Caption
|
||||||
|
{
|
||||||
|
public TimeSpan Start { get; private set; }
|
||||||
|
public TimeSpan Duration { get; private set; }
|
||||||
|
public TimeSpan End
|
||||||
|
{
|
||||||
|
get { return Start + Duration; }
|
||||||
|
}
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
public Caption(int startTime, int duration, string text)
|
||||||
|
{
|
||||||
|
Start = TimeSpan.FromMilliseconds(startTime);
|
||||||
|
Duration = TimeSpan.FromMilliseconds(duration);
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,9 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Margin="0,75">
|
Margin="0,55">
|
||||||
|
|
||||||
<Grid Background="#99000000">
|
<Grid Background="#99000000">
|
||||||
<TextBlock Text="Hello, World!" Margin="5" FontSize="24"/>
|
<TextBlock Text="Hello, World!" Name="text" Margin="5" FontSize="24"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FoxTube.Classes;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -12,6 +13,8 @@ using Windows.UI.Xaml.Data;
|
|||||||
using Windows.UI.Xaml.Input;
|
using Windows.UI.Xaml.Input;
|
||||||
using Windows.UI.Xaml.Media;
|
using Windows.UI.Xaml.Media;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
@@ -19,9 +22,67 @@ namespace FoxTube.Controls
|
|||||||
{
|
{
|
||||||
public sealed partial class LiveCaptions : UserControl
|
public sealed partial class LiveCaptions : UserControl
|
||||||
{
|
{
|
||||||
|
public MediaElement Player { get; set; }
|
||||||
|
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(10) };
|
||||||
|
List<Caption> captions = new List<Caption>();
|
||||||
|
Caption currentCaption = null;
|
||||||
|
|
||||||
public LiveCaptions()
|
public LiveCaptions()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
|
timer.Tick += UpdateCaption;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCaption(object sender, object e)
|
||||||
|
{
|
||||||
|
TimeSpan currentPosition = Player.Position;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
captions.ForEach((x) =>
|
||||||
|
{
|
||||||
|
if (Player.Position >= x.Start && Player.Position <= x.End)
|
||||||
|
{
|
||||||
|
currentCaption = x;
|
||||||
|
text.Text = currentCaption.Text;
|
||||||
|
Visibility = Visibility.Visible;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
currentCaption = null;
|
||||||
|
Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(string source)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.Load(source);
|
||||||
|
|
||||||
|
foreach (XmlElement i in doc["timedtext"]["body"].ChildNodes)
|
||||||
|
captions.Add(new Caption(int.Parse(i.GetAttribute("t")), int.Parse(i.GetAttribute("d")), i.InnerText));
|
||||||
|
|
||||||
|
captions.ForEach((x) =>
|
||||||
|
{
|
||||||
|
if(Player.Position > x.Start && Player.Position < x.End)
|
||||||
|
{
|
||||||
|
currentCaption = x;
|
||||||
|
text.Text = currentCaption.Text;
|
||||||
|
Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
captions.Clear();
|
||||||
|
currentCaption = null;
|
||||||
|
Visibility = Visibility.Collapsed;
|
||||||
|
timer.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<Grid Background="White" Name="grid" Tapped="UserControl_Tapped">
|
<Grid Background="White" Name="grid" Tapped="UserControl_Tapped">
|
||||||
<MediaElement IsDoubleTapEnabled="False" CurrentStateChanged="videoSource_CurrentStateChanged" AutoPlay="False" Name="videoSource" AreTransportControlsEnabled="False" PosterSource="ms-appx:///Assets/videoThumbSample.png"/>
|
<MediaElement IsDoubleTapEnabled="False" CurrentStateChanged="videoSource_CurrentStateChanged" AutoPlay="False" Name="videoSource" AreTransportControlsEnabled="False" PosterSource="ms-appx:///Assets/videoThumbSample.png"/>
|
||||||
|
|
||||||
<controls1:LiveCaptions/>
|
<controls1:LiveCaptions Player="{x:Bind videoSource}" Visibility="Collapsed"/>
|
||||||
|
|
||||||
<Grid Name="controls" Visibility="Visible">
|
<Grid Name="controls" Visibility="Visible">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<Button Click="minimize_Click" Name="minimize" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Minimize"/>
|
<Button Click="minimize_Click" Name="minimize" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Minimize"/>
|
||||||
<StackPanel Grid.Column="1" Margin="10,0,10,0" VerticalAlignment="Center">
|
<StackPanel Grid.Column="1" Margin="10,0,10,0" VerticalAlignment="Center">
|
||||||
<TextBlock Name="title" Text="[Title]" Foreground="White" VerticalAlignment="Center" TextWrapping="WrapWholeWords" FontSize="20" MaxLines="1" ToolTipService.ToolTip="Title"/>
|
<TextBlock Name="title" Text="[Title]" Foreground="White" VerticalAlignment="Center" TextWrapping="WrapWholeWords" FontSize="20" MaxLines="1" ToolTipService.ToolTip="Title"/>
|
||||||
<TextBlock Foreground="Gray" Text="[Channel name]" Name="channelName" FontStyle="Italic"/>
|
<TextBlock Foreground="LightGray" Text="[Channel name]" Name="channelName" FontStyle="Italic"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
<Button Name="closeHeader" Click="close_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Close video"/>
|
<Button Name="closeHeader" Click="close_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Close video"/>
|
||||||
@@ -83,14 +83,17 @@
|
|||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<Button Click="play_Click" Name="play" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Play"/>
|
<Button Click="play_Click" Name="play" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Play"/>
|
||||||
<Button Name="next" Click="next_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Next video"/>
|
<Button Name="next" Click="next_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Next video"/>
|
||||||
<Button Name="openVolume" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Volume" Click="openVolume_Click"/>
|
<Button Name="openVolume" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Volume">
|
||||||
</StackPanel>
|
<Button.Flyout>
|
||||||
<Popup Grid.Column="0" Margin="100,-200,50,0" IsOpen="False" IsLightDismissEnabled="True" Name="volumePane">
|
<Flyout>
|
||||||
<StackPanel Background="#7F000000" Width="50" Height="200">
|
<StackPanel Orientation="Horizontal" Margin="-10">
|
||||||
<Slider Orientation="Vertical" HorizontalAlignment="Center" Height="135" Margin="5,10,10,5" Name="volume" ValueChanged="volume_ValueChanged"/>
|
|
||||||
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Mute" Name="muteBtn" Click="muteBtn_Click"/>
|
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Mute" Name="muteBtn" Click="muteBtn_Click"/>
|
||||||
|
<Slider Orientation="Horizontal" Width="150" Margin="10,5,10,0" VerticalAlignment="Center" Name="volume" ValueChanged="volume_ValueChanged"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Flyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Popup>
|
|
||||||
|
|
||||||
<Grid Grid.Column="1">
|
<Grid Grid.Column="1">
|
||||||
<TextBlock Name="elapsedTime" Foreground="White" Text="[Elapsed]" VerticalAlignment="Bottom" HorizontalAlignment="Left" ToolTipService.ToolTip="Time elapsed"/>
|
<TextBlock Name="elapsedTime" Foreground="White" Text="[Elapsed]" VerticalAlignment="Bottom" HorizontalAlignment="Left" ToolTipService.ToolTip="Time elapsed"/>
|
||||||
@@ -104,23 +107,20 @@
|
|||||||
|
|
||||||
<Line Stroke="White" StrokeThickness="2" Y1="5" Y2="45"/>
|
<Line Stroke="White" StrokeThickness="2" Y1="5" Y2="45"/>
|
||||||
|
|
||||||
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Subtitles" Name="openSubs" Click="openSubs_Click"/>
|
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Subtitles" Name="captionsBtn">
|
||||||
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality" Name="openSets" Click="openSets_Click"/>
|
<Button.Flyout>
|
||||||
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Full screen" Name="fullscreen" Click="fullscreen_Click"/>
|
<Flyout>
|
||||||
|
<StackPanel Width="225">
|
||||||
|
<ToggleSwitch Name="subsSwitch" Toggled="subsSwitch_Toggled" OnContent="Subtitles" OffContent="Subtitles"/>
|
||||||
|
<ComboBox Name="subsLang" Header="Language" PlaceholderText="No subtitles are available" Visibility="Collapsed" HorizontalAlignment="Stretch" SelectionChanged="subsLang_SelectionChanged"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</Flyout>
|
||||||
<Popup Grid.Column="2" Margin="0,-100,50,0" IsOpen="False" IsLightDismissEnabled="True" Name="subsPane">
|
</Button.Flyout>
|
||||||
<StackPanel Background="#7F000000" Width="252" Height="100" Padding="10">
|
</Button>
|
||||||
<ToggleSwitch Name="subsSwitch" Toggled="subsSwitch_Toggled" Foreground="White" OffContent="Show subtitles" OnContent="Show subtitles"/>
|
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality">
|
||||||
<ComboBox Name="subsLang" Width="232" PlaceholderText="No subtitles are available"/>
|
<Button.Flyout>
|
||||||
</StackPanel>
|
<Flyout>
|
||||||
</Popup>
|
<ComboBox Width="225" Header="Quality" Name="quality" SelectionChanged="quality_SelectionChanged">
|
||||||
|
|
||||||
<Popup Grid.Column="2" IsOpen="False" Margin="0,-75,0,0" IsLightDismissEnabled="True" Name="qualityPane">
|
|
||||||
<StackPanel Background="#7F000000" Width="252" Height="75" Padding="10">
|
|
||||||
<TextBlock Text="Quality" Foreground="White"/>
|
|
||||||
<Line X1="0" X2="232" Stroke="White" StrokeThickness="2"/>
|
|
||||||
<ComboBox Width="232" Name="quality" SelectionChanged="quality_SelectionChanged">
|
|
||||||
<!--<ComboBoxItem Content="Auto"/>-->
|
<!--<ComboBoxItem Content="Auto"/>-->
|
||||||
<ComboBoxItem Content="2160P" Visibility="Collapsed"/>
|
<ComboBoxItem Content="2160P" Visibility="Collapsed"/>
|
||||||
<ComboBoxItem Content="1080p" Visibility="Collapsed"/>
|
<ComboBoxItem Content="1080p" Visibility="Collapsed"/>
|
||||||
@@ -130,8 +130,11 @@
|
|||||||
<ComboBoxItem Content="240p" Visibility="Collapsed"/>
|
<ComboBoxItem Content="240p" Visibility="Collapsed"/>
|
||||||
<ComboBoxItem Content="144p" Visibility="Collapsed"/>
|
<ComboBoxItem Content="144p" Visibility="Collapsed"/>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
|
</Flyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Full screen" Name="fullscreen" Click="fullscreen_Click"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Popup>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ using Microsoft.Toolkit.Uwp.UI.Animations;
|
|||||||
using Google.Apis.YouTube.v3.Data;
|
using Google.Apis.YouTube.v3.Data;
|
||||||
using Google.Apis.YouTube.v3;
|
using Google.Apis.YouTube.v3;
|
||||||
using Windows.UI.Xaml.Media.Imaging;
|
using Windows.UI.Xaml.Media.Imaging;
|
||||||
using MyToolkit.Multimedia;
|
|
||||||
using Windows.Networking.Connectivity;
|
using Windows.Networking.Connectivity;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Windows.Media;
|
using Windows.Media;
|
||||||
@@ -32,6 +31,10 @@ using Windows.UI;
|
|||||||
using Windows.Graphics.Display;
|
using Windows.Graphics.Display;
|
||||||
using Windows.Media.Casting;
|
using Windows.Media.Casting;
|
||||||
using YoutubeExplode.Models.MediaStreams;
|
using YoutubeExplode.Models.MediaStreams;
|
||||||
|
using YoutubeExplode;
|
||||||
|
using YoutubeExplode.Models.ClosedCaptions;
|
||||||
|
using System.Globalization;
|
||||||
|
using FoxTube.Controls;
|
||||||
|
|
||||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
@@ -56,11 +59,15 @@ namespace FoxTube
|
|||||||
|
|
||||||
Video item;
|
Video item;
|
||||||
string avatar;
|
string avatar;
|
||||||
double timecodeBackup;
|
double timecodeBackup = 0;
|
||||||
|
bool needUpdateTimecode = false;
|
||||||
|
|
||||||
SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView();
|
SystemMediaTransportControls systemControls = SystemMediaTransportControls.GetForCurrentView();
|
||||||
|
LiveCaptions captions;
|
||||||
|
|
||||||
List<YouTubeUri> uris = new List<YouTubeUri>();
|
YoutubeClient client = new YoutubeClient();
|
||||||
|
IReadOnlyList<ClosedCaptionTrackInfo> ccInfo;
|
||||||
|
MediaStreamInfoSet streamInfo;
|
||||||
|
|
||||||
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
|
||||||
Timer t = new Timer()
|
Timer t = new Timer()
|
||||||
@@ -81,6 +88,8 @@ namespace FoxTube
|
|||||||
if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
|
if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
|
||||||
miniViewBtn.Visibility = Visibility.Collapsed;;
|
miniViewBtn.Visibility = Visibility.Collapsed;;
|
||||||
|
|
||||||
|
captions = grid.Children[1] as LiveCaptions;
|
||||||
|
|
||||||
volume.Value = Convert.ToDouble(settings.Values["volume"]);
|
volume.Value = Convert.ToDouble(settings.Values["volume"]);
|
||||||
videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"];
|
videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"];
|
||||||
|
|
||||||
@@ -94,121 +103,48 @@ namespace FoxTube
|
|||||||
avatar = channelAvatar;
|
avatar = channelAvatar;
|
||||||
videoId = item.Id;
|
videoId = item.Id;
|
||||||
|
|
||||||
#region Checking qualities availability
|
#region Retrieving info for CC and Media streams
|
||||||
uris = new List<YouTubeUri>(await YouTube.GetUrisAsync(videoId));
|
//Loading streams
|
||||||
|
streamInfo = await client.GetVideoMediaStreamInfosAsync(item.Id);
|
||||||
foreach (YouTubeUri i in uris.ToList())
|
foreach(MuxedStreamInfo i in streamInfo.Muxed)
|
||||||
if (!i.HasAudio || !i.HasVideo)
|
|
||||||
uris.Remove(i);
|
|
||||||
|
|
||||||
foreach (YouTubeUri u in uris)
|
|
||||||
{
|
{
|
||||||
Debug.WriteLine("-----------------");
|
if (i.VideoQuality == VideoQuality.High2160)
|
||||||
Debug.WriteLine("URI: " + u.Uri);
|
|
||||||
Debug.WriteLine("Has video: " + u.HasVideo);
|
|
||||||
Debug.WriteLine("Has audio: " + u.HasAudio);
|
|
||||||
Debug.WriteLine("Type: " + u.Type);
|
|
||||||
Debug.WriteLine("Video quality: " + u.VideoQuality);
|
|
||||||
Debug.WriteLine("Audio quality: " + u.AudioQuality);
|
|
||||||
Debug.WriteLine("-----------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(YouTubeUri i in uris)
|
|
||||||
switch(i.VideoQuality)
|
|
||||||
{
|
|
||||||
case YouTubeQuality.Quality2160P:
|
|
||||||
(quality.Items[0] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[0] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.High1080)
|
||||||
case YouTubeQuality.Quality1080P:
|
|
||||||
(quality.Items[1] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[1] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.High720)
|
||||||
case YouTubeQuality.Quality720P:
|
|
||||||
(quality.Items[2] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[2] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.Medium480)
|
||||||
case YouTubeQuality.Quality480P:
|
|
||||||
(quality.Items[3] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[3] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.Medium360)
|
||||||
case YouTubeQuality.Quality360P:
|
|
||||||
(quality.Items[4] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[4] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.Low240)
|
||||||
case YouTubeQuality.Quality240P:
|
|
||||||
(quality.Items[5] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[5] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
if (i.VideoQuality == VideoQuality.Low144)
|
||||||
case YouTubeQuality.Quality144P:
|
|
||||||
(quality.Items[6] as ComboBoxItem).Visibility = Visibility.Visible;
|
(quality.Items[6] as ComboBoxItem).Visibility = Visibility.Visible;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int k = (int)settings.Values["quality"];
|
int k = (int)settings.Values["quality"];
|
||||||
switch(k)
|
if ((quality.Items[k] as ComboBoxItem).Visibility == Visibility.Visible)
|
||||||
|
quality.SelectedIndex = k;
|
||||||
|
else
|
||||||
|
quality.SelectedItem = quality.Items.First(x => (x as ComboBoxItem).Visibility == Visibility.Visible);
|
||||||
|
|
||||||
|
//Loading captions
|
||||||
|
ccInfo = await client.GetVideoClosedCaptionTrackInfosAsync(item.Id);
|
||||||
|
foreach (ClosedCaptionTrackInfo cc in ccInfo)
|
||||||
|
subsLang.Items.Add(new ComboBoxItem()
|
||||||
{
|
{
|
||||||
case 0:
|
Content = string.Format("{1}{0}", CultureInfo.GetCultureInfo(cc.Language.Code).DisplayName, cc.IsAutoGenerated ? " (Auto-generated)" : ""),
|
||||||
foreach(YouTubeUri i in uris)
|
Tag = cc
|
||||||
if(i.VideoQuality == YouTubeQuality.Quality2160P)
|
});
|
||||||
{
|
if(ccInfo.Count > 0)
|
||||||
quality.SelectedIndex = 0;
|
subsLang.SelectedIndex = 0;
|
||||||
break;
|
else
|
||||||
}
|
captionsBtn.Visibility = Visibility.Collapsed;
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality1080P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality720P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality480P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality360P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality240P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 5;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality144P)
|
|
||||||
{
|
|
||||||
quality.SelectedIndex = 6;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SetFirstQuality();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
if(item.ContentDetails.ContentRating != null)
|
if (item.ContentDetails.ContentRating != null)
|
||||||
{
|
{
|
||||||
if(SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
|
if(SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
|
||||||
{
|
{
|
||||||
@@ -261,34 +197,6 @@ namespace FoxTube
|
|||||||
Visibility = Visibility.Visible;
|
Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstQuality()
|
|
||||||
{
|
|
||||||
switch (uris[0].VideoQuality)
|
|
||||||
{
|
|
||||||
case YouTubeQuality.Quality2160P:
|
|
||||||
quality.SelectedIndex = 0;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality1080P:
|
|
||||||
quality.SelectedIndex = 1;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality720P:
|
|
||||||
quality.SelectedIndex = 2;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality480P:
|
|
||||||
quality.SelectedIndex = 3;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality360P:
|
|
||||||
quality.SelectedIndex = 4;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality240P:
|
|
||||||
quality.SelectedIndex = 5;
|
|
||||||
break;
|
|
||||||
case YouTubeQuality.Quality144P:
|
|
||||||
quality.SelectedIndex = 6;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
private async void SystemControls_Engaged(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
|
||||||
{
|
{
|
||||||
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||||
@@ -327,18 +235,15 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Elapsed()
|
void Elapsed()
|
||||||
{
|
|
||||||
if(!volumePane.IsOpen && !qualityPane.IsOpen && !subsPane.IsOpen)
|
|
||||||
{
|
{
|
||||||
controls.Visibility = Visibility.Collapsed;
|
controls.Visibility = Visibility.Collapsed;
|
||||||
if(!miniView)
|
if (!miniView)
|
||||||
touchCentral.Visibility = Visibility.Collapsed;
|
touchCentral.Visibility = Visibility.Collapsed;
|
||||||
if (pointerCaptured)
|
if (pointerCaptured)
|
||||||
Window.Current.CoreWindow.PointerCursor = null;
|
Window.Current.CoreWindow.PointerCursor = null;
|
||||||
seekIndicator.Visibility = Visibility.Collapsed;
|
seekIndicator.Visibility = Visibility.Collapsed;
|
||||||
t.Stop();
|
t.Stop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateSize()
|
public void UpdateSize()
|
||||||
{
|
{
|
||||||
@@ -349,11 +254,6 @@ namespace FoxTube
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openVolume_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
volumePane.IsOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void volume_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
private void volume_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||||
{
|
{
|
||||||
double v = volume.Value;
|
double v = volume.Value;
|
||||||
@@ -373,17 +273,6 @@ namespace FoxTube
|
|||||||
videoSource.Volume = volume.Value * 0.01;
|
videoSource.Volume = volume.Value * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openSets_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
qualityPane.IsOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openSubs_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
subsPane.IsOpen = true;
|
|
||||||
subsSwitch.IsOn = !subsSwitch.IsOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void muteBtn_Click(object sender, RoutedEventArgs e)
|
private void muteBtn_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if(volume.Value != 0)
|
if(volume.Value != 0)
|
||||||
@@ -397,7 +286,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.Mouse)
|
if (e.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch)
|
||||||
{
|
{
|
||||||
touchCentral.Visibility = Visibility.Visible;
|
touchCentral.Visibility = Visibility.Visible;
|
||||||
if (t.Enabled)
|
if (t.Enabled)
|
||||||
@@ -405,7 +294,6 @@ namespace FoxTube
|
|||||||
else
|
else
|
||||||
ShowControls();
|
ShowControls();
|
||||||
}
|
}
|
||||||
//else play_Click(this, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
|
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
|
||||||
@@ -426,91 +314,64 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if(uris.Count > 0)
|
try
|
||||||
{
|
{
|
||||||
videoSource.Pause();
|
videoSource.Pause();
|
||||||
timecodeBackup = videoSource.Position.TotalSeconds;
|
timecodeBackup = videoSource.Position.TotalSeconds;
|
||||||
|
|
||||||
switch(quality.SelectedIndex)
|
switch((quality.SelectedItem as ComboBoxItem).Content)
|
||||||
{
|
{
|
||||||
case 0:
|
case "2160p":
|
||||||
foreach (YouTubeUri i in uris)
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High2160).Url);
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality2160P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
break;
|
||||||
}
|
case "1080p":
|
||||||
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High1080).Url);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case "720p":
|
||||||
foreach (YouTubeUri i in uris)
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High720).Url);
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality1080P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
break;
|
||||||
}
|
case "480p":
|
||||||
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium480).Url);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case "360p":
|
||||||
foreach (YouTubeUri i in uris)
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium360).Url);
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality720P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
break;
|
||||||
}
|
case "240p":
|
||||||
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low240).Url);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case "144p":
|
||||||
foreach (YouTubeUri i in uris)
|
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low144).Url);
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality480P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality360P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality240P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
foreach (YouTubeUri i in uris)
|
|
||||||
if (i.VideoQuality == YouTubeQuality.Quality144P)
|
|
||||||
{
|
|
||||||
videoSource.Source = i.Uri;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
needUpdateTimecode = true;
|
||||||
videoSource.Play();
|
videoSource.Play();
|
||||||
|
|
||||||
Timer timer = new Timer(1000);
|
|
||||||
timer.Elapsed += Timer_Elapsed;
|
|
||||||
timer.Start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
private async void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
}
|
||||||
{
|
|
||||||
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
|
||||||
{
|
|
||||||
(sender as Timer).Stop();
|
|
||||||
videoSource.Position = TimeSpan.FromSeconds(timecodeBackup);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void subsSwitch_Toggled(object sender, RoutedEventArgs e)
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
captions.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fullscreen_Click(object sender, RoutedEventArgs e)
|
private void fullscreen_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -543,6 +404,12 @@ namespace FoxTube
|
|||||||
|
|
||||||
private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e)
|
private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
if(videoSource.CurrentState == MediaElementState.Playing && needUpdateTimecode)
|
||||||
|
{
|
||||||
|
videoSource.Position = TimeSpan.FromSeconds(timecodeBackup);
|
||||||
|
needUpdateTimecode = false;
|
||||||
|
}
|
||||||
|
|
||||||
switch(videoSource.CurrentState)
|
switch(videoSource.CurrentState)
|
||||||
{
|
{
|
||||||
case MediaElementState.Buffering:
|
case MediaElementState.Buffering:
|
||||||
@@ -824,5 +691,11 @@ namespace FoxTube
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void subsLang_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (subsSwitch.IsOn)
|
||||||
|
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Classes\Caption.cs" />
|
||||||
<Compile Include="Classes\InboxItem.cs" />
|
<Compile Include="Classes\InboxItem.cs" />
|
||||||
<Compile Include="Classes\Methods.cs" />
|
<Compile Include="Classes\Methods.cs" />
|
||||||
<Compile Include="Classes\ObjectEventArgs.cs" />
|
<Compile Include="Classes\ObjectEventArgs.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user