using Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace butterflow_ui { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { #region Members /// True if is the user has started clipping, false if not. private bool isClipping; /// The temporary storage for the clip start time. private TimeSpan clipStart; #endregion #region Properties /// Gets or sets the butterflow options configuration. /// The options configuration. public OptionsConfiguration OptionsConfiguration { get; set; } = new OptionsConfiguration(); /// The butterflow wrapper used to call butterflow. public ButterflowWrapper ButterflowWrapper { get; set; } = new ButterflowWrapper(); #endregion /// Default constructor. public MainWindow() { this.ButterflowWrapper.ParsedConsoleOutputRecieved += ButterflowWrapper_ParsedConsoleOutputRecieved; InitializeComponent(); } /// Butterflow wrapper parsed console output recieved. /// Source of the event. /// The ButterflowOutputArgs to process. private void ButterflowWrapper_ParsedConsoleOutputRecieved(object sender, ButterflowWrapper.ButterflowOutputArgs e) { switch (e.OutputType) { case ButterflowWrapper.ButterflowOutputType.Width: this.OptionsConfiguration.Width = e.Value; break; case ButterflowWrapper.ButterflowOutputType.Height: this.OptionsConfiguration.Height = e.Value; break; case ButterflowWrapper.ButterflowOutputType.Progress: break; default: break; } } /// Event handler. Called by btnFilePicker for click events. /// Source of the event. /// Routed event information. private void btnFilePicker_Click(object sender, RoutedEventArgs e) { var ofd = new OpenFileDialog(); ofd.Filter = "Supported Video Files|*.mp4;*.mkv"; var result = ofd.ShowDialog(this); if (result.HasValue && result.Value) { this.OptionsConfiguration.VideoInput = ofd.FileName; //this.ButterflowWrapper.ConsoleOutputRecieved += (o, ce) => this.txtConsoleOutput.Text = ce.ConsoleOutput; this.ButterflowWrapper.Probe(ofd.FileName); //Hack to get the first frame to display in the media preview element. //This also triggers the MediaOpened event so we can get the metadata from the element. mediaPreview.Play(); mediaPreview.PausePlayback(); } } /// Event handler. Called by PlaybackRate radio buttons for checked events. /// Source of the event. /// Routed event information. private void PlaybackRateRadioButton_Checked(object sender, RoutedEventArgs e) { var typedSender = (RadioButton)sender; if (typedSender != null) { var tag = typedSender.Tag.ToString(); this.OptionsConfiguration.PlaybackRate = tag; } } /// Event handler. Called by bntVideoPlay for click events. /// Source of the event. /// Routed event information. private void bntVideoPlay_Click(object sender, RoutedEventArgs e) { if (this.mediaPreview.CanPlay() || this.mediaPreview.CanPause.GetValueOrDefault(false)) { this.mediaPreview.TogglePlayPause(); } if (this.mediaPreview.IsPlaying) { this.PlayPauseButtonIcon.Template = Application.Current.Resources["PauseIcon"] as ControlTemplate; } else { this.PlayPauseButtonIcon.Template = Application.Current.Resources["PlayIcon"] as ControlTemplate; } } /// Event handler. Called by bntVideoStop for click events. /// Source of the event. /// Routed event information. private void bntVideoStop_Click(object sender, RoutedEventArgs e) { this.PlayPauseButtonIcon.Template = Application.Current.Resources["PlayIcon"] as ControlTemplate; this.mediaPreview.Stop(); } /// Event handler. Called by bntVideoForward for click events. /// Source of the event. /// Routed event information. private void bntVideoForward_Click(object sender, RoutedEventArgs e) { if (this.mediaPreview.CanSkipForward(null)) { this.mediaPreview.SkipForward(null); } } /// Event handler. Called by bntVideoBackward for click events. /// Source of the event. /// Routed event information. private void bntVideoBackward_Click(object sender, RoutedEventArgs e) { if (this.mediaPreview.CanSkipBack(null)) { this.mediaPreview.SkipBack(null); } } /// Event handler. Called by bntClip for click events. /// Source of the event. /// Routed event information. private void bntClip_Click(object sender, RoutedEventArgs e) { if (this.mediaPreview.Position.HasValue) { if (!this.isClipping) { //start clipping this.isClipping = true; this.ClippingButtonIcon.Template = Application.Current.Resources["SnipCloseIcon"] as ControlTemplate; this.clipStart = this.mediaPreview.Position.Value; } else { //end clipping this.isClipping = false; this.ClippingButtonIcon.Template = Application.Current.Resources["SnipOpenIcon"] as ControlTemplate; this.OptionsConfiguration.Subregions.Add(new ButterflowSubregion() { Start = this.clipStart, End = this.mediaPreview.Position.Value, ToEnd = false, Value = 1, SubregionType = RegionType.spd }); this.clipStart = TimeSpan.Zero; } } } /// Event handler. Called by mediaPreview for media opened events. /// Source of the event. /// Routed event information. private void mediaPreview_MediaOpened(object sender, RoutedEventArgs e) { //this.OptionsConfiguration.Width = this.mediaPreview.NaturalVideoWidth.ToString(); //this.OptionsConfiguration.Height = this.mediaPreview.NaturalVideoHeight.ToString(); } /// Event handler. Called by mediaPreview for media ended events. /// Source of the event. /// Routed event information. private void mediaPreview_MediaEnded(object sender, RoutedEventArgs e) { this.PlayPauseButtonIcon.Template = Application.Current.Resources["PlayIcon"] as ControlTemplate; } /// Event handler. Called by ScrollViewer for scroll changed events. /// Source of the event. /// Scroll changed event information. /// /// This code autoscrolls the scroll viewer as more text is added. It is based on this example /// from Stack Overflow: /// https://stackoverflow.com/questions/2984803/how-to-automatically-scroll-scrollviewer-only-if-the-user-did-not-change-scrol. /// private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { var scrollViewer = sender as ScrollViewer; bool autoScroll = true; if (scrollViewer != null) { if (e.ExtentHeightChange == 0) { // Content unchanged : user scroll event if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight) { // Scroll bar is in bottom // Set auto-scroll mode autoScroll = true; } else { // Scroll bar isn't in bottom // Unset auto-scroll mode autoScroll = false; } } // Content scroll event : auto-scroll eventually if (autoScroll && e.ExtentHeightChange != 0) { // Content changed and auto-scroll mode set // Autoscroll scrollViewer.ScrollToEnd(); } } } } }