using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using csmic;
namespace butterflow_ui
{
/// The butterflow options configuration. Contians all the options necessary to run butterflow and process a video.
[Serializable]
public class OptionsConfiguration : PropertyChangedAlerter
{
#region Members
/// An interpreter used to ensure numeric input is correctly calculated.
private InputInterpreter interpreter = new InputInterpreter();
/// The aspect ratio used for calculating heights when the aspect ratio is locked.
private decimal aspectRatio = 0;
private string playbackRate;
private bool keepAudio;
private int width;
private int height;
private bool keepAspectRatio;
private bool losslessQuality;
private bool smoothMotion;
private bool lockAspectRatio;
private string videoInput;
private string videoOutput;
private bool fastPyramid;
private decimal pyramidScale;
private int levels;
private int windowSize;
private int iterations;
private int pixelNeighborhood;
private decimal smoothDerivativeStandardDeviation;
private ObservableCollection subregions = new ObservableCollection();
#endregion
#region Properties
/// Gets the command line output given the current configuration.
/// The command line output.
public string CommandLineOutput
{
get
{
return ToButterflowArguments();
}
}
/// Gets or sets the playback rate.
/// The playback rate.
public string PlaybackRate
{
get
{
return this.playbackRate;
}
set
{
this.playbackRate = value;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether the keep audio.
/// True if keep audio, false if not.
public bool KeepAudio
{
get
{
return this.keepAudio;
}
set
{
this.keepAudio = value;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether the butterflow should be turned toward smooth motion.
/// True if tuned toward smooth motion, false if not.
public bool SmoothMotion
{
get
{
return this.smoothMotion;
}
set
{
this.smoothMotion = value;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether to lock aspect ratio of the video.
/// True if locking aspect ratio of the video, false if not.
public bool LockAspectRatio
{
get
{
return this.lockAspectRatio;
}
set
{
if (value)
{
this.aspectRatio = Convert.ToDecimal(this.height) / Convert.ToDecimal(this.width);
}
this.lockAspectRatio = value;
OnPropertyChanged();
}
}
/// Gets or sets the width of the video output.
/// The width of the video output.
public string Width
{
get
{
return this.width.ToString();
}
set
{
var oldWidth = this.width;
interpreter.Interpret(value);
this.width = interpreter.Int;
OnPropertyChanged();
if (this.lockAspectRatio)
{
interpreter.Interpret(string.Format("{0} * {1}", this.aspectRatio, this.width));
this.height = interpreter.Int;
OnPropertyChanged("Height");
}
}
}
/// Gets or sets the height of the video output.
/// The height of the video output.
public string Height
{
get
{
return this.height.ToString();
}
set
{
interpreter.Interpret(value);
this.height = interpreter.Int;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether the keep aspect ratio of the input video file for the output video file.
/// True if keep aspect ratio, false if not.
public bool KeepAspectRatio
{
get
{
return this.keepAspectRatio;
}
set
{
this.keepAspectRatio = value;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether the result is rendered in lossless quality.
/// True if lossless quality is selected, false if not.
public bool LosslessQuality
{
get
{
return this.losslessQuality;
}
set
{
this.losslessQuality = value;
OnPropertyChanged();
}
}
/// Gets or sets the video input file path.
/// The video input file path.
public string VideoInput
{
get
{
return this.videoInput;
}
set
{
this.videoInput = value;
OnPropertyChanged();
}
}
/// Gets or sets the video output file path.
/// The video output file path.
public string VideoOutput
{
get
{
return this.videoOutput;
}
set
{
this.videoOutput = value;
OnPropertyChanged();
}
}
/// Gets or sets a value indicating whether to use fast pyramids.
/// True if using fast pyramids, false if not.
public bool FastPyramid
{
get
{
return this.fastPyramid;
}
set
{
this.fastPyramid = value;
OnPropertyChanged();
}
}
/// Gets or sets the pyramid scale factor.
/// The pyramid scale factor.
public string PyramidScale
{
get
{
return this.pyramidScale.ToString();
}
set
{
interpreter.Interpret(value);
this.pyramidScale = interpreter.Decimal;
OnPropertyChanged();
}
}
/// Gets or sets the number of pyramid layers.
/// The number of pyramid layers.
public string Levels
{
get
{
return this.levels.ToString();
}
set
{
interpreter.Interpret(value);
this.levels = interpreter.Int;
OnPropertyChanged();
}
}
/// Gets or sets the size of the windowing average.
/// The size of the windowing average.
public string WindowSize
{
get
{
return this.windowSize.ToString();
}
set
{
interpreter.Interpret(value);
this.windowSize = interpreter.Int;
OnPropertyChanged();
}
}
/// Gets or sets the number of iterations at each pyramid level.
/// The number of iterations at each pyramid level.
public string Iterations
{
get
{
return this.iterations.ToString();
}
set
{
interpreter.Interpret(value);
this.iterations = interpreter.Int;
OnPropertyChanged();
}
}
/// Gets or sets the size of the pixel neighborhood.
/// The size of the pixel neighborhood.
public string PixelNeighborhood
{
get
{
return this.pixelNeighborhood.ToString();
}
set
{
interpreter.Interpret(value);
this.pixelNeighborhood = interpreter.Int;
OnPropertyChanged();
}
}
/// Gets or sets the standard deviation of smooth derivatives.
/// The standard deviation of smooth derivatives.
public string SmoothDerivativeStandardDeviation
{
get
{
return this.smoothDerivativeStandardDeviation.ToString();
}
set
{
interpreter.Interpret(value);
this.smoothDerivativeStandardDeviation = interpreter.Decimal;
OnPropertyChanged();
}
}
/// Gets or sets the subregions of the video on which to work.
/// The subregions of the video.
public ObservableCollection Subregions
{
get
{
return this.subregions;
}
set
{
this.subregions = value;
OnPropertyChanged();
}
}
#endregion
#region Contructors
/// Default constructor.
public OptionsConfiguration()
{
AddConstantCallProperty("CommandLineOutput");
this.subregions.CollectionChanged += SubregionsCollectionChanged;
}
private void SubregionsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (ButterflowSubregion newItem in e.NewItems)
{
newItem.PropertyChanged += SubregionPropertyChanged;
}
}
if (e.OldItems != null)
{
foreach (ButterflowSubregion oldItem in e.OldItems)
{
oldItem.PropertyChanged -= SubregionPropertyChanged;
}
}
OnPropertyChanged("CommandLineOutput");
}
#endregion
#region Methods
private void SubregionPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("CommandLineOutput");
}
/// Converts this object to a butterflow options.
/// This object as a string.
public string ToButterflowArguments()
{
var stringBuilder = new StringBuilder("-v "); //Verbose
if (this.KeepAspectRatio)
{
stringBuilder.AppendFormat("-vs {0}:-1 ", this.Width);
}
else
{
stringBuilder.AppendFormat("-vs {0}:{1} ", this.Width, this.Height);
}
if (!string.IsNullOrWhiteSpace(this.PlaybackRate)) stringBuilder.AppendFormat("-r {0} ", this.PlaybackRate);
if (this.KeepAudio) stringBuilder.Append("-audio ");
if (this.LosslessQuality) stringBuilder.Append("-l ");
stringBuilder.AppendFormat("\"{0}\"", this.VideoInput);
if (this.Subregions.Any())
{
foreach (var anon in this.Subregions.Select((sr, index) => new { Index = index, Subregion = sr }))
{
string format = "ss\\.fff";
if (anon.Index > 0)
{
stringBuilder.Append(":");
}
if (anon.Subregion.Start.TotalHours > 1)
{
format = "h\\:m\\:s\\.fff";
}
else if (anon.Subregion.Start.TotalMinutes > 1)
{
format = "m\\:s\\.fff";
}
stringBuilder.AppendFormat("a={0},b={1},{2}={3}", anon.Subregion.Start.ToString(format), anon.Subregion.ToEnd ? "end" : anon.Subregion.End.ToString(format), anon.Subregion.SubregionType, anon.Subregion.Value);
}
stringBuilder.Append(" ");
}
return stringBuilder.ToString();
}
/// Returns a string that represents the current object.
/// A string that represents the current object.
public override string ToString()
{
return ToButterflowArguments();
}
#endregion
}
}