namespace VideoBrowser.Core
{
using Newtonsoft.Json.Linq;
using System;
using System.ComponentModel;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
///
/// Defines the
///
public class VideoFormat : INotifyPropertyChanged
{
#region Fields
internal long _fileSize;
private WebRequest request;
#endregion Fields
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The videoInfo
/// The token
public VideoFormat(VideoInfo videoInfo, JToken token)
{
this.AudioBitRate = -1;
this.VideoInfo = videoInfo;
this.DeserializeJson(token);
}
#endregion Constructors
#region Events
///
/// Defines the PropertyChanged
///
public event PropertyChangedEventHandler PropertyChanged;
#endregion Events
#region Properties
///
/// Gets the ACodec
///
public string ACodec { get; private set; }
///
/// Gets the audio bit rate. Returns -1 if not defined.
///
public double AudioBitRate { get; private set; }
///
/// Gets a value indicating whether AudioOnly
/// Gets whether the format is audio only.
///
public bool AudioOnly { get; private set; }
///
/// Gets a value indicating whether DASH
/// Gets whether format is a DASH format.
///
public bool DASH { get; private set; }
///
/// Gets the download url.
///
public string DownloadUrl { get; private set; }
///
/// Gets the file extension, excluding the period.
///
public string Extension { get; private set; }
///
/// Gets the file size as bytes count.
///
public long FileSize
{
get { return _fileSize; }
private set
{
_fileSize = value;
this.OnPropertyChanged();
}
}
///
/// Gets the format text.
///
public string Format { get; private set; }
///
/// Gets the format ID.
///
public string FormatID { get; private set; }
///
/// Gets the frames per second. Null if not defined.
///
public string FPS { get; private set; }
///
/// Gets a value indicating whether HasAudioAndVideo
///
public bool HasAudioAndVideo => !this.AudioOnly && !this.VideoOnly;
///
/// Gets the format title, displaying some basic information.
///
public string Title => this.ToString();
///
/// Gets the VCodec
///
public string VCodec { get; private set; }
///
/// Gets the associated VideoInfo.
///
public VideoInfo VideoInfo { get; private set; }
///
/// Gets a value indicating whether VideoOnly
///
public bool VideoOnly { get; private set; }
#endregion Properties
#region Methods
///
/// Aborts request for file size.
///
public void AbortUpdateFileSize()
{
if (request != null)
{
request.Abort();
}
}
///
/// The OnPropertyChanged
///
/// The propertyName
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
this.OnPropertyChangedExplicit(propertyName);
}
///
/// The OnPropertyChangedExplicit
///
/// The propertyName
public void OnPropertyChangedExplicit(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
///
/// The ToString
///
/// The
public override string ToString()
{
var text = string.Empty;
if (this.AudioOnly)
{
text = this.AudioBitRate > -1
? string.Format("Audio Only - {0} kbps (.{1})", this.AudioBitRate, this.Extension)
: string.Format("Audio Only (.{0})", this.Extension);
}
else
{
var fps = !string.IsNullOrEmpty(this.FPS) ? $" - {this.FPS}fps" : string.Empty;
text = string.Format("{0}{1} (.{2})", this.Format, fps, this.Extension);
}
return text;
}
///
/// Starts a WebRequest to update the file size.
///
public async void UpdateFileSizeAsync()
{
if (this.FileSize > 0)
{
// Probably already got the file size from .json file.
this.VideoInfo.OnFileSizeUpdated(this);
return;
}
WebResponse response = null;
try
{
request = WebRequest.Create(this.DownloadUrl);
request.Method = "HEAD";
response = await request.GetResponseAsync();
var bytes = response.ContentLength;
this.FileSize = bytes;
this.VideoInfo.OnFileSizeUpdated(this);
}
catch (OperationCanceledException e)
{
Console.WriteLine(e);
Console.WriteLine("Canceled update file size");
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine("Update file size error");
}
finally
{
if (response != null)
{
response.Close();
}
}
}
///
/// The DeserializeJson
///
/// The token
private void DeserializeJson(JToken token)
{
this.ACodec = token["acodec"]?.ToString();
this.VCodec = token["vcodec"]?.ToString();
this.DownloadUrl = token["url"].ToString();
var formatnote = token.SelectToken("format_note");
if (formatnote != null)
{
this.DASH = token["format_note"].ToString().ToLower().Contains("dash");
}
this.Extension = token["ext"].ToString();
this.Format = Regex.Match(token["format"].ToString(), @".*-\s([^\(\n]*)").Groups[1].Value.Trim();
this.FormatID = token["format_id"].ToString();
// Check if format is audio only or video only
this.AudioOnly = this.Format.Contains("audio only");
this.VideoOnly = this.ACodec == "none";
// Check for abr token (audio bit rate?)
var abr = token.SelectToken("abr");
if (abr != null)
{
this.AudioBitRate = double.Parse(abr.ToString());
}
// Check for filesize token
var filesize = token.SelectToken("filesize");
if (filesize != null && !string.IsNullOrEmpty(filesize.ToString()))
{
this.FileSize = long.Parse(filesize.ToString());
}
// Check for 60fps videos. If there is no 'fps' token, default to 30fps.
var fps = token.SelectToken("fps", false);
this.FPS = fps == null || fps.ToString() == "null" ? string.Empty : fps.ToString();
this.UpdateFileSizeAsync();
}
#endregion Methods
}
}