twitch vod downloading done
ffmpeg essentials fix Project reorganized git lfs ffmpeg removed ffmpeg added
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Authentication
|
||||
{
|
||||
public class AuthenticationConfiguration
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AuthenticationConfiguration(IConfiguration configuration)
|
||||
{
|
||||
IConfigurationSection section = configuration.GetSection("authentication");
|
||||
FilePath = section["file_path"];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Authentication
|
||||
{
|
||||
public class AuthenticationData
|
||||
{
|
||||
#region PROPERTY
|
||||
|
||||
[JsonProperty("twitch")]
|
||||
public AuthenticationDataTwitch Twitch { get; internal set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AuthenticationData()
|
||||
{
|
||||
Twitch = new AuthenticationDataTwitch();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Extensions;
|
||||
|
||||
namespace VDownload.Services.Authentication
|
||||
{
|
||||
public interface IAuthenticationService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
AuthenticationData? AuthenticationData { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
Task Load();
|
||||
Task Save();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class AuthenticationService : IAuthenticationService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
private AuthenticationConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private string _authenticationDataFile;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public AuthenticationData AuthenticationData { get; private set; }
|
||||
|
||||
public bool AuthenticationDataLoaded => AuthenticationData is not null;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AuthenticationService(AuthenticationConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
|
||||
_authenticationDataFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), _configuration.FilePath);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task Load()
|
||||
{
|
||||
AuthenticationData = null;
|
||||
|
||||
if (File.Exists(_authenticationDataFile))
|
||||
{
|
||||
string content = await File.ReadAllTextAsync(_authenticationDataFile);
|
||||
AuthenticationData = JsonConvert.DeserializeObject<AuthenticationData>(content);
|
||||
}
|
||||
|
||||
AuthenticationData ??= new AuthenticationData();
|
||||
}
|
||||
|
||||
public async Task Save()
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_authenticationDataFile));
|
||||
string content = JsonConvert.SerializeObject(AuthenticationData);
|
||||
await File.WriteAllTextAsync(_authenticationDataFile, content);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Newtonsoft.Json;
|
||||
using VDownload.Services.Data.Authentication.Models;
|
||||
|
||||
namespace VDownload.Services.Data.Authentication
|
||||
{
|
||||
public class AuthenticationData
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[JsonProperty("twitch")]
|
||||
public TokenAuthenticationData Twitch { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AuthenticationData()
|
||||
{
|
||||
Twitch = new TokenAuthenticationData();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Services.Data.Configuration;
|
||||
|
||||
namespace VDownload.Services.Data.Authentication
|
||||
{
|
||||
public interface IAuthenticationDataService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
AuthenticationData Data { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
Task Load();
|
||||
Task Save();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class AuthenticationDataService : IAuthenticationDataService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
protected readonly string _filePath;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public AuthenticationData Data { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public AuthenticationDataService(IConfigurationService configurationService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
|
||||
string appdataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
string appdataDirectoryName = _configurationService.Common.Path.Appdata.DirectoryName;
|
||||
string appdataAuthenticationFilename = _configurationService.Common.Path.Appdata.AuthenticationFile;
|
||||
_filePath = Path.Combine(appdataPath, appdataDirectoryName, appdataAuthenticationFilename);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task Load()
|
||||
{
|
||||
Data = null;
|
||||
|
||||
if (File.Exists(_filePath))
|
||||
{
|
||||
string content = await File.ReadAllTextAsync(_filePath);
|
||||
Data = JsonConvert.DeserializeObject<AuthenticationData>(content);
|
||||
}
|
||||
|
||||
Data ??= new AuthenticationData();
|
||||
}
|
||||
|
||||
public async Task Save()
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_filePath));
|
||||
string content = JsonConvert.SerializeObject(Data);
|
||||
await File.WriteAllTextAsync(_filePath, content);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Authentication
|
||||
namespace VDownload.Services.Data.Authentication.Models
|
||||
{
|
||||
public class AuthenticationDataTwitch
|
||||
public class TokenAuthenticationData
|
||||
{
|
||||
[JsonProperty("token")]
|
||||
public byte[]? Token { get; set; }
|
||||
@@ -7,12 +7,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\VDownload.Extensions\VDownload.Extensions.csproj" />
|
||||
<ProjectReference Include="..\VDownload.Services.Data.Configuration\VDownload.Services.Data.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Text.Json.Serialization;
|
||||
using VDownload.Services.Data.Configuration.Models;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration
|
||||
{
|
||||
public class CommonConfiguration
|
||||
{
|
||||
[ConfigurationKeyName("path")]
|
||||
public Models.Path Path { get; set; }
|
||||
|
||||
[ConfigurationKeyName("processing")]
|
||||
public Processing Processing { get; set; }
|
||||
|
||||
[ConfigurationKeyName("string_resources_assembly")]
|
||||
public string StringResourcesAssembly { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Sources.Twitch.Configuration;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration
|
||||
{
|
||||
public interface IConfigurationService
|
||||
{
|
||||
CommonConfiguration Common { get; }
|
||||
TwitchConfiguration Twitch { get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ConfigurationService : IConfigurationService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public CommonConfiguration Common { get; protected set; }
|
||||
public TwitchConfiguration Twitch { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public ConfigurationService(IConfiguration configuration)
|
||||
{
|
||||
Common = configuration.GetSection("common").Get<CommonConfiguration>()!;
|
||||
Twitch = configuration.GetSection("twitch").Get<TwitchConfiguration>()!;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration.Models
|
||||
{
|
||||
public class Appdata
|
||||
{
|
||||
[ConfigurationKeyName("directory_name")]
|
||||
public string DirectoryName { get; set; }
|
||||
|
||||
[ConfigurationKeyName("authentication_file")]
|
||||
public string AuthenticationFile { get; set; }
|
||||
|
||||
[ConfigurationKeyName("settings_file")]
|
||||
public string SettingsFile { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration.Models
|
||||
{
|
||||
public class Muxer
|
||||
{
|
||||
[ConfigurationKeyName("extension")]
|
||||
public string Extension { get; set; }
|
||||
|
||||
[ConfigurationKeyName("video_codecs")]
|
||||
public List<string> VideoCodecs { get; } = new List<string>();
|
||||
|
||||
[ConfigurationKeyName("audio_codecs")]
|
||||
public List<string> AudioCodecs { get; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration.Models
|
||||
{
|
||||
public class Path
|
||||
{
|
||||
[ConfigurationKeyName("appdata")]
|
||||
public Appdata Appdata { get; set; }
|
||||
|
||||
[ConfigurationKeyName("temp")]
|
||||
public Temp Temp { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration.Models
|
||||
{
|
||||
public class Processing
|
||||
{
|
||||
[ConfigurationKeyName("muxers")]
|
||||
public List<Muxer> Muxers { get; } = new List<Muxer>();
|
||||
|
||||
[ConfigurationKeyName("processed_filename")]
|
||||
public string ProcessedFilename { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Configuration.Models
|
||||
{
|
||||
public class Temp
|
||||
{
|
||||
[ConfigurationKeyName("tasks_directory")]
|
||||
public string TasksDirectory { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\VDownload.Sources\VDownload.Sources.Twitch\VDownload.Sources.Twitch.Configuration\VDownload.Sources.Twitch.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,36 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Models;
|
||||
using VDownload.Services.Data.Settings.Models;
|
||||
|
||||
namespace VDownload.Services.Data.Settings
|
||||
{
|
||||
public class CommonSettings
|
||||
{
|
||||
[JsonProperty("max_number_of_videos_to_get_from_playlist")]
|
||||
public int MaxNumberOfVideosToGetFromPlaylist { get; set; } = 0;
|
||||
|
||||
[JsonProperty("max_number_of_running_tasks")]
|
||||
public int MaxNumberOfRunningTasks { get; set; } = 5;
|
||||
|
||||
[JsonProperty("temp_directory")]
|
||||
public string TempDirectory { get; set; } = $"{Path.GetTempPath()}\\VDownload";
|
||||
|
||||
[JsonProperty("delete_temp_on_error")]
|
||||
public bool DeleteTempOnError { get; set; } = true;
|
||||
|
||||
[JsonProperty("default_task_settings")]
|
||||
public DefaultTaskSettings DefaultTaskSettings { get; set; } = new DefaultTaskSettings();
|
||||
|
||||
[JsonProperty("notifications")]
|
||||
public Notifications Notifications { get; set; } = new Notifications();
|
||||
|
||||
[JsonProperty("processing")]
|
||||
public Processing Processing { get; set; } = new Processing();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Models;
|
||||
|
||||
namespace VDownload.Services.Data.Settings.Models
|
||||
{
|
||||
public class DefaultTaskSettings
|
||||
{
|
||||
[JsonProperty("media_type")]
|
||||
public MediaType MediaType { get; set; } = MediaType.Original;
|
||||
|
||||
[JsonProperty("video_extension")]
|
||||
public VideoExtension VideoExtension { get; set; } = VideoExtension.MP4;
|
||||
|
||||
[JsonProperty("audio_extension")]
|
||||
public AudioExtension AudioExtension { get; set; } = AudioExtension.MP3;
|
||||
|
||||
[JsonProperty("output_directory")]
|
||||
public string OutputDirectory { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
|
||||
[JsonProperty("save_last_output_directory")]
|
||||
public bool SaveLastOutputDirectory { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.Data.Settings.Models
|
||||
{
|
||||
public class Notifications
|
||||
{
|
||||
[JsonProperty("on_successful")]
|
||||
public bool OnSuccessful { get; set; } = true;
|
||||
|
||||
[JsonProperty("on_unsuccessful")]
|
||||
public bool OnUnsuccessful { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Models;
|
||||
|
||||
namespace VDownload.Services.Data.Settings.Models
|
||||
{
|
||||
public class Processing
|
||||
{
|
||||
[JsonProperty("ffmpeg_location")]
|
||||
public string FFmpegLocation { get; set; } = $"{AppDomain.CurrentDomain.BaseDirectory}\\FFmpeg";
|
||||
|
||||
[JsonProperty("use_multithreading")]
|
||||
public bool UseMultithreading { get; set; } = true;
|
||||
|
||||
[JsonProperty("use_hardware_acceleration")]
|
||||
public bool UseHardwareAcceleration { get; set; } = true;
|
||||
|
||||
[JsonProperty("speed")]
|
||||
public ProcessingSpeed Speed { get; set; } = ProcessingSpeed.UltraFast;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
using VDownload.Sources.Twitch.Settings;
|
||||
|
||||
namespace VDownload.Services.Data.Settings
|
||||
{
|
||||
public class SettingsData
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
[JsonProperty("common")]
|
||||
public CommonSettings Common { get; set; }
|
||||
|
||||
[JsonProperty("twitch")]
|
||||
public TwitchSettings Twitch { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
internal SettingsData()
|
||||
{
|
||||
Common = new CommonSettings();
|
||||
Twitch = new TwitchSettings();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Services.Data.Configuration;
|
||||
|
||||
namespace VDownload.Services.Data.Settings
|
||||
{
|
||||
public interface ISettingsService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
SettingsData Data { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
Task Load();
|
||||
Task Save();
|
||||
Task Restore();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class SettingsService : ISettingsService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
protected readonly string _filePath;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public SettingsData Data { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public SettingsService(IConfigurationService configurationService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
|
||||
string appdataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
string appdataDirectoryName = _configurationService.Common.Path.Appdata.DirectoryName;
|
||||
string appdataAuthenticationFilename = _configurationService.Common.Path.Appdata.SettingsFile;
|
||||
_filePath = Path.Combine(appdataPath, appdataDirectoryName, appdataAuthenticationFilename);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task Load()
|
||||
{
|
||||
Data = null;
|
||||
|
||||
if (File.Exists(_filePath))
|
||||
{
|
||||
string content = await File.ReadAllTextAsync(_filePath);
|
||||
Data = JsonConvert.DeserializeObject<SettingsData>(content);
|
||||
}
|
||||
|
||||
Data ??= new SettingsData();
|
||||
}
|
||||
|
||||
public async Task Save()
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_filePath));
|
||||
string content = JsonConvert.SerializeObject(Data);
|
||||
await File.WriteAllTextAsync(_filePath, content);
|
||||
}
|
||||
|
||||
public async Task Restore()
|
||||
{
|
||||
Data = new SettingsData();
|
||||
await Save();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\VDownload.Models\VDownload.Models.csproj" />
|
||||
<ProjectReference Include="..\..\..\VDownload.Sources\VDownload.Sources.Twitch\VDownload.Sources.Twitch.Settings\VDownload.Sources.Twitch.Settings.csproj" />
|
||||
<ProjectReference Include="..\VDownload.Services.Data.Configuration\VDownload.Services.Data.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,93 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Common;
|
||||
using VDownload.Common.Exceptions;
|
||||
using VDownload.Common.Models;
|
||||
using VDownload.Common.Services;
|
||||
using VDownload.Sources.Twitch;
|
||||
using VDownload.Sources.Twitch.Configuration;
|
||||
using VDownload.Sources.Twitch.Search;
|
||||
|
||||
namespace VDownload.Services.Search
|
||||
{
|
||||
public interface ISearchService
|
||||
{
|
||||
Task<Playlist> SearchPlaylist(string url, int maxVideoCount);
|
||||
Task<Video> SearchVideo(string url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class SearchService : ISearchService
|
||||
{
|
||||
#region FIELDS
|
||||
|
||||
private readonly List<(Regex Regex, ISourceSearchService Service)> _urlMappings;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public SearchService(TwitchConfiguration twitchConfiguration, ITwitchSearchService twitchSearchService)
|
||||
{
|
||||
_urlMappings = new List<(Regex, ISourceSearchService)>();
|
||||
_urlMappings.AddRange(twitchConfiguration.Search.GeneralRegexes.Select(x => (x, (ISourceSearchService)twitchSearchService)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task<Video> SearchVideo(string url)
|
||||
{
|
||||
BaseUrlCheck(url);
|
||||
|
||||
foreach ((Regex Regex, ISourceSearchService Service) mapping in _urlMappings)
|
||||
{
|
||||
if (mapping.Regex.IsMatch(url))
|
||||
{
|
||||
return await mapping.Service.SearchVideo(url);
|
||||
}
|
||||
}
|
||||
throw new MediaSearchException("Source is not supported");
|
||||
}
|
||||
|
||||
public async Task<Playlist> SearchPlaylist(string url, int maxVideoCount)
|
||||
{
|
||||
BaseUrlCheck(url);
|
||||
|
||||
foreach ((Regex Regex, ISourceSearchService Service) mapping in _urlMappings)
|
||||
{
|
||||
if (mapping.Regex.IsMatch(url))
|
||||
{
|
||||
return await mapping.Service.SearchPlaylist(url, maxVideoCount);
|
||||
}
|
||||
}
|
||||
throw new MediaSearchException("Source is not supported");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private void BaseUrlCheck(string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
throw new MediaSearchException("Url cannot be empty");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\VDownload.Common\VDownload.Common.csproj" />
|
||||
<ProjectReference Include="..\..\VDownload.Sources\VDownload.Sources.Twitch\VDownload.Sources.Twitch.Search\VDownload.Sources.Twitch.Search.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,101 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Common;
|
||||
|
||||
namespace VDownload.Services.Tasks
|
||||
{
|
||||
public interface ITasksService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
ObservableCollection<DownloadTask> Tasks { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
void AddTask(DownloadTask task);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class TasksService : ITasksService
|
||||
{
|
||||
#region FIELDS
|
||||
|
||||
private readonly Task _taskMonitor;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public ObservableCollection<DownloadTask> Tasks { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public TasksService()
|
||||
{
|
||||
Tasks = new ObservableCollection<DownloadTask>();
|
||||
|
||||
_taskMonitor = Task.Run(TaskMonitor);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public void AddTask(DownloadTask task)
|
||||
{
|
||||
Tasks.Add(task);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private void TaskMonitor()
|
||||
{
|
||||
int maxTaskNumber = 5; //TODO: from settings
|
||||
DownloadTaskStatus[] pendingStatuses =
|
||||
[
|
||||
DownloadTaskStatus.Initializing,
|
||||
DownloadTaskStatus.Downloading,
|
||||
DownloadTaskStatus.Processing,
|
||||
DownloadTaskStatus.Finalizing
|
||||
];
|
||||
while (true)
|
||||
{
|
||||
IEnumerable<DownloadTask> pendingTasks = Tasks.Where(x => pendingStatuses.Contains(x.Status));
|
||||
int freeSlots = maxTaskNumber - pendingTasks.Count();
|
||||
if (freeSlots > 0)
|
||||
{
|
||||
IEnumerable<DownloadTask> queuedTasks = Tasks.Where(x => x.Status == DownloadTaskStatus.Queued).OrderBy(x => x.CreateDate).Take(freeSlots);
|
||||
foreach (DownloadTask queuedTask in queuedTasks)
|
||||
{
|
||||
queuedTask.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\VDownload.Common\VDownload.Common.csproj" />
|
||||
<ProjectReference Include="..\..\VDownload.Tasks\VDownload.Tasks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Dialogs
|
||||
{
|
||||
public enum DialogResult
|
||||
{
|
||||
Primary,
|
||||
Secondary,
|
||||
Cancelled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Dialogs
|
||||
{
|
||||
public enum DialogResultOkCancel
|
||||
{
|
||||
Ok,
|
||||
Cancel
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Dialogs
|
||||
{
|
||||
public enum DialogResultYesNo
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Dialogs
|
||||
{
|
||||
public enum DialogResultYesNoCancel
|
||||
{
|
||||
Yes,
|
||||
No,
|
||||
Cancelled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Dialogs
|
||||
{
|
||||
public interface IDialogsService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
XamlRoot DefaultRoot { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
Task ShowClose(string title, string message);
|
||||
Task<DialogResult> ShowDouble(string title, string message, string primaryButtonText, string secondaryButtonText);
|
||||
Task ShowOk(string title, string message);
|
||||
Task<DialogResultOkCancel> ShowOkCancel(string title, string message);
|
||||
Task ShowSingle(string title, string message, string buttonText);
|
||||
Task<DialogResult> ShowTriple(string title, string message, string primaryButtonText, string secondaryButtonText, string cancelButtonText);
|
||||
Task<DialogResultYesNo> ShowYesNo(string title, string message);
|
||||
Task<DialogResultYesNoCancel> ShowYesNoCancel(string title, string message);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DialogsService : IDialogsService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public XamlRoot DefaultRoot { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task ShowOk(string title, string message) => await ShowSingle(title, message, "OK");
|
||||
public async Task ShowClose(string title, string message) => await ShowSingle(title, message, "Close");
|
||||
public async Task ShowSingle(string title, string message, string buttonText)
|
||||
{
|
||||
ContentDialog contentDialog = BuildDialog(title, message);
|
||||
contentDialog.CloseButtonText = buttonText;
|
||||
await ShowDialog(contentDialog);
|
||||
}
|
||||
|
||||
public async Task<DialogResultOkCancel> ShowOkCancel(string title, string message) => await ShowDouble(title, message, "OK", "Cancel") switch
|
||||
{
|
||||
DialogResult.Primary => DialogResultOkCancel.Ok,
|
||||
_ => DialogResultOkCancel.Cancel
|
||||
};
|
||||
public async Task<DialogResultYesNo> ShowYesNo(string title, string message) => await ShowDouble(title, message, "Yes", "No") switch
|
||||
{
|
||||
DialogResult.Primary => DialogResultYesNo.Yes,
|
||||
_ => DialogResultYesNo.No
|
||||
};
|
||||
public async Task<DialogResult> ShowDouble(string title, string message, string primaryButtonText, string secondaryButtonText)
|
||||
{
|
||||
ContentDialog contentDialog = BuildDialog(title, message);
|
||||
contentDialog.PrimaryButtonText = primaryButtonText;
|
||||
contentDialog.SecondaryButtonText = secondaryButtonText;
|
||||
return await ShowDialog(contentDialog);
|
||||
}
|
||||
|
||||
public async Task<DialogResultYesNoCancel> ShowYesNoCancel(string title, string message) => await ShowTriple(title, message, "Yes", "No", "Cancel") switch
|
||||
{
|
||||
DialogResult.Primary => DialogResultYesNoCancel.Yes,
|
||||
DialogResult.Secondary => DialogResultYesNoCancel.Yes,
|
||||
_ => DialogResultYesNoCancel.Cancelled
|
||||
};
|
||||
public async Task<DialogResult> ShowTriple(string title, string message, string primaryButtonText, string secondaryButtonText, string cancelButtonText)
|
||||
{
|
||||
ContentDialog contentDialog = BuildDialog(title, message);
|
||||
contentDialog.PrimaryButtonText = primaryButtonText;
|
||||
contentDialog.SecondaryButtonText = secondaryButtonText;
|
||||
contentDialog.CloseButtonText = cancelButtonText;
|
||||
return await ShowDialog(contentDialog);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private ContentDialog BuildDialog(string title, string message)
|
||||
{
|
||||
return new ContentDialog()
|
||||
{
|
||||
Title = title,
|
||||
Content = message,
|
||||
XamlRoot = DefaultRoot
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<DialogResult> ShowDialog(ContentDialog dialog)
|
||||
{
|
||||
ContentDialogResult result = await dialog.ShowAsync();
|
||||
return result switch
|
||||
{
|
||||
ContentDialogResult.Primary => DialogResult.Primary,
|
||||
ContentDialogResult.Secondary => DialogResult.Secondary,
|
||||
_ => DialogResult.Cancelled
|
||||
}; ;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.Dialogs</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.DictionaryResources
|
||||
{
|
||||
public interface IDictionaryResourcesService
|
||||
{
|
||||
T Get<T>(string key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class DictionaryResourcesService : IDictionaryResourcesService
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public DictionaryResourcesService() { }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public T Get<T>(string key)
|
||||
{
|
||||
Application.Current.Resources.TryGetValue(key, out object value);
|
||||
if (value is not null && value is T cast)
|
||||
{
|
||||
return cast;
|
||||
}
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.DictionaryResources</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.230913002" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.Windows.AppNotifications;
|
||||
using Microsoft.Windows.AppNotifications.Builder;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.Notifications
|
||||
{
|
||||
public interface INotificationsService
|
||||
{
|
||||
void SendNotification(string title, IEnumerable<string> message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class NotificationsService : INotificationsService
|
||||
{
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public void SendNotification(string title, IEnumerable<string> message)
|
||||
{
|
||||
AppNotificationBuilder builder = new AppNotificationBuilder();
|
||||
builder.AddText(title);
|
||||
foreach (string text in message)
|
||||
{
|
||||
builder.AddText(text);
|
||||
}
|
||||
AppNotification notification = builder.BuildNotification();
|
||||
AppNotificationManager.Default.Show(notification);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.Notifications</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.StoragePicker
|
||||
{
|
||||
public class FileSavePickerFileTypeChoice
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public string Description { get; private set; }
|
||||
public IEnumerable<string> Extensions { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public FileSavePickerFileTypeChoice(string description, string[] extensions)
|
||||
{
|
||||
Description = description;
|
||||
Extensions = extensions.Select(x => x.StartsWith('.') ? x : $".{x}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace VDownload.Services.UI.StoragePicker
|
||||
{
|
||||
public interface IStoragePickerService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
Window DefaultRoot { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region METHODS
|
||||
|
||||
Task<string?> OpenDirectory();
|
||||
Task<string?> OpenDirectory(StoragePickerStartLocation startLocation);
|
||||
Task<IEnumerable<string>> OpenMultipleFiles();
|
||||
Task<IEnumerable<string>> OpenMultipleFiles(StoragePickerStartLocation startLocation);
|
||||
Task<IEnumerable<string>> OpenMultipleFiles(string[] fileTypes);
|
||||
Task<IEnumerable<string>> OpenMultipleFiles(string[] fileTypes, StoragePickerStartLocation startLocation);
|
||||
Task<string?> OpenSingleFile();
|
||||
Task<string?> OpenSingleFile(StoragePickerStartLocation startLocation);
|
||||
Task<string?> OpenSingleFile(string[] fileTypes);
|
||||
Task<string?> OpenSingleFile(string[] fileTypes, StoragePickerStartLocation startLocation);
|
||||
Task<string?> SaveFile(FileSavePickerFileTypeChoice[] fileTypes, string defaultFileType);
|
||||
Task<string?> SaveFile(FileSavePickerFileTypeChoice[] fileTypes, string defaultFileType, StoragePickerStartLocation startLocation);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class StoragePickerService : IStoragePickerService
|
||||
{
|
||||
#region PROPERTIES
|
||||
|
||||
public Window DefaultRoot { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public async Task<string?> OpenDirectory() => await OpenDirectory(StoragePickerStartLocation.Unspecified);
|
||||
public async Task<string?> OpenDirectory(StoragePickerStartLocation startLocation)
|
||||
{
|
||||
FolderPicker picker = new FolderPicker();
|
||||
InitializePicker(picker);
|
||||
|
||||
ConfigureFolderPicker(picker, startLocation);
|
||||
|
||||
StorageFolder directory = await picker.PickSingleFolderAsync();
|
||||
return directory?.Path;
|
||||
}
|
||||
|
||||
public async Task<string?> OpenSingleFile() => await OpenSingleFile(["*"], StoragePickerStartLocation.Unspecified);
|
||||
public async Task<string?> OpenSingleFile(string[] fileTypes) => await OpenSingleFile(fileTypes, StoragePickerStartLocation.Unspecified);
|
||||
public async Task<string?> OpenSingleFile(StoragePickerStartLocation startLocation) => await OpenSingleFile(["*"], startLocation);
|
||||
public async Task<string?> OpenSingleFile(string[] fileTypes, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
FileOpenPicker picker = new FileOpenPicker();
|
||||
InitializePicker(picker);
|
||||
|
||||
ConfigureFileOpenPicker(picker, fileTypes, startLocation);
|
||||
|
||||
StorageFile storageFile = await picker.PickSingleFileAsync();
|
||||
return storageFile?.Path;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<string>> OpenMultipleFiles() => await OpenMultipleFiles(["*"], StoragePickerStartLocation.Unspecified);
|
||||
public async Task<IEnumerable<string>> OpenMultipleFiles(string[] fileTypes) => await OpenMultipleFiles(fileTypes, StoragePickerStartLocation.Unspecified);
|
||||
public async Task<IEnumerable<string>> OpenMultipleFiles(StoragePickerStartLocation startLocation) => await OpenMultipleFiles(["*"], startLocation);
|
||||
public async Task<IEnumerable<string>> OpenMultipleFiles(string[] fileTypes, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
FileOpenPicker picker = new FileOpenPicker();
|
||||
InitializePicker(picker);
|
||||
|
||||
ConfigureFileOpenPicker(picker, fileTypes, startLocation);
|
||||
|
||||
IEnumerable<StorageFile> list = await picker.PickMultipleFilesAsync();
|
||||
return list.Select(x => x.Path);
|
||||
}
|
||||
|
||||
public async Task<string?> SaveFile(FileSavePickerFileTypeChoice[] fileTypes, string defaultFileType) => await SaveFile(fileTypes, defaultFileType, StoragePickerStartLocation.Unspecified);
|
||||
public async Task<string?> SaveFile(FileSavePickerFileTypeChoice[] fileTypes, string defaultFileType, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
FileSavePicker picker = new FileSavePicker();
|
||||
InitializePicker(picker);
|
||||
|
||||
ConfigureFileSavePicker(picker, fileTypes, defaultFileType, startLocation);
|
||||
|
||||
StorageFile file = await picker.PickSaveFileAsync();
|
||||
return file?.Path;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected void InitializePicker(object picker)
|
||||
{
|
||||
var hwnd = WindowNative.GetWindowHandle(DefaultRoot);
|
||||
InitializeWithWindow.Initialize(picker, hwnd);
|
||||
}
|
||||
|
||||
protected void ConfigureFolderPicker(FolderPicker picker, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
if (startLocation != StoragePickerStartLocation.Unspecified)
|
||||
{
|
||||
picker.SuggestedStartLocation = (PickerLocationId)startLocation;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ConfigureFileOpenPicker(FileOpenPicker picker, string[] fileTypes, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
foreach (string fileType in fileTypes)
|
||||
{
|
||||
picker.FileTypeFilter.Add(fileType);
|
||||
}
|
||||
|
||||
if (startLocation != StoragePickerStartLocation.Unspecified)
|
||||
{
|
||||
picker.SuggestedStartLocation = (PickerLocationId)startLocation;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ConfigureFileSavePicker(FileSavePicker picker, FileSavePickerFileTypeChoice[] fileTypes, string defaultFileType, StoragePickerStartLocation startLocation)
|
||||
{
|
||||
if (startLocation != StoragePickerStartLocation.Unspecified)
|
||||
{
|
||||
picker.SuggestedStartLocation = (PickerLocationId)startLocation;
|
||||
}
|
||||
|
||||
foreach (FileSavePickerFileTypeChoice fileType in fileTypes)
|
||||
{
|
||||
picker.FileTypeChoices.Add(fileType.Description, fileType.Extensions.ToList());
|
||||
}
|
||||
|
||||
if (!defaultFileType.StartsWith('.'))
|
||||
{
|
||||
defaultFileType = $".{defaultFileType}";
|
||||
}
|
||||
|
||||
if (!fileTypes.Any(x => x.Extensions.Contains(defaultFileType)))
|
||||
{
|
||||
picker.FileTypeChoices.Add("Default", [defaultFileType]);
|
||||
}
|
||||
|
||||
picker.DefaultFileExtension = defaultFileType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.StoragePicker
|
||||
{
|
||||
public enum StoragePickerStartLocation
|
||||
{
|
||||
Documents = 0,
|
||||
Computer = 1,
|
||||
Desktop = 2,
|
||||
Downloads = 3,
|
||||
Music = 5,
|
||||
Pictures = 6,
|
||||
Videos = 7,
|
||||
Unspecified = 999
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.StoragePicker</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,37 @@
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.StringResources
|
||||
{
|
||||
public class StringResources
|
||||
{
|
||||
#region FIELDS
|
||||
|
||||
protected ResourceLoader _resourceLoader;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
internal StringResources(ResourceLoader resourceLoader)
|
||||
{
|
||||
_resourceLoader = resourceLoader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public string Get(string key) => _resourceLoader.GetString(key);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using VDownload.Services.Data.Configuration;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace VDownload.Services.UI.StringResources
|
||||
{
|
||||
public interface IStringResourcesService
|
||||
{
|
||||
StringResources BaseViewResources { get; }
|
||||
StringResources HomeViewResources { get; }
|
||||
StringResources HomeVideoViewResources { get; }
|
||||
StringResources HomeDownloadsViewResources { get; }
|
||||
StringResources AuthenticationViewResources { get; }
|
||||
StringResources NotificationsResources { get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class StringResourcesService : IStringResourcesService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PROPERTIES
|
||||
|
||||
public StringResources BaseViewResources { get; protected set; }
|
||||
public StringResources HomeViewResources { get; protected set; }
|
||||
public StringResources HomeVideoViewResources { get; protected set; }
|
||||
public StringResources HomeDownloadsViewResources { get; protected set; }
|
||||
public StringResources AuthenticationViewResources { get; protected set; }
|
||||
public StringResources NotificationsResources { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public StringResourcesService(IConfigurationService configurationService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
|
||||
BaseViewResources = BuildResource("BaseViewResources");
|
||||
HomeViewResources = BuildResource("HomeViewResources");
|
||||
HomeVideoViewResources = BuildResource("HomeVideoViewResources");
|
||||
HomeDownloadsViewResources = BuildResource("HomeDownloadsViewResources");
|
||||
AuthenticationViewResources = BuildResource("AuthenticationViewResources");
|
||||
NotificationsResources = BuildResource("NotificationsResources");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected StringResources BuildResource(string resourceName) => new StringResources(ResourceLoader.GetForViewIndependentUse($"{_configurationService.Common.StringResourcesAssembly}/{resourceName}"));
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.StringResources</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.230913002" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\VDownload.Core\VDownload.Core.Strings\VDownload.Core.Strings.csproj" />
|
||||
<ProjectReference Include="..\..\VDownload.Services.Data\VDownload.Services.Data.Configuration\VDownload.Services.Data.Configuration.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RootNamespace>VDownload.Services.UI.WebView</RootNamespace>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<UseRidGraph>true</UseRidGraph>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="WebViewWindow.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="WebViewWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.UI.WebView
|
||||
{
|
||||
public interface IWebViewService
|
||||
{
|
||||
Task<string> Show(Uri url, Predicate<string> closePredicate, string name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class WebViewService : IWebViewService
|
||||
{
|
||||
#region METHODS
|
||||
|
||||
public async Task<string> Show(Uri url, Predicate<string> closePredicate, string name)
|
||||
{
|
||||
WebViewWindow window = new WebViewWindow(name);
|
||||
return await window.Show(url, closePredicate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Window
|
||||
x:Class="VDownload.Services.UI.WebView.WebViewWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:VDownload.Services.UI.WebView"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Closed="Window_Closed">
|
||||
<WebView2 x:Name="WebView" NavigationCompleted="WebView_NavigationCompleted"/>
|
||||
</Window>
|
||||
@@ -0,0 +1,89 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
namespace VDownload.Services.UI.WebView
|
||||
{
|
||||
public sealed partial class WebViewWindow : Window
|
||||
{
|
||||
#region FIEDLS
|
||||
|
||||
private readonly Predicate<string> _defaultClosePredicate = args => false;
|
||||
|
||||
private bool _isOpened;
|
||||
private Predicate<string> _closePredicate;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public WebViewWindow(string name)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.Title = name;
|
||||
|
||||
_isOpened = false;
|
||||
_closePredicate = _defaultClosePredicate;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
internal async Task<string> Show(Uri url, Predicate<string> closePredicate)
|
||||
{
|
||||
this.WebView.Source = url;
|
||||
_closePredicate = closePredicate;
|
||||
|
||||
this.Activate();
|
||||
_isOpened = true;
|
||||
while (_isOpened)
|
||||
{
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
_closePredicate = _defaultClosePredicate;
|
||||
|
||||
return this.WebView.Source.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region EVENT HANDLER
|
||||
|
||||
|
||||
private void WebView_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args)
|
||||
{
|
||||
if (_closePredicate.Invoke(this.WebView.Source.ToString()))
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Closed(object sender, WindowEventArgs args)
|
||||
{
|
||||
_isOpened = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Security.Cryptography;
|
||||
using System.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VDownload.Services.Encryption
|
||||
namespace VDownload.Services.Utility.Encryption
|
||||
{
|
||||
public interface IEncryptionService
|
||||
{
|
||||
@@ -0,0 +1,191 @@
|
||||
using FFMpegCore;
|
||||
using FFMpegCore.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Models;
|
||||
using VDownload.Services.Data.Configuration;
|
||||
using VDownload.Services.Data.Settings;
|
||||
|
||||
namespace VDownload.Services.Utility.FFmpeg
|
||||
{
|
||||
public class FFmpegBuilder
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
protected readonly ISettingsService _settingsService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
protected TimeSpan? _trimStart;
|
||||
protected TimeSpan? _trimEnd;
|
||||
|
||||
protected bool _progressReporterJoined = false;
|
||||
protected Action<double> _progressReporter;
|
||||
protected TimeSpan _progressReporterVideoDuration;
|
||||
|
||||
protected bool _cancellationTokenJoined = false;
|
||||
protected CancellationToken _cancellationToken;
|
||||
|
||||
protected MediaType _mediaType = MediaType.Original;
|
||||
|
||||
protected string _inputFile;
|
||||
protected string _outputFile;
|
||||
|
||||
protected FFOptions _options;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
internal FFmpegBuilder(IConfigurationService configurationService, ISettingsService settingsService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_settingsService = settingsService;
|
||||
|
||||
_options = new FFOptions
|
||||
{
|
||||
BinaryFolder = _settingsService.Data.Common.Processing.FFmpegLocation,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public FFmpegBuilder SetMediaType(MediaType mediaType)
|
||||
{
|
||||
_mediaType = mediaType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FFmpegBuilder TrimStart(TimeSpan start)
|
||||
{
|
||||
_trimStart = start;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FFmpegBuilder TrimEnd(TimeSpan end)
|
||||
{
|
||||
_trimEnd = end;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FFmpegBuilder JoinProgressReporter(Action<double> progressReporter, TimeSpan videoDuration)
|
||||
{
|
||||
_progressReporterJoined = true;
|
||||
_progressReporter = progressReporter;
|
||||
_progressReporterVideoDuration = videoDuration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FFmpegBuilder JoinCancellationToken(CancellationToken cancellationToken)
|
||||
{
|
||||
_cancellationTokenJoined = true;
|
||||
_cancellationToken = cancellationToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
public async Task RunAsync(string inputFile, string outputFile)
|
||||
{
|
||||
_inputFile = inputFile;
|
||||
_outputFile = outputFile;
|
||||
|
||||
FFMpegArgumentProcessor ffmpegArguments = FFMpegArguments.FromFileInput(inputFile, true, async (options) => await BuildInputArgumentOptions(options))
|
||||
.OutputToFile(outputFile, true, async (options) => await BuildOutputArgumentOptions(options));
|
||||
|
||||
if (_cancellationTokenJoined)
|
||||
{
|
||||
ffmpegArguments = ffmpegArguments.CancellableThrough(_cancellationToken);
|
||||
}
|
||||
|
||||
if (_progressReporterJoined)
|
||||
{
|
||||
ffmpegArguments = ffmpegArguments.NotifyOnProgress(_progressReporter, _progressReporterVideoDuration);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await ffmpegArguments.ProcessAsynchronously(true, _options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private async Task BuildInputArgumentOptions(FFMpegArgumentOptions options)
|
||||
{
|
||||
options.UsingMultithreading(_settingsService.Data.Common.Processing.UseMultithreading);
|
||||
options.WithSpeedPreset((Speed)_settingsService.Data.Common.Processing.Speed);
|
||||
if (_settingsService.Data.Common.Processing.UseHardwareAcceleration)
|
||||
{
|
||||
options.WithHardwareAcceleration(HardwareAccelerationDevice.Auto);
|
||||
}
|
||||
|
||||
if (_trimStart is not null)
|
||||
{
|
||||
options.WithCustomArgument($"-ss {_trimStart}");
|
||||
}
|
||||
|
||||
if (_trimEnd is not null)
|
||||
{
|
||||
options.WithCustomArgument($"-to {_trimEnd}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task BuildOutputArgumentOptions(FFMpegArgumentOptions options)
|
||||
{
|
||||
IMediaAnalysis analysis = await FFProbe.AnalyseAsync(_inputFile, _options);
|
||||
string audioCodec = analysis.AudioStreams.First().CodecName;
|
||||
string videoCodec = analysis.VideoStreams.First().CodecName;
|
||||
|
||||
string extension = Path.GetExtension(_outputFile).Replace(".", string.Empty);
|
||||
Data.Configuration.Models.Muxer muxer = _configurationService.Common.Processing.Muxers.First(x => x.Extension == extension);
|
||||
|
||||
if (_mediaType != MediaType.OnlyAudio)
|
||||
{
|
||||
IEnumerable<string> availableCodecs = muxer.VideoCodecs;
|
||||
string selectedCodec = availableCodecs.Contains(videoCodec) ? "copy" : availableCodecs.First();
|
||||
options.WithCustomArgument($"-vcodec {selectedCodec}");
|
||||
}
|
||||
else
|
||||
{
|
||||
options.WithCustomArgument("-vn");
|
||||
}
|
||||
|
||||
if (_mediaType != MediaType.OnlyVideo)
|
||||
{
|
||||
IEnumerable<string> availableCodecs = muxer.AudioCodecs;
|
||||
string selectedCodec = availableCodecs.Contains(audioCodec) ? "copy" : availableCodecs.First();
|
||||
options.WithCustomArgument($"-acodec {selectedCodec}");
|
||||
}
|
||||
else
|
||||
{
|
||||
options.WithCustomArgument("-an");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using FFMpegCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VDownload.Services.Data.Configuration;
|
||||
using VDownload.Services.Data.Settings;
|
||||
|
||||
namespace VDownload.Services.Utility.FFmpeg
|
||||
{
|
||||
public interface IFFmpegService
|
||||
{
|
||||
FFmpegBuilder CreateBuilder();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class FFmpegService : IFFmpegService
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
protected readonly IConfigurationService _configurationService;
|
||||
protected readonly ISettingsService _settingsService;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public FFmpegService(IConfigurationService configurationService, ISettingsService settingsService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_settingsService = settingsService;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PUBLIC METHODS
|
||||
|
||||
public FFmpegBuilder CreateBuilder() => new FFmpegBuilder(_configurationService, _settingsService);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FFMpegCore" Version="5.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\VDownload.Models\VDownload.Models.csproj" />
|
||||
<ProjectReference Include="..\..\VDownload.Services.Data\VDownload.Services.Data.Settings\VDownload.Services.Data.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -9,7 +9,7 @@ using System.Xml.Serialization;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Collections;
|
||||
|
||||
namespace VDownload.Services.HttpClient
|
||||
namespace VDownload.Services.Utility.HttpClient
|
||||
{
|
||||
public interface IHttpClientService
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.HttpClient
|
||||
namespace VDownload.Services.Utility.HttpClient
|
||||
{
|
||||
public enum HttpMethodType
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.HttpClient
|
||||
namespace VDownload.Services.Utility.HttpClient
|
||||
{
|
||||
public class HttpRequest
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VDownload.Services.HttpClient
|
||||
namespace VDownload.Services.Utility.HttpClient
|
||||
{
|
||||
public class Token
|
||||
{
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace VDownload.Services
|
||||
{
|
||||
public class ServiceProvider
|
||||
{
|
||||
#region CONSTRUCTORS
|
||||
|
||||
public static IServiceProvider Instance { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user