Archived
1
0

Closed captions

This commit is contained in:
Michael Gordeev
2018-09-08 23:49:56 +03:00
parent de240c8188
commit cc117a161c
6 changed files with 235 additions and 271 deletions
+26
View File
@@ -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;
}
}
}
+2 -2
View File
@@ -8,9 +8,9 @@
mc:Ignorable="d"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Margin="0,75">
Margin="0,55">
<Grid Background="#99000000">
<TextBlock Text="Hello, World!" Margin="5" FontSize="24"/>
<TextBlock Text="Hello, World!" Name="text" Margin="5" FontSize="24"/>
</Grid>
</UserControl>
+62 -1
View File
@@ -1,4 +1,5 @@
using System;
using FoxTube.Classes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -12,6 +13,8 @@ using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
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
@@ -19,9 +22,67 @@ namespace FoxTube.Controls
{
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()
{
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();
}
}
}
+28 -25
View File
@@ -19,7 +19,7 @@
<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"/>
<controls1:LiveCaptions/>
<controls1:LiveCaptions Player="{x:Bind videoSource}" Visibility="Collapsed"/>
<Grid Name="controls" Visibility="Visible">
<Grid.RowDefinitions>
@@ -36,7 +36,7 @@
<Button Click="minimize_Click" Name="minimize" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE011;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Minimize"/>
<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 Foreground="Gray" Text="[Channel name]" Name="channelName" FontStyle="Italic"/>
<TextBlock Foreground="LightGray" Text="[Channel name]" Name="channelName" FontStyle="Italic"/>
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="closeHeader" Click="close_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE10A;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Close video"/>
@@ -83,14 +83,17 @@
<StackPanel Orientation="Horizontal">
<Button Click="play_Click" Name="play" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE768;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Play"/>
<Button Name="next" Click="next_Click" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE101;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Next video"/>
<Button Name="openVolume" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE995;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Volume" Click="openVolume_Click"/>
</StackPanel>
<Popup Grid.Column="0" Margin="100,-200,50,0" IsOpen="False" IsLightDismissEnabled="True" Name="volumePane">
<StackPanel Background="#7F000000" Width="50" Height="200">
<Slider Orientation="Vertical" HorizontalAlignment="Center" Height="135" Margin="5,10,10,5" Name="volume" ValueChanged="volume_ValueChanged"/>
<Button Name="openVolume" Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE995;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Volume">
<Button.Flyout>
<Flyout>
<StackPanel Orientation="Horizontal" Margin="-10">
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE995;" 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>
</Popup>
<Grid Grid.Column="1">
<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"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE190;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Subtitles" Name="openSubs" Click="openSubs_Click"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality" Name="openSets" Click="openSets_Click"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE740;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Full screen" Name="fullscreen" Click="fullscreen_Click"/>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE190;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Subtitles" Name="captionsBtn">
<Button.Flyout>
<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>
<Popup Grid.Column="2" Margin="0,-100,50,0" IsOpen="False" IsLightDismissEnabled="True" Name="subsPane">
<StackPanel Background="#7F000000" Width="252" Height="100" Padding="10">
<ToggleSwitch Name="subsSwitch" Toggled="subsSwitch_Toggled" Foreground="White" OffContent="Show subtitles" OnContent="Show subtitles"/>
<ComboBox Name="subsLang" Width="232" PlaceholderText="No subtitles are available"/>
</StackPanel>
</Popup>
<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">
</Flyout>
</Button.Flyout>
</Button>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE713;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Video quality">
<Button.Flyout>
<Flyout>
<ComboBox Width="225" Header="Quality" Name="quality" SelectionChanged="quality_SelectionChanged">
<!--<ComboBoxItem Content="Auto"/>-->
<ComboBoxItem Content="2160P" Visibility="Collapsed"/>
<ComboBoxItem Content="1080p" Visibility="Collapsed"/>
@@ -130,8 +130,11 @@
<ComboBoxItem Content="240p" Visibility="Collapsed"/>
<ComboBoxItem Content="144p" Visibility="Collapsed"/>
</ComboBox>
</Flyout>
</Button.Flyout>
</Button>
<Button Background="Transparent" FontFamily="Segoe MDL2 Assets" Content="&#xE740;" Foreground="White" Width="50" Height="50" FontSize="25" ToolTipService.ToolTip="Full screen" Name="fullscreen" Click="fullscreen_Click"/>
</StackPanel>
</Popup>
</Grid>
</Grid>
</Grid>
+90 -217
View File
@@ -20,7 +20,6 @@ using Microsoft.Toolkit.Uwp.UI.Animations;
using Google.Apis.YouTube.v3.Data;
using Google.Apis.YouTube.v3;
using Windows.UI.Xaml.Media.Imaging;
using MyToolkit.Multimedia;
using Windows.Networking.Connectivity;
using System.Diagnostics;
using Windows.Media;
@@ -32,6 +31,10 @@ using Windows.UI;
using Windows.Graphics.Display;
using Windows.Media.Casting;
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
@@ -56,11 +59,15 @@ namespace FoxTube
Video item;
string avatar;
double timecodeBackup;
double timecodeBackup = 0;
bool needUpdateTimecode = false;
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;
Timer t = new Timer()
@@ -81,6 +88,8 @@ namespace FoxTube
if (!ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
miniViewBtn.Visibility = Visibility.Collapsed;;
captions = grid.Children[1] as LiveCaptions;
volume.Value = Convert.ToDouble(settings.Values["volume"]);
videoSource.AutoPlay = (bool)settings.Values["videoAutoplay"];
@@ -94,121 +103,48 @@ namespace FoxTube
avatar = channelAvatar;
videoId = item.Id;
#region Checking qualities availability
uris = new List<YouTubeUri>(await YouTube.GetUrisAsync(videoId));
foreach (YouTubeUri i in uris.ToList())
if (!i.HasAudio || !i.HasVideo)
uris.Remove(i);
foreach (YouTubeUri u in uris)
#region Retrieving info for CC and Media streams
//Loading streams
streamInfo = await client.GetVideoMediaStreamInfosAsync(item.Id);
foreach(MuxedStreamInfo i in streamInfo.Muxed)
{
Debug.WriteLine("-----------------");
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:
if (i.VideoQuality == VideoQuality.High2160)
(quality.Items[0] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality1080P:
if (i.VideoQuality == VideoQuality.High1080)
(quality.Items[1] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality720P:
if (i.VideoQuality == VideoQuality.High720)
(quality.Items[2] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality480P:
if (i.VideoQuality == VideoQuality.Medium480)
(quality.Items[3] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality360P:
if (i.VideoQuality == VideoQuality.Medium360)
(quality.Items[4] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality240P:
if (i.VideoQuality == VideoQuality.Low240)
(quality.Items[5] as ComboBoxItem).Visibility = Visibility.Visible;
break;
case YouTubeQuality.Quality144P:
if (i.VideoQuality == VideoQuality.Low144)
(quality.Items[6] as ComboBoxItem).Visibility = Visibility.Visible;
break;
}
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:
foreach(YouTubeUri i in uris)
if(i.VideoQuality == YouTubeQuality.Quality2160P)
{
quality.SelectedIndex = 0;
break;
}
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;
}
Content = string.Format("{1}{0}", 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 (item.ContentDetails.ContentRating != null)
{
if(SecretsVault.IsAuthorized && settings.Values["showMature"] != null)
{
@@ -261,34 +197,6 @@ namespace FoxTube
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)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
@@ -327,18 +235,15 @@ namespace FoxTube
}
void Elapsed()
{
if(!volumePane.IsOpen && !qualityPane.IsOpen && !subsPane.IsOpen)
{
controls.Visibility = Visibility.Collapsed;
if(!miniView)
if (!miniView)
touchCentral.Visibility = Visibility.Collapsed;
if (pointerCaptured)
Window.Current.CoreWindow.PointerCursor = null;
seekIndicator.Visibility = Visibility.Collapsed;
t.Stop();
}
}
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)
{
double v = volume.Value;
@@ -373,17 +273,6 @@ namespace FoxTube
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)
{
if(volume.Value != 0)
@@ -397,7 +286,7 @@ namespace FoxTube
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;
if (t.Enabled)
@@ -405,7 +294,6 @@ namespace FoxTube
else
ShowControls();
}
//else play_Click(this, null);
}
private void UserControl_PointerMoved(object sender, PointerRoutedEventArgs e)
@@ -426,91 +314,64 @@ namespace FoxTube
private void quality_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(uris.Count > 0)
try
{
videoSource.Pause();
timecodeBackup = videoSource.Position.TotalSeconds;
switch(quality.SelectedIndex)
switch((quality.SelectedItem as ComboBoxItem).Content)
{
case 0:
foreach (YouTubeUri i in uris)
if (i.VideoQuality == YouTubeQuality.Quality2160P)
{
videoSource.Source = i.Uri;
case "2160p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High2160).Url);
break;
}
case "1080p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High1080).Url);
break;
case 1:
foreach (YouTubeUri i in uris)
if (i.VideoQuality == YouTubeQuality.Quality1080P)
{
videoSource.Source = i.Uri;
case "720p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.High720).Url);
break;
}
case "480p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium480).Url);
break;
case 2:
foreach (YouTubeUri i in uris)
if (i.VideoQuality == YouTubeQuality.Quality720P)
{
videoSource.Source = i.Uri;
case "360p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Medium360).Url);
break;
}
case "240p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low240).Url);
break;
case 3:
foreach (YouTubeUri i in uris)
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;
}
case "144p":
videoSource.Source = new Uri(streamInfo.Muxed.First(x => x.VideoQuality == VideoQuality.Low144).Url);
break;
}
needUpdateTimecode = true;
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)
{
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)
@@ -543,6 +404,12 @@ namespace FoxTube
private void videoSource_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if(videoSource.CurrentState == MediaElementState.Playing && needUpdateTimecode)
{
videoSource.Position = TimeSpan.FromSeconds(timecodeBackup);
needUpdateTimecode = false;
}
switch(videoSource.CurrentState)
{
case MediaElementState.Buffering:
@@ -824,5 +691,11 @@ namespace FoxTube
break;
}
}
private void subsLang_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (subsSwitch.IsOn)
captions.Initialize(ccInfo[subsLang.SelectedIndex].Url);
}
}
}
+1
View File
@@ -96,6 +96,7 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Classes\Caption.cs" />
<Compile Include="Classes\InboxItem.cs" />
<Compile Include="Classes\Methods.cs" />
<Compile Include="Classes\ObjectEventArgs.cs" />