Projektdateien hinzufügen.
This commit is contained in:
46
VideoBrowser/Helpers/BindingProxy.cs
Normal file
46
VideoBrowser/Helpers/BindingProxy.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System.Windows;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="BindingProxy" />.
|
||||
/// </summary>
|
||||
public class BindingProxy : Freezable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// The binding data context property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DataProperty =
|
||||
DependencyProperty.Register(nameof(DataContext), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DataContext.
|
||||
/// </summary>
|
||||
public object DataContext
|
||||
{
|
||||
get { return GetValue(DataProperty); }
|
||||
set { SetValue(DataProperty, value); }
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The CreateInstanceCore.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Freezable"/>.</returns>
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new BindingProxy();
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
27
VideoBrowser/Helpers/DebugHelper.cs
Normal file
27
VideoBrowser/Helpers/DebugHelper.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the <see cref="DebugHelper" />.
|
||||
/// </summary>
|
||||
public class DebugHelper
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether IsDebug.
|
||||
/// </summary>
|
||||
internal static bool IsDebug
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
}
|
||||
}
|
||||
104
VideoBrowser/Helpers/DelayCall.cs
Normal file
104
VideoBrowser/Helpers/DelayCall.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="DelayCall" />.
|
||||
/// </summary>
|
||||
public class DelayCall
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DelayCall"/> class.
|
||||
/// </summary>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
/// <param name="milliSecondDelay">The milliSecondDelay<see cref="int"/>.</param>
|
||||
/// <param name="callInUIThread">The callInUIThread<see cref="bool"/>.</param>
|
||||
public DelayCall(Action action, int milliSecondDelay, bool callInUIThread = false)
|
||||
{
|
||||
this.Action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
this.MilliSecondDelay = milliSecondDelay;
|
||||
this.IsCallInUIThread = callInUIThread;
|
||||
this.Timer = new Timer();
|
||||
this.Timer.Tick += this.OnTimer_Tick;
|
||||
this.Timer.Interval = this.MilliSecondDelay;
|
||||
this.Timer.Stop();
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Action.
|
||||
/// </summary>
|
||||
public Action Action { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether IsCallInUIThread.
|
||||
/// </summary>
|
||||
public bool IsCallInUIThread { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the MilliSecondDelay.
|
||||
/// </summary>
|
||||
public int MilliSecondDelay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Timer.
|
||||
/// </summary>
|
||||
public Timer Timer { get; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The Call.
|
||||
/// </summary>
|
||||
public void Call()
|
||||
{
|
||||
this.Restart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnThick.
|
||||
/// </summary>
|
||||
/// <param name="state">The state<see cref="object"/>.</param>
|
||||
private void OnThick(object state)
|
||||
{
|
||||
this.Timer.Stop();
|
||||
if (this.IsCallInUIThread)
|
||||
{
|
||||
UIThreadHelper.Invoke(this.Action);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Action();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OnTimer_Tick.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender<see cref="object"/>.</param>
|
||||
/// <param name="e">The e<see cref="EventArgs"/>.</param>
|
||||
private void OnTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Restart.
|
||||
/// </summary>
|
||||
private void Restart()
|
||||
{
|
||||
this.Timer.Stop();
|
||||
this.Timer.Start();
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
1027
VideoBrowser/Helpers/FFMpeg.cs
Normal file
1027
VideoBrowser/Helpers/FFMpeg.cs
Normal file
File diff suppressed because it is too large
Load Diff
27
VideoBrowser/Helpers/FFMpegFileType.cs
Normal file
27
VideoBrowser/Helpers/FFMpegFileType.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Defines the FFMpegFileType
|
||||
/// </summary>
|
||||
public enum FFMpegFileType
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the Audio
|
||||
/// </summary>
|
||||
Audio,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the Error
|
||||
/// </summary>
|
||||
Error,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the Video
|
||||
/// </summary>
|
||||
Video
|
||||
}
|
||||
|
||||
#endregion Enums
|
||||
}
|
||||
1050
VideoBrowser/Helpers/FFMpegHelper.cs
Normal file
1050
VideoBrowser/Helpers/FFMpegHelper.cs
Normal file
File diff suppressed because it is too large
Load Diff
72
VideoBrowser/Helpers/FFMpegResult.cs
Normal file
72
VideoBrowser/Helpers/FFMpegResult.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="FFMpegResult{T}" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class FFMpegResult<T>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FFMpegResult{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="exitCode">The exitCode<see cref="int"/></param>
|
||||
/// <param name="errors">The errors<see cref="IEnumerable{string}"/></param>
|
||||
public FFMpegResult(int exitCode, IEnumerable<string> errors)
|
||||
{
|
||||
this.Value = default(T);
|
||||
this.ExitCode = exitCode;
|
||||
this.Errors = new List<string>(errors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FFMpegResult{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="result">The result<see cref="T"/></param>
|
||||
public FFMpegResult(T result)
|
||||
{
|
||||
this.Value = result;
|
||||
this.ExitCode = 0;
|
||||
this.Errors = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FFMpegResult{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The value<see cref="T"/></param>
|
||||
/// <param name="exitCode">The exitCode<see cref="int"/></param>
|
||||
/// <param name="errors">The errors<see cref="IEnumerable{string}"/></param>
|
||||
public FFMpegResult(T value, int exitCode, IEnumerable<string> errors)
|
||||
{
|
||||
this.Value = value;
|
||||
this.ExitCode = exitCode;
|
||||
this.Errors = new List<string>(errors);
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Errors
|
||||
/// Gets a list of errors from running FFmpeg. Returns null if there wasn't any errors.
|
||||
/// </summary>
|
||||
public List<string> Errors { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ExitCode
|
||||
/// Gets the FFmpeg exit code.
|
||||
/// </summary>
|
||||
public int ExitCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the result value.
|
||||
/// </summary>
|
||||
public T Value { get; private set; }
|
||||
|
||||
#endregion Properties
|
||||
}
|
||||
}
|
||||
139
VideoBrowser/Helpers/FileHelper.cs
Normal file
139
VideoBrowser/Helpers/FileHelper.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="FileHelper" />
|
||||
/// </summary>
|
||||
public static class FileHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns valid file name.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename to validate.</param>
|
||||
public static string GetValidFilename(string filename)
|
||||
{
|
||||
var illegalChars = Path.GetInvalidFileNameChars();
|
||||
|
||||
// Check if filename contains illegal characters
|
||||
// Returning true for some reason: valid = filename.Any(x => illegalChars.Contains(x));
|
||||
var valid = filename.IndexOfAny(illegalChars) <= -1;
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
string new_filename = YoutubeHelper.FormatTitle(filename);
|
||||
filename = new_filename;
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to delete given file(s), ignoring exceptions for 10 tries, with 2 second delay between each try.
|
||||
/// </summary>
|
||||
/// <param name="files">The files to delete.</param>
|
||||
public static void DeleteFiles(params string[] files)
|
||||
{
|
||||
new Thread(delegate ()
|
||||
{
|
||||
var dict = new Dictionary<string, int>();
|
||||
var keys = new List<string>();
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
dict.Add(file, 0);
|
||||
keys.Add(file);
|
||||
}
|
||||
|
||||
while (dict.Count > 0)
|
||||
{
|
||||
foreach (string key in keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(key))
|
||||
{
|
||||
File.Delete(key);
|
||||
}
|
||||
|
||||
// Remove file from dictionary since it either got deleted
|
||||
// or it doesn't exist anymore.
|
||||
dict.Remove(key);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (dict[key] == 10)
|
||||
{
|
||||
dict.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
dict[key]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GetDirectorySize
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory<see cref="string"/></param>
|
||||
/// <returns>The <see cref="long"/></returns>
|
||||
public static long GetDirectorySize(string directory)
|
||||
{
|
||||
return Directory
|
||||
.GetFiles(directory, "*.*", SearchOption.AllDirectories)
|
||||
.Sum(f => new FileInfo(f).Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GetDirectorySizeFormatted
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory<see cref="string"/></param>
|
||||
/// <returns>The <see cref="string"/></returns>
|
||||
public static string GetDirectorySizeFormatted(string directory) => FormatString.FormatFileSize(GetDirectorySize(directory));
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the ETA (estimated time of accomplishment).
|
||||
/// </summary>
|
||||
/// <param name="speed">The speed as bytes. (Bytes per second?)</param>
|
||||
/// <param name="totalBytes">The total amount of bytes.</param>
|
||||
/// <param name="downloadedBytes">The amount of downloaded bytes.</param>
|
||||
/// <returns>The <see cref="long"/></returns>
|
||||
public static long GetETA(int speed, long totalBytes, long downloadedBytes)
|
||||
{
|
||||
if (speed == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var remainBytes = totalBytes - downloadedBytes;
|
||||
return remainBytes / speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a long of the file size from given file in bytes.
|
||||
/// </summary>
|
||||
/// <param name="file">The file to get file size from.</param>
|
||||
/// <returns>The <see cref="long"/></returns>
|
||||
public static long GetFileSize(string file) => !File.Exists(file) ? 0 : new FileInfo(file).Length;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an formatted string of the given file's size.
|
||||
/// </summary>
|
||||
/// <param name="file">The file<see cref="string"/></param>
|
||||
/// <returns>The <see cref="string"/></returns>
|
||||
public static string GetFileSizeFormatted(string file) => FormatString.FormatFileSize(GetFileSize(file));
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
90
VideoBrowser/Helpers/Format.cs
Normal file
90
VideoBrowser/Helpers/Format.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System;
|
||||
using VideoBrowser.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="FormatString" />.
|
||||
/// </summary>
|
||||
public static class FormatString
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static readonly string[] TimeUnitsNames = { "Milli", "Sec", "Min", "Hour", "Day", "Month", "Year", "Decade", "Century" };
|
||||
|
||||
private static int[] TimeUnitsValue = { 1000, 60, 60, 24, 30, 12, 10, 10 };// Reference unit is milli
|
||||
|
||||
#endregion Fields
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a formatted string of the given file size.
|
||||
/// </summary>
|
||||
/// <param name="size">The file size as long to format.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FormatFileSize(this long size)
|
||||
{
|
||||
return string.Format(new ByteFormatProvider(), "{0:fs}", size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The FormatLeftTime.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">The milliseconds<see cref="long"/>.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FormatLeftTime(this long milliseconds)
|
||||
{
|
||||
var format = "";
|
||||
for (var i = 0; i < TimeUnitsValue.Length; i++)
|
||||
{
|
||||
var y = milliseconds % TimeUnitsValue[i];
|
||||
milliseconds = milliseconds / TimeUnitsValue[i];
|
||||
|
||||
if (y == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
format = y + " " + TimeUnitsNames[i] + " , " + format;
|
||||
}
|
||||
|
||||
format = format.Trim(',', ' ');
|
||||
return format == "" ? "0 Sec" : format;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a formatted string of the video length.
|
||||
/// </summary>
|
||||
/// <param name="duration">The video duration as long.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FormatVideoLength(this long duration)
|
||||
{
|
||||
return FormatVideoLength(TimeSpan.FromSeconds(duration));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a formatted string of the video length.
|
||||
/// </summary>
|
||||
/// <param name="duration">The video duration as TimeSpan.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FormatVideoLength(this TimeSpan duration)
|
||||
{
|
||||
return duration.Hours > 0
|
||||
? string.Format("{0}:{1:00}:{2:00}", duration.Hours, duration.Minutes, duration.Seconds)
|
||||
: string.Format("{0}:{1:00}", duration.Minutes, duration.Seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The GetDirectorySizeFormatted.
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory<see cref="string"/>.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string GetDirectorySizeFormatted(this string directory)
|
||||
{
|
||||
return FormatFileSize(FileHelper.GetDirectorySize(directory));
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
33
VideoBrowser/Helpers/ImageHelper.cs
Normal file
33
VideoBrowser/Helpers/ImageHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System.Drawing;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ImageHelper" />.
|
||||
/// </summary>
|
||||
public static class ImageHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The ToImageSource.
|
||||
/// </summary>
|
||||
/// <param name="icon">The icon<see cref="Icon"/>.</param>
|
||||
/// <returns>The <see cref="ImageSource"/>.</returns>
|
||||
public static ImageSource ToImageSource(this Icon icon)
|
||||
{
|
||||
var imageSource = Imaging.CreateBitmapSourceFromHIcon(
|
||||
icon.Handle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
|
||||
return imageSource;
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
82
VideoBrowser/Helpers/ProcessHelper.cs
Normal file
82
VideoBrowser/Helpers/ProcessHelper.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using VideoBrowser.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="ProcessHelper" />
|
||||
/// </summary>
|
||||
public static class ProcessHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Process with the given arguments, then returns it.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The fileName<see cref="string"/></param>
|
||||
/// <param name="arguments">The arguments<see cref="string"/></param>
|
||||
/// <param name="output">The output<see cref="Action{Process, string}"/></param>
|
||||
/// <param name="error">The error<see cref="Action{Process, string}"/></param>
|
||||
/// <param name="environmentVariables">The environmentVariables<see cref="Dictionary{string, string}"/></param>
|
||||
/// <returns>The <see cref="Process"/></returns>
|
||||
public static Process StartProcess(string fileName,
|
||||
string arguments,
|
||||
Action<Process, string> output,
|
||||
Action<Process, string> error,
|
||||
Dictionary<string, string> environmentVariables)
|
||||
{
|
||||
var psi = new ProcessStartInfo(fileName, arguments)
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
WorkingDirectory = AppEnvironment.GetLogsDirectory()
|
||||
};
|
||||
|
||||
if (environmentVariables != null)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> pair in environmentVariables)
|
||||
psi.EnvironmentVariables.Add(pair.Key, pair.Value);
|
||||
}
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
EnableRaisingEvents = true,
|
||||
StartInfo = psi
|
||||
};
|
||||
|
||||
process.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Info(e.Data);
|
||||
output?.Invoke(process, e.Data);
|
||||
};
|
||||
process.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Info(e.Data);
|
||||
error?.Invoke(process, e.Data);
|
||||
};
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
return process;
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
112
VideoBrowser/Helpers/UIThreadHelper.cs
Normal file
112
VideoBrowser/Helpers/UIThreadHelper.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="UIThreadHelper" />.
|
||||
/// </summary>
|
||||
public static class UIThreadHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The DelayedInvokeAsync.
|
||||
/// </summary>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
/// <param name="milliSecondsDelay">The milliSecondsDelay<see cref="int"/>.</param>
|
||||
public static void DelayedInvokeAsync(Action action, int milliSecondsDelay)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(milliSecondsDelay);
|
||||
InvokeAsync(action);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Invoke.
|
||||
/// </summary>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
public static void Invoke(Action action)
|
||||
{
|
||||
if (Application.Current == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dispatcher = Application.Current.Dispatcher;
|
||||
if (dispatcher.CheckAccess())
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.Invoke(() => action?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Invoke.
|
||||
/// </summary>
|
||||
/// <param name="dispatcherObject">The dispatcherObject<see cref="DispatcherObject"/>.</param>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
public static void Invoke(this DispatcherObject dispatcherObject, Action action)
|
||||
{
|
||||
var dispatcher = dispatcherObject.Dispatcher;
|
||||
if (dispatcher.CheckAccess())
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.Invoke(() => action?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The InvokeAsync.
|
||||
/// </summary>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
public static void InvokeAsync(Action action)
|
||||
{
|
||||
if (Application.Current == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.InvokeAsync(action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The InvokeAsync.
|
||||
/// </summary>
|
||||
/// <param name="dispatcher">The dispatcher<see cref="Dispatcher"/>.</param>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
public static void InvokeAsync(this Dispatcher dispatcher, Action action)
|
||||
{
|
||||
if (dispatcher.CheckAccess())
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.InvokeAsync(() => action?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The InvokeAsync.
|
||||
/// </summary>
|
||||
/// <param name="dispatcherObject">The dispatcherObject<see cref="DispatcherObject"/>.</param>
|
||||
/// <param name="action">The action<see cref="Action"/>.</param>
|
||||
public static void InvokeAsync(this DispatcherObject dispatcherObject, Action action)
|
||||
{
|
||||
dispatcherObject.Dispatcher.InvokeAsync(action);
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
53
VideoBrowser/Helpers/UrlHelper.cs
Normal file
53
VideoBrowser/Helpers/UrlHelper.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="UrlHelper" />.
|
||||
/// </summary>
|
||||
internal static class UrlHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// The GetValidUrl.
|
||||
/// </summary>
|
||||
/// <param name="url">The url<see cref="string"/>.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string GetValidUrl(string url)
|
||||
{
|
||||
if (!IsValidUrl(url))
|
||||
{
|
||||
var encodedUrl = HttpUtility.UrlEncode(url);
|
||||
url = $"https://www.youtube.com/results?search_query={encodedUrl}";
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The IsValidUrl.
|
||||
/// </summary>
|
||||
/// <param name="url">The url<see cref="string"/>.</param>
|
||||
/// <returns>The <see cref="bool"/>.</returns>
|
||||
public static bool IsValidUrl(string url)
|
||||
{
|
||||
if (!url.Contains("."))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!url.Contains("http"))
|
||||
{
|
||||
url = $"http://{url}";
|
||||
}
|
||||
|
||||
var result = Uri.TryCreate(url, UriKind.Absolute, out Uri uriResult)
|
||||
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
140
VideoBrowser/Helpers/YoutubeHelper.cs
Normal file
140
VideoBrowser/Helpers/YoutubeHelper.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
namespace VideoBrowser.Helpers
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using VideoBrowser.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the <see cref="YoutubeHelper" />.
|
||||
/// </summary>
|
||||
public static class YoutubeHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a fixed URL, stripped of unnecessary invalid information.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to fix.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FixUrl(string url)
|
||||
{
|
||||
// Remove "Watch Later" information, causes error
|
||||
url = url.Replace("&index=6&list=WL", "");
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a formatted string of the given title, stripping illegal characters and replacing HTML entities with their actual character. (e.g. " -> ').
|
||||
/// </summary>
|
||||
/// <param name="title">The title to format.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string FormatTitle(string title)
|
||||
{
|
||||
var illegalCharacters = new string[] { "/", @"\", "*", "?", "\"", "<", ">" };
|
||||
var replace = new Dictionary<string, string>()
|
||||
{
|
||||
{"|", "-"},
|
||||
{"'", "'"},
|
||||
{""", "'"},
|
||||
{"<", "("},
|
||||
{">", ")"},
|
||||
{"+", " "},
|
||||
{":", "-"},
|
||||
{"amp;", "&"}
|
||||
};
|
||||
|
||||
var sb = new System.Text.StringBuilder(title);
|
||||
foreach (string s in illegalCharacters)
|
||||
{
|
||||
sb.Replace(s, string.Empty);
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<string, string> s in replace)
|
||||
{
|
||||
sb.Replace(s.Key, s.Value);
|
||||
}
|
||||
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the highest quality audio format from the given VideoFormat.
|
||||
/// </summary>
|
||||
/// <param name="format">The format to get audio format from.</param>
|
||||
/// <returns>The <see cref="VideoFormat"/>.</returns>
|
||||
public static VideoFormat GetAudioFormat(VideoFormat format)
|
||||
{
|
||||
var audio = new List<VideoFormat>();
|
||||
|
||||
// Add all audio only formats
|
||||
audio.AddRange(format.VideoInfo.Formats.FindAll(f => f.AudioOnly == true && f.Extension != "webm"));
|
||||
|
||||
// Return null if no audio is found
|
||||
if (audio.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return either the one with the highest audio bit rate, or the last found one
|
||||
return audio.OrderBy(a => a.AudioBitRate).Last();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the playlist id from given url.
|
||||
/// </summary>
|
||||
/// <param name="url">The url to get playlist id from.</param>
|
||||
/// <returns>The <see cref="string"/>.</returns>
|
||||
public static string GetPlaylistId(string url)
|
||||
{
|
||||
var regex = new Regex(@"^(?:https?://)?(?:www.)?youtube.com/.*list=([0-9a-zA-Z\-_]*).*$");
|
||||
return regex.Match(url).Groups[1].Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given url is a playlist YouTube url.
|
||||
/// </summary>
|
||||
/// <param name="url">The url to check.</param>
|
||||
/// <returns>The <see cref="bool"/>.</returns>
|
||||
public static bool IsPlaylist(string url)
|
||||
{
|
||||
var regex = new Regex(@"^(?:https?://)?(?:www.)?youtube.com/.*list=([0-9a-zA-Z\-_]*).*$");
|
||||
return regex.IsMatch(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given url is a valid YouTube url.
|
||||
/// </summary>
|
||||
/// <param name="url">The url to check.</param>
|
||||
/// <returns>The <see cref="bool"/>.</returns>
|
||||
public static bool IsValidYouTubeUrl(string url)
|
||||
{
|
||||
if (!url.ToLower().Contains("www.youtube.com/watch?"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var pattern = @"^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?$";
|
||||
var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
return regex.IsMatch(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The CheckFormats.
|
||||
/// </summary>
|
||||
/// <param name="list">The list<see cref="IList{VideoFormat}"/>.</param>
|
||||
/// <returns>The <see cref="VideoFormat[]"/>.</returns>
|
||||
internal static VideoFormat[] CheckFormats(IList<VideoFormat> list)
|
||||
{
|
||||
var formats = new List<VideoFormat>(list.Distinct());
|
||||
formats.RemoveAll(f => f.Extension.Contains("webm") ||
|
||||
f.HasAudioAndVideo ||
|
||||
f.FormatID == "meta");
|
||||
|
||||
return formats.ToArray();
|
||||
}
|
||||
|
||||
#endregion Methods
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user