diff options
author | sr55 <[email protected]> | 2014-11-23 21:26:15 +0000 |
---|---|---|
committer | sr55 <[email protected]> | 2014-11-23 21:26:15 +0000 |
commit | 041b565e4316317e07b00e4db815307d7280b27f (patch) | |
tree | 872948418b48bd9885443a93982a6f609feafc59 /win/CS/HandBrakeWPF | |
parent | 40b699f2cbb07961e08a8f828bdd7ea4c2dbfe29 (diff) |
WinGui: Move the preset system out of the services package.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6544 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'win/CS/HandBrakeWPF')
21 files changed, 1620 insertions, 1 deletions
diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj index 0d85fb289..a1dcac720 100644 --- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj +++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj @@ -110,6 +110,7 @@ <Reference Include="LumenWorks.Framework.IO">
<HintPath>..\libraries\CsvReader\LumenWorks.Framework.IO.dll</HintPath>
</Reference>
+ <Reference Include="Microsoft.CSharp" />
<Reference Include="Ookii.Dialogs.Wpf">
<HintPath>..\libraries\OokiiDialogs\Ookii.Dialogs.Wpf.dll</HintPath>
</Reference>
@@ -153,14 +154,19 @@ <Compile Include="Converters\Filters\DenoisePresetConverter.cs" />
<Compile Include="Converters\Subtitles\SubtitleBehaviourConverter.cs" />
<Compile Include="Converters\Video\ScalingConverter.cs" />
+ <Compile Include="Services\Presets\Factories\PlistPresetFactory.cs" />
<Compile Include="Helpers\FileHelper.cs" />
+ <Compile Include="Model\Preset\Preset.cs" />
<Compile Include="Model\ScanMode.cs" />
<Compile Include="Factories\HBConfigurationFactory.cs" />
+ <Compile Include="Services\Presets\Interfaces\IPresetService.cs" />
<Compile Include="Services\Interfaces\IUserSettingService.cs" />
+ <Compile Include="Services\Presets\PresetService.cs" />
<Compile Include="Services\UserSettingService.cs" />
<Compile Include="Utilities\DelayedActionProcessor.cs" />
<Compile Include="Utilities\DPIAwareness.cs" />
<Compile Include="Utilities\HandBrakeApp.cs" />
+ <Compile Include="Services\Presets\Factories\PlistFactory.cs" />
<Compile Include="ViewModels\CountdownAlertViewModel.cs" />
<Compile Include="ViewModels\Interfaces\ICountdownAlertViewModel.cs" />
<Compile Include="Controls\SourceSelection.xaml.cs">
diff --git a/win/CS/HandBrakeWPF/Model/Preset/Preset.cs b/win/CS/HandBrakeWPF/Model/Preset/Preset.cs new file mode 100644 index 000000000..d7c93838b --- /dev/null +++ b/win/CS/HandBrakeWPF/Model/Preset/Preset.cs @@ -0,0 +1,151 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="Preset.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// A Preset for encoding with.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Model.Preset
+{
+ using Caliburn.Micro;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Audio;
+ using HandBrake.ApplicationServices.Model.Subtitle;
+
+ /// <summary>
+ /// A Preset for encoding with.
+ /// </summary>
+ public class Preset : PropertyChangedBase
+ {
+ #region Constants and Fields
+
+ /// <summary>
+ /// The is default.
+ /// </summary>
+ private bool isDefault;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the category which the preset resides under
+ /// </summary>
+ public string Category { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Description for the preset
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this is a built in preset
+ /// </summary>
+ public bool IsBuildIn { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether IsDefault.
+ /// </summary>
+ public bool IsDefault
+ {
+ get
+ {
+ return this.isDefault;
+ }
+ set
+ {
+ this.isDefault = value;
+ this.NotifyOfPropertyChange(() => this.IsDefault);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the preset name
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets PictureSettingsMode.
+ /// Source Maximum, Custom or None
+ /// </summary>
+ public PresetPictureSettingsMode PictureSettingsMode { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether use deinterlace.
+ /// </summary>
+ public bool UseDeinterlace { get; set; }
+
+ /// <summary>
+ /// Gets or sets task.
+ /// </summary>
+ public EncodeTask Task { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Picture Filters are used with this preset.
+ /// </summary>
+ public bool UsePictureFilters { get; set; }
+
+ /// <summary>
+ /// Gets or sets The version number which associates this preset with a HB build
+ /// </summary>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// Gets or sets the audio track behaviours.
+ /// </summary>
+ public AudioBehaviours AudioTrackBehaviours { get; set; }
+
+ /// <summary>
+ /// Gets or sets the subtitle track behaviours.
+ /// </summary>
+ public SubtitleBehaviours SubtitleTrackBehaviours { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Update this preset.
+ /// The given parameters should be copy-constructed.
+ /// </summary>
+ /// <param name="task">
+ /// The task.
+ /// </param>
+ /// <param name="audioBehaviours">
+ /// The audio behaviours.
+ /// </param>
+ /// <param name="subtitleBehaviours">
+ /// The subtitle behaviours.
+ /// </param>
+ public void Update(EncodeTask task, AudioBehaviours audioBehaviours, SubtitleBehaviours subtitleBehaviours)
+ {
+ // Copy over Max Width / Height for the following picture settings modes.
+ if (this.PictureSettingsMode == PresetPictureSettingsMode.Custom
+ || this.PictureSettingsMode == PresetPictureSettingsMode.SourceMaximum)
+ {
+ task.MaxWidth = this.Task.MaxWidth;
+ task.MaxHeight = this.Task.MaxHeight;
+ }
+
+ this.Task = task;
+ this.AudioTrackBehaviours = audioBehaviours;
+ this.SubtitleTrackBehaviours = subtitleBehaviours;
+ }
+
+ /// <summary>
+ /// Override the ToString Method
+ /// </summary>
+ /// <returns>
+ /// The Preset Name
+ /// </returns>
+ public override string ToString()
+ {
+ return this.Name;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistFactory.cs b/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistFactory.cs new file mode 100644 index 000000000..1efc290e7 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistFactory.cs @@ -0,0 +1,343 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="PlistUtility.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Plist Preset Converter
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets.Factories
+{
+ using System.Text;
+ using System.Xml;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Encoding;
+ using HandBrake.ApplicationServices.Utilities;
+ using HandBrake.Interop.Model.Encoding;
+
+ using HandBrakeWPF.Model.Preset;
+
+ /// <summary>
+ /// Plist Preset Converter
+ /// </summary>
+ public class PlistUtility
+ {
+ #region Export
+
+ /// <summary>
+ /// Export a MacGui style plist preset.
+ /// </summary>
+ /// <param name="path">
+ /// The path.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ /// <param name="build">
+ /// The build.PictureModulusPictureModulus
+ /// </param>
+ public static void Export(string path, Preset preset, string build)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ return;
+ }
+
+ EncodeTask parsed = new EncodeTask(preset.Task);
+ using (XmlTextWriter xmlWriter = new XmlTextWriter(path, Encoding.UTF8) { Formatting = Formatting.Indented })
+ {
+ // Header
+ xmlWriter.WriteStartDocument();
+ xmlWriter.WriteDocType(
+ "plist", "-//Apple//DTD PLIST 1.0//EN", @"http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
+
+ xmlWriter.WriteStartElement("plist");
+ xmlWriter.WriteStartElement("array");
+
+ // Add New Preset Here. Can write multiple presets here if required in future.
+ WritePreset(xmlWriter, parsed, preset, build);
+
+ // Footer
+ xmlWriter.WriteEndElement();
+ xmlWriter.WriteEndElement();
+
+ xmlWriter.WriteEndDocument();
+
+ // Closeout
+ xmlWriter.Close();
+ }
+ }
+
+ /// <summary>
+ /// Write the Preset to a file
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ /// <param name="build">
+ /// The build.
+ /// </param>
+ private static void WritePreset(XmlTextWriter xmlWriter, EncodeTask parsed, Preset preset, string build)
+ {
+ xmlWriter.WriteStartElement("dict");
+ AudioListArrayDict(xmlWriter, parsed);
+ AddEncodeSettings(xmlWriter, parsed, preset, build);
+
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// The get null bool value.
+ /// </summary>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ /// <returns>
+ /// The System.String.
+ /// </returns>
+ private static string getNullBoolValue(bool? value)
+ {
+ if (!value.HasValue)
+ {
+ return "1";
+ }
+
+ return value.Value ? "1" : "0";
+ }
+
+ /// <summary>
+ /// Add the encode settings to the preset
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ /// <param name="preset">
+ /// The preset.
+ /// </param>
+ /// <param name="build">
+ /// The build.
+ /// </param>
+ private static void AddEncodeSettings(XmlTextWriter xmlWriter, EncodeTask parsed, Preset preset, string build)
+ {
+ AddBooleanElement(xmlWriter, "AudioAllowAACPass", parsed.AllowedPassthruOptions.AudioAllowAACPass);
+ AddBooleanElement(xmlWriter, "AudioAllowAC3Pass", parsed.AllowedPassthruOptions.AudioAllowAC3Pass);
+ AddBooleanElement(xmlWriter, "AudioAllowDTSHDPass", parsed.AllowedPassthruOptions.AudioAllowDTSHDPass);
+ AddBooleanElement(xmlWriter, "AudioAllowDTSPass", parsed.AllowedPassthruOptions.AudioAllowDTSPass);
+ AddBooleanElement(xmlWriter, "AudioAllowMP3Pass", parsed.AllowedPassthruOptions.AudioAllowMP3Pass);
+
+ // TODO Update
+ AddEncodeElement(xmlWriter, "AudioEncoderFallback", "string", EnumHelper<AudioEncoder>.GetDisplay(parsed.AllowedPassthruOptions.AudioEncoderFallback));
+
+ AddBooleanElement(xmlWriter, "ChapterMarkers", parsed.IncludeChapterMarkers);
+ AddEncodeElement(xmlWriter, "Default", "integer", "0");
+ AddEncodeElement(xmlWriter, "FileFormat", "string", (parsed.OutputFormat == OutputFormat.Mp4) ? "MP4 file" : "MKV file"); // TODO
+ AddBooleanElement(xmlWriter, "Folder", false);
+ AddEncodeElement(xmlWriter, "Mp4HttpOptimize", "integer", parsed.OptimizeMP4 ? "1" : "0");
+ AddEncodeElement(xmlWriter, "Mp4iPodCompatible", "integer", parsed.IPod5GSupport ? "1" : "0");
+ AddEncodeElement(xmlWriter, "PictureAutoCrop", "integer", "1");
+
+
+ // Filters
+ AddEncodeElement(xmlWriter, "PictureDeblock", "integer", parsed.Deblock.ToString());
+
+ AddBooleanElement(xmlWriter, "PictureDecombDeinterlace", parsed.Decomb != Decomb.Off);
+ AddEncodeElement(xmlWriter, "PictureDecombCustom", "string", parsed.Decomb == Decomb.Custom ? parsed.CustomDecomb : string.Empty);
+ AddEncodeElement(xmlWriter, "PictureDecomb", "integer", ((int)parsed.Decomb).ToString());
+ AddEncodeElement(xmlWriter, "PictureDeinterlaceCustom", "string", parsed.Deinterlace == Deinterlace.Custom ? parsed.CustomDeinterlace : string.Empty);
+ AddEncodeElement(xmlWriter, "PictureDeinterlace", "integer", ((int)parsed.Deinterlace).ToString());
+
+
+ AddEncodeElement(xmlWriter, "PictureDenoiseFilter", "string", parsed.Denoise.ToString().ToLower());
+ AddEncodeElement(xmlWriter, "PictureDenoiseCustom", "string", parsed.DenoisePreset == DenoisePreset.Custom ? parsed.CustomDenoise : string.Empty);
+ AddEncodeElement(xmlWriter, "PictureDenoisePreset", "string", parsed.DenoisePreset.ToString().ToLower());
+ if (parsed.Denoise == Denoise.NLMeans)
+ {
+ AddEncodeElement(xmlWriter, "PictureDenoiseTune", "string", parsed.DenoiseTune.ToString().ToLower());
+ }
+
+ AddEncodeElement(xmlWriter, "PictureDetelecine", "integer", ((int)parsed.Detelecine).ToString());
+ AddEncodeElement(xmlWriter, "PictureDetelecineCustom", "string", parsed.Detelecine == Detelecine.Custom ? parsed.CustomDecomb : string.Empty);
+
+ // Picture Settings
+ AddEncodeElement(xmlWriter, "PictureHeight", "integer", parsed.Height.ToString());
+ AddEncodeElement(xmlWriter, "PictureKeepRatio", "integer", parsed.KeepDisplayAspect ? "1" : "0");
+ AddEncodeElement(xmlWriter, "PictureModulus", "integer", parsed.Modulus.ToString());
+ AddEncodeElement(xmlWriter, "PicturePAR", "integer", ((int)parsed.Anamorphic).ToString());
+ AddEncodeElement(xmlWriter, "PictureLeftCrop", "integer", parsed.Cropping.Left.ToString());
+ AddEncodeElement(xmlWriter, "PictureRightCrop", "integer", parsed.Cropping.Right.ToString());
+ AddEncodeElement(xmlWriter, "PictureTopCrop", "integer", parsed.Cropping.Top.ToString());
+ AddEncodeElement(xmlWriter, "PictureBottomCrop", "integer", parsed.Cropping.Bottom.ToString());
+ AddEncodeElement(xmlWriter, "PictureWidth", "integer", parsed.Width.ToString());
+
+ // Preset Information
+ AddEncodeElement(xmlWriter, "PresetBuildNumber", "string", build);
+ AddEncodeElement(xmlWriter, "PresetDescription", "string", "No Description");
+ AddEncodeElement(xmlWriter, "PresetName", "string", preset.Name);
+ AddEncodeElement(xmlWriter, "Type", "integer", "1"); // 1 is user preset, 0 is built in
+
+ // Preset Settings
+ AddEncodeElement(xmlWriter, "UsesMaxPictureSettings", "integer", (parsed.MaxWidth != 0 || parsed.MaxHeight != 0) ? "1" : "0");
+ AddEncodeElement(xmlWriter, "UsesPictureFilters", "integer", "1");
+ AddEncodeElement(xmlWriter, "UsesPictureSettings", "integer", "1");
+
+ // Video Settings
+ AddEncodeElement(xmlWriter, "VideoAvgBitrate", "string", parsed.VideoBitrate.ToString());
+ AddEncodeElement(xmlWriter, "VideoEncoder", "string", EnumHelper<VideoEncoder>.GetDisplay(parsed.VideoEncoder));
+ AddEncodeElement(xmlWriter, "VideoFramerate", "string", parsed.Framerate == null ? "Same as source" : parsed.Framerate.ToString());
+ AddEncodeElement(xmlWriter, "VideoFramerateMode", "string", parsed.FramerateMode.ToString().ToLower());
+ AddBooleanElement(xmlWriter, "VideoGrayScale", parsed.Grayscale);
+ AddEncodeElement(xmlWriter, "VideoQualitySlider", "real", parsed.Quality.ToString());
+ AddEncodeElement(xmlWriter, "h264Level", "string", parsed.H264Level);
+ AddEncodeElement(xmlWriter, "x264OptionExtra", "string", parsed.AdvancedEncoderOptions);
+ AddEncodeElement(xmlWriter, "x264Preset", "string", parsed.X264Preset.ToString().ToLower());
+ AddEncodeElement(xmlWriter, "h264Profile", "string", parsed.H264Profile.ToString().ToLower());
+ string tune = parsed.X264Tune.ToString().ToLower();
+ if (parsed.FastDecode)
+ {
+ tune = tune == "none" ? "fastdecode" : tune + ",fastdecode";
+ }
+ AddEncodeElement(xmlWriter, "x264Tune", "string", tune);
+ AddEncodeElement(xmlWriter, "x264UseAdvancedOptions", "integer", parsed.ShowAdvancedTab ? "1" : "0");
+
+ AddEncodeElement(xmlWriter, "h265Profile", "string", parsed.H265Profile.ToString().ToLower());
+ AddEncodeElement(xmlWriter, "x265Preset", "string", parsed.X265Preset.ToString().ToLower());
+ AddEncodeElement(xmlWriter, "x265Tune", "string", parsed.X265Tune.ToString().ToLower());
+
+ int videoQualityType = 0;
+ if (parsed.VideoBitrate != null) videoQualityType = 1;
+ else if (parsed.Quality != null) videoQualityType = 2;
+
+ AddEncodeElement(xmlWriter, "VideoQualityType", "integer", videoQualityType.ToString());
+ AddEncodeElement(xmlWriter, "VideoTargetSize", "string", string.Empty);
+ AddEncodeElement(xmlWriter, "VideoTurboTwoPass", "integer", parsed.TurboFirstPass ? "1" : "0");
+ AddEncodeElement(xmlWriter, "VideoTwoPass", "integer", parsed.TwoPass ? "1" : "0");
+
+ // x264 string
+ AddEncodeElement(xmlWriter, "x264Option", "string", parsed.AdvancedEncoderOptions);
+ }
+
+ /// <summary>
+ /// Add a boolean element
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="keyName">
+ /// The key name.
+ /// </param>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ private static void AddBooleanElement(XmlTextWriter xmlWriter, string keyName, bool? value)
+ {
+ xmlWriter.WriteStartElement("key");
+ xmlWriter.WriteString(keyName);
+ xmlWriter.WriteEndElement();
+ xmlWriter.WriteStartElement(value.HasValue ? value.Value ? "true" : "false" : "false");
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Add an encode setting element
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="keyName">
+ /// The key name.
+ /// </param>
+ /// <param name="type">
+ /// The type.
+ /// </param>
+ /// <param name="value">
+ /// The value.
+ /// </param>
+ private static void AddEncodeElement(XmlTextWriter xmlWriter, string keyName, string type, string value)
+ {
+ xmlWriter.WriteElementString("key", keyName);
+
+ // This is a hack for Apples XML parser. It doesn't understand <integer /> so instead, always set a default value
+ // of 0 if the value is empty.
+ if (type == "integer" && string.IsNullOrEmpty(value))
+ {
+ value = "0";
+ }
+ xmlWriter.WriteElementString(type, value);
+ }
+
+ /// <summary>
+ /// Add an Audio Track Array Dict
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="parsed">
+ /// The parsed.
+ /// </param>
+ private static void AudioListArrayDict(XmlTextWriter xmlWriter, EncodeTask parsed)
+ {
+ xmlWriter.WriteStartElement("key");
+ xmlWriter.WriteString("AudioList");
+ xmlWriter.WriteEndElement();
+
+ xmlWriter.WriteStartElement("array");
+ foreach (AudioTrack track in parsed.AudioTracks)
+ {
+ AddAudioItem(xmlWriter, track);
+ }
+ xmlWriter.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Add an audio track
+ /// </summary>
+ /// <param name="xmlWriter">
+ /// The xml writer.
+ /// </param>
+ /// <param name="audioTrack">
+ /// The audio track.
+ /// </param>
+ private static void AddAudioItem(XmlTextWriter xmlWriter, AudioTrack audioTrack)
+ {
+ xmlWriter.WriteStartElement("dict");
+
+ xmlWriter.WriteElementString("key", "AudioBitrate");
+ xmlWriter.WriteElementString("string", audioTrack.Bitrate.ToString());
+
+ xmlWriter.WriteElementString("key", "AudioEncoder");
+ xmlWriter.WriteElementString("string", EnumHelper<AudioEncoder>.GetDisplay(audioTrack.Encoder));
+
+ xmlWriter.WriteElementString("key", "AudioMixdown");
+ xmlWriter.WriteElementString("string", EnumHelper<Mixdown>.GetDisplay(audioTrack.MixDown));
+
+ xmlWriter.WriteElementString("key", "AudioSamplerate");
+ xmlWriter.WriteElementString("string", audioTrack.SampleRate.ToString().Replace("0", "Auto"));
+
+ xmlWriter.WriteElementString("key", "AudioTrack");
+ xmlWriter.WriteElementString("integer", audioTrack.Track.ToString());
+
+ xmlWriter.WriteElementString("key", "AudioTrackDRCSlider");
+ xmlWriter.WriteElementString("real", audioTrack.DRC.ToString());
+
+ xmlWriter.WriteElementString("key", "AudioTrackDescription");
+ xmlWriter.WriteElementString("string", "Unknown");
+
+ xmlWriter.WriteElementString("key", "AudioTrackGainSlider");
+ xmlWriter.WriteElementString("real", audioTrack.Gain.ToString());
+
+ xmlWriter.WriteEndElement();
+ }
+ #endregion
+ }
+}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistPresetFactory.cs b/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistPresetFactory.cs new file mode 100644 index 000000000..fc098d972 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Presets/Factories/PlistPresetFactory.cs @@ -0,0 +1,460 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="PlistPresetFactory.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// A Factory to translate a Plist object into a Preset.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets.Factories
+{
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.ComponentModel;
+ using System.Globalization;
+ using System.Linq;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Model.Audio;
+ using HandBrake.ApplicationServices.Model.Encoding;
+ using HandBrake.ApplicationServices.Model.Subtitle;
+ using HandBrake.ApplicationServices.Utilities;
+ using HandBrake.Interop.Model.Encoding;
+ using HandBrake.Interop.Model.Encoding.x264;
+ using HandBrake.Interop.Model.Encoding.x265;
+
+ using HandBrakeWPF.Model.Preset;
+ using HandBrakeWPF.Services.Presets;
+
+ /// <summary>
+ /// A Factory to translate a Plist object into a Preset.
+ /// </summary>
+ public class PlistPresetFactory
+ {
+ /// <summary>
+ /// The lang list.
+ /// </summary>
+ private static IDictionary<string, string> langList;
+
+ /// <summary>
+ /// Initializes static members of the <see cref="PlistPresetFactory"/> class.
+ /// </summary>
+ static PlistPresetFactory()
+ {
+ IDictionary<string, string> langMap = LanguageUtilities.MapLanguages();
+ langList = (from entry in langMap select entry).ToDictionary(pair => pair.Value, pair => pair.Key);
+ }
+
+ /// <summary>
+ /// The create preset.
+ /// </summary>
+ /// <param name="plist">
+ /// The plist.
+ /// </param>
+ /// <returns>
+ /// The <see cref="Preset"/>.
+ /// </returns>
+ public static Preset CreatePreset(PList plist)
+ {
+ Preset preset = new Preset
+ {
+ Task = new EncodeTask(),
+ Category = PresetService.UserPresetCatgoryName,
+ AudioTrackBehaviours = new AudioBehaviours(),
+ SubtitleTrackBehaviours = new SubtitleBehaviours()
+ };
+
+ // Parse the settings out.
+ foreach (var item in plist)
+ {
+ if (item.Key == "AudioList")
+ {
+ List<AudioTrack> tracks = ParseAudioTracks(item.Value);
+ preset.Task.AudioTracks = new ObservableCollection<AudioTrack>(tracks);
+ }
+ else
+ {
+ ParseSetting(item, preset);
+ }
+ }
+
+ // Handle the PictureDecombDeinterlace key
+ if (preset.UseDeinterlace)
+ {
+ preset.Task.Decomb = Decomb.Off;
+ preset.Task.CustomDecomb = string.Empty;
+ }
+
+ // Depending on the selected preset options, we may need to change some settings around.
+ // If the user chose not to use fitlers, remove them.
+ if (!preset.UsePictureFilters)
+ {
+ preset.Task.Detelecine = Detelecine.Off;
+ preset.Task.Denoise = Denoise.Off;
+ preset.Task.Deinterlace = Deinterlace.Off;
+ preset.Task.Decomb = Decomb.Off;
+ preset.Task.Deblock = 0;
+ preset.Task.Grayscale = false;
+ }
+
+ // IF we are using Source Max, Set the Max Width / Height values.
+ if (preset.PictureSettingsMode == PresetPictureSettingsMode.SourceMaximum)
+ {
+ preset.Task.MaxWidth = preset.Task.Height;
+ preset.Task.MaxHeight = preset.Task.Width;
+ }
+
+ return preset;
+ }
+
+ /// <summary>
+ /// Parse a setting and set it in the given preset.
+ /// </summary>
+ /// <param name="kvp">
+ /// The kvp setting pair.
+ /// </param>
+ /// <param name="preset">
+ /// The preset object.
+ /// </param>
+ private static void ParseSetting(KeyValuePair<string, dynamic> kvp, Preset preset)
+ {
+ switch (kvp.Key)
+ {
+ // Output Settings
+ case "FileFormat":
+ preset.Task.OutputFormat = Converters.GetFileFormat(kvp.Value.Replace("file", string.Empty).Trim());
+ break;
+ case "Mp4HttpOptimize":
+ preset.Task.OptimizeMP4 = kvp.Value == 1;
+ break;
+ case "Mp4iPodCompatible":
+ preset.Task.IPod5GSupport = kvp.Value == 1;
+ break;
+
+ // Picture Settings
+ case "PictureAutoCrop":
+ preset.Task.HasCropping = kvp.Value != 1;
+ break;
+ case "PictureTopCrop":
+ preset.Task.Cropping.Top = kvp.Value;
+ break;
+ case "PictureBottomCrop":
+ preset.Task.Cropping.Bottom = kvp.Value;
+ break;
+ case "PictureLeftCrop":
+ preset.Task.Cropping.Left = kvp.Value;
+ break;
+ case "PictureRightCrop":
+ preset.Task.Cropping.Right = kvp.Value;
+ break;
+ case "PictureHeight":
+ preset.Task.Height = kvp.Value == null || kvp.Value == 0 ? null : kvp.Value;
+ break;
+ case "PictureWidth":
+ preset.Task.Width = kvp.Value == null || kvp.Value == 0 ? null : kvp.Value;
+ break;
+ case "PictureKeepRatio":
+ preset.Task.KeepDisplayAspect = kvp.Value == 1;
+ break;
+ case "PicturePAR":
+ preset.Task.Anamorphic = (Anamorphic)kvp.Value;
+ break;
+ case "PictureModulus":
+ preset.Task.Modulus = kvp.Value;
+ break;
+
+ // Filters
+ case "PictureDeblock":
+ preset.Task.Deblock = kvp.Value;
+ break;
+ case "PictureDecomb":
+ preset.Task.Decomb = (Decomb)kvp.Value;
+ break;
+ case "PictureDecombCustom":
+ preset.Task.CustomDecomb = kvp.Value;
+ break;
+ case "PictureDecombDeinterlace":
+ preset.UseDeinterlace = kvp.Value == true;
+ break;
+ case "PictureDeinterlace":
+ preset.Task.Deinterlace = (Deinterlace)kvp.Value;
+ break;
+ case "PictureDeinterlaceCustom":
+ preset.Task.CustomDeinterlace = kvp.Value;
+ break;
+ case "PictureDenoise":
+ preset.Task.Denoise = (Denoise)kvp.Value;
+ break;
+ case "DenoisePreset":
+ preset.Task.DenoisePreset = (DenoisePreset)kvp.Value; // TODO to be confirmed.
+ break;
+ case "DenoiseTune":
+ preset.Task.DenoiseTune = (DenoiseTune)kvp.Value; // TODO to be confirmed.
+ break;
+ case "PictureDenoiseCustom":
+ preset.Task.CustomDenoise = kvp.Value;
+ break;
+ case "PictureDetelecine":
+ preset.Task.Detelecine = (Detelecine)kvp.Value;
+ break;
+ case "PictureDetelecineCustom":
+ preset.Task.CustomDetelecine = kvp.Value;
+ break;
+
+ // Video Tab
+ case "VideoAvgBitrate":
+ if (!string.IsNullOrEmpty(kvp.Value))
+ {
+ preset.Task.VideoBitrate = int.Parse(kvp.Value);
+ }
+ break;
+ case "VideoEncoder":
+ preset.Task.VideoEncoder = EnumHelper<VideoEncoder>.GetValue(kvp.Value);
+ break;
+ case "VideoFramerate":
+ preset.Task.Framerate = kvp.Value == "Same as source" || string.IsNullOrEmpty(kvp.Value) ? null : double.Parse(kvp.Value, CultureInfo.InvariantCulture);
+ break;
+ case "VideoFramerateMode":
+ string parsedValue = kvp.Value;
+ switch (parsedValue)
+ {
+ case "vfr":
+ preset.Task.FramerateMode = FramerateMode.VFR;
+ break;
+ case "cfr":
+ preset.Task.FramerateMode = FramerateMode.CFR;
+ break;
+ default:
+ preset.Task.FramerateMode = FramerateMode.PFR;
+ break;
+ }
+ break;
+ case "VideoGrayScale":
+ preset.Task.Grayscale = kvp.Value == true;
+ break;
+ case "VideoQualitySlider":
+ preset.Task.Quality = double.Parse(kvp.Value.ToString(), CultureInfo.InvariantCulture);
+ break;
+ case "VideoQualityType": // The Type of Quality Mode used
+ preset.Task.VideoEncodeRateType = (VideoEncodeRateType)kvp.Value;
+ break;
+ case "VideoTurboTwoPass":
+ preset.Task.TurboFirstPass = kvp.Value == 1;
+ break;
+ case "VideoTwoPass":
+ preset.Task.TwoPass = kvp.Value == 1;
+ break;
+ case "x264OptionExtra":
+ preset.Task.AdvancedEncoderOptions = kvp.Value;
+ break;
+ case "x264Preset":
+ preset.Task.X264Preset = EnumHelper<x264Preset>.GetValue(kvp.Value, true);
+ break;
+ case "h264Profile":
+ preset.Task.H264Profile = EnumHelper<x264Profile>.GetValue(kvp.Value, true);
+ break;
+ case "x264Tune":
+ string value = kvp.Value;
+ if (value.Contains("fastdecode"))
+ {
+ preset.Task.FastDecode = true;
+ value = value.Replace("fastdecode", string.Empty).Replace(",", string.Empty);
+ }
+ preset.Task.X264Tune = EnumHelper<x264Tune>.GetValue(value, true);
+ break;
+ case "h264Level":
+ preset.Task.H264Level = kvp.Value;
+ break;
+ case "QsvPreset":
+ preset.Task.QsvPreset = EnumHelper<QsvPreset>.GetValue(kvp.Value, true);
+ break;
+ case "h265Profile":
+ preset.Task.H265Profile = EnumHelper<x265Profile>.GetValue(kvp.Value, true);
+ break;
+ case "x265Tune":
+ preset.Task.X265Tune = EnumHelper<x265Tune>.GetValue(kvp.Value, true);
+ break;
+ case "x265Preset":
+ preset.Task.X265Preset = EnumHelper<x265Preset>.GetValue(kvp.Value, true);
+ break;
+
+ // Chapter Markers Tab
+ case "ChapterMarkers":
+ preset.Task.IncludeChapterMarkers = kvp.Value == true;
+ break;
+
+ // Advanced x264 tab
+ case "x264Option":
+ if (preset.Task.VideoEncoder == VideoEncoder.X264) // TODO Temp fix until a better solution is found.
+ {
+ preset.Task.AdvancedEncoderOptions = kvp.Value;
+ }
+ break;
+
+ case "lavcOption":
+ if (preset.Task.VideoEncoder != VideoEncoder.X264) // TODO Temp fix until a better solution is found.
+ {
+ preset.Task.AdvancedEncoderOptions = kvp.Value;
+ }
+ break;
+
+ // Preset Information
+ case "PresetBuildNumber":
+ preset.Version = kvp.Value;
+ break;
+ case "PresetDescription":
+ preset.Description = kvp.Value;
+ break;
+ case "PresetName":
+ preset.Name = kvp.Value;
+ break;
+ case "Type":
+ // preset.Task.Type = kvp.Value; // TODO find out what this is
+ break;
+ case "UsesMaxPictureSettings":
+ // TODO Not sure if this is used now!?
+ break;
+ case "UsesPictureFilters":
+ preset.UsePictureFilters = kvp.Value == 1;
+ break;
+ case "UsesPictureSettings":
+ preset.PictureSettingsMode = (PresetPictureSettingsMode)kvp.Value;
+ break;
+
+ // Allowed Passthru
+ case "AudioAllowAACPass":
+ preset.Task.AllowedPassthruOptions.AudioAllowAACPass = kvp.Value == true;
+ break;
+ case "AudioAllowAC3Pass":
+ preset.Task.AllowedPassthruOptions.AudioAllowAC3Pass = kvp.Value == true;
+ break;
+ case "AudioAllowDTSHDPass":
+ preset.Task.AllowedPassthruOptions.AudioAllowDTSHDPass = kvp.Value == true;
+ break;
+ case "AudioAllowDTSPass":
+ preset.Task.AllowedPassthruOptions.AudioAllowDTSPass = kvp.Value == true;
+ break;
+ case "AudioAllowMP3Pass":
+ preset.Task.AllowedPassthruOptions.AudioAllowMP3Pass = kvp.Value == true;
+ break;
+ case "AudioEncoderFallback":
+ preset.Task.AllowedPassthruOptions.AudioEncoderFallback = EnumHelper<AudioEncoder>.GetValue(kvp.Value);
+ break;
+
+ // Audio Defaults
+ case "AudioLanguageList":
+ preset.AudioTrackBehaviours.SelectedLangauges = new BindingList<string>(ParseLangaugeCodeList(kvp.Value));
+ break;
+ case "AudioSecondaryEncoderMode":
+ break;
+ case "AudioTrackSelectionBehavior":
+ preset.AudioTrackBehaviours.SelectedBehaviour = kvp.Value == "all"
+ ? AudioBehaviourModes.AllMatching
+ : kvp.Value == "first"
+ ? AudioBehaviourModes.FirstMatch
+ : AudioBehaviourModes.None;
+ break;
+
+ // Subtitle Defaults
+ case "SubtitleAddForeignAudioSearch":
+ preset.SubtitleTrackBehaviours.AddForeignAudioScanTrack = kvp.Value == true;
+ break;
+ case "SubtitleAddCC":
+ preset.SubtitleTrackBehaviours.AddClosedCaptions = kvp.Value == true;
+ break;
+ case "SubtitleLanguageList":
+ preset.SubtitleTrackBehaviours.SelectedLangauges = new BindingList<string>(ParseLangaugeCodeList(kvp.Value));
+ break;
+ case "SubtitleTrackSelectionBehavior":
+ preset.SubtitleTrackBehaviours.SelectedBehaviour = kvp.Value == "all"
+ ? SubtitleBehaviourModes.AllMatching
+ : kvp.Value == "first"
+ ? SubtitleBehaviourModes.FirstMatch
+ : SubtitleBehaviourModes.None;
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Parse a number of audio tracks
+ /// </summary>
+ /// <param name="audioList">
+ /// The audio list.
+ /// </param>
+ /// <returns>
+ /// The <see cref="List"/> of audio tracks
+ /// </returns>
+ private static List<AudioTrack> ParseAudioTracks(IEnumerable<dynamic> audioList)
+ {
+ return audioList.Select(item => ParseAudioTrackParameters(item)).Cast<AudioTrack>().ToList();
+ }
+
+ /// <summary>
+ /// The parse langauge code list.
+ /// </summary>
+ /// <param name="languages">
+ /// The languages.
+ /// </param>
+ /// <returns>
+ /// The <see cref="IEnumerable"/>.
+ /// </returns>
+ private static IEnumerable<string> ParseLangaugeCodeList(IEnumerable<object> languages)
+ {
+ List<string> languageCodesList = new List<string>();
+ foreach (var item in languages)
+ {
+ string language;
+ if (langList.TryGetValue(item.ToString(), out language))
+ {
+ languageCodesList.Add(language);
+ }
+ }
+
+ return languageCodesList;
+ }
+
+ /// <summary>
+ /// Parse an audio track's parameters.
+ /// </summary>
+ /// <param name="audioTrack">
+ /// The audio track params
+ /// </param>
+ /// <returns>
+ /// An <see cref="AudioTrack"/> Object
+ /// </returns>
+ private static AudioTrack ParseAudioTrackParameters(Dictionary<string, dynamic> audioTrack)
+ {
+ AudioTrack track = new AudioTrack();
+ foreach (var item in audioTrack)
+ {
+ switch (item.Key)
+ {
+ case "AudioBitrate":
+ track.Bitrate = int.Parse(item.Value);
+ break;
+ case "AudioEncoder":
+ track.Encoder = Converters.GetAudioEncoder(item.Value.Trim());
+ break;
+ case "AudioMixdown":
+ track.MixDown = Converters.GetAudioMixDown(item.Value.Trim());
+ break;
+ case "AudioSamplerate":
+ track.SampleRate = item.Value == "Auto" ? 0 : double.Parse(item.Value);
+ break;
+ case "AudioTrack":
+ // track.SourceTrack = value; We don't do anything with this one.
+ break;
+ case "AudioTrackDRCSlider":
+ track.DRC = item.Value;
+ break;
+ case "AudioTrackGainSlider":
+ track.Gain = (int)item.Value;
+ break;
+ }
+ }
+
+ return track;
+ }
+ }
+}
diff --git a/win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetService.cs b/win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetService.cs new file mode 100644 index 000000000..90dd855fb --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetService.cs @@ -0,0 +1,131 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IPresetService.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The Preset Service Interface
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets.Interfaces
+{
+ using System.Collections.ObjectModel;
+
+ using HandBrakeWPF.Model.Preset;
+
+ /// <summary>
+ /// The Preset Service Interface
+ /// </summary>
+ public interface IPresetService
+ {
+ /// <summary>
+ /// Gets a Collection of presets.
+ /// </summary>
+ ObservableCollection<Preset> Presets { get; }
+
+ /// <summary>
+ /// Gets DefaultPreset.
+ /// </summary>
+ Preset DefaultPreset { get; }
+
+ /// <summary>
+ /// The load.
+ /// </summary>
+ void Load();
+
+ /// <summary>
+ /// Add a new preset to the system
+ /// </summary>
+ /// <param name="preset">
+ /// A Preset to add
+ /// </param>
+ /// <returns>
+ /// True if added,
+ /// False if name already exists
+ /// </returns>
+ bool Add(Preset preset);
+
+ /// <summary>
+ /// Update a preset
+ /// </summary>
+ /// <param name="update">
+ /// The updated preset
+ /// </param>
+ void Update(Preset update);
+
+ /// <summary>
+ /// Remove a preset with a given name from either the built in or user preset list.
+ /// </summary>
+ /// <param name="preset">
+ /// The Preset to remove
+ /// </param>
+ void Remove(Preset preset);
+
+ /// <summary>
+ /// Remove a group of presets by category
+ /// </summary>
+ /// <param name="category">
+ /// The Category to remove
+ /// </param>
+ void RemoveGroup(string category);
+
+ /// <summary>
+ /// Get a Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name of the preset to get
+ /// </param>
+ /// <returns>
+ /// A Preset or null object
+ /// </returns>
+ Preset GetPreset(string name);
+
+ /// <summary>
+ /// Clear Built-in Presets
+ /// </summary>
+ void ClearBuiltIn();
+
+ /// <summary>
+ /// Clear all presets
+ /// </summary>
+ void ClearAll();
+
+ /// <summary>
+ /// Set Default Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name.
+ /// </param>
+ void SetDefault(Preset name);
+
+ /// <summary>
+ /// Returns a value if the preset can be updated / resaved
+ /// </summary>
+ /// <param name="name">
+ /// The name.
+ /// </param>
+ /// <returns>
+ /// True if it's not a built-in preset, false otherwise.
+ /// </returns>
+ bool CanUpdatePreset(string name);
+
+ /// <summary>
+ /// Reads the CLI's CLI output format and load's them into the preset List Preset
+ /// </summary>
+ void UpdateBuiltInPresets();
+
+ /// <summary>
+ /// Check if the built in Presets stored are not out of date.
+ /// Update them if they are.
+ /// </summary>
+ /// <returns>true if out of date</returns>
+ bool CheckIfPresetsAreOutOfDate();
+
+ /// <summary>
+ /// Check if the preset "name" exists in either Presets or UserPresets lists.
+ /// </summary>
+ /// <param name="name">Name of the preset</param>
+ /// <returns>True if found</returns>
+ bool CheckIfPresetExists(string name);
+ }
+}
\ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs b/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs new file mode 100644 index 000000000..5afb3cf23 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Presets/PresetService.cs @@ -0,0 +1,503 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="PresetService.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The preset service manages HandBrake's presets
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Xml.Serialization;
+
+ using HandBrake.ApplicationServices.Exceptions;
+ using HandBrake.ApplicationServices.Model.Encoding;
+ using HandBrake.ApplicationServices.Utilities;
+
+ using HandBrakeWPF.Model.Preset;
+ using HandBrakeWPF.Services.Presets.Interfaces;
+
+ /// <summary>
+ /// The preset service manages HandBrake's presets
+ /// </summary>
+ public class PresetService : IPresetService
+ {
+ #region Private Variables
+
+ /// <summary>
+ /// XML Serializer
+ /// </summary>
+ private static readonly XmlSerializer Ser = new XmlSerializer(typeof(List<Preset>));
+
+ /// <summary>
+ /// User Preset Default Catgory Name
+ /// </summary>
+ public static string UserPresetCatgoryName = "User Presets";
+
+ /// <summary>
+ /// The User Preset file
+ /// </summary>
+ private readonly string userPresetFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\user_presets.xml";
+
+ /// <summary>
+ /// The Built In Presets File
+ /// </summary>
+ private readonly string builtInPresetFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\presets.xml";
+
+ /// <summary>
+ /// A Collection of presets
+ /// </summary>
+ private readonly ObservableCollection<Preset> presets = new ObservableCollection<Preset>();
+
+ #endregion
+
+ /// <summary>
+ /// Gets a Collection of presets.
+ /// </summary>
+ public ObservableCollection<Preset> Presets
+ {
+ get
+ {
+ return this.presets;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets LastPresetAdded.
+ /// </summary>
+ public Preset LastPresetAdded { get; set; }
+
+ /// <summary>
+ /// Gets the DefaultPreset.
+ /// </summary>
+ public Preset DefaultPreset
+ {
+ get
+ {
+ return this.presets.FirstOrDefault(p => p.IsDefault);
+ }
+ }
+
+ #region Public Methods
+
+ /// <summary>
+ /// The load.
+ /// </summary>
+ public void Load()
+ {
+ // If the preset file doesn't exist. Create it.
+ if (!File.Exists(this.builtInPresetFile))
+ {
+ this.UpdateBuiltInPresets();
+ }
+
+ this.LoadPresets();
+ }
+
+ /// <summary>
+ /// Add a new preset to the system.
+ /// Performs an Update if it already exists
+ /// </summary>
+ /// <param name="preset">
+ /// A Preset to add
+ /// </param>
+ /// <returns>
+ /// True if added,
+ /// False if name already exists
+ /// </returns>
+ public bool Add(Preset preset)
+ {
+ if (this.CheckIfPresetExists(preset.Name) == false)
+ {
+ this.presets.Add(preset);
+ this.LastPresetAdded = preset;
+
+ // Update the presets file
+ this.UpdatePresetFiles();
+ return true;
+ }
+
+ this.Update(preset);
+ return true;
+ }
+
+ /// <summary>
+ /// Update a preset
+ /// </summary>
+ /// <param name="update">
+ /// The updated preset
+ /// </param>
+ public void Update(Preset update)
+ {
+ // TODO - Change this to be a lookup
+ foreach (Preset preset in this.presets)
+ {
+ if (preset.Name == update.Name)
+ {
+ preset.Task = update.Task;
+ preset.UsePictureFilters = update.UsePictureFilters;
+ preset.PictureSettingsMode = update.PictureSettingsMode;
+ preset.Category = update.Category;
+ preset.Description = update.Description;
+
+ // Update the presets file
+ this.UpdatePresetFiles();
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Remove a preset with a given name from either the built in or user preset list.
+ /// </summary>
+ /// <param name="preset">
+ /// The Preset to remove
+ /// </param>
+ public void Remove(Preset preset)
+ {
+ if (preset == null || preset.IsDefault)
+ {
+ return;
+ }
+
+ this.presets.Remove(preset);
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Remove a group of presets by category
+ /// </summary>
+ /// <param name="category">
+ /// The Category to remove
+ /// </param>
+ public void RemoveGroup(string category)
+ {
+ List<Preset> removeList = this.presets.Where(p => p.Category == category).ToList();
+ foreach (Preset preset in removeList)
+ {
+ if (preset.IsDefault)
+ {
+ // Skip default preset
+ continue;
+ }
+
+ this.presets.Remove(preset);
+ }
+
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Set Default Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name.
+ /// </param>
+ public void SetDefault(Preset name)
+ {
+ foreach (Preset preset in this.presets)
+ {
+ preset.IsDefault = false;
+ }
+
+ name.IsDefault = true;
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Get a Preset
+ /// </summary>
+ /// <param name="name">
+ /// The name of the preset to get
+ /// </param>
+ /// <returns>
+ /// A Preset or null object
+ /// </returns>
+ public Preset GetPreset(string name)
+ {
+ return this.presets.FirstOrDefault(item => item.Name == name);
+ }
+
+ /// <summary>
+ /// Clear Built-in Presets
+ /// </summary>
+ public void ClearBuiltIn()
+ {
+ List<Preset> remove = this.presets.Where(p => p.IsBuildIn).ToList();
+ foreach (Preset preset in remove)
+ {
+ this.presets.Remove(preset);
+ }
+ }
+
+ /// <summary>
+ /// Clear all presets
+ /// </summary>
+ public void ClearAll()
+ {
+ this.presets.Clear();
+ }
+
+ /// <summary>
+ /// Reads the CLI's CLI output format and load's them into the preset List Preset
+ /// </summary>
+ public void UpdateBuiltInPresets()
+ {
+ // Create a new tempory file and execute the CLI to get the built in Presets.
+ string handbrakeCLIPath = Path.Combine(System.Windows.Forms.Application.StartupPath, "HandBrakeCLI.exe");
+ string presetsPath = Path.Combine(Path.GetTempPath(), "temp_presets.dat");
+ string strCmdLine = String.Format(@"cmd /c """"{0}"" --preset-list >""{1}"" 2>&1""", handbrakeCLIPath, presetsPath);
+
+ ProcessStartInfo getPresets = new ProcessStartInfo("CMD.exe", strCmdLine) { WindowStyle = ProcessWindowStyle.Hidden };
+
+ Process hbproc = Process.Start(getPresets);
+ hbproc.WaitForExit();
+ hbproc.Dispose();
+ hbproc.Close();
+
+ // Clear the current built in Presets and now parse the tempory Presets file.
+ this.ClearBuiltIn();
+
+ if (File.Exists(presetsPath))
+ {
+ using (StreamReader presetInput = new StreamReader(presetsPath))
+ {
+ StringBuilder contents = new StringBuilder();
+
+ string category = String.Empty;
+
+ while (!presetInput.EndOfStream)
+ {
+ string line = presetInput.ReadLine();
+ contents.AppendLine(line);
+
+ // Found the beginning of a preset block )
+ if (line != null && line.Contains("<") && !line.Contains("<<"))
+ {
+ category = line.Replace("<", string.Empty).Trim();
+ }
+
+ // Found a preset
+ if (line != null && line.Contains("+"))
+ {
+ Regex r = new Regex("(: )"); // Split on hyphens.
+ string[] presetName = r.Split(line);
+
+ Preset newPreset = new Preset
+ {
+ Category = category,
+ Name = presetName[0].Replace("+", string.Empty).Trim(),
+ Version = VersionHelper.GetVersion(),
+ Description = string.Empty, // Maybe one day we will populate this.
+ IsBuildIn = true,
+ UsePictureFilters = true,
+ Task = QueryParserUtility.Parse(presetName[2])
+ };
+
+ if (newPreset.Name == "iPod")
+ {
+ newPreset.Task.KeepDisplayAspect = true;
+ }
+
+ newPreset.Task.AllowedPassthruOptions = new AllowedPassthru(true); // We don't want to override the built-in preset
+
+ if (newPreset.Name == "Normal")
+ {
+ newPreset.IsDefault = true;
+ }
+
+ this.presets.Add(newPreset);
+ }
+ }
+
+ // Verify we have presets.
+ if (this.presets.Count == 0)
+ {
+ throw new GeneralApplicationException("Failed to load built-in presets.", "Restarting HandBrake may resolve this issue", new Exception(contents.ToString()));
+ }
+ }
+ }
+ else
+ {
+ // Something really bad must have happened if the file is missing.
+ throw new GeneralApplicationException("Preset Export Failed. Unable to load in Presets.", "Please restart HandBrake", null);
+ }
+
+ // Finally, Create a new or update the current Presets.xml file
+ this.UpdatePresetFiles();
+ }
+
+ /// <summary>
+ /// Check if the built in Presets stored are not out of date.
+ /// Update them if they are.
+ /// </summary>
+ /// <returns>true if out of date</returns>
+ public bool CheckIfPresetsAreOutOfDate()
+ {
+ // Update built-in Presets if the built-in Presets belong to an older version.
+ if (this.presets.Count != 0)
+ {
+ List<Preset> preset = this.presets.Where(p => p.IsBuildIn).ToList();
+ if (preset.Count > 0)
+ {
+ if (preset[0].Version != VersionHelper.GetVersion())
+ {
+ this.UpdateBuiltInPresets();
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Check if the preset "name" exists in either Presets or UserPresets lists.
+ /// </summary>
+ /// <param name="name">Name of the preset</param>
+ /// <returns>True if found</returns>
+ public bool CheckIfPresetExists(string name)
+ {
+ return name == string.Empty || this.presets.Any(item => item.Name == name);
+ }
+
+ /// <summary>
+ /// Returns a value if the preset can be updated / resaved
+ /// </summary>
+ /// <param name="name">
+ /// The name.
+ /// </param>
+ /// <returns>
+ /// True if it's not a built-in preset, false otherwise.
+ /// </returns>
+ public bool CanUpdatePreset(string name)
+ {
+ return this.presets.Where(preset => preset.Name == name).Any(preset => preset.IsBuildIn == false);
+ }
+
+ #endregion
+
+ #region Private Helpers
+
+ /// <summary>
+ /// Recover from a courrpted preset file
+ /// Add .old to the current filename, and delete the current file.
+ /// </summary>
+ /// <param name="file">
+ /// The broken presets file.
+ /// </param>
+ private static void RecoverFromCorruptedPresetFile(string file)
+ {
+ try
+ {
+ // Recover from Error.
+ if (File.Exists(file))
+ {
+ string disabledFile = string.Format("{0}.{1}", file, GeneralUtilities.ProcessId);
+ File.Move(file, disabledFile);
+ if (File.Exists(file))
+ {
+ File.Delete(file);
+ }
+ }
+ }
+ catch (IOException)
+ {
+ // Give up
+ }
+ }
+
+ /// <summary>
+ /// Load in the Built-in and User presets into the collection
+ /// </summary>
+ private void LoadPresets()
+ {
+ // First clear the Presets arraylists
+ this.presets.Clear();
+
+ // Load in the Presets from Presets.xml
+ try
+ {
+ if (File.Exists(this.builtInPresetFile))
+ {
+ using (StreamReader reader = new StreamReader(this.builtInPresetFile))
+ {
+ List<Preset> list = (List<Preset>)Ser.Deserialize(reader);
+ foreach (Preset preset in list)
+ {
+ preset.IsBuildIn = true;
+ // Older versions did not have this flag so explicitly make sure it is set.
+ this.presets.Add(preset);
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+ RecoverFromCorruptedPresetFile(this.builtInPresetFile);
+ this.UpdateBuiltInPresets();
+ }
+
+ // Load in the users Presets from UserPresets.xml
+ try
+ {
+ if (File.Exists(this.userPresetFile))
+ {
+ using (StreamReader reader = new StreamReader(this.userPresetFile))
+ {
+ List<Preset> list = (List<Preset>)Ser.Deserialize(reader);
+ foreach (Preset preset in list)
+ {
+ this.presets.Add(preset);
+ }
+ }
+ }
+ }
+ catch (Exception exc)
+ {
+ RecoverFromCorruptedPresetFile(this.userPresetFile);
+ throw new GeneralApplicationException("HandBrake has detected a problem with your presets.", "Your old presets file has been renamed so that it doesn't get loaded on next launch.", exc);
+ }
+ }
+
+ /// <summary>
+ /// Update the preset files
+ /// </summary>
+ private void UpdatePresetFiles()
+ {
+ try
+ {
+ string directory = Path.GetDirectoryName(this.userPresetFile);
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ using (FileStream strm = new FileStream(this.builtInPresetFile, FileMode.Create, FileAccess.Write))
+ {
+ Ser.Serialize(strm, this.presets.Where(p => p.IsBuildIn).ToList());
+ }
+
+ using (FileStream strm = new FileStream(this.userPresetFile, FileMode.Create, FileAccess.Write))
+ {
+ Ser.Serialize(strm, this.presets.Where(p => p.IsBuildIn == false).ToList());
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new GeneralApplicationException("Unable to write to the presets file.", "The details section below may indicate why this error has occured.", exc);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs index 379fcec91..c22d881cb 100644 --- a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs +++ b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs @@ -26,6 +26,8 @@ namespace HandBrakeWPF.Startup using HandBrakeWPF.Commands;
using HandBrakeWPF.Commands.Interfaces;
+ using HandBrakeWPF.Services.Presets;
+ using HandBrakeWPF.Services.Presets.Interfaces;
using ViewModels;
using ViewModels.Interfaces;
@@ -63,6 +65,7 @@ namespace HandBrakeWPF.Startup this.windsorContainer.Register(Component.For<INotificationService>().ImplementedBy<NotificationService>().LifeStyle.Is(LifestyleType.Singleton));
this.windsorContainer.Register(Component.For<IPrePostActionService>().ImplementedBy<PrePostActionService>().LifeStyle.Is(LifestyleType.Singleton));
this.windsorContainer.Register(Component.For<IUserSettingService>().ImplementedBy<UserSettingService>());
+ this.windsorContainer.Register(Component.For<IPresetService>().ImplementedBy<PresetService>());
// Commands
this.windsorContainer.Register(Component.For<IAdvancedEncoderOptionsCommand>().ImplementedBy<AdvancedEncoderOptionsCommand>().LifeStyle.Is(LifestyleType.Singleton));
diff --git a/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs index 16b26bb83..4c2eccf41 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AddPresetViewModel.cs @@ -21,8 +21,12 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Utilities;
using HandBrake.Interop.Model.Encoding;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Properties;
+ using HandBrakeWPF.Services;
using HandBrakeWPF.Services.Interfaces;
+ using HandBrakeWPF.Services.Presets;
+ using HandBrakeWPF.Services.Presets.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
/// <summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs index 470a27be2..bfc445c74 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs @@ -13,6 +13,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Parsing;
using HandBrake.Interop.Model.Encoding;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.ViewModels.Interfaces;
/// <summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs index b297782f2..faba373d7 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs @@ -23,6 +23,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Utilities;
using HandBrake.Interop.Model.Encoding;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
diff --git a/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs index c1bc619a5..7768cda9b 100644 --- a/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs @@ -21,6 +21,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Model.Encoding;
using HandBrake.ApplicationServices.Parsing;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
diff --git a/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs index 42407aadf..9da0b7361 100644 --- a/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/EncoderOptionsViewModel.cs @@ -15,6 +15,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Parsing;
using HandBrake.Interop.Model.Encoding;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.ViewModels.Interfaces;
/// <summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs index 019bf0418..8ed024a09 100644 --- a/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs @@ -20,6 +20,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Utilities;
using HandBrake.Interop.Model.Encoding;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
diff --git a/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs index dcaf1a7f4..f31a633e2 100644 --- a/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs @@ -32,7 +32,9 @@ namespace HandBrakeWPF.ViewModels using HandBrakeWPF.Factories;
using HandBrakeWPF.Helpers;
using HandBrakeWPF.Model;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Services.Interfaces;
+ using HandBrakeWPF.Services.Presets.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
using HandBrakeWPF.Views;
diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs index e08d2d9ff..ac7bf0106 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs @@ -11,6 +11,8 @@ namespace HandBrakeWPF.ViewModels.Interfaces {
using HandBrake.ApplicationServices.Model;
+ using HandBrakeWPF.Model.Preset;
+
/// <summary>
/// The Main Window View Model
/// </summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs index 42ca560f4..1cdc634a9 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs @@ -12,6 +12,8 @@ namespace HandBrakeWPF.ViewModels.Interfaces using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Parsing;
+ using HandBrakeWPF.Model.Preset;
+
/// <summary>
/// Common interface for all the main tab panels
/// </summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index 3665c7acf..0252a1945 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -21,7 +21,6 @@ namespace HandBrakeWPF.ViewModels using Caliburn.Micro;
- using HandBrake.ApplicationServices.Factories;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Model.Audio;
using HandBrake.ApplicationServices.Model.Encoding;
@@ -34,8 +33,12 @@ namespace HandBrakeWPF.ViewModels using HandBrakeWPF.Factories;
using HandBrakeWPF.Helpers;
using HandBrakeWPF.Model;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Properties;
using HandBrakeWPF.Services.Interfaces;
+ using HandBrakeWPF.Services.Presets.Factories;
+ using HandBrakeWPF.Services.Presets.Interfaces;
+ using HandBrakeWPF.Utilities;
using HandBrakeWPF.ViewModels.Interfaces;
using HandBrakeWPF.Views;
diff --git a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs index d569b7824..3d08327d6 100644 --- a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs @@ -19,6 +19,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.Interop.Model.Encoding;
using HandBrakeWPF.Helpers;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Utilities;
using HandBrakeWPF.ViewModels.Interfaces;
diff --git a/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs index 0161c562b..ce0c6f764 100644 --- a/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs @@ -20,6 +20,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Parsing;
using HandBrake.ApplicationServices.Utilities;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.ViewModels.Interfaces;
using Ookii.Dialogs.Wpf;
diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs index ccb5cd73a..3e62828e0 100644 --- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs @@ -28,6 +28,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.Interop.Model.Encoding.x265;
using HandBrakeWPF.Commands.Interfaces;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.Properties;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
diff --git a/win/CS/HandBrakeWPF/ViewModels/X264ViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/X264ViewModel.cs index 94d425c7e..39db9776a 100644 --- a/win/CS/HandBrakeWPF/ViewModels/X264ViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/X264ViewModel.cs @@ -21,6 +21,7 @@ namespace HandBrakeWPF.ViewModels using HandBrakeWPF.Commands.Interfaces;
using HandBrakeWPF.Helpers;
using HandBrakeWPF.Model;
+ using HandBrakeWPF.Model.Preset;
using HandBrakeWPF.ViewModels.Interfaces;
/// <summary>
|