1.0-dev10 (Code cleaning)

This commit is contained in:
2022-03-02 22:13:28 +01:00
Unverified
parent 25041f9d43
commit d8eb103dcc
36 changed files with 338 additions and 336 deletions

View File

@@ -1,6 +1,6 @@
namespace VDownload.Core.Enums namespace VDownload.Core.Enums
{ {
public enum VideoStatus public enum TaskStatus
{ {
Idle, Idle,
Waiting, Waiting,

View File

@@ -0,0 +1,8 @@
namespace VDownload.Core.EventArgs
{
public class PlaylistSearchEventArgs : System.EventArgs
{
public string Phrase { get; set; }
public int Count { get; set; }
}
}

View File

@@ -4,13 +4,13 @@ using VDownload.Core.Interfaces;
using VDownload.Core.Objects; using VDownload.Core.Objects;
using Windows.Storage; using Windows.Storage;
namespace VDownload.Core.EventArgsObjects namespace VDownload.Core.EventArgs
{ {
public class VideoAddEventArgs : EventArgs public class VideoAddEventArgs : System.EventArgs
{ {
public IVideoService VideoService { get; set; } public IVideoService VideoService { get; set; }
public MediaType MediaType { get; set; } public MediaType MediaType { get; set; }
public Stream Stream { get; set; } public IBaseStream Stream { get; set; }
public TimeSpan TrimStart { get; set; } public TimeSpan TrimStart { get; set; }
public TimeSpan TrimEnd { get; set; } public TimeSpan TrimEnd { get; set; }
public string Filename { get; set; } public string Filename { get; set; }

View File

@@ -0,0 +1,7 @@
namespace VDownload.Core.EventArgs
{
public class VideoSearchEventArgs : System.EventArgs
{
public string Phrase { get; set; }
}
}

View File

@@ -1,10 +0,0 @@
using System;
namespace VDownload.Core.EventArgsObjects
{
public class PlaylistSearchEventArgs : EventArgs
{
public string Phrase { get; set; }
public int Count { get; set; }
}
}

View File

@@ -1,9 +0,0 @@
using System;
namespace VDownload.Core.EventArgsObjects
{
public class VideoSearchEventArgs : EventArgs
{
public string Phrase { get; set; }
}
}

View File

@@ -1,18 +0,0 @@
using System;
using VDownload.Core.Enums;
namespace VDownload.Core.Interfaces
{
public interface IAStream
{
#region PROPERTIES
Uri Url { get; }
bool IsChunked { get; }
StreamType StreamType { get; }
int AudioBitrate { get; }
string AudioCodec { get; }
#endregion
}
}

View File

@@ -1,19 +1,21 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
namespace VDownload.Core.Interfaces namespace VDownload.Core.Interfaces
{ {
public interface IVStream public interface IBaseStream
{ {
#region PROPERTIES #region PROPERTIES
Uri Url { get; } Uri Url { get; }
bool IsChunked { get; } bool IsChunked { get; }
StreamType StreamType { get; } StreamType StreamType { get; }
int Width { get; }
int Height { get; } int Height { get; }
int FrameRate { get; } int FrameRate { get; }
string VideoCodec { get; }
#endregion #endregion
} }

View File

@@ -7,6 +7,7 @@ namespace VDownload.Core.Interfaces
{ {
#region PROPERTIES #region PROPERTIES
// PLAYLIST PROPERTIES
string ID { get; } string ID { get; }
string Name { get; } string Name { get; }
@@ -16,8 +17,10 @@ namespace VDownload.Core.Interfaces
#region METHODS #region METHODS
// GET PLAYLIST METADATA
Task GetMetadataAsync(CancellationToken cancellationToken = default); Task GetMetadataAsync(CancellationToken cancellationToken = default);
// GET VIDEOS FROM PLAYLIST
Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default); Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default);
#endregion #endregion

View File

@@ -3,7 +3,6 @@ using System.ComponentModel;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using VDownload.Core.Objects;
using Windows.Storage; using Windows.Storage;
namespace VDownload.Core.Interfaces namespace VDownload.Core.Interfaces
@@ -21,7 +20,7 @@ namespace VDownload.Core.Interfaces
TimeSpan Duration { get; } TimeSpan Duration { get; }
long Views { get; } long Views { get; }
Uri Thumbnail { get; } Uri Thumbnail { get; }
Stream[] Streams { get; } IBaseStream[] BaseStreams { get; }
#endregion #endregion
@@ -36,14 +35,7 @@ namespace VDownload.Core.Interfaces
Task GetStreamsAsync(CancellationToken cancellationToken = default); Task GetStreamsAsync(CancellationToken cancellationToken = default);
// DOWNLOAD VIDEO // DOWNLOAD VIDEO
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default); Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IBaseStream baseStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default);
Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default);
#endregion #endregion

View File

@@ -4,7 +4,7 @@ using VDownload.Core.Interfaces;
namespace VDownload.Core.Objects namespace VDownload.Core.Objects
{ {
public class Stream : IVStream, IAStream public class Stream : IBaseStream
{ {
#region CONSTRUCTORS #region CONSTRUCTORS

View File

@@ -1,5 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using Windows.Media.Editing; using Windows.Media.Editing;
using Windows.Storage; using Windows.Storage;

View File

@@ -15,7 +15,7 @@ namespace VDownload.Core.Services
{ {
public class MediaProcessor public class MediaProcessor
{ {
#region CONSTRUCTOR #region CONSTRUCTORS
public MediaProcessor(StorageFile outputFile, TimeSpan trimStart, TimeSpan trimEnd) public MediaProcessor(StorageFile outputFile, TimeSpan trimStart, TimeSpan trimEnd)
{ {
@@ -40,10 +40,11 @@ namespace VDownload.Core.Services
#region STANDARD METHODS #region STANDARD METHODS
// SINGLE AUDIO & VIDEO FILE PROCESSING
public async Task Run(StorageFile audioVideoInputFile, MediaFileExtension extension, MediaType mediaType, CancellationToken cancellationToken = default) public async Task Run(StorageFile audioVideoInputFile, MediaFileExtension extension, MediaType mediaType, CancellationToken cancellationToken = default)
{ {
// Invoke ProcessingStarted event // Invoke ProcessingStarted event
ProcessingStarted?.Invoke(this, EventArgs.Empty); ProcessingStarted?.Invoke(this, System.EventArgs.Empty);
// Init transcoder // Init transcoder
MediaTranscoder mediaTranscoder = new MediaTranscoder MediaTranscoder mediaTranscoder = new MediaTranscoder
@@ -55,31 +56,31 @@ namespace VDownload.Core.Services
}; };
// Start transcoding operation // Start transcoding operation
cancellationToken.ThrowIfCancellationRequested();
using (IRandomAccessStream outputFileOpened = await OutputFile.OpenAsync(FileAccessMode.ReadWrite)) using (IRandomAccessStream outputFileOpened = await OutputFile.OpenAsync(FileAccessMode.ReadWrite))
{ {
PrepareTranscodeResult transcodingPreparated = await mediaTranscoder.PrepareStreamTranscodeAsync(await audioVideoInputFile.OpenAsync(FileAccessMode.Read), outputFileOpened, await GetMediaEncodingProfile(audioVideoInputFile, extension, mediaType)); PrepareTranscodeResult transcodingPreparated = await mediaTranscoder.PrepareStreamTranscodeAsync(await audioVideoInputFile.OpenAsync(FileAccessMode.Read), outputFileOpened, await GetMediaEncodingProfile(audioVideoInputFile, extension, mediaType));
IAsyncActionWithProgress<double> transcodingTask = transcodingPreparated.TranscodeAsync(); IAsyncActionWithProgress<double> transcodingTask = transcodingPreparated.TranscodeAsync();
try await transcodingTask.AsTask(cancellationToken, new Progress<double>((percent) => { ProcessingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(percent), null)); }));
{ await outputFileOpened.FlushAsync();
await transcodingTask.AsTask(cancellationToken, new Progress<double>((percent) => { ProcessingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(percent), null)); }));
await outputFileOpened.FlushAsync();
}
catch (TaskCanceledException) { }
transcodingTask.Close(); transcodingTask.Close();
} }
// Invoke ProcessingCompleted event // Invoke ProcessingCompleted event
ProcessingCompleted?.Invoke(this, EventArgs.Empty); ProcessingCompleted?.Invoke(this, System.EventArgs.Empty);
} }
// SEPARATE AUDIO & VIDEO FILES PROCESSING
public async Task Run(StorageFile audioFile, StorageFile videoFile, VideoFileExtension extension, CancellationToken cancellationToken = default) public async Task Run(StorageFile audioFile, StorageFile videoFile, VideoFileExtension extension, CancellationToken cancellationToken = default)
{ {
// Invoke ProcessingStarted event // Invoke ProcessingStarted event
ProcessingStarted?.Invoke(this, EventArgs.Empty); ProcessingStarted?.Invoke(this, System.EventArgs.Empty);
// Init editor // Init editor
MediaComposition mediaEditor = new MediaComposition(); MediaComposition mediaEditor = new MediaComposition();
// Add media files // Add media files
cancellationToken.ThrowIfCancellationRequested();
Task<MediaClip> getVideoFileTask = MediaClip.CreateFromFileAsync(videoFile).AsTask(); Task<MediaClip> getVideoFileTask = MediaClip.CreateFromFileAsync(videoFile).AsTask();
Task<BackgroundAudioTrack> getAudioFileTask = BackgroundAudioTrack.CreateFromFileAsync(audioFile).AsTask(); Task<BackgroundAudioTrack> getAudioFileTask = BackgroundAudioTrack.CreateFromFileAsync(audioFile).AsTask();
await Task.WhenAll(getVideoFileTask, getAudioFileTask); await Task.WhenAll(getVideoFileTask, getAudioFileTask);
@@ -97,11 +98,14 @@ namespace VDownload.Core.Services
// Start rendering operation // Start rendering operation
var renderOperation = mediaEditor.RenderToFileAsync(OutputFile, (MediaTrimmingPreference)Config.GetValue("media_editing_algorithm"), await GetMediaEncodingProfile(videoFile, audioFile, (MediaFileExtension)extension, MediaType.AudioVideo)); var renderOperation = mediaEditor.RenderToFileAsync(OutputFile, (MediaTrimmingPreference)Config.GetValue("media_editing_algorithm"), await GetMediaEncodingProfile(videoFile, audioFile, (MediaFileExtension)extension, MediaType.AudioVideo));
renderOperation.Progress += (info, progress) => { ProcessingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(progress), null)); }; renderOperation.Progress += (info, progress) => { ProcessingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(progress), null)); };
cancellationToken.ThrowIfCancellationRequested();
await renderOperation.AsTask(cancellationToken); await renderOperation.AsTask(cancellationToken);
// Invoke ProcessingCompleted event // Invoke ProcessingCompleted event
ProcessingCompleted?.Invoke(this, EventArgs.Empty); ProcessingCompleted?.Invoke(this, System.EventArgs.Empty);
} }
// SINGLE AUDIO OR VIDEO FILES PROCESSING
public async Task Run(StorageFile audioFile, AudioFileExtension extension, CancellationToken cancellationToken = default) { await Run(audioFile, (MediaFileExtension)extension, MediaType.OnlyAudio, cancellationToken); } public async Task Run(StorageFile audioFile, AudioFileExtension extension, CancellationToken cancellationToken = default) { await Run(audioFile, (MediaFileExtension)extension, MediaType.OnlyAudio, cancellationToken); }
public async Task Run(StorageFile videoFile, VideoFileExtension extension, CancellationToken cancellationToken = default) { await Run(videoFile, (MediaFileExtension)extension, MediaType.OnlyVideo, cancellationToken); } public async Task Run(StorageFile videoFile, VideoFileExtension extension, CancellationToken cancellationToken = default) { await Run(videoFile, (MediaFileExtension)extension, MediaType.OnlyVideo, cancellationToken); }

View File

@@ -1,9 +1,4 @@
using System; using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
namespace VDownload.Core.Services namespace VDownload.Core.Services
@@ -12,6 +7,7 @@ namespace VDownload.Core.Services
{ {
#region CONSTANTS #region CONSTANTS
// VIDEO SOURCES REGULAR EXPRESSIONS
private static readonly (Regex Regex, VideoSource Type)[] VideoSources = new (Regex Regex, VideoSource Type)[] private static readonly (Regex Regex, VideoSource Type)[] VideoSources = new (Regex Regex, VideoSource Type)[]
{ {
(new Regex(@"^https://www.twitch.tv/videos/(?<id>\d+)"), VideoSource.TwitchVod), (new Regex(@"^https://www.twitch.tv/videos/(?<id>\d+)"), VideoSource.TwitchVod),
@@ -19,6 +15,7 @@ namespace VDownload.Core.Services
(new Regex(@"^https://clips.twitch.tv/(?<id>[^?]+)"), VideoSource.TwitchClip), (new Regex(@"^https://clips.twitch.tv/(?<id>[^?]+)"), VideoSource.TwitchClip),
}; };
// PLAYLIST SOURCES REGULAR EXPRESSIONS
private static readonly (Regex Regex, PlaylistSource Type)[] PlaylistSources = new (Regex Regex, PlaylistSource Type)[] private static readonly (Regex Regex, PlaylistSource Type)[] PlaylistSources = new (Regex Regex, PlaylistSource Type)[]
{ {
(new Regex(@"^https://www.twitch.tv/(?<id>[^?]+)"), PlaylistSource.TwitchChannel), (new Regex(@"^https://www.twitch.tv/(?<id>[^?]+)"), PlaylistSource.TwitchChannel),
@@ -30,6 +27,7 @@ namespace VDownload.Core.Services
#region METHODS #region METHODS
// GET VIDEO SOURCE
public static (VideoSource Type, string ID) GetVideoSource(string url) public static (VideoSource Type, string ID) GetVideoSource(string url)
{ {
foreach ((Regex Regex, VideoSource Type) Source in VideoSources) foreach ((Regex Regex, VideoSource Type) Source in VideoSources)
@@ -40,6 +38,7 @@ namespace VDownload.Core.Services
return (VideoSource.Null, null); return (VideoSource.Null, null);
} }
// GET PLAYLIST SOURCE
public static (PlaylistSource Type, string ID) GetPlaylistSource(string url) public static (PlaylistSource Type, string ID) GetPlaylistSource(string url)
{ {
foreach ((Regex Regex, PlaylistSource Type) Source in PlaylistSources) foreach ((Regex Regex, PlaylistSource Type) Source in PlaylistSources)

View File

@@ -65,7 +65,7 @@ namespace VDownload.Core.Services.Sources.Twitch
StorageFile authDataFile = await authDataFolder.CreateFileAsync("Twitch.auth", CreationCollisionOption.ReplaceExisting); StorageFile authDataFile = await authDataFolder.CreateFileAsync("Twitch.auth", CreationCollisionOption.ReplaceExisting);
// Save data // Save data
FileIO.WriteTextAsync(authDataFile, accessToken); await FileIO.WriteTextAsync(authDataFile, accessToken);
} }
// DELETE ACCESS TOKEN // DELETE ACCESS TOKEN

View File

@@ -40,14 +40,13 @@ namespace VDownload.Core.Services.Sources.Twitch
// GET CHANNEL METADATA // GET CHANNEL METADATA
public async Task GetMetadataAsync(CancellationToken cancellationToken = default) public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Get access token // Get access token
cancellationToken.ThrowIfCancellationRequested();
string accessToken = await Auth.ReadAccessTokenAsync(); string accessToken = await Auth.ReadAccessTokenAsync();
if (accessToken == null) throw new TwitchAccessTokenNotFoundException(); if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
// Check access token // Check access token
cancellationToken.ThrowIfCancellationRequested();
var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken); var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken);
if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException(); if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException();
@@ -58,6 +57,7 @@ namespace VDownload.Core.Services.Sources.Twitch
// Get response // Get response
client.QueryString.Add("login", ID); client.QueryString.Add("login", ID);
cancellationToken.ThrowIfCancellationRequested();
JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/users"))["data"][0]; JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/users"))["data"][0];
// Set parameters // Set parameters
@@ -68,10 +68,8 @@ namespace VDownload.Core.Services.Sources.Twitch
// GET CHANNEL VIDEOS // GET CHANNEL VIDEOS
public async Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default) public async Task GetVideosAsync(int numberOfVideos, CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Get access token // Get access token
cancellationToken.ThrowIfCancellationRequested();
string accessToken = await Auth.ReadAccessTokenAsync(); string accessToken = await Auth.ReadAccessTokenAsync();
if (accessToken == null) throw new TwitchAccessTokenNotFoundException(); if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
@@ -88,6 +86,7 @@ namespace VDownload.Core.Services.Sources.Twitch
do do
{ {
// Check access token // Check access token
cancellationToken.ThrowIfCancellationRequested();
var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken); var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken);
if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException(); if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException();
@@ -104,6 +103,7 @@ namespace VDownload.Core.Services.Sources.Twitch
client.QueryString.Add("first", count.ToString()); client.QueryString.Add("first", count.ToString());
client.QueryString.Add("after", pagination); client.QueryString.Add("after", pagination);
cancellationToken.ThrowIfCancellationRequested();
JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos")); JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos"));
pagination = (string)response["pagination"]["cursor"]; pagination = (string)response["pagination"]["cursor"];

View File

@@ -48,7 +48,7 @@ namespace VDownload.Core.Services.Sources.Twitch
public TimeSpan Duration { get; private set; } public TimeSpan Duration { get; private set; }
public long Views { get; private set; } public long Views { get; private set; }
public Uri Thumbnail { get; private set; } public Uri Thumbnail { get; private set; }
public Stream[] Streams { get; private set; } public IBaseStream[] BaseStreams { get; private set; }
#endregion #endregion
@@ -59,14 +59,13 @@ namespace VDownload.Core.Services.Sources.Twitch
// GET CLIP METADATA // GET CLIP METADATA
public async Task GetMetadataAsync(CancellationToken cancellationToken = default) public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Get access token // Get access token
cancellationToken.ThrowIfCancellationRequested();
string accessToken = await Auth.ReadAccessTokenAsync(); string accessToken = await Auth.ReadAccessTokenAsync();
if (accessToken == null) throw new TwitchAccessTokenNotFoundException(); if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
// Check access token // Check access token
cancellationToken.ThrowIfCancellationRequested();
var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken); var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken);
if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException(); if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException();
@@ -93,14 +92,12 @@ namespace VDownload.Core.Services.Sources.Twitch
public async Task GetStreamsAsync(CancellationToken cancellationToken = default) public async Task GetStreamsAsync(CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Create client // Create client
WebClient client = new WebClient { Encoding = Encoding.UTF8 }; WebClient client = new WebClient { Encoding = Encoding.UTF8 };
client.Headers.Add("Client-ID", Auth.GQLApiClientID); client.Headers.Add("Client-ID", Auth.GQLApiClientID);
// Get video streams // Get video streams
cancellationToken.ThrowIfCancellationRequested();
JToken[] response = JArray.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "[{\"operationName\":\"VideoAccessToken_Clip\",\"variables\":{\"slug\":\"" + ID + "\"},\"extensions\":{\"persistedQuery\":{\"version\":1,\"sha256Hash\":\"36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11\"}}}]"))[0]["data"]["clip"]["videoQualities"].ToArray(); JToken[] response = JArray.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "[{\"operationName\":\"VideoAccessToken_Clip\",\"variables\":{\"slug\":\"" + ID + "\"},\"extensions\":{\"persistedQuery\":{\"version\":1,\"sha256Hash\":\"36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11\"}}}]"))[0]["data"]["clip"]["videoQualities"].ToArray();
// Init streams list // Init streams list
@@ -126,60 +123,55 @@ namespace VDownload.Core.Services.Sources.Twitch
} }
// Set Streams parameter // Set Streams parameter
Streams = streams.ToArray(); BaseStreams = streams.ToArray();
} }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IBaseStream baseStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Invoke DownloadingStarted event // Invoke DownloadingStarted event
DownloadingStarted?.Invoke(this, EventArgs.Empty); DownloadingStarted?.Invoke(this, System.EventArgs.Empty);
// Create client // Create client
WebClient client = new WebClient(); WebClient client = new WebClient();
client.Headers.Add("Client-Id", Auth.GQLApiClientID); client.Headers.Add("Client-Id", Auth.GQLApiClientID);
// Get video GQL access token // Get video GQL access token
cancellationToken.ThrowIfCancellationRequested();
JToken videoAccessToken = JArray.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "[{\"operationName\":\"VideoAccessToken_Clip\",\"variables\":{\"slug\":\"" + ID + "\"},\"extensions\":{\"persistedQuery\":{\"version\":1,\"sha256Hash\":\"36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11\"}}}]"))[0]["data"]["clip"]["playbackAccessToken"]; JToken videoAccessToken = JArray.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "[{\"operationName\":\"VideoAccessToken_Clip\",\"variables\":{\"slug\":\"" + ID + "\"},\"extensions\":{\"persistedQuery\":{\"version\":1,\"sha256Hash\":\"36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11\"}}}]"))[0]["data"]["clip"]["playbackAccessToken"];
// Download // Download
cancellationToken.ThrowIfCancellationRequested();
StorageFile rawFile = await downloadingFolder.CreateFileAsync("raw.mp4"); StorageFile rawFile = await downloadingFolder.CreateFileAsync("raw.mp4");
using (client = new WebClient()) using (client = new WebClient())
{ {
client.DownloadProgressChanged += (s, a) => { DownloadingProgressChanged(this, new ProgressChangedEventArgs(a.ProgressPercentage, null)); }; client.DownloadProgressChanged += (s, a) => { DownloadingProgressChanged(this, new ProgressChangedEventArgs(a.ProgressPercentage, null)); };
client.QueryString.Add("sig", (string)videoAccessToken["signature"]); client.QueryString.Add("sig", (string)videoAccessToken["signature"]);
client.QueryString.Add("token", HttpUtility.UrlEncode((string)videoAccessToken["value"])); client.QueryString.Add("token", HttpUtility.UrlEncode((string)videoAccessToken["value"]));
cancellationToken.ThrowIfCancellationRequested();
using (cancellationToken.Register(client.CancelAsync)) using (cancellationToken.Register(client.CancelAsync))
{ {
await client.DownloadFileTaskAsync(audioVideoStream.Url, rawFile.Path); await client.DownloadFileTaskAsync(baseStream.Url, rawFile.Path);
} }
} }
DownloadingCompleted?.Invoke(this, EventArgs.Empty); DownloadingCompleted?.Invoke(this, System.EventArgs.Empty);
// Processing // Processing
StorageFile outputFile = rawFile; StorageFile outputFile = rawFile;
if (extension != MediaFileExtension.MP4 || mediaType != MediaType.AudioVideo || trimStart > new TimeSpan(0) || trimEnd < Duration) if (extension != MediaFileExtension.MP4 || mediaType != MediaType.AudioVideo || trimStart > new TimeSpan(0) || trimEnd < Duration)
{ {
cancellationToken.ThrowIfCancellationRequested();
outputFile = await downloadingFolder.CreateFileAsync($"transcoded.{extension.ToString().ToLower()}"); outputFile = await downloadingFolder.CreateFileAsync($"transcoded.{extension.ToString().ToLower()}");
MediaProcessor mediaProcessor = new MediaProcessor(outputFile, trimStart, trimEnd); MediaProcessor mediaProcessor = new MediaProcessor(outputFile, trimStart, trimEnd);
mediaProcessor.ProcessingStarted += ProcessingStarted; mediaProcessor.ProcessingStarted += ProcessingStarted;
mediaProcessor.ProcessingProgressChanged += ProcessingProgressChanged; mediaProcessor.ProcessingProgressChanged += ProcessingProgressChanged;
mediaProcessor.ProcessingCompleted += ProcessingCompleted; mediaProcessor.ProcessingCompleted += ProcessingCompleted;
cancellationToken.ThrowIfCancellationRequested();
await mediaProcessor.Run(rawFile, extension, mediaType, cancellationToken); await mediaProcessor.Run(rawFile, extension, mediaType, cancellationToken);
} }
// Return output file // Return output file
return outputFile; return outputFile;
} }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioVideoStream, extension, mediaType, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch Clip download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioStream, videoStream, extension, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch Clip download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioStream, extension, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch Clip download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, videoStream, extension, new TimeSpan(0), Duration, cancellationToken); }
#endregion #endregion

View File

@@ -2,7 +2,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -51,7 +50,7 @@ namespace VDownload.Core.Services.Sources.Twitch
public TimeSpan Duration { get; private set; } public TimeSpan Duration { get; private set; }
public long Views { get; private set; } public long Views { get; private set; }
public Uri Thumbnail { get; private set; } public Uri Thumbnail { get; private set; }
public Stream[] Streams { get; private set; } public IBaseStream[] BaseStreams { get; private set; }
#endregion #endregion
@@ -62,14 +61,13 @@ namespace VDownload.Core.Services.Sources.Twitch
// GET VOD METADATA // GET VOD METADATA
public async Task GetMetadataAsync(CancellationToken cancellationToken = default) public async Task GetMetadataAsync(CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Get access token // Get access token
cancellationToken.ThrowIfCancellationRequested();
string accessToken = await Auth.ReadAccessTokenAsync(); string accessToken = await Auth.ReadAccessTokenAsync();
if (accessToken == null) throw new TwitchAccessTokenNotFoundException(); if (accessToken == null) throw new TwitchAccessTokenNotFoundException();
// Check access token // Check access token
cancellationToken.ThrowIfCancellationRequested();
var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken); var twitchAccessTokenValidation = await Auth.ValidateAccessTokenAsync(accessToken);
if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException(); if (!twitchAccessTokenValidation.IsValid) throw new TwitchAccessTokenNotValidException();
@@ -80,6 +78,7 @@ namespace VDownload.Core.Services.Sources.Twitch
// Get response // Get response
client.QueryString.Add("id", ID); client.QueryString.Add("id", ID);
cancellationToken.ThrowIfCancellationRequested();
JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos")).GetValue("data")[0]; JToken response = JObject.Parse(await client.DownloadStringTaskAsync("https://api.twitch.tv/helix/videos")).GetValue("data")[0];
// Set parameters // Set parameters
@@ -102,17 +101,16 @@ namespace VDownload.Core.Services.Sources.Twitch
// GET VOD STREAMS // GET VOD STREAMS
public async Task GetStreamsAsync(CancellationToken cancellationToken = default) public async Task GetStreamsAsync(CancellationToken cancellationToken = default)
{ {
// Set cancellation token
cancellationToken.ThrowIfCancellationRequested();
// Create client // Create client
WebClient client = new WebClient(); WebClient client = new WebClient();
client.Headers.Add("Client-Id", Auth.GQLApiClientID); client.Headers.Add("Client-Id", Auth.GQLApiClientID);
// Get video GQL access token // Get video GQL access token
cancellationToken.ThrowIfCancellationRequested();
JToken videoAccessToken = JObject.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "{\"operationName\":\"PlaybackAccessToken_Template\",\"query\":\"query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: \\\"web\\\", playerBackend: \\\"mediaplayer\\\", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: \\\"web\\\", playerBackend: \\\"mediaplayer\\\", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}\",\"variables\":{\"isLive\":false,\"login\":\"\",\"isVod\":true,\"vodID\":\"" + ID + "\",\"playerType\":\"embed\"}}"))["data"]["videoPlaybackAccessToken"]; JToken videoAccessToken = JObject.Parse(await client.UploadStringTaskAsync("https://gql.twitch.tv/gql", "{\"operationName\":\"PlaybackAccessToken_Template\",\"query\":\"query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, $isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, params: {platform: \\\"web\\\", playerBackend: \\\"mediaplayer\\\", playerType: $playerType}) @include(if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, params: {platform: \\\"web\\\", playerBackend: \\\"mediaplayer\\\", playerType: $playerType}) @include(if: $isVod) { value signature __typename }}\",\"variables\":{\"isLive\":false,\"login\":\"\",\"isVod\":true,\"vodID\":\"" + ID + "\",\"playerType\":\"embed\"}}"))["data"]["videoPlaybackAccessToken"];
// Get video streams // Get video streams
cancellationToken.ThrowIfCancellationRequested();
string[] response = (await client.DownloadStringTaskAsync($"http://usher.twitch.tv/vod/{ID}?nauth={videoAccessToken["value"]}&nauthsig={videoAccessToken["signature"]}&allow_source=true&player=twitchweb")).Split("\n"); string[] response = (await client.DownloadStringTaskAsync($"http://usher.twitch.tv/vod/{ID}?nauth={videoAccessToken["value"]}&nauthsig={videoAccessToken["signature"]}&allow_source=true&player=twitchweb")).Split("\n");
// Init streams list // Init streams list
@@ -147,74 +145,64 @@ namespace VDownload.Core.Services.Sources.Twitch
} }
// Set Streams parameter // Set Streams parameter
Streams = streams.ToArray(); BaseStreams = streams.ToArray();
} }
// DOWNLOAD AND TRANSCODE VOD // DOWNLOAD AND TRANSCODE VOD
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IBaseStream baseStream, MediaFileExtension extension, MediaType mediaType, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default)
{ {
// Invoke DownloadingStarted event // Invoke DownloadingStarted event
if (!cancellationToken.IsCancellationRequested) DownloadingStarted?.Invoke(this, EventArgs.Empty); DownloadingStarted?.Invoke(this, System.EventArgs.Empty);
// Get video chunks // Get video chunks
List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunksList = null; cancellationToken.ThrowIfCancellationRequested();
if (!cancellationToken.IsCancellationRequested) chunksList = await ExtractChunksFromM3U8Async(audioVideoStream.Url); List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunksList = await ExtractChunksFromM3U8Async(baseStream.Url, cancellationToken);
// Passive trim // Passive trim
if ((bool)Config.GetValue("twitch_vod_passive_trim")) (trimStart, trimEnd) = PassiveVideoTrim(chunksList, trimStart, trimEnd, Duration); if ((bool)Config.GetValue("twitch_vod_passive_trim")) (trimStart, trimEnd) = PassiveVideoTrim(chunksList, trimStart, trimEnd, Duration);
// Download // Download
StorageFile rawFile = null; cancellationToken.ThrowIfCancellationRequested();
if (!cancellationToken.IsCancellationRequested) StorageFile rawFile = await downloadingFolder.CreateFileAsync("raw.ts");
float chunksDownloaded = 0;
Task<byte[]> downloadTask;
Task writeTask;
cancellationToken.ThrowIfCancellationRequested();
downloadTask = DownloadChunkAsync(chunksList[0].ChunkUrl);
await downloadTask;
for (int i = 1; i < chunksList.Count; i++)
{ {
rawFile = await downloadingFolder.CreateFileAsync("raw.ts"); cancellationToken.ThrowIfCancellationRequested();
float chunksDownloaded = 0; writeTask = WriteChunkToFileAsync(rawFile, downloadTask.Result);
downloadTask = DownloadChunkAsync(chunksList[i].ChunkUrl);
Task<byte[]> downloadTask; await Task.WhenAll(writeTask, downloadTask);
Task writeTask; DownloadingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(++chunksDownloaded * 100 / chunksList.Count), null));
downloadTask = DownloadChunkAsync(chunksList[0].ChunkUrl);
await downloadTask;
for (int i = 1; i < chunksList.Count && !cancellationToken.IsCancellationRequested; i++)
{
writeTask = WriteChunkToFileAsync(rawFile, downloadTask.Result);
downloadTask = DownloadChunkAsync(chunksList[i].ChunkUrl);
await Task.WhenAll(writeTask, downloadTask);
DownloadingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(++chunksDownloaded * 100 / chunksList.Count), null));
}
if (!cancellationToken.IsCancellationRequested)
{
await WriteChunkToFileAsync(rawFile, downloadTask.Result);
DownloadingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(++chunksDownloaded * 100 / chunksList.Count), null));
DownloadingCompleted?.Invoke(this, EventArgs.Empty);
}
} }
cancellationToken.ThrowIfCancellationRequested();
await WriteChunkToFileAsync(rawFile, downloadTask.Result);
DownloadingProgressChanged(this, new ProgressChangedEventArgs((int)Math.Round(++chunksDownloaded * 100 / chunksList.Count), null));
DownloadingCompleted?.Invoke(this, System.EventArgs.Empty);
// Processing // Processing
StorageFile outputFile = null; cancellationToken.ThrowIfCancellationRequested();
if (!cancellationToken.IsCancellationRequested) StorageFile outputFile = await downloadingFolder.CreateFileAsync($"transcoded.{extension.ToString().ToLower()}");
{
outputFile = await downloadingFolder.CreateFileAsync($"transcoded.{extension.ToString().ToLower()}"); MediaProcessor mediaProcessor = new MediaProcessor(outputFile, trimStart, trimEnd);
mediaProcessor.ProcessingStarted += ProcessingStarted;
mediaProcessor.ProcessingProgressChanged += ProcessingProgressChanged;
mediaProcessor.ProcessingCompleted += ProcessingCompleted;
cancellationToken.ThrowIfCancellationRequested();
await mediaProcessor.Run(rawFile, extension, mediaType, cancellationToken);
MediaProcessor mediaProcessor = new MediaProcessor(outputFile, trimStart, trimEnd);
mediaProcessor.ProcessingStarted += ProcessingStarted;
mediaProcessor.ProcessingProgressChanged += ProcessingProgressChanged;
mediaProcessor.ProcessingCompleted += ProcessingCompleted;
await mediaProcessor.Run(rawFile, extension, mediaType, cancellationToken);
}
// Return output file // Return output file
return outputFile; return outputFile;
} }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, Stream audioVideoStream, MediaFileExtension extension, MediaType mediaType, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioVideoStream, extension, mediaType, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch VOD download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioStream, videoStream, extension, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch VOD download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IAStream audioStream, AudioFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, audioStream, extension, new TimeSpan(0), Duration, cancellationToken); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, TimeSpan trimStart, TimeSpan trimEnd, CancellationToken cancellationToken = default) { throw new NotImplementedException("Twitch VOD download service doesn't support separate video and audio streams"); }
public async Task<StorageFile> DownloadAndTranscodeAsync(StorageFolder downloadingFolder, IVStream videoStream, VideoFileExtension extension, CancellationToken cancellationToken = default) { return await DownloadAndTranscodeAsync(downloadingFolder, videoStream, extension, new TimeSpan(0), Duration, cancellationToken); }
#endregion #endregion
@@ -223,14 +211,16 @@ namespace VDownload.Core.Services.Sources.Twitch
#region LOCAL METHODS #region LOCAL METHODS
// GET CHUNKS DATA FROM M3U8 PLAYLIST // GET CHUNKS DATA FROM M3U8 PLAYLIST
private static async Task<List<(Uri ChunkUrl, TimeSpan ChunkDuration)>> ExtractChunksFromM3U8Async(Uri streamUrl) private static async Task<List<(Uri ChunkUrl, TimeSpan ChunkDuration)>> ExtractChunksFromM3U8Async(Uri streamUrl, CancellationToken cancellationToken = default)
{ {
// Create client // Create client
WebClient client = new WebClient(); WebClient client = new WebClient();
client.Headers.Add("Client-Id", Auth.GQLApiClientID); client.Headers.Add("Client-Id", Auth.GQLApiClientID);
// Get playlist // Get playlist
cancellationToken.ThrowIfCancellationRequested();
string response = await client.DownloadStringTaskAsync(streamUrl); string response = await client.DownloadStringTaskAsync(streamUrl);
// Create dictionary // Create dictionary
List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunks = new List<(Uri ChunkUrl, TimeSpan ChunkDuration)>(); List<(Uri ChunkUrl, TimeSpan ChunkDuration)> chunks = new List<(Uri ChunkUrl, TimeSpan ChunkDuration)>();
@@ -273,11 +263,12 @@ namespace VDownload.Core.Services.Sources.Twitch
} }
// DOWNLOAD CHUNK // DOWNLOAD CHUNK
private static async Task<byte[]> DownloadChunkAsync(Uri chunkUrl) private static async Task<byte[]> DownloadChunkAsync(Uri chunkUrl, CancellationToken cancellationToken = default)
{ {
int retriesCount = 0; int retriesCount = 0;
while ((bool)Config.GetValue("twitch_vod_downloading_chunk_retry_after_error") && retriesCount < (int)Config.GetValue("twitch_vod_downloading_chunk_max_retries")) while ((bool)Config.GetValue("twitch_vod_downloading_chunk_retry_after_error") && retriesCount < (int)Config.GetValue("twitch_vod_downloading_chunk_max_retries"))
{ {
cancellationToken.ThrowIfCancellationRequested();
try try
{ {
using (WebClient client = new WebClient()) using (WebClient client = new WebClient())

View File

@@ -1,38 +1,56 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VDownload.Core.Services namespace VDownload.Core.Services
{ {
public class TaskId public class TaskId
{ {
// VARIABLES #region CONSTANTS
// RANDOM
private static readonly Random Random = new Random(); private static readonly Random Random = new Random();
private static readonly char[] CharsID = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
private static readonly int LengthID = 10; // ID SETTINGS
private static readonly char[] IDChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
private static readonly int IDLength = 10;
#endregion
#region PROPERTIES
// USED IDS LIST
private static readonly List<string> UsedIDs = new List<string>(); private static readonly List<string> UsedIDs = new List<string>();
// METHOD #endregion
#region METHODS
// GET TASK ID
public static string Get() public static string Get()
{ {
string id; string id;
do do
{ {
id = ""; id = "";
while (id.Length < LengthID) while (id.Length < IDLength)
{ {
id += CharsID[Random.Next(0, CharsID.Length)]; id += IDChars[Random.Next(0, IDChars.Length)];
} }
} while (UsedIDs.Contains(id)); } while (UsedIDs.Contains(id));
UsedIDs.Add(id); UsedIDs.Add(id);
return id; return id;
} }
// DISPOSE TASK ID
public static void Dispose(string id) public static void Dispose(string id)
{ {
UsedIDs.Remove(id); UsedIDs.Remove(id);
} }
#endregion
} }
} }

View File

@@ -127,16 +127,15 @@
<Compile Include="Enums\StreamType.cs" /> <Compile Include="Enums\StreamType.cs" />
<Compile Include="Enums\VideoFileExtension.cs" /> <Compile Include="Enums\VideoFileExtension.cs" />
<Compile Include="Enums\VideoSource.cs" /> <Compile Include="Enums\VideoSource.cs" />
<Compile Include="Enums\VideoStatus.cs" /> <Compile Include="Enums\TaskStatus.cs" />
<Compile Include="EventArgsObjects\VideoAddEventArgs.cs" /> <Compile Include="EventArgs\VideoAddEventArgs.cs" />
<Compile Include="EventArgsObjects\VideoSearchEventArgs.cs" /> <Compile Include="EventArgs\VideoSearchEventArgs.cs" />
<Compile Include="EventArgsObjects\PlaylistSearchEventArgs.cs" /> <Compile Include="EventArgs\PlaylistSearchEventArgs.cs" />
<Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" /> <Compile Include="Exceptions\TwitchAccessTokenNotFoundException.cs" />
<Compile Include="Exceptions\TwitchAccessTokenNotValidException.cs" /> <Compile Include="Exceptions\TwitchAccessTokenNotValidException.cs" />
<Compile Include="Interfaces\IAStream.cs" /> <Compile Include="Interfaces\IBaseStream.cs" />
<Compile Include="Interfaces\IPlaylistService.cs" /> <Compile Include="Interfaces\IPlaylistService.cs" />
<Compile Include="Interfaces\IVideoService.cs" /> <Compile Include="Interfaces\IVideoService.cs" />
<Compile Include="Interfaces\IVStream.cs" />
<Compile Include="Objects\Stream.cs" /> <Compile Include="Objects\Stream.cs" />
<Compile Include="Services\Config.cs" /> <Compile Include="Services\Config.cs" />
<Compile Include="Services\MediaProcessor.cs" /> <Compile Include="Services\MediaProcessor.cs" />

View File

@@ -11,18 +11,27 @@ using Windows.Storage;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using System.Diagnostics; using Windows.Storage.AccessCache;
namespace VDownload namespace VDownload
{ {
sealed partial class App : Application sealed partial class App : Application
{ {
#region CONSTRUCTORS
public App() public App()
{ {
InitializeComponent(); InitializeComponent();
Suspending += OnSuspending; Suspending += OnSuspending;
} }
#endregion
#region EVENT HANDLERS VOIDS
// ON LAUNCHED
protected override async void OnLaunched(LaunchActivatedEventArgs e) protected override async void OnLaunched(LaunchActivatedEventArgs e)
{ {
// Rebuild configuration file // Rebuild configuration file
@@ -31,7 +40,12 @@ namespace VDownload
// Delete temp on start // Delete temp on start
if ((bool)Config.GetValue("delete_temp_on_start")) if ((bool)Config.GetValue("delete_temp_on_start"))
{ {
IReadOnlyList<IStorageItem> tempItems = await ApplicationData.Current.TemporaryFolder.GetItemsAsync(); IReadOnlyList<IStorageItem> tempItems;
if ((bool)Config.GetValue("custom_temp_location") && StorageApplicationPermissions.FutureAccessList.ContainsItem("custom_temp_location"))
tempItems = await (await StorageApplicationPermissions.FutureAccessList.GetFolderAsync("custom_temp_location")).GetItemsAsync();
else
tempItems = await ApplicationData.Current.TemporaryFolder.GetItemsAsync();
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
foreach (IStorageItem item in tempItems) tasks.Add(item.DeleteAsync().AsTask()); foreach (IStorageItem item in tempItems) tasks.Add(item.DeleteAsync().AsTask());
await Task.WhenAll(tasks); await Task.WhenAll(tasks);
@@ -64,16 +78,20 @@ namespace VDownload
} }
} }
// ON NAVIGATION FAILED
private void OnNavigationFailed(object sender, NavigationFailedEventArgs e) private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{ {
throw new Exception("Failed to load Page " + e.SourcePageType.FullName); throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
} }
// ON SUSPENDING
private void OnSuspending(object sender, SuspendingEventArgs e) private void OnSuspending(object sender, SuspendingEventArgs e)
{ {
var deferral = e.SuspendingOperation.GetDeferral(); var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity //TODO: Save application state and stop any background activity
deferral.Complete(); deferral.Complete();
} }
#endregion
} }
} }

View File

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

View File

@@ -0,0 +1,5 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<BitmapImage x:Name="UnknownThumbnailImage" UriSource="ms-appx:///Assets/Images/UnknownThumbnail.png"/>
</ResourceDictionary>

View File

@@ -196,6 +196,27 @@ The number in the numberbox indicades how many videos will be got from playlist.
<data name="HomeOptionsBarVideoSearchingTwitchAccessTokenNotValidErrorDialogDescription" xml:space="preserve"> <data name="HomeOptionsBarVideoSearchingTwitchAccessTokenNotValidErrorDialogDescription" xml:space="preserve">
<value>There is a problem with linked Twitch account. Check Twitch login status in Sources page.</value> <value>There is a problem with linked Twitch account. Check Twitch login status in Sources page.</value>
</data> </data>
<data name="HomeTaskPanelStateTextCancelled" xml:space="preserve">
<value>Cancelled</value>
</data>
<data name="HomeTaskPanelStateTextDone" xml:space="preserve">
<value>Done</value>
</data>
<data name="HomeTaskPanelStateTextDownloading" xml:space="preserve">
<value>Downloading</value>
</data>
<data name="HomeTaskPanelStateTextFinalizing" xml:space="preserve">
<value>Finalizing</value>
</data>
<data name="HomeTaskPanelStateTextIdle" xml:space="preserve">
<value>Idle</value>
</data>
<data name="HomeTaskPanelStateTextProcessing" xml:space="preserve">
<value>Processing</value>
</data>
<data name="HomeTaskPanelStateTextWaiting" xml:space="preserve">
<value>Queued</value>
</data>
<data name="HomeVideoAddingDownloadingOptionsHeaderTextBlock.Text" xml:space="preserve"> <data name="HomeVideoAddingDownloadingOptionsHeaderTextBlock.Text" xml:space="preserve">
<value>Downloading options</value> <value>Downloading options</value>
</data> </data>
@@ -220,27 +241,6 @@ The number in the numberbox indicades how many videos will be got from playlist.
<data name="HomeVideoAddingTrimSettingControl.Title" xml:space="preserve"> <data name="HomeVideoAddingTrimSettingControl.Title" xml:space="preserve">
<value>Trim</value> <value>Trim</value>
</data> </data>
<data name="HomeVideoPanelStateTextCancelled" xml:space="preserve">
<value>Cancelled</value>
</data>
<data name="HomeVideoPanelStateTextDone" xml:space="preserve">
<value>Done</value>
</data>
<data name="HomeVideoPanelStateTextDownloading" xml:space="preserve">
<value>Downloading</value>
</data>
<data name="HomeVideoPanelStateTextFinalizing" xml:space="preserve">
<value>Finalizing</value>
</data>
<data name="HomeVideoPanelStateTextIdle" xml:space="preserve">
<value>Idle</value>
</data>
<data name="HomeVideoPanelStateTextProcessing" xml:space="preserve">
<value>Processing</value>
</data>
<data name="HomeVideoPanelStateTextWaiting" xml:space="preserve">
<value>Queued</value>
</data>
<data name="MainPageNavigationPanelHomeItem.Content" xml:space="preserve"> <data name="MainPageNavigationPanelHomeItem.Content" xml:space="preserve">
<value>Home</value> <value>Home</value>
</data> </data>

View File

@@ -140,10 +140,9 @@
<Compile Include="Views\Home\HomeVideoAddingPanel.xaml.cs"> <Compile Include="Views\Home\HomeVideoAddingPanel.xaml.cs">
<DependentUpon>HomeVideoAddingPanel.xaml</DependentUpon> <DependentUpon>HomeVideoAddingPanel.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Home\HomeVideoPanel.xaml.cs"> <Compile Include="Views\Home\HomeTaskPanel.xaml.cs">
<DependentUpon>HomeVideoPanel.xaml</DependentUpon> <DependentUpon>HomeTaskPanel.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Views\Home\HomeVideosList.cs" />
<Compile Include="Views\MainPage.xaml.cs"> <Compile Include="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
@@ -250,7 +249,8 @@
<Content Include="Assets\Logo\Wide310x150Logo.scale-200.png" /> <Content Include="Assets\Logo\Wide310x150Logo.scale-200.png" />
<Content Include="Assets\Logo\Wide310x150Logo.scale-400.png" /> <Content Include="Assets\Logo\Wide310x150Logo.scale-400.png" />
<Content Include="Assets\Icons\Twitch.png" /> <Content Include="Assets\Icons\Twitch.png" />
<Content Include="Assets\UnknownThumbnail.png" /> <Content Include="Assets\Images\UnknownThumbnail.png" />
<Content Include="Assets\Sources\Twitch.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ApplicationDefinition Include="App.xaml"> <ApplicationDefinition Include="App.xaml">
@@ -269,6 +269,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Resources\Images.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\About\AboutMain.xaml"> <Page Include="Views\About\AboutMain.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@@ -293,7 +297,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Views\Home\HomeVideoPanel.xaml"> <Page Include="Views\Home\HomeTaskPanel.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>

View File

@@ -54,13 +54,13 @@
</VisualStateManager.VisualStateGroups> </VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition x:Name="HomeVideosListRow" Height="1*"/> <RowDefinition x:Name="HomeTasksListRow" Height="1*"/>
<RowDefinition x:Name="HomeOptionBarAndAddingPanelRow" Height="Auto"/> <RowDefinition x:Name="HomeOptionBarAndAddingPanelRow" Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- VIDEOS LIST --> <!-- VIDEOS LIST -->
<ScrollViewer Margin="0,0,0,10" CornerRadius="{ThemeResource ControlCornerRadius}"> <ScrollViewer Margin="0,0,0,10" CornerRadius="{ThemeResource ControlCornerRadius}">
<StackPanel x:Name="HomeVideosList" Spacing="10"/> <StackPanel x:Name="HomeTasksList" Spacing="10"/>
</ScrollViewer> </ScrollViewer>
<!-- OPTIONS BAR AND ADDING PANEL --> <!-- OPTIONS BAR AND ADDING PANEL -->

View File

@@ -6,12 +6,11 @@ using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using VDownload.Core.EventArgsObjects; using VDownload.Core.EventArgs;
using VDownload.Core.Exceptions; using VDownload.Core.Exceptions;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Services; using VDownload.Core.Services;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;
using Windows.UI.Core;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
@@ -42,8 +41,8 @@ namespace VDownload.Views.Home
private CancellationTokenSource SearchingCancellationToken = new CancellationTokenSource(); private CancellationTokenSource SearchingCancellationToken = new CancellationTokenSource();
// HOME VIDEOS LIST // HOME VIDEOS LIST
private static StackPanel HomeVideosListOldPanel = null; private static StackPanel HomeTasksListParent = null;
public static List<HomeVideoPanel> VideoPanelsList = new List<HomeVideoPanel>(); public static List<HomeTaskPanel> TaskPanelsList = new List<HomeTaskPanel>();
#endregion #endregion
@@ -54,9 +53,9 @@ namespace VDownload.Views.Home
// ON NAVIGATED TO // ON NAVIGATED TO
protected override async void OnNavigatedTo(NavigationEventArgs e) protected override async void OnNavigatedTo(NavigationEventArgs e)
{ {
if (HomeVideosListOldPanel != null) HomeVideosListOldPanel.Children.Clear(); if (HomeTasksListParent != null) HomeTasksListParent.Children.Clear();
HomeVideosListOldPanel = HomeVideosList; HomeTasksListParent = HomeTasksList;
foreach (HomeVideoPanel homeVideoPanel in VideoPanelsList) HomeVideosList.Children.Add(homeVideoPanel); foreach (HomeTaskPanel homeVideoPanel in TaskPanelsList) HomeTasksList.Children.Add(homeVideoPanel);
} }
// ADD VIDEO BUTTON CHECKED // ADD VIDEO BUTTON CHECKED
@@ -158,7 +157,7 @@ namespace VDownload.Views.Home
HomeOptionBarAndAddingPanelRow.Height = new GridLength(1, GridUnitType.Star); HomeOptionBarAndAddingPanelRow.Height = new GridLength(1, GridUnitType.Star);
HomeVideosListRow.Height = new GridLength(0); HomeTasksListRow.Height = new GridLength(0);
HomeVideoAddingPanel addingPanel = new HomeVideoAddingPanel(videoService); HomeVideoAddingPanel addingPanel = new HomeVideoAddingPanel(videoService);
addingPanel.VideoAddRequest += HomeVideoAddingPanel_VideoAddRequest; addingPanel.VideoAddRequest += HomeVideoAddingPanel_VideoAddRequest;
HomeAddingPanel.Content = addingPanel; HomeAddingPanel.Content = addingPanel;
@@ -170,19 +169,19 @@ namespace VDownload.Views.Home
// Uncheck video button // Uncheck video button
HomeOptionsBarAddVideoButton.IsChecked = false; HomeOptionsBarAddVideoButton.IsChecked = false;
// Create video panel/task // Create video task
HomeVideoPanel videoPanel = new HomeVideoPanel(e.VideoService, e.MediaType, e.Stream, e.TrimStart, e.TrimEnd, e.Filename, e.Extension, e.Location); HomeTaskPanel taskPanel = new HomeTaskPanel(e.VideoService, e.MediaType, e.Stream, e.TrimStart, e.TrimEnd, e.Filename, e.Extension, e.Location);
videoPanel.VideoRemovingRequested += (s, a) => taskPanel.TaskRemovingRequested += (s, a) =>
{ {
// Remove video panel/task from videos list // Remove task from tasks lists
VideoPanelsList.Remove(videoPanel); TaskPanelsList.Remove(taskPanel);
HomeVideosList.Children.Remove(videoPanel); HomeTasksList.Children.Remove(taskPanel);
}; };
// Add video panel/task to videos list // Add task to tasks lists
HomeVideosList.Children.Add(videoPanel); HomeTasksList.Children.Add(taskPanel);
VideoPanelsList.Add(videoPanel); TaskPanelsList.Add(taskPanel);
} }
@@ -287,7 +286,7 @@ namespace VDownload.Views.Home
SearchingCancellationToken = new CancellationTokenSource(); SearchingCancellationToken = new CancellationTokenSource();
HomeOptionBarAndAddingPanelRow.Height = GridLength.Auto; HomeOptionBarAndAddingPanelRow.Height = GridLength.Auto;
HomeVideosListRow.Height = new GridLength(1, GridUnitType.Star); HomeTasksListRow.Height = new GridLength(1, GridUnitType.Star);
HomeAddingPanel.Content = null; HomeAddingPanel.Content = null;
HomeOptionsBarAddingControl.Content = null; HomeOptionsBarAddingControl.Content = null;
@@ -298,7 +297,7 @@ namespace VDownload.Views.Home
// DOWNLOAD ALL BUTTON CLICKED // DOWNLOAD ALL BUTTON CLICKED
private async void HomeOptionsBarDownloadAllButton_Click(object sender, RoutedEventArgs e) private async void HomeOptionsBarDownloadAllButton_Click(object sender, RoutedEventArgs e)
{ {
foreach (HomeVideoPanel videoPanel in HomeVideosList.Children.Where(video => ((HomeVideoPanel)video).VideoStatus == VideoStatus.Idle)) foreach (HomeTaskPanel videoPanel in HomeTasksList.Children.Where((object video) => ((HomeTaskPanel)video).TaskStatus == Core.Enums.TaskStatus.Idle))
{ {
await Task.Delay(50); await Task.Delay(50);
videoPanel.Start(); videoPanel.Start();
@@ -314,7 +313,7 @@ namespace VDownload.Views.Home
// WAIT IN QUEUE // WAIT IN QUEUE
public static async Task WaitInQueue(CancellationToken token) public static async Task WaitInQueue(CancellationToken token)
{ {
while (VideoPanelsList.Where(video => video.VideoStatus == VideoStatus.InProgress).Count() >= (int)Config.GetValue("max_active_video_task") && !token.IsCancellationRequested) while (TaskPanelsList.Where((HomeTaskPanel video) => video.TaskStatus == Core.Enums.TaskStatus.InProgress).Count() >= (int)Config.GetValue("max_active_video_task") && !token.IsCancellationRequested)
{ {
await Task.Delay(50); await Task.Delay(50);
} }

View File

@@ -1,5 +1,5 @@
using System; using System;
using VDownload.Core.EventArgsObjects; using VDownload.Core.EventArgs;
using VDownload.Core.Services; using VDownload.Core.Services;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -24,9 +24,6 @@ namespace VDownload.Views.Home
// MAX VIDEOS NUMBERBOX DEFAULT VALUE // MAX VIDEOS NUMBERBOX DEFAULT VALUE
public int DefaultMaxPlaylistVideos = (int)Config.GetValue("default_max_playlist_videos"); public int DefaultMaxPlaylistVideos = (int)Config.GetValue("default_max_playlist_videos");
// SEARCH BUTTON EVENT HANDLER
public event EventHandler<PlaylistSearchEventArgs> SearchButtonClicked;
#endregion #endregion
@@ -56,5 +53,13 @@ namespace VDownload.Views.Home
} }
#endregion #endregion
#region EVENT HANDLERS
public event EventHandler<PlaylistSearchEventArgs> SearchButtonClicked;
#endregion
} }
} }

View File

@@ -1,5 +1,5 @@
using System; using System;
using VDownload.Core.EventArgsObjects; using VDownload.Core.EventArgs;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -18,16 +18,7 @@ namespace VDownload.Views.Home
#region PROPERTIES #region EVENT HANDLERS VOIDS
// SEARCH BUTTON EVENT HANDLER
public event EventHandler<VideoSearchEventArgs> SearchButtonClicked;
#endregion
#region EVENT HANDLERS
// SEARCH BUTTON CLICKED // SEARCH BUTTON CLICKED
private void HomeOptionsBarAddVideoControlSearchButton_Click(object sender, RoutedEventArgs e) private void HomeOptionsBarAddVideoControlSearchButton_Click(object sender, RoutedEventArgs e)
@@ -51,5 +42,13 @@ namespace VDownload.Views.Home
} }
#endregion #endregion
#region EVENT HANDLERS
public event EventHandler<VideoSearchEventArgs> SearchButtonClicked;
#endregion
} }
} }

View File

@@ -1,10 +1,11 @@
<UserControl <UserControl
x:Class="VDownload.Views.Home.HomeVideoPanel" x:Class="VDownload.Views.Home.HomeTaskPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VDownload.Views.Home" xmlns:local="using:VDownload.Views.Home"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d" mc:Ignorable="d"
CornerRadius="{ThemeResource ControlCornerRadius}" CornerRadius="{ThemeResource ControlCornerRadius}"
d:DesignHeight="150" d:DesignHeight="150"
@@ -52,12 +53,12 @@
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Duration}"/> <TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind Duration}"/>
<Image Grid.Row="2" Grid.Column="0" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource FileIcon}"/> <Image Grid.Row="2" Grid.Column="0" Width="{StaticResource MetadataIconSize}" Source="{ThemeResource FileIcon}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind File}"/> <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}" Text="{x:Bind File}"/>
<Image x:Name="HomeVideoPanelStateIcon" Grid.Row="3" Grid.Column="0" Width="{StaticResource MetadataIconSize}"/> <Image x:Name="HomeTaskPanelStateIcon" Grid.Row="3" Grid.Column="0" Width="{StaticResource MetadataIconSize}"/>
<TextBlock x:Name="HomeVideoPanelStateText" Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}"/> <TextBlock x:Name="HomeTaskPanelStateText" Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" FontSize="{StaticResource MetadataTextSize}"/>
<muxc:ProgressBar x:Name="HomeVideoPanelStateProgressBar" Grid.Row="3" Grid.Column="2" Margin="10,0,0,0" VerticalAlignment="Center"/> <muxc:ProgressBar x:Name="HomeTaskPanelStateProgressBar" Grid.Row="3" Grid.Column="2" Margin="10,0,0,0" VerticalAlignment="Center"/>
</Grid> </Grid>
<AppBarButton Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="{x:Bind SourceImage}" Click="HomeVideoPanelSourceButton_Click"/> <AppBarButton Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="{x:Bind SourceImage}" Click="HomeTaskPanelSourceButton_Click"/>
<AppBarButton x:Name="HomeVideoPanelStartStopButton" Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="Download" Click="HomeVideoPanelStartStopButton_Click"/> <AppBarButton x:Name="HomeTaskPanelStartStopButton" Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="Download" Click="HomeTaskPanelStartStopButton_Click"/>
<AppBarButton Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="Cancel" Click="HomeVideoPanelRemoveButton_Click"/> <AppBarButton Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" Width="40" Height="48" Margin="-3" Icon="Cancel" Click="HomeTaskPanelRemoveButton_Click"/>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@@ -5,7 +5,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Objects;
using VDownload.Core.Services; using VDownload.Core.Services;
using Windows.ApplicationModel.ExtendedExecution; using Windows.ApplicationModel.ExtendedExecution;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;
@@ -16,15 +15,14 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace VDownload.Views.Home namespace VDownload.Views.Home
{ {
public sealed partial class HomeVideoPanel : UserControl public sealed partial class HomeTaskPanel : UserControl
{ {
#region CONSTANTS #region CONSTANTS
ResourceDictionary IconsRes = new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Icons.xaml") }; ResourceDictionary IconsRes = new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Icons.xaml") };
ResourceDictionary ImagesRes = new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Images.xaml") };
#endregion #endregion
@@ -32,12 +30,12 @@ namespace VDownload.Views.Home
#region CONSTRUCTORS #region CONSTRUCTORS
public HomeVideoPanel(IVideoService videoService, MediaType mediaType, Stream stream, TimeSpan trimStart, TimeSpan trimEnd, string filename, MediaFileExtension extension, StorageFolder location) public HomeTaskPanel(IVideoService videoService, MediaType mediaType, IBaseStream stream, TimeSpan trimStart, TimeSpan trimEnd, string filename, MediaFileExtension extension, StorageFolder location)
{ {
this.InitializeComponent(); this.InitializeComponent();
// Set video status // Set video status
VideoStatus = VideoStatus.Idle; TaskStatus = Core.Enums.TaskStatus.Idle;
// Set video service object // Set video service object
VideoService = videoService; VideoService = videoService;
@@ -55,8 +53,8 @@ namespace VDownload.Views.Home
Location = location; Location = location;
// Set metadata // Set metadata
ThumbnailImage = new BitmapImage { UriSource = VideoService.Thumbnail ?? new Uri("ms-appx:///Assets/UnknownThumbnail.png") }; ThumbnailImage = (BitmapImage)ImagesRes["UnknownThumbnailImage"];
SourceImage = new BitmapIcon { UriSource = new Uri($"ms-appx:///Assets/Icons/{VideoService.GetType().Namespace.Split(".").Last()}.png"), ShowAsMonochrome = false }; SourceImage = new BitmapIcon { UriSource = new Uri($"ms-appx:///Assets/Sources/{VideoService.GetType().Namespace.Split(".").Last()}.png"), ShowAsMonochrome = false };
Title = VideoService.Title; Title = VideoService.Title;
Author = VideoService.Author; Author = VideoService.Author;
TimeSpan newDuration = TrimEnd.Subtract(TrimStart); TimeSpan newDuration = TrimEnd.Subtract(TrimStart);
@@ -67,9 +65,9 @@ namespace VDownload.Views.Home
File += $@"{(Location != null ? Location.Path : $@"{UserDataPaths.GetDefault().Downloads}\VDownload")}\{Filename}.{Extension.ToString().ToLower()}"; File += $@"{(Location != null ? Location.Path : $@"{UserDataPaths.GetDefault().Downloads}\VDownload")}\{Filename}.{Extension.ToString().ToLower()}";
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateIdleIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateIdleIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextIdle"); HomeTaskPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextIdle");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed; HomeTaskPanelStateProgressBar.Visibility = Visibility.Collapsed;
} }
#endregion #endregion
@@ -79,9 +77,9 @@ namespace VDownload.Views.Home
#region PROPERTIES #region PROPERTIES
// VIDEO STATUS // VIDEO STATUS
public VideoStatus VideoStatus { get; set; } public Core.Enums.TaskStatus TaskStatus { get; set; }
// VIDEO CANECELLATION TOKEN // TASK CANCELLATION TOKEN
public CancellationTokenSource CancellationTokenSource { get; set; } public CancellationTokenSource CancellationTokenSource { get; set; }
// VIDEO SERVICE // VIDEO SERVICE
@@ -89,7 +87,7 @@ namespace VDownload.Views.Home
// VIDEO OPTIONS // VIDEO OPTIONS
private MediaType MediaType { get; set; } private MediaType MediaType { get; set; }
private Stream Stream { get; set; } private IBaseStream Stream { get; set; }
private TimeSpan TrimStart { get; set; } private TimeSpan TrimStart { get; set; }
private TimeSpan TrimEnd { get; set; } private TimeSpan TrimEnd { get; set; }
private string Filename { get; set; } private string Filename { get; set; }
@@ -114,26 +112,26 @@ namespace VDownload.Views.Home
public async Task Start() public async Task Start()
{ {
// Change icon // Change icon
HomeVideoPanelStartStopButton.Icon = new SymbolIcon(Symbol.Stop); HomeTaskPanelStartStopButton.Icon = new SymbolIcon(Symbol.Stop);
// Create cancellation token // Create cancellation token
CancellationTokenSource = new CancellationTokenSource(); CancellationTokenSource = new CancellationTokenSource();
// Set video status // Set task status
VideoStatus = VideoStatus.Waiting; TaskStatus = Core.Enums.TaskStatus.Waiting;
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateWaitingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateWaitingIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextWaiting"); HomeTaskPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextWaiting");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Visible; HomeTaskPanelStateProgressBar.Visibility = Visibility.Visible;
HomeVideoPanelStateProgressBar.IsIndeterminate = true; HomeTaskPanelStateProgressBar.IsIndeterminate = true;
// Wait in queue // Wait in queue
await HomeMain.WaitInQueue(CancellationTokenSource.Token); await HomeMain.WaitInQueue(CancellationTokenSource.Token);
if (!CancellationTokenSource.IsCancellationRequested) if (!CancellationTokenSource.IsCancellationRequested)
{ {
// Set video status // Set task status
VideoStatus = VideoStatus.InProgress; TaskStatus = Core.Enums.TaskStatus.InProgress;
// Get task unique ID // Get task unique ID
string uniqueID = TaskId.Get(); string uniqueID = TaskId.Get();
@@ -148,7 +146,7 @@ namespace VDownload.Views.Home
try try
{ {
// Set cancellation token to throw exception on request // Throw exception if cancellation requested
CancellationTokenSource.Token.ThrowIfCancellationRequested(); CancellationTokenSource.Token.ThrowIfCancellationRequested();
// Start stopwatch // Start stopwatch
@@ -157,28 +155,28 @@ namespace VDownload.Views.Home
// Set progress event handlers // Set progress event handlers
VideoService.DownloadingStarted += (s, a) => VideoService.DownloadingStarted += (s, a) =>
{ {
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDownloadingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDownloadingIcon"];
HomeVideoPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextDownloading")} (0%)"; HomeTaskPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextDownloading")} (0%)";
HomeVideoPanelStateProgressBar.IsIndeterminate = false; HomeTaskPanelStateProgressBar.IsIndeterminate = false;
HomeVideoPanelStateProgressBar.Value = 0; HomeTaskPanelStateProgressBar.Value = 0;
}; };
VideoService.DownloadingProgressChanged += (s, a) => VideoService.DownloadingProgressChanged += (s, a) =>
{ {
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDownloadingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDownloadingIcon"];
HomeVideoPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextDownloading")} ({a.ProgressPercentage}%)"; HomeTaskPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextDownloading")} ({a.ProgressPercentage}%)";
HomeVideoPanelStateProgressBar.Value = a.ProgressPercentage; HomeTaskPanelStateProgressBar.Value = a.ProgressPercentage;
}; };
VideoService.ProcessingStarted += (s, a) => VideoService.ProcessingStarted += (s, a) =>
{ {
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateProcessingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateProcessingIcon"];
HomeVideoPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextProcessing")} (0%)"; HomeTaskPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextProcessing")} (0%)";
HomeVideoPanelStateProgressBar.Value = 0; HomeTaskPanelStateProgressBar.Value = 0;
}; };
VideoService.ProcessingProgressChanged += (s, a) => VideoService.ProcessingProgressChanged += (s, a) =>
{ {
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateProcessingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateProcessingIcon"];
HomeVideoPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextProcessing")} ({a.ProgressPercentage}%)"; HomeTaskPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextProcessing")} ({a.ProgressPercentage}%)";
HomeVideoPanelStateProgressBar.Value = a.ProgressPercentage; HomeTaskPanelStateProgressBar.Value = a.ProgressPercentage;
}; };
// Request extended session // Request extended session
@@ -186,7 +184,8 @@ namespace VDownload.Views.Home
await session.RequestExtensionAsync(); await session.RequestExtensionAsync();
// Start task // Start task
StorageFile tempOutputFile = await VideoService.DownloadAndTranscodeAsync(tempFolder, Stream, Extension, MediaType, CancellationTokenSource.Token); CancellationTokenSource.Token.ThrowIfCancellationRequested();
StorageFile tempOutputFile = await VideoService.DownloadAndTranscodeAsync(tempFolder, Stream, Extension, MediaType, TrimStart, TrimEnd, CancellationTokenSource.Token);
// Dispose session // Dispose session
session.Dispose(); session.Dispose();
@@ -195,13 +194,12 @@ namespace VDownload.Views.Home
CancellationTokenSource.Token.ThrowIfCancellationRequested(); CancellationTokenSource.Token.ThrowIfCancellationRequested();
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateFinalizingIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateFinalizingIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextFinalizing"); HomeTaskPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextFinalizing");
HomeVideoPanelStateProgressBar.IsIndeterminate = true; HomeTaskPanelStateProgressBar.IsIndeterminate = true;
// Move to output location // Move to output location
StorageFile outputFile; StorageFile outputFile;
Debug.WriteLine($"{Filename}.{Extension.ToString().ToLower()}");
if (Location != null) outputFile = await Location.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName); if (Location != null) outputFile = await Location.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName);
else outputFile = await DownloadsFolder.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName); else outputFile = await DownloadsFolder.CreateFileAsync($"{Filename}.{Extension.ToString().ToLower()}", (bool)Config.GetValue("replace_output_file_if_exists") ? CreationCollisionOption.ReplaceExisting : CreationCollisionOption.GenerateUniqueName);
await tempOutputFile.MoveAndReplaceAsync(outputFile); await tempOutputFile.MoveAndReplaceAsync(outputFile);
@@ -210,25 +208,25 @@ namespace VDownload.Views.Home
taskStopwatch.Stop(); taskStopwatch.Stop();
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDoneIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateDoneIcon"];
HomeVideoPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextDone")} ({(Math.Floor(taskStopwatch.Elapsed.TotalHours) > 0 ? $"{ Math.Floor(taskStopwatch.Elapsed.TotalHours):0}:" : "")}{taskStopwatch.Elapsed.Minutes:00}:{taskStopwatch.Elapsed.Seconds:00})"; HomeTaskPanelStateText.Text = $"{ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextDone")} ({(Math.Floor(taskStopwatch.Elapsed.TotalHours) > 0 ? $"{ Math.Floor(taskStopwatch.Elapsed.TotalHours):0}:" : "")}{taskStopwatch.Elapsed.Minutes:00}:{taskStopwatch.Elapsed.Seconds:00})";
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed; HomeTaskPanelStateProgressBar.Visibility = Visibility.Collapsed;
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateCancelledIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateCancelledIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextCancelled"); HomeTaskPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextCancelled");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed; HomeTaskPanelStateProgressBar.Visibility = Visibility.Collapsed;
} }
finally finally
{ {
// Change icon // Change icon
HomeVideoPanelStartStopButton.Icon = new SymbolIcon(Symbol.Download); HomeTaskPanelStartStopButton.Icon = new SymbolIcon(Symbol.Download);
// Set video status // Set video status
VideoStatus = VideoStatus.Idle; TaskStatus = Core.Enums.TaskStatus.Idle;
// Delete temporary files // Delete temporary files
await tempFolder.DeleteAsync(); await tempFolder.DeleteAsync();
@@ -240,9 +238,9 @@ namespace VDownload.Views.Home
else else
{ {
// Set state controls // Set state controls
HomeVideoPanelStateIcon.Source = (SvgImageSource)IconsRes["StateCancelledIcon"]; HomeTaskPanelStateIcon.Source = (SvgImageSource)IconsRes["StateCancelledIcon"];
HomeVideoPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeVideoPanelStateTextCancelled"); HomeTaskPanelStateText.Text = ResourceLoader.GetForCurrentView().GetString("HomeTaskPanelStateTextCancelled");
HomeVideoPanelStateProgressBar.Visibility = Visibility.Collapsed; HomeTaskPanelStateProgressBar.Visibility = Visibility.Collapsed;
} }
} }
@@ -253,24 +251,24 @@ namespace VDownload.Views.Home
#region EVENT HANDLERS VOIDS #region EVENT HANDLERS VOIDS
// SOURCE BUTTON CLICKED // SOURCE BUTTON CLICKED
private async void HomeVideoPanelSourceButton_Click(object sender, RoutedEventArgs e) private async void HomeTaskPanelSourceButton_Click(object sender, RoutedEventArgs e)
{ {
// Launch the website // Launch the website
await Windows.System.Launcher.LaunchUriAsync(VideoService.VideoUrl); await Windows.System.Launcher.LaunchUriAsync(VideoService.VideoUrl);
} }
// START STOP BUTTON CLICKED // START STOP BUTTON CLICKED
private async void HomeVideoPanelStartStopButton_Click(object sender, RoutedEventArgs e) private async void HomeTaskPanelStartStopButton_Click(object sender, RoutedEventArgs e)
{ {
if (VideoStatus == VideoStatus.InProgress || VideoStatus == VideoStatus.Waiting) CancellationTokenSource.Cancel(); if (TaskStatus == Core.Enums.TaskStatus.InProgress || TaskStatus == Core.Enums.TaskStatus.Waiting) CancellationTokenSource.Cancel();
else await Start(); else await Start();
} }
// REMOVE BUTTON CLICKED // REMOVE BUTTON CLICKED
private void HomeVideoPanelRemoveButton_Click(object sender, RoutedEventArgs e) private void HomeTaskPanelRemoveButton_Click(object sender, RoutedEventArgs e)
{ {
if (VideoStatus == VideoStatus.InProgress || VideoStatus == VideoStatus.Waiting) CancellationTokenSource.Cancel(); if (TaskStatus == Core.Enums.TaskStatus.InProgress || TaskStatus == Core.Enums.TaskStatus.Waiting) CancellationTokenSource.Cancel();
VideoRemovingRequested?.Invoke(sender, EventArgs.Empty); TaskRemovingRequested?.Invoke(sender, EventArgs.Empty);
} }
#endregion #endregion
@@ -279,7 +277,7 @@ namespace VDownload.Views.Home
#region EVENT HANDLERS #region EVENT HANDLERS
public event EventHandler VideoRemovingRequested; public event EventHandler TaskRemovingRequested;
#endregion #endregion
} }

View File

@@ -1,13 +1,11 @@
using Microsoft.Toolkit.Uwp.UI; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using VDownload.Core.Enums; using VDownload.Core.Enums;
using VDownload.Core.EventArgsObjects; using VDownload.Core.EventArgs;
using VDownload.Core.Interfaces; using VDownload.Core.Interfaces;
using VDownload.Core.Objects; using VDownload.Core.Objects;
using VDownload.Core.Services; using VDownload.Core.Services;
@@ -20,12 +18,18 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace VDownload.Views.Home namespace VDownload.Views.Home
{ {
public sealed partial class HomeVideoAddingPanel : UserControl public sealed partial class HomeVideoAddingPanel : UserControl
{ {
#region CONSTANTS
ResourceDictionary ImagesRes = new ResourceDictionary { Source = new Uri("ms-appx:///Resources/Images.xaml") };
#endregion
#region CONSTRUCTORS #region CONSTRUCTORS
public HomeVideoAddingPanel(IVideoService videoService) public HomeVideoAddingPanel(IVideoService videoService)
@@ -36,8 +40,8 @@ namespace VDownload.Views.Home
VideoService = videoService; VideoService = videoService;
// Set metadata // Set metadata
ThumbnailImage = new BitmapImage { UriSource = VideoService.Thumbnail ?? new Uri("ms-appx:///Assets/UnknownThumbnail.png") }; ThumbnailImage = VideoService.Thumbnail != null ? new BitmapImage { UriSource = VideoService.Thumbnail } : (BitmapImage)ImagesRes["UnknownThumbnailImage"];
SourceImage = new BitmapIcon { UriSource = new Uri($"ms-appx:///Assets/Icons/{VideoService.GetType().Namespace.Split(".").Last()}.png"), ShowAsMonochrome = false }; SourceImage = new BitmapIcon { UriSource = new Uri($"ms-appx:///Assets/Sources/{VideoService.GetType().Namespace.Split(".").Last()}.png"), ShowAsMonochrome = false };
Title = VideoService.Title; Title = VideoService.Title;
Author = VideoService.Author; Author = VideoService.Author;
Views = VideoService.Views.ToString(); Views = VideoService.Views.ToString();
@@ -53,7 +57,7 @@ namespace VDownload.Views.Home
HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex = (int)Config.GetValue("default_media_type"); HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex = (int)Config.GetValue("default_media_type");
// Set quality // Set quality
foreach (Stream stream in VideoService.Streams) foreach (IBaseStream stream in VideoService.BaseStreams)
{ {
HomeVideoAddingQualitySettingControlComboBox.Items.Add($"{stream.Height}p{(stream.FrameRate > 0 ? stream.FrameRate.ToString() : "N/A")}"); HomeVideoAddingQualitySettingControlComboBox.Items.Add($"{stream.Height}p{(stream.FrameRate > 0 ? stream.FrameRate.ToString() : "N/A")}");
} }
@@ -130,7 +134,7 @@ namespace VDownload.Views.Home
// VIDEO OPTIONS // VIDEO OPTIONS
private MediaType MediaType { get; set; } private MediaType MediaType { get; set; }
private Stream Stream { get; set; } private IBaseStream Stream { get; set; }
private TimeSpan TrimStart { get; set; } private TimeSpan TrimStart { get; set; }
private TimeSpan TrimEnd { get; set; } private TimeSpan TrimEnd { get; set; }
private string Filename { get; set; } private string Filename { get; set; }
@@ -150,7 +154,7 @@ namespace VDownload.Views.Home
if (HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex == (int)MediaType.OnlyAudio) if (HomeVideoAddingMediaTypeSettingControlComboBox.SelectedIndex == (int)MediaType.OnlyAudio)
{ {
HomeVideoAddingQualitySettingControl.Visibility = Visibility.Collapsed; HomeVideoAddingQualitySettingControl.Visibility = Visibility.Collapsed;
HomeVideoAddingQualitySettingControlComboBox.SelectedIndex = VideoService.Streams.Count() - 1; HomeVideoAddingQualitySettingControlComboBox.SelectedIndex = VideoService.BaseStreams.Count() - 1;
HomeVideoAddingExtensionComboBox.Items.Clear(); HomeVideoAddingExtensionComboBox.Items.Clear();
foreach (AudioFileExtension extension in Enum.GetValues(typeof(AudioFileExtension))) foreach (AudioFileExtension extension in Enum.GetValues(typeof(AudioFileExtension)))
@@ -176,7 +180,7 @@ namespace VDownload.Views.Home
// QUALITY COMBOBOX SELECTION CHANGED // QUALITY COMBOBOX SELECTION CHANGED
private void HomeVideoAddingQualitySettingControlComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) private void HomeVideoAddingQualitySettingControlComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
Stream = VideoService.Streams[HomeVideoAddingQualitySettingControlComboBox.SelectedIndex]; Stream = VideoService.BaseStreams[HomeVideoAddingQualitySettingControlComboBox.SelectedIndex];
} }
// TRIM START TEXTBOX TEXT CHANGED // TRIM START TEXTBOX TEXT CHANGED

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VDownload.Views.Home
{
public class HomeVideosList
{
}
}

View File

@@ -10,9 +10,14 @@
<Page.Resources> <Page.Resources>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness> <ResourceDictionary>
<Thickness x:Key="NavigationViewContentGridBorderThickness">0</Thickness> <ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent"></SolidColorBrush> <ResourceDictionary Source="ms-appx:///Resources/Icons.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Thickness x:Key="NavigationViewContentMargin">0,48,0,0</Thickness>
<Thickness x:Key="NavigationViewContentGridBorderThickness">0</Thickness>
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent"/>
</ResourceDictionary>
</Page.Resources> </Page.Resources>

View File

@@ -1,7 +1,6 @@
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using Windows.ApplicationModel.Resources; using Windows.ApplicationModel.Resources;