using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace butterflow_ui
{
/// A butterflow wrapper. Provides interaction with the butterflow executable.
public class ButterflowWrapper : PropertyChangedAlerter
{
#region Members
/// The RegEx string for matching probed resolution.
private const string REGEX_RESOLUTION = @"Resolution\s*:\s(?\d+)x(?\d+)";
/// The RegEx string for matching the probed playback rate..
private const string REGEX_RATE = @"Rate\s*:\s(?\d+\.\d+) fps";
/// Full pathname of the butterflow executable file.
private Lazy executablePath = new Lazy(() => Path.Combine(Directory.GetCurrentDirectory(), "ThirdPartyCompiled", "butterflow.exe"));
/// The console output from butterflow.
private string consoleOutput = string.Empty;
/// Event queue for all listeners interested in ParsedConsoleOutputRecieved events.
public event EventHandler ParsedConsoleOutputRecieved;
#endregion
#region Properties
/// Gets the console output from butterflow.
/// The console output from butterflow.
public string ConsoleOutput
{
get
{
return this.consoleOutput;
}
private set
{
this.consoleOutput = value;
OnPropertyChanged();
}
}
#endregion
#region Methods
/// Runs butterflow with the given .
/// The options configuration.
public void Run(OptionsConfiguration optionsConfiguration)
{
string arguments = optionsConfiguration.ToButterflowArguments();
Run(arguments);
}
/// Probes a video file.
/// The video file to be probed.
public void Probe(string videoFile)
{
string arguments = string.Format("-prb \"{0}\"", videoFile);
Run(arguments);
}
/// Runs butterflow with the given .
/// Options for controlling the operation.
private void Run(string arguments)
{
var process = new Process();
process.StartInfo = new ProcessStartInfo(executablePath.Value, arguments);
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.EnableRaisingEvents = true;
process.OutputDataReceived += Process_OutputDataReceived; ;
process.Start();
process.BeginOutputReadLine();
}
///
/// Parses console output and attempts to find known values. If a known value is found, the
/// event is triggered.
///
/// The console output from butterflow.
private void ParseConsoleOutput(string consoleOutput)
{
if (string.IsNullOrWhiteSpace(consoleOutput))
{
//Ignore null content and just escape.
return;
}
//Test for resolution
var regex = new Regex(REGEX_RESOLUTION);
foreach (Match match in regex.Matches(consoleOutput))
{
var width = match.Groups["Width"].Value;
var height = match.Groups["Height"].Value;
OnParsedConsoleOutputRecieved(ButterflowOutputType.Width, width, consoleOutput);
OnParsedConsoleOutputRecieved(ButterflowOutputType.Height, height, consoleOutput);
}
//Test for playback rate
regex = new Regex(REGEX_RATE);
foreach(Match match in regex.Matches(consoleOutput))
{
var rate = match.Groups["Rate"].Value;
OnParsedConsoleOutputRecieved(ButterflowOutputType.Rate, rate, consoleOutput);
}
}
/// Executes the parsed console output recieved action.
/// Type of the output.
/// The value.
/// The console output from butterflow.
private void OnParsedConsoleOutputRecieved(ButterflowOutputType outputType, string value, string consoleOutput)
{
if (this.ParsedConsoleOutputRecieved != null)
{
this.ParsedConsoleOutputRecieved(this, new ButterflowOutputArgs(outputType, value, consoleOutput));
}
}
/// Event handler. Called by Process for output data received events.
/// Source of the event.
/// Data received event information.
private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
this.ConsoleOutput += string.Format("{0}{1}", e.Data, Environment.NewLine);
ParseConsoleOutput(e.Data);
}
#endregion
#region Subclasses
/// Arguments for butterflow output events where a known value of type can be parsed.
public class ButterflowOutputArgs : ButterflowConsoleOutputArgs
{
#region Properties
/// Gets or sets the type of the output detected from butterflow.
/// The type of the output detected from butterflow.
public ButterflowOutputType OutputType { get; private set; }
/// Gets or sets the value detected from butterflow.
/// The value detected from butterflow.
public string Value { get; private set; }
#endregion
/// Constructor.
/// The type of the output detected from butterflow.
/// The value detected from butterflow.
/// The console output.
public ButterflowOutputArgs(ButterflowOutputType outputType, string value, string consoleOutput)
: base(consoleOutput)
{
this.OutputType = outputType;
this.Value = value;
}
}
/// Arguments for butterflow console output events.
public class ButterflowConsoleOutputArgs : EventArgs
{
#region Properties
/// Gets the console output.
/// The console output.
public string ConsoleOutput { get; private set; }
#endregion
#region Constructors
/// Constructor.
/// The console output.
public ButterflowConsoleOutputArgs(string consoleOutput)
{
this.ConsoleOutput = consoleOutput;
}
#endregion
}
/// Values that represent butterflow output types.
public enum ButterflowOutputType
{
/// Video Width.
Width,
/// Video Height.
Height,
/// Video playback rate.
Rate,
/// Video processing progress.
Progress
}
#endregion
}
}