// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // The User Setting Service // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrakeWPF.Services { using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using HandBrake.Interop.Interop; using HandBrake.Interop.Interop.Interfaces.Model.Picture; using HandBrake.Interop.Utilities; using HandBrakeWPF.Extensions; using HandBrakeWPF.Model; using HandBrakeWPF.Model.Video; using HandBrakeWPF.Properties; using HandBrakeWPF.Services.Interfaces; using HandBrakeWPF.Utilities; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using GeneralApplicationException = Exceptions.GeneralApplicationException; using SettingChangedEventArgs = EventArgs.SettingChangedEventArgs; using SystemInfo = HandBrakeWPF.Utilities.SystemInfo; /// /// The User Setting Service /// public class UserSettingService : IUserSettingService { 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 readonly JsonSerializerSettings settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; private Dictionary userSettings; /// /// Initializes a new instance of the class. /// public UserSettingService() { this.Load(); } /// /// The setting changed. /// public event SettingEventHandler SettingChanged; /// /// Set the specified user setting. /// /// /// Name of the property /// /// /// The value to store. /// public void SetUserSetting(string name, object value) { this.userSettings[name] = value; this.Save(); this.OnSettingChanged(new SettingChangedEventArgs { Key = name, Value = value }); } /// /// Get user setting for a given key. /// /// /// The name. /// /// /// The Type of the setting /// /// /// The user setting /// public T GetUserSetting(string name) { if (this.userSettings.ContainsKey(name)) { if (typeof(T) == typeof(int)) { object storedValue = this.userSettings[name]; object converted = storedValue?.ToString().ToInt(); return (T)converted; } // Treat String Arrays as StringCollections. TODO refactor upstream code to more traditional string arrays. object settingValue = this.userSettings[name]; if (settingValue != null && settingValue.GetType() == typeof(JArray)) { string[] stringArr = ((JArray)settingValue).ToObject(); StringCollection stringCollection = new StringCollection(); foreach (var item in stringArr) { stringCollection.Add(item); } settingValue = stringCollection; } return (T)settingValue; } return default(T); } public void ResetSettingsToDefaults() { this.userSettings.Clear(); // Set Defaults Dictionary 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(); } } /// /// The on setting changed. /// /// /// The e. /// protected virtual void OnSettingChanged(SettingChangedEventArgs e) { SettingEventHandler handler = this.SettingChanged; if (handler != null) { handler(this, e); } } /// /// Save the User Settings /// 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 = JsonConvert.SerializeObject(this.userSettings, Formatting.Indented, this.settings); file.Write(appSettings); } } catch (Exception exc) { throw new GeneralApplicationException( Resources.UserSettings_AnErrorOccured, Resources.SettingService_SaveErrorReset, exc); } } /// /// Load the User Settings /// 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 deserialisedSettings = JsonConvert.DeserializeObject>(appSettings); this.userSettings = deserialisedSettings; } } 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 deserialisedSettings = JsonConvert.DeserializeObject>(appSettings); this.userSettings = deserialisedSettings; } } else { this.userSettings = new Dictionary(); } // Add any missing / new settings Dictionary 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.IsWindows10() || SystemInfo.GetCpuCoreCount < 4) { this.userSettings[UserSettingConstants.ProcessIsolationEnabled] = false; this.userSettings[UserSettingConstants.SimultaneousEncodes] = 1; } } /// /// Load Default Settings /// /// /// The get defaults. /// private Dictionary GetDefaults() { Dictionary defaults = new Dictionary(); defaults.Add(UserSettingConstants.Verbosity, 1); // General defaults.Add(UserSettingConstants.UpdateStatus, true); defaults.Add(UserSettingConstants.LastUpdateCheckDate, DateTime.Now.Date.AddDays(-30)); defaults.Add(UserSettingConstants.DaysBetweenUpdateCheck, 1); defaults.Add(UserSettingConstants.DarkThemeMode, DarkThemeMode.Light); 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"); // Output Files defaults.Add(UserSettingConstants.AutoNaming, true); defaults.Add(UserSettingConstants.AutoNamePath, string.Empty); defaults.Add(UserSettingConstants.AutoNameFormat, "{source}-{title}"); defaults.Add(UserSettingConstants.AutonameFilePrePostString, "output_"); defaults.Add(UserSettingConstants.AutoNameTitleCase, true); defaults.Add(UserSettingConstants.AutoNameRemoveUnderscore, true); defaults.Add(UserSettingConstants.AutonameFileCollisionBehaviour, 0); 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 defaults.Add(UserSettingConstants.EnableQuickSyncEncoding, true); defaults.Add(UserSettingConstants.EnableQuickSyncDecoding, true); defaults.Add(UserSettingConstants.UseQSVDecodeForNonQSVEnc, false); defaults.Add(UserSettingConstants.EnableVceEncoder, true); defaults.Add(UserSettingConstants.EnableNvencEncoder, true); defaults.Add(UserSettingConstants.EnableQuickSyncLowPower, true); // 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.ProcessPriorityInt, 3); defaults.Add(UserSettingConstants.X264Step, 0.5); defaults.Add(UserSettingConstants.SaveLogToCopyDirectory, false); defaults.Add(UserSettingConstants.SaveLogWithVideo, false); defaults.Add(UserSettingConstants.ClearOldLogs, true); // Preview defaults.Add(UserSettingConstants.PreviewRotationFlip, false); defaults.Add(UserSettingConstants.LastPreviewDuration, 30); defaults.Add(UserSettingConstants.DefaultPlayer, false); // Experimental defaults.Add(UserSettingConstants.ProcessIsolationEnabled, SystemInfo.IsWindows10()); defaults.Add(UserSettingConstants.ProcessIsolationPort, 8037); defaults.Add(UserSettingConstants.SimultaneousEncodes, 1); // Misc defaults.Add(UserSettingConstants.ScalingMode, 0); defaults.Add(UserSettingConstants.ForcePresetReset, 3); defaults.Add(UserSettingConstants.MetadataPassthru, true); defaults.Add(UserSettingConstants.PreviewShowPictureSettingsOverlay, false); return defaults; } } }