// --------------------------------------------------------------------------------------------------------------------
//
// 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;
}
}
}