. | using Newtonsoft.Json; |
| using Playnite.SDK.Data; |
| using System; |
| using System; |
| using System.Collections.Generic; |
| using System.Collections.Generic; |
| using System.Collections.ObjectModel; |
| using System.Collections.ObjectModel; |
| using System.ComponentModel; |
| using System.ComponentModel; |
| using System.Linq; |
| using System.Linq; |
| using System.Text; |
| using System.Text; |
| using System.Threading.Tasks; |
| using System.Threading.Tasks; |
| |
| |
| namespace Playnite.SDK.Models |
| namespace Playnite.SDK.Models |
| { |
| { |
| /// <summary> |
| /// <summary> |
. | |
| /// Represents built-in region defition. |
| |
| /// </summary> |
| |
| public class EmulatedRegion : IEquatable<EmulatedRegion> |
| |
| { |
| |
| /// <summary> |
| |
| /// Gets region id. |
| |
| /// </summary> |
| |
| public string Id { get; set; } |
| |
| /// <summary> |
| |
| /// Gets region name. |
| |
| /// </summary> |
| |
| public string Name { get; set; } |
| |
| /// <summary> |
| |
| /// Gets value indicating whether the region should be imported into new libraries. |
| |
| /// </summary> |
| |
| public bool DefaultImport { get; set; } |
| |
| /// <summary> |
| |
| /// Gets ID of the region on IGDB database. |
| |
| /// </summary> |
| |
| public ulong IgdbId { get; set; } |
| |
| /// <summary> |
| |
| /// Gets region codes. |
| |
| /// </summary> |
| |
| public List<string> Codes { get; set; } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override int GetHashCode() |
| |
| { |
| |
| return Id?.GetHashCode() ?? 0; |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public bool Equals(EmulatedRegion other) |
| |
| { |
| |
| return other.Id == Id; |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override bool Equals(object obj) |
| |
| { |
| |
| if (obj is EmulatedRegion region) |
| |
| { |
| |
| return Equals(region); |
| |
| } |
| |
| else |
| |
| { |
| |
| return false; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override string ToString() |
| |
| { |
| |
| return Name; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Represents built-in platform definition. |
| |
| /// </summary> |
| |
| public class EmulatedPlatform : IEquatable<EmulatedPlatform> |
| |
| { |
| |
| /// <summary> |
| |
| /// Gets ID of the platform on IGDB database. |
| |
| /// </summary> |
| |
| public ulong IgdbId { get; set; } |
| |
| /// <summary> |
| |
| /// Gets platform name. |
| |
| /// </summary> |
| |
| public string Name { get; set; } |
| |
| /// <summary> |
| |
| /// Gets platform id. |
| |
| /// </summary> |
| |
| public string Id { get; set; } |
| |
| /// <summary> |
| |
| /// Gets list of platform ROM database ids. |
| |
| /// </summary> |
| |
| public List<string> Databases { get; set; } |
| |
| /// <summary> |
| |
| /// Gets liust of emulator IDs supporting this platform. |
| |
| /// </summary> |
| |
| public List<string> Emulators { get; set; } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override int GetHashCode() |
| |
| { |
| |
| return Id?.GetHashCode() ?? 0; |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public bool Equals(EmulatedPlatform other) |
| |
| { |
| |
| return other.Id == Id; |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override bool Equals(object obj) |
| |
| { |
| |
| if (obj is EmulatedPlatform platform) |
| |
| { |
| |
| return Equals(platform); |
| |
| } |
| |
| else |
| |
| { |
| |
| return false; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override string ToString() |
| |
| { |
| |
| return Name; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// |
| |
| /// </summary> |
| |
| public abstract class EmulatorProfile : ObservableObject |
| |
| { |
| |
| private string id; |
| |
| /// <summary> |
| |
| /// Gets emulator profile ID. |
| |
| /// </summary> |
| |
| public string Id |
| |
| { |
| |
| get => id; |
| |
| set |
| |
| { |
| |
| id = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private string name; |
| |
| /// <summary> |
| |
| /// Gets profile name. |
| |
| /// </summary> |
| |
| public string Name |
| |
| { |
| |
| get => name; |
| |
| set |
| |
| { |
| |
| name = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private string preScript; |
| |
| /// <summary> |
| |
| /// Gets pre-execution script. |
| |
| /// </summary> |
| |
| public string PreScript |
| |
| { |
| |
| get => preScript; |
| |
| set |
| |
| { |
| |
| preScript = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private string postScript; |
| |
| /// <summary> |
| |
| /// Gets post-execution script. |
| |
| /// </summary> |
| |
| public string PostScript |
| |
| { |
| |
| get => postScript; |
| |
| set |
| |
| { |
| |
| postScript = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private string exitScript; |
| |
| /// <summary> |
| |
| /// Gets exit-execution script. |
| |
| /// </summary> |
| |
| public string ExitScript |
| |
| { |
| |
| get => exitScript; |
| |
| set |
| |
| { |
| |
| exitScript = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Gets emulator profile object type. |
| |
| /// </summary> |
| |
| [DontSerialize] |
| |
| public Type Type => GetType(); |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public override string ToString() |
| |
| { |
| |
| return Name; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Represents built-in emulator profile. |
| |
| /// </summary> |
| |
| public class BuiltInEmulatorProfile : EmulatorProfile, IEquatable<BuiltInEmulatorProfile> |
| |
| { |
| |
| internal static readonly string ProfilePrefix = "#builtin_"; |
| |
| |
| |
| private string builtInProfileName; |
| |
| /// <summary> |
| |
| /// Gets name of built-in profile represented by this definition. |
| |
| /// </summary> |
| |
| public string BuiltInProfileName |
| |
| { |
| |
| get => builtInProfileName; |
| |
| set |
| |
| { |
| |
| builtInProfileName = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Creates new instance of <see cref="BuiltInEmulatorProfile"/>. |
| |
| /// </summary> |
| |
| public BuiltInEmulatorProfile() : base() |
| |
| { |
| |
| Id = ProfilePrefix + Guid.NewGuid(); |
| |
| } |
| |
| |
| |
| /// <inheritdoc/> |
| |
| public bool Equals(BuiltInEmulatorProfile other) |
| |
| { |
| |
| if (other is null) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(BuiltInProfileName, other.BuiltInProfileName, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(Name, other.Name, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(ExitScript, other.ExitScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(PostScript, other.PostScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(PreScript, other.PreScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| return true; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| /// Represents emulator profile. |
| /// Represents emulator profile. |
| /// </summary> |
| /// </summary> |
. | public class EmulatorProfile : DatabaseObject, IEquatable<EmulatorProfile> |
| public class CustomEmulatorProfile : EmulatorProfile, IEquatable<CustomEmulatorProfile> |
| { |
| { |
. | |
| internal static readonly string ProfilePrefix = "#custom_"; |
| |
| |
| |
| private string startupScript; |
| |
| /// <summary> |
| |
| /// Gets startup script. |
| |
| /// </summary> |
| |
| public string StartupScript |
| |
| { |
| |
| get => startupScript; |
| |
| set |
| |
| { |
| |
| startupScript = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| private List<Guid> platforms; |
| private List<Guid> platforms; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets platforms supported by profile. |
| /// Gets or sets platforms supported by profile. |
| /// </summary> |
| /// </summary> |
| public List<Guid> Platforms |
| public List<Guid> Platforms |
| { |
| { |
| get => platforms; |
| get => platforms; |
| set |
| set |
| { |
| { |
| platforms = value; |
| platforms = value; |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| private List<string> imageExtensions; |
| private List<string> imageExtensions; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets file extension supported by profile. |
| /// Gets or sets file extension supported by profile. |
| /// </summary> |
| /// </summary> |
| public List<string> ImageExtensions |
| public List<string> ImageExtensions |
| { |
| { |
| get => imageExtensions; |
| get => imageExtensions; |
| set |
| set |
| { |
| { |
| imageExtensions = value; |
| imageExtensions = value; |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| private string executable; |
| private string executable; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets executable path used to launch emulator. |
| /// Gets or sets executable path used to launch emulator. |
| /// </summary> |
| /// </summary> |
| public string Executable |
| public string Executable |
| { |
| { |
| get => executable; |
| get => executable; |
| set |
| set |
| { |
| { |
| executable = value; |
| executable = value; |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| private string arguments; |
| private string arguments; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets arguments for emulator executable. |
| /// Gets or sets arguments for emulator executable. |
| /// </summary> |
| /// </summary> |
| public string Arguments |
| public string Arguments |
| { |
| { |
| get => arguments; |
| get => arguments; |
| set |
| set |
| { |
| { |
| arguments = value; |
| arguments = value; |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| private string workingDirectory; |
| private string workingDirectory; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets working directory of emulator process. |
| /// Gets or sets working directory of emulator process. |
| /// </summary> |
| /// </summary> |
| public string WorkingDirectory |
| public string WorkingDirectory |
| { |
| { |
| get => workingDirectory; |
| get => workingDirectory; |
| set |
| set |
| { |
| { |
| workingDirectory = value; |
| workingDirectory = value; |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
| } |
| } |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// |
| /// |
| /// </summary> |
| /// </summary> |
| /// <returns></returns> |
| /// <returns></returns> |
| public override string ToString() |
| public override string ToString() |
| { |
| { |
| return Name; |
| return Name; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Creates new instance of EmulatorProfile. |
| /// Creates new instance of EmulatorProfile. |
| /// </summary> |
| /// </summary> |
. | public EmulatorProfile() : base() |
| public CustomEmulatorProfile() : base() |
| { |
| { |
. | |
| Id = ProfilePrefix + Guid.NewGuid(); |
| } |
| } |
| |
| |
| /// <inheritdoc/> |
| /// <inheritdoc/> |
. | public bool Equals(EmulatorProfile other) |
| public bool Equals(CustomEmulatorProfile other) |
| { |
| { |
| if (other is null) |
| if (other is null) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | |
| if (!string.Equals(Id, other.Id, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(Name, other.Name, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| if (!Platforms.IsListEqual(other.Platforms)) |
| if (!Platforms.IsListEqual(other.Platforms)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (!ImageExtensions.IsListEqual(other.ImageExtensions)) |
| if (!ImageExtensions.IsListEqual(other.ImageExtensions)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (!string.Equals(Executable, other.Executable, StringComparison.Ordinal)) |
| if (!string.Equals(Executable, other.Executable, StringComparison.Ordinal)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (!string.Equals(Arguments, other.Arguments, StringComparison.Ordinal)) |
| if (!string.Equals(Arguments, other.Arguments, StringComparison.Ordinal)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (!string.Equals(WorkingDirectory, other.WorkingDirectory, StringComparison.Ordinal)) |
| if (!string.Equals(WorkingDirectory, other.WorkingDirectory, StringComparison.Ordinal)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
| if (!string.Equals(Name, other.Name, StringComparison.Ordinal)) |
| if (!string.Equals(Name, other.Name, StringComparison.Ordinal)) |
| { |
| { |
| return false; |
| return false; |
| } |
| } |
| |
| |
. | |
| if (!string.Equals(ExitScript, other.ExitScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(PostScript, other.PostScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(PreScript, other.PreScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| |
| if (!string.Equals(StartupScript, other.StartupScript, StringComparison.Ordinal)) |
| |
| { |
| |
| return false; |
| |
| } |
| |
| |
| return true; |
| return true; |
| } |
| } |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Represents system emulator. |
| /// Represents system emulator. |
| /// </summary> |
| /// </summary> |
| public class Emulator : DatabaseObject |
| public class Emulator : DatabaseObject |
| { |
| { |
. | private ObservableCollection<EmulatorProfile> profile; |
| private string builtInConfigId; |
| |
| /// <summary> |
| |
| /// Gets id of built-in emulator profile. |
| |
| /// </summary> |
| |
| public string BuiltInConfigId |
| |
| { |
| |
| get => builtInConfigId; |
| |
| set |
| |
| { |
| |
| builtInConfigId = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private string installDir; |
| |
| /// <summary> |
| |
| /// Gets emulator installation directory. |
| |
| /// </summary> |
| |
| public string InstallDir |
| |
| { |
| |
| get => installDir; |
| |
| set |
| |
| { |
| |
| installDir = value; |
| |
| OnPropertyChanged(); |
| |
| } |
| |
| } |
| |
| |
| |
| private ObservableCollection<BuiltInEmulatorProfile> builtinProfiles; |
| /// <summary> |
| /// <summary> |
| /// Gets or sets list of emulator profiles. |
| /// Gets or sets list of emulator profiles. |
| /// </summary> |
| /// </summary> |
. | public ObservableCollection<EmulatorProfile> Profiles |
| public ObservableCollection<BuiltInEmulatorProfile> BuiltinProfiles |
| { |
| { |
. | get => profile; |
| get => builtinProfiles; |
| set |
| set |
| { |
| { |
. | profile = value; |
| if (builtinProfiles != null) |
| |
| { |
| |
| builtinProfiles.CollectionChanged -= Profiles_CollectionChanged; |
| |
| } |
| |
| |
| |
| builtinProfiles = value; |
| |
| if (builtinProfiles != null) |
| |
| { |
| |
| builtinProfiles.CollectionChanged += Profiles_CollectionChanged; |
| |
| } |
| |
| |
| OnPropertyChanged(); |
| OnPropertyChanged(); |
. | |
| OnPropertyChanged(nameof(AllProfiles)); |
| |
| OnPropertyChanged(nameof(SelectableProfiles)); |
| |
| } |
| |
| } |
| |
| |
| |
| private ObservableCollection<CustomEmulatorProfile> customProfiles; |
| |
| /// <summary> |
| |
| /// Gets or sets list of emulator profiles. |
| |
| /// </summary> |
| |
| public ObservableCollection<CustomEmulatorProfile> CustomProfiles |
| |
| { |
| |
| get => customProfiles; |
| |
| set |
| |
| { |
| |
| if (customProfiles != null) |
| |
| { |
| |
| customProfiles.CollectionChanged -= Profiles_CollectionChanged; |
| |
| } |
| |
| |
| |
| customProfiles = value; |
| |
| if (customProfiles != null) |
| |
| { |
| |
| customProfiles.CollectionChanged += Profiles_CollectionChanged; |
| |
| } |
| |
| |
| |
| OnPropertyChanged(); |
| |
| OnPropertyChanged(nameof(AllProfiles)); |
| |
| OnPropertyChanged(nameof(SelectableProfiles)); |
| |
| } |
| |
| } |
| |
| |
| |
| private void Profiles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) |
| |
| { |
| |
| OnPropertyChanged(nameof(AllProfiles)); |
| |
| OnPropertyChanged(nameof(SelectableProfiles)); |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Gets list of all profiles including option for profile auto-select. |
| |
| /// </summary> |
| |
| [DontSerialize] |
| |
| public List<EmulatorProfile> SelectableProfiles |
| |
| { |
| |
| get |
| |
| { |
| |
| var selProfiles = new List<EmulatorProfile>(); |
| |
| if (BuiltinProfiles.HasItems()) |
| |
| { |
| |
| selProfiles.AddRange(BuiltinProfiles.OrderBy(a => a.Name)); |
| |
| } |
| |
| |
| |
| if (CustomProfiles.HasItems()) |
| |
| { |
| |
| selProfiles.AddRange(CustomProfiles.OrderBy(a => a.Name)); |
| |
| } |
| |
| |
| |
| selProfiles.Insert(0, new CustomEmulatorProfile { Id = null, Name = ResourceProvider.GetString("LOCGameActionSelectOnStart") }); |
| |
| return selProfiles; |
| |
| } |
| |
| } |
| |
| |
| |
| /// <summary> |
| |
| /// Gets list of all profiles. |
| |
| /// </summary> |
| |
| [DontSerialize] |
| |
| public List<EmulatorProfile> AllProfiles |
| |
| { |
| |
| get |
| |
| { |
| |
| var selProfiles = new List<EmulatorProfile>(); |
| |
| if (BuiltinProfiles.HasItems()) |
| |
| { |
| |
| selProfiles.AddRange(BuiltinProfiles.OrderBy(a => a.Name)); |
| |
| } |
| |
| |
| |
| if (CustomProfiles.HasItems()) |
| |
| { |
| |
| selProfiles.AddRange(CustomProfiles.OrderBy(a => a.Name)); |
| |
| } |
| |
| |
| |
| return selProfiles; |
| } |
| } |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Creates new instance of Emulator. |
| /// Creates new instance of Emulator. |
| /// </summary> |
| /// </summary> |
| public Emulator() : base() |
| public Emulator() : base() |
| { |
| { |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// Creates new instance of Emulator with specific name. |
| /// Creates new instance of Emulator with specific name. |
| /// </summary> |
| /// </summary> |
| /// <param name="name">Emulator name.</param> |
| /// <param name="name">Emulator name.</param> |
| public Emulator(string name) : this() |
| public Emulator(string name) : this() |
| { |
| { |
| Name = name; |
| Name = name; |
| } |
| } |
| |
| |
| /// <summary> |
| /// <summary> |
| /// |
| /// |
| /// </summary> |
| /// </summary> |
| /// <returns></returns> |
| /// <returns></returns> |
| public override string ToString() |
| public override string ToString() |
| { |
| { |
| return Name; |
| return Name; |
| } |
| } |
| |
| |
. | |
| /// <summary> |
| |
| /// Gets profile by id. |
| |
| /// </summary> |
| |
| /// <param name="profileId"></param> |
| |
| /// <returns></returns> |
| |
| public EmulatorProfile GetProfile(string profileId) |
| |
| { |
| |
| var cus = CustomProfiles?.FirstOrDefault(a => a.Id == profileId); |
| |
| if (cus != null) |
| |
| { |
| |
| return cus; |
| |
| } |
| |
| |
| |
| return BuiltinProfiles?.FirstOrDefault(a => a.Id == profileId); |
| |
| } |
| |
| |
| /// <inheritdoc/> |
| /// <inheritdoc/> |
| public override void CopyDiffTo(object target) |
| public override void CopyDiffTo(object target) |
| { |
| { |
| base.CopyDiffTo(target); |
| base.CopyDiffTo(target); |
| |
| |
| if (target is Emulator tro) |
| if (target is Emulator tro) |
| { |
| { |
. | if (!Profiles.IsListEqualExact(tro.Profiles)) |
| if (!CustomProfiles.IsListEqualExact(tro.CustomProfiles)) |
| |
| { |
| |
| tro.CustomProfiles = CustomProfiles; |
| |
| } |
| |
| |
| |
| if (!BuiltinProfiles.IsListEqualExact(tro.BuiltinProfiles)) |
| |
| { |
| |
| tro.BuiltinProfiles = BuiltinProfiles; |
| |
| } |
| |
| |
| |
| if (!string.Equals(BuiltInConfigId, tro.BuiltInConfigId, StringComparison.Ordinal)) |
| |
| { |
| |
| tro.BuiltInConfigId = BuiltInConfigId; |
| |
| } |
| |
| |
| |
| if (!string.Equals(InstallDir, tro.InstallDir, StringComparison.Ordinal)) |
| { |
| { |
. | tro.Profiles = Profiles; |
| tro.InstallDir = InstallDir; |
| } |
| } |
| } |
| } |
| else |
| else |
| { |
| { |
| throw new ArgumentException($"Target object has to be of type {GetType().Name}"); |
| throw new ArgumentException($"Target object has to be of type {GetType().Name}"); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |