// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// The Video View Model
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.ViewModels
{
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Globalization;
using Caliburn.Micro;
using HandBrake.ApplicationServices;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Model.Encoding;
using HandBrake.ApplicationServices.Parsing;
using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrake.ApplicationServices.Utilities;
using HandBrake.Interop.Model.Encoding;
using HandBrake.Interop.Model.Encoding.x264;
using HandBrakeWPF.ViewModels.Interfaces;
///
/// The Video View Model
///
[Export(typeof(IVideoViewModel))]
public class VideoViewModel : ViewModelBase, IVideoViewModel
{
#region Constants and Fields
///
/// Backing field for the user setting service.
///
private IUserSettingService userSettingService;
///
/// Backing field used to display / hide the x264 options
///
private bool displayX264Options;
///
/// The quality max.
///
private int qualityMax;
///
/// The quality min.
///
private int qualityMin;
///
/// The show peak framerate.
///
private bool showPeakFramerate;
///
/// The show peak framerate.
///
private int rf;
#endregion
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
///
/// The window manager.
///
///
/// The user Setting Service.
///
public VideoViewModel(IWindowManager windowManager, IUserSettingService userSettingService)
{
this.Task = new EncodeTask { VideoEncoder = VideoEncoder.X264 };
this.userSettingService = userSettingService;
this.QualityMin = 0;
this.QualityMax = 51;
this.IsConstantQuantity = true;
this.VideoEncoders = EnumHelper.GetEnumList();
//X264Presets = EnumHelper.GetEnumList();
//X264Profiles = EnumHelper.GetEnumList();
//X264Tunes = EnumHelper.GetEnumList();
}
#endregion
#region Public Properties
///
/// Gets or sets the current Encode Task.
///
public EncodeTask Task { get; set; }
///
/// Gets Framerates.
///
public IEnumerable Framerates
{
get
{
return new List { "Same as source", "5", "10", "12", "15", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60" };
}
}
///
/// Gets or sets a value indicating whether IsConstantFramerate.
///
public bool IsConstantFramerate
{
get
{
return this.Task.FramerateMode == FramerateMode.CFR;
}
set
{
if (value)
{
this.Task.FramerateMode = FramerateMode.CFR;
this.IsVariableFramerate = false;
this.IsPeakFramerate = false;
}
this.NotifyOfPropertyChange(() => this.IsConstantFramerate);
}
}
///
/// Gets or sets a value indicating whether IsConstantQuantity.
///
public bool IsConstantQuantity
{
get
{
return this.Task.VideoEncodeRateType == VideoEncodeRateType.ConstantQuality;
}
set
{
if (value)
{
this.Task.VideoEncodeRateType = VideoEncodeRateType.ConstantQuality;
this.Task.TwoPass = false;
this.Task.TurboFirstPass = false;
this.Task.VideoBitrate = null;
this.NotifyOfPropertyChange(() => this.Task);
}
else
{
this.Task.VideoEncodeRateType = VideoEncodeRateType.AverageBitrate;
}
this.NotifyOfPropertyChange(() => this.IsConstantQuantity);
}
}
///
/// Gets or sets a value indicating whether IsPeakFramerate.
///
public bool IsPeakFramerate
{
get
{
return this.Task.FramerateMode == FramerateMode.PFR;
}
set
{
if (value)
{
this.Task.FramerateMode = FramerateMode.PFR;
this.IsVariableFramerate = false;
this.IsConstantFramerate = false;
}
this.NotifyOfPropertyChange(() => this.IsPeakFramerate);
}
}
///
/// Gets or sets a value indicating whether IsVariableFramerate.
///
public bool IsVariableFramerate
{
get
{
return this.Task.FramerateMode == FramerateMode.VFR;
}
set
{
if (value)
{
this.IsPeakFramerate = false;
this.IsConstantFramerate = false;
this.Task.FramerateMode = FramerateMode.VFR;
}
this.NotifyOfPropertyChange(() => this.IsVariableFramerate);
}
}
///
/// Gets or sets QualityMax.
///
public int QualityMax
{
get
{
return this.qualityMax;
}
set
{
if (!qualityMax.Equals(value))
{
this.qualityMax = value;
this.NotifyOfPropertyChange(() => this.QualityMax);
}
}
}
///
/// Gets or sets QualityMin.
///
public int QualityMin
{
get
{
return this.qualityMin;
}
set
{
if (!qualityMin.Equals(value))
{
this.qualityMin = value;
this.NotifyOfPropertyChange(() => this.QualityMin);
}
}
}
///
/// Gets or sets RF.
///
public int RF
{
get
{
return rf;
}
set
{
this.rf = value;
double cqStep = userSettingService.GetUserSetting(ASUserSettingConstants.X264Step);
this.SetQualitySliderBounds();
switch (this.SelectedVideoEncoder)
{
case VideoEncoder.FFMpeg:
case VideoEncoder.FFMpeg2:
this.Task.Quality = (32 - value);
break;
case VideoEncoder.X264:
double rfValue = 51.0 - value * cqStep;
rfValue = Math.Round(rfValue, 2);
this.Task.Quality = rfValue;
// TODO: Lossless warning.
break;
case VideoEncoder.Theora:
Task.Quality = value;
break;
}
this.NotifyOfPropertyChange(() => this.RF);
this.NotifyOfPropertyChange(() => this.DisplayRF);
}
}
///
/// Gets DisplayRF.
///
public double DisplayRF
{
get
{
return Task.Quality.HasValue ? this.Task.Quality.Value : 0;
}
}
///
/// Gets or sets SelectedFramerate.
///
public string SelectedFramerate
{
get
{
if (this.Task.Framerate == null)
{
return "Same as source";
}
return this.Task.Framerate.ToString();
}
set
{
if (value == "Same as source")
{
this.Task.Framerate = null;
this.ShowPeakFramerate = false;
if (this.Task.FramerateMode == FramerateMode.PFR)
{
this.IsVariableFramerate = true;
}
}
else if (!string.IsNullOrEmpty(value))
{
this.ShowPeakFramerate = true;
if (this.Task.FramerateMode == FramerateMode.VFR)
{
this.IsPeakFramerate = true;
}
this.Task.Framerate = double.Parse(value);
}
this.NotifyOfPropertyChange(() => this.SelectedFramerate);
this.NotifyOfPropertyChange(() => this.Task);
}
}
///
/// Gets or sets SelectedVideoEncoder.
///
public VideoEncoder SelectedVideoEncoder
{
get
{
return this.Task.VideoEncoder;
}
set
{
this.Task.VideoEncoder = value;
this.NotifyOfPropertyChange(() => this.SelectedVideoEncoder);
// Tell the Advanced Panel off the change
IAdvancedViewModel advancedViewModel = IoC.Get();
advancedViewModel.SetEncoder(this.Task.VideoEncoder);
// Update the Quality Slider. Make sure the bounds are up to date with the users settings.
this.SetQualitySliderBounds();
}
}
///
/// Gets or sets a value indicating whether ShowPeakFramerate.
///
public bool ShowPeakFramerate
{
get
{
return this.showPeakFramerate;
}
set
{
this.showPeakFramerate = value;
this.NotifyOfPropertyChange(() => this.ShowPeakFramerate);
}
}
///
/// Gets or sets VideoEncoders.
///
public IEnumerable VideoEncoders { get; set; }
#endregion
#region Public Methods
///
/// Setup this window for a new source
///
///
/// The title.
///
///
/// The preset.
///
///
/// The task.
///
public void SetSource(Title title, Preset preset, EncodeTask task)
{
this.Task = task;
}
///
/// Setup this tab for the specified preset.
///
///
/// The preset.
///
///
/// The task.
///
public void SetPreset(Preset preset, EncodeTask task)
{
this.Task = task;
if (preset == null || preset.Task == null)
{
return;
}
this.SelectedVideoEncoder = preset.Task.VideoEncoder;
if (preset.Task.Framerate.HasValue)
{
this.SelectedFramerate = preset.Task.Framerate.Value.ToString(CultureInfo.InvariantCulture);
}
this.IsConstantQuantity = preset.Task.VideoEncodeRateType == VideoEncodeRateType.ConstantQuality;
switch (preset.Task.FramerateMode)
{
case FramerateMode.CFR:
this.IsConstantFramerate = true;
break;
case FramerateMode.VFR:
this.IsVariableFramerate = true;
this.ShowPeakFramerate = false;
break;
case FramerateMode.PFR:
this.IsPeakFramerate = true;
this.ShowPeakFramerate = true;
break;
}
double cqStep = userSettingService.GetUserSetting(ASUserSettingConstants.X264Step);
double rfValue = 0;
this.SetQualitySliderBounds();
switch (this.SelectedVideoEncoder)
{
case VideoEncoder.FFMpeg:
case VideoEncoder.FFMpeg2:
int cq;
if (preset.Task.Quality.HasValue)
{
int.TryParse(preset.Task.Quality.Value.ToString(CultureInfo.InvariantCulture), out cq);
this.RF = 32 - cq;
}
break;
case VideoEncoder.X264:
double multiplier = 1.0 / cqStep;
if (preset.Task.Quality.HasValue)
{
rfValue = preset.Task.Quality.Value * multiplier;
}
this.RF = this.QualityMax - (int)Math.Round(rfValue, 0);
break;
case VideoEncoder.Theora:
if (preset.Task.Quality.HasValue)
{
this.RF = (int)preset.Task.Quality.Value;
}
break;
}
this.Task.TwoPass = preset.Task.TwoPass;
this.Task.TurboFirstPass = preset.Task.TurboFirstPass;
this.Task.VideoBitrate = preset.Task.VideoBitrate;
this.NotifyOfPropertyChange(() => this.Task);
//if (preset != null && preset.Task != null)
//{
// this.Query = preset.Task.AdvancedEncoderOptions;
// this.SetEncoder(preset.Task.VideoEncoder);
// this.X264Preset = preset.Task.x264Preset;
// this.X264Profile = preset.Task.x264Profile;
// this.X264Tune = preset.Task.X264Tune;
//}
}
///
/// Update all the UI controls based on the encode task passed in.
///
///
/// The task.
///
public void UpdateTask(EncodeTask task)
{
this.Task = task;
this.NotifyOfPropertyChange(() => this.IsConstantFramerate);
this.NotifyOfPropertyChange(() => this.IsConstantQuantity);
this.NotifyOfPropertyChange(() => this.IsPeakFramerate);
this.NotifyOfPropertyChange(() => this.IsVariableFramerate);
this.NotifyOfPropertyChange(() => this.SelectedVideoEncoder);
this.NotifyOfPropertyChange(() => this.SelectedFramerate);
this.NotifyOfPropertyChange(() => this.RF);
this.NotifyOfPropertyChange(() => this.DisplayRF);
this.NotifyOfPropertyChange(() => this.Task.VideoBitrate);
this.NotifyOfPropertyChange(() => this.Task.TwoPass);
this.NotifyOfPropertyChange(() => this.Task.TurboFirstPass);
}
///
/// Set the currently selected encoder.
///
///
/// The Video Encoder.
///
public void SetEncoder(VideoEncoder encoder)
{
//this.DisplayX264Options = encoder == VideoEncoder.X264;
}
///
/// Trigger a Notify Property Changed on the Task to force various UI elements to update.
///
public void RefreshTask()
{
this.NotifyOfPropertyChange(() => this.Task);
if (Task.OutputFormat == OutputFormat.Mp4 && this.SelectedVideoEncoder == VideoEncoder.Theora)
{
this.SelectedVideoEncoder = VideoEncoder.X264;
}
}
#endregion
///
/// Set the bounds of the Constant Quality Slider
///
private void SetQualitySliderBounds()
{
// Note Updating bounds to the same values won't trigger an update.
// The properties are smart enough to not take in equal values.
switch (this.SelectedVideoEncoder)
{
case VideoEncoder.FFMpeg:
case VideoEncoder.FFMpeg2:
this.QualityMin = 1;
this.QualityMax = 31;
break;
case VideoEncoder.X264:
this.QualityMin = 0;
this.QualityMax = (int)(51 / userSettingService.GetUserSetting(ASUserSettingConstants.X264Step));
break;
case VideoEncoder.Theora:
this.QualityMin = 0;
this.QualityMax = 63;
break;
}
}
#region Advanced
/////
///// Gets or sets State.
/////
//public string Query
//{
// get
// {
// return this.Task.AdvancedEncoderOptions;
// }
// set
// {
// this.Task.AdvancedEncoderOptions = value;
// this.NotifyOfPropertyChange(() => this.Query);
// }
//}
/////
///// Gets or sets X264Preset.
/////
//public x264Preset X264Preset
//{
// get
// {
// return this.Task.x264Preset;
// }
// set
// {
// this.Task.x264Preset = value;
// this.NotifyOfPropertyChange(() => this.X264Preset);
// }
//}
/////
///// Gets or sets X264Profile.
/////
//public x264Profile X264Profile
//{
// get
// {
// return this.Task.x264Profile;
// }
// set
// {
// this.Task.x264Profile = value;
// this.NotifyOfPropertyChange(() => this.X264Profile);
// }
//}
/////
///// Gets or sets X264Tune.
/////
//public x264Tune X264Tune
//{
// get
// {
// return this.Task.X264Tune;
// }
// set
// {
// this.Task.X264Tune = value;
// this.NotifyOfPropertyChange(() => this.X264Tune);
// }
//}
/////
///// Gets or sets X264Presets.
/////
//public IEnumerable X264Presets { get; set; }
/////
///// Gets or sets X264Profiles.
/////
//public IEnumerable X264Profiles { get; set; }
/////
///// Gets or sets X264Tunes.
/////
//public IEnumerable X264Tunes { get; set; }
/////
///// Gets or sets a value indicating whether DisplayX264Options.
/////
//public bool DisplayX264Options
//{
// get
// {
// return this.displayX264Options;
// }
// set
// {
// this.displayX264Options = value;
// this.NotifyOfPropertyChange(() => this.DisplayX264Options);
// }
//}
#endregion
}
}