HandBrake/win/CS/HandBrakeWPF/Services/UserSettingService.cs

395 lines
17 KiB
C#

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UserSettingService.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 User Setting Service
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.Services
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using HandBrake.App.Core.Utilities;
using HandBrake.Interop.Interop;
using HandBrake.Interop.Utilities;
using HandBrakeWPF.Model;
using HandBrakeWPF.Model.Options;
using HandBrakeWPF.Model.Video;
using HandBrakeWPF.Properties;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.Services.Logging.Interfaces;
using HandBrakeWPF.Utilities;
using GeneralApplicationException = HandBrake.App.Core.Exceptions.GeneralApplicationException;
using SettingChangedEventArgs = EventArgs.SettingChangedEventArgs;
using SystemInfo = Utilities.SystemInfo;
/// <summary>
/// The User Setting Service
/// </summary>
public class UserSettingService : IUserSettingService
{
private readonly ILog logService;
private readonly string settingsFile = Path.Combine(DirectoryUtilities.GetUserStoragePath(HandBrakeVersionHelper.IsNightly()), "settings.json");
private readonly string releaseSettingsFile = Path.Combine(DirectoryUtilities.GetUserStoragePath(false), "settings.json");
private readonly string nightlySettingsFile = Path.Combine(DirectoryUtilities.GetUserStoragePath(true), "settings.json");
private Dictionary<string, object> userSettings;
/// <summary>
/// Initializes a new instance of the <see cref="UserSettingService"/> class.
/// </summary>
public UserSettingService(ILog logService)
{
this.logService = logService;
this.Load();
}
/// <summary>
/// The setting changed.
/// </summary>
public event SettingEventHandler SettingChanged;
/// <summary>
/// Set the specified user setting.
/// </summary>
/// <param name="name">
/// Name of the property
/// </param>
/// <param name="value">
/// The value to store.
/// </param>
public void SetUserSetting(string name, object value)
{
this.userSettings[name] = value;
this.Save();
this.OnSettingChanged(new SettingChangedEventArgs { Key = name, Value = value });
}
/// <summary>
/// Get user setting for a given key.
/// </summary>
/// <param name="name">
/// The name.
/// </param>
/// <typeparam name="T">
/// The Type of the setting
/// </typeparam>
/// <returns>
/// The user setting
/// </returns>
public T GetUserSetting<T>(string name)
{
try
{
if (this.userSettings.ContainsKey(name))
{
object settingValue = this.userSettings[name];
if (settingValue is JsonElement)
{
T rawValue = JsonSerializer.Deserialize<T>(
((JsonElement)settingValue).GetRawText(),
JsonSettings.Options);
return rawValue;
}
T objectElement = (T)this.userSettings[name];
return objectElement;
}
}
catch (Exception e)
{
this.logService.LogMessage("Unable to fetch user setting: " + name + " - " + e);
return GetDefaultValue<T>(name);
}
return default(T);
}
public void ResetSettingsToDefaults()
{
this.userSettings.Clear();
// Set Defaults
Dictionary<string, object> defaults = this.GetDefaults();
foreach (var item in defaults.Where(item => !this.userSettings.Keys.Contains(item.Key)))
{
this.userSettings.Add(item.Key, item.Value);
this.Save();
}
}
/// <summary>
/// The on setting changed.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
protected virtual void OnSettingChanged(SettingChangedEventArgs e)
{
SettingEventHandler handler = this.SettingChanged;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Save the User Settings
/// </summary>
private void Save()
{
try
{
string directory = Path.GetDirectoryName(this.settingsFile);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (StreamWriter file = new StreamWriter(new FileStream(this.settingsFile, FileMode.Create, FileAccess.Write)))
{
string appSettings = JsonSerializer.Serialize(this.userSettings, JsonSettings.Options);
file.Write(appSettings);
}
}
catch (Exception exc)
{
throw new GeneralApplicationException(
Resources.UserSettings_AnErrorOccurred,
Resources.SettingService_SaveErrorReset,
exc);
}
}
/// <summary>
/// Load the User Settings
/// </summary>
private void Load()
{
try
{
// Load up the users current settings file.
if (File.Exists(this.settingsFile))
{
using (StreamReader reader = new StreamReader(this.settingsFile))
{
string appSettings = reader.ReadToEnd();
Dictionary<string, object> deserializedSettings = JsonSerializer.Deserialize<Dictionary<string, object>>(appSettings, JsonSettings.Options);
this.userSettings = deserializedSettings;
}
}
else if (HandBrakeVersionHelper.IsNightly() && File.Exists(this.releaseSettingsFile))
{
// Port the release versions config to the nightly.
if (!Directory.Exists(DirectoryUtilities.GetUserStoragePath(true)))
{
Directory.CreateDirectory(DirectoryUtilities.GetUserStoragePath(true));
}
File.Copy(this.releaseSettingsFile, this.nightlySettingsFile);
using (StreamReader reader = new StreamReader(this.settingsFile))
{
string appSettings = reader.ReadToEnd();
Dictionary<string, object> deserializedSettings = JsonSerializer.Deserialize<Dictionary<string, object>>(appSettings, JsonSettings.Options);
this.userSettings = deserializedSettings;
}
}
else
{
this.userSettings = new Dictionary<string, object>();
}
// Add any missing / new settings
Dictionary<string, object> defaults = this.GetDefaults();
foreach (var item in defaults.Where(item => !this.userSettings.Keys.Contains(item.Key)))
{
this.userSettings.Add(item.Key, item.Value);
this.Save();
}
this.ResetUnsupportedSettings();
}
catch (Exception exc)
{
try
{
this.userSettings = this.GetDefaults();
if (File.Exists(this.settingsFile))
{
File.Delete(this.settingsFile);
}
this.Save();
throw new GeneralApplicationException(Resources.UserSettings_YourSettingsHaveBeenReset, Resources.UserSettings_YourSettingsAreCorrupt, exc);
}
catch (Exception)
{
throw new GeneralApplicationException(string.Format(Resources.UserSettings_UnableToLoad, this.settingsFile), Resources.UserSettings_UnableToLoadSolution, exc);
}
}
}
private void ResetUnsupportedSettings()
{
// Legacy Settings forced Reset.
this.userSettings[UserSettingConstants.ScalingMode] = VideoScaler.Lanczos;
if (SystemInfo.MaximumSimultaneousInstancesSupported < 2)
{
this.userSettings[UserSettingConstants.ProcessIsolationEnabled] = false;
this.userSettings[UserSettingConstants.SimultaneousEncodes] = 1;
}
// Handle change of language code zh to zh-CN
object language;
if (this.userSettings.TryGetValue(UserSettingConstants.UiLanguage, out language))
{
if (language is string and "zh")
{
// Reset to use system language if we have the old zh stored in settings.
this.userSettings[UserSettingConstants.UiLanguage] = InterfaceLanguageUtilities.UseSystemLanguage;
}
}
}
/// <summary>
/// Load Default Settings
/// </summary>
/// <returns>
/// The get defaults.
/// </returns>
private Dictionary<string, object> GetDefaults()
{
Dictionary<string, object> defaults = new Dictionary<string, object>();
defaults.Add(UserSettingConstants.Verbosity, 1);
// General
defaults.Add(UserSettingConstants.UpdateStatus, false);
defaults.Add(UserSettingConstants.LastUpdateCheckDate, DateTime.Now.Date.AddDays(-30));
defaults.Add(UserSettingConstants.DaysBetweenUpdateCheck, 1);
defaults.Add(UserSettingConstants.DarkThemeMode, AppThemeMode.System);
defaults.Add(UserSettingConstants.ShowPreviewOnSummaryTab, true);
defaults.Add(UserSettingConstants.MainWindowMinimize, false);
defaults.Add(UserSettingConstants.ClearCompletedFromQueue, false);
defaults.Add(UserSettingConstants.ShowStatusInTitleBar, false);
defaults.Add(UserSettingConstants.ShowAddAllToQueue, false);
defaults.Add(UserSettingConstants.ShowAddSelectionToQueue, false);
defaults.Add(UserSettingConstants.MediaPlayerPath, @"C:\Program Files\VideoLAN\vlc\vlc.exe");
defaults.Add(UserSettingConstants.PresetMenuDisplayMode, 0);
defaults.Add(UserSettingConstants.RightToLeftUi, 0);
defaults.Add(UserSettingConstants.PresetUiType, 1);
// Output Files
defaults.Add(UserSettingConstants.AutoNaming, true);
defaults.Add(UserSettingConstants.AutoNamePath, string.Empty);
defaults.Add(UserSettingConstants.AutoNameFormat, "{source}");
defaults.Add(UserSettingConstants.AutonameFilePrePostString, "output_");
defaults.Add(UserSettingConstants.AutoNameTitleCase, true);
defaults.Add(UserSettingConstants.AutoNameRemoveUnderscore, true);
defaults.Add(UserSettingConstants.AutonameFileCollisionBehaviour, 0);
defaults.Add(UserSettingConstants.UseIsoDateFormat, false);
defaults.Add(UserSettingConstants.AlwaysUseDefaultPath, true);
defaults.Add(UserSettingConstants.RemovePunctuation, false);
defaults.Add(UserSettingConstants.FileOverwriteBehaviour, 0);
defaults.Add(UserSettingConstants.UseM4v, 0);
// When Done
defaults.Add(UserSettingConstants.SendFile, false);
defaults.Add(UserSettingConstants.WhenCompleteAction, 0);
defaults.Add(UserSettingConstants.WhenDonePerformActionImmediately, false);
defaults.Add(UserSettingConstants.PlaySoundWhenDone, false);
defaults.Add(UserSettingConstants.PlaySoundWhenQueueDone, false);
defaults.Add(UserSettingConstants.WhenDoneAudioFile, string.Empty);
// Video
bool intelDefaultSetting = HandBrakeHardwareEncoderHelper.IsQsvAvailable;
bool nvidiaDefaultSetting = HandBrakeHardwareEncoderHelper.IsNVEncH264Available;
defaults.Add(UserSettingConstants.EnableQuickSyncDecoding, intelDefaultSetting);
defaults.Add(UserSettingConstants.EnableQuickSyncHyperEncode, false);
defaults.Add(UserSettingConstants.UseQSVDecodeForNonQSVEnc, false);
defaults.Add(UserSettingConstants.EnableNvDecSupport, nvidiaDefaultSetting);
defaults.Add(UserSettingConstants.EnableQuickSyncLowPower, true);
defaults.Add(UserSettingConstants.EnableDirectXDecoding, SystemInfo.IsArmDevice);
// Advanced
defaults.Add(UserSettingConstants.PreventSleep, true);
defaults.Add(UserSettingConstants.PauseEncodingOnLowBattery, true);
defaults.Add(UserSettingConstants.LowBatteryLevel, 15);
defaults.Add(UserSettingConstants.DisableLibDvdNav, false);
defaults.Add(UserSettingConstants.PauseOnLowDiskspace, true);
defaults.Add(UserSettingConstants.PauseQueueOnLowDiskspaceLevel, 2000000000L);
defaults.Add(UserSettingConstants.PreviewScanCount, 10);
defaults.Add(UserSettingConstants.MinScanDuration, 10);
defaults.Add(UserSettingConstants.MaxScanDuration, 0);
defaults.Add(UserSettingConstants.KeepDuplicateTitles, false);
defaults.Add(UserSettingConstants.ProcessPriorityInt, 2);
defaults.Add(UserSettingConstants.X264Step, 0.5);
defaults.Add(UserSettingConstants.SaveLogToCopyDirectory, false);
defaults.Add(UserSettingConstants.SaveLogWithVideo, false);
defaults.Add(UserSettingConstants.ClearOldLogs, true);
defaults.Add(UserSettingConstants.ExcludedExtensions, new List<string> { "png", "jpg", "srt", "ass", "ssa", "txt" });
defaults.Add(UserSettingConstants.RecursiveFolderScan, false);
defaults.Add(UserSettingConstants.DefaultRangeMode, DefaultRangeMode.Chapters);
// Preview
defaults.Add(UserSettingConstants.LastPreviewDuration, 30);
defaults.Add(UserSettingConstants.UseExternalPlayer, false);
// Experimental
defaults.Add(UserSettingConstants.ProcessIsolationEnabled, true);
defaults.Add(UserSettingConstants.ProcessIsolationPort, 8037);
defaults.Add(UserSettingConstants.SimultaneousEncodes, 1);
// Misc
defaults.Add(UserSettingConstants.ScalingMode, 0);
defaults.Add(UserSettingConstants.ForcePresetReset, 3);
defaults.Add(UserSettingConstants.PreviewShowPictureSettingsOverlay, false);
defaults.Add(UserSettingConstants.RunCounter, 0);
defaults.Add(UserSettingConstants.ForceSoftwareRendering, false);
defaults.Add(UserSettingConstants.IsUpdateAvailableBuild, 0);
defaults.Add(UserSettingConstants.ExtendedQueueDisplay, true);
defaults.Add(UserSettingConstants.HardwareDetectTimeoutSeconds, 12);
defaults.Add(UserSettingConstants.SimpleQueueView, false);
defaults.Add(UserSettingConstants.ShowPresetDesc, true);
defaults.Add(UserSettingConstants.IsLegacyMenuShown, true);
return defaults;
}
private T GetDefaultValue<T>(string name)
{
try
{
// If the current setting is corrupt, return the default and log it.
Dictionary<string, object> defaults = this.GetDefaults();
if (defaults.ContainsKey(name))
{
return (T)this.userSettings[name];
}
}
catch (Exception e)
{
this.logService.LogMessage("Unable to fetch default setting: " + name + " - " + e);
return default(T);
}
return default(T);
}
}
}