diff --git a/.idea/.idea.Aaru/.idea/contentModel.xml b/.idea/.idea.Aaru/.idea/contentModel.xml
index 9a7a69f85..0fe6ecc5a 100644
--- a/.idea/.idea.Aaru/.idea/contentModel.xml
+++ b/.idea/.idea.Aaru/.idea/contentModel.xml
@@ -1,27 +1,28 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
@@ -70,6 +71,13 @@
+
+
+
+
+
+
+
@@ -80,18 +88,12 @@
-
-
-
-
-
-
@@ -100,13 +102,6 @@
-
-
-
-
-
-
-
@@ -114,12 +109,19 @@
+
+
+
+
+
+
+
+
-
@@ -178,13 +180,6 @@
-
-
-
-
-
-
-
@@ -205,10 +200,19 @@
+
+
+
+
+
+
+
+
+
@@ -217,7 +221,6 @@
-
@@ -235,7 +238,6 @@
-
@@ -256,8 +258,8 @@
-
+
@@ -267,11 +269,11 @@
-
+
-
+
@@ -285,17 +287,17 @@
-
-
+
+
-
+
@@ -315,19 +317,12 @@
-
+
-
-
-
-
-
-
-
@@ -344,61 +339,68 @@
+
+
+
+
+
+
+
+
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
@@ -423,6 +425,7 @@
+
@@ -434,12 +437,11 @@
-
-
+
@@ -461,9 +463,9 @@
-
+
@@ -493,13 +495,6 @@
-
-
-
-
-
-
-
@@ -563,11 +558,11 @@
-
+
@@ -587,10 +582,17 @@
+
+
+
+
+
+
+
+
-
@@ -647,13 +649,6 @@
-
-
-
-
-
-
-
@@ -666,17 +661,28 @@
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
@@ -684,16 +690,13 @@
-
-
-
+
+
-
-
@@ -729,13 +732,11 @@
-
-
-
+
@@ -743,14 +744,11 @@
+
-
-
-
-
@@ -790,8 +788,8 @@
-
+
@@ -800,8 +798,8 @@
-
+
@@ -810,8 +808,8 @@
-
+
@@ -838,15 +836,8 @@
-
-
-
-
-
-
-
-
+
@@ -864,11 +855,11 @@
+
-
@@ -891,17 +882,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
@@ -909,18 +917,12 @@
-
-
-
-
-
-
@@ -1014,12 +1016,6 @@
-
-
-
-
-
-
@@ -1044,6 +1040,12 @@
+
+
+
+
+
+
@@ -1126,8 +1128,6 @@
-
-
@@ -1143,18 +1143,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1167,6 +1155,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1175,14 +1175,14 @@
+
+
-
-
@@ -1205,10 +1205,12 @@
+
+
+
-
@@ -1216,16 +1218,12 @@
-
-
-
-
-
+
@@ -1248,16 +1246,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -1314,6 +1302,7 @@
+
@@ -1352,6 +1341,8 @@
+
+
@@ -1365,6 +1356,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -1373,7 +1375,6 @@
-
@@ -1381,6 +1382,10 @@
+
+
+
+
@@ -1388,9 +1393,6 @@
-
-
-
@@ -1473,7 +1475,16 @@
-
+
+
+
+
+
+
+
+
+
+
@@ -1495,16 +1506,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -1538,6 +1539,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -1575,16 +1586,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -1675,8 +1676,8 @@
-
+
@@ -1710,17 +1711,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -1731,12 +1721,16 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -1920,16 +1914,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -1940,6 +1924,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -1958,6 +1952,14 @@
+
+
+
+
+
+
+
+
@@ -1965,7 +1967,6 @@
-
@@ -1973,13 +1974,6 @@
-
-
-
-
-
-
-
@@ -1989,11 +1983,20 @@
-
+
+
+
+
+
+
+
+
+
+
@@ -2002,13 +2005,19 @@
-
-
-
+
-
+
+
+
+
+
+
+
+
+
@@ -2042,8 +2051,8 @@
-
+
@@ -2051,7 +2060,7 @@
-
+
@@ -2074,14 +2083,7 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Aaru.Gui/Forms/frmDump.xeto b/Aaru.Gui/Forms/frmDump.xeto
deleted file mode 100644
index fdce69a77..000000000
--- a/Aaru.Gui/Forms/frmDump.xeto
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
\ No newline at end of file
diff --git a/Aaru.Gui/Forms/frmDump.xeto.cs b/Aaru.Gui/Forms/frmDump.xeto.cs
deleted file mode 100644
index 128c6d88c..000000000
--- a/Aaru.Gui/Forms/frmDump.xeto.cs
+++ /dev/null
@@ -1,684 +0,0 @@
-// /***************************************************************************
-// Aaru Data Preservation Suite
-// ----------------------------------------------------------------------------
-//
-// Filename : frmDump.xeto.cs
-// Author(s) : Natalia Portillo
-//
-// Component : Media dump window.
-//
-// --[ Description ] ----------------------------------------------------------
-//
-// Implements the media dump GUI window.
-//
-// --[ License ] --------------------------------------------------------------
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General public License for more details.
-//
-// You should have received a copy of the GNU General public License
-// along with this program. If not, see .
-//
-// ----------------------------------------------------------------------------
-// Copyright © 2011-2020 Natalia Portillo
-// ****************************************************************************/
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Xml.Serialization;
-using Aaru.CommonTypes;
-using Aaru.CommonTypes.Enums;
-using Aaru.CommonTypes.Interfaces;
-using Aaru.CommonTypes.Metadata;
-using Aaru.Core;
-using Aaru.Core.Devices.Dumping;
-using Aaru.Core.Logging;
-using Aaru.Core.Media.Info;
-using Aaru.Devices;
-using Eto.Forms;
-using Eto.Serialization.Xaml;
-using Schemas;
-using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo;
-using MediaType = Aaru.CommonTypes.MediaType;
-
-// ReSharper disable UnusedMember.Local
-
-namespace Aaru.Gui.Forms
-{
- public class frmDump : Form
- {
- readonly string _devicePath;
- Device _dev;
- Dump _dumper;
- string _outputPrefix;
- Resume _resume;
- CICMMetadataType _sidecar;
-
- public frmDump(string devicePath, DeviceInfo deviceInfo, ScsiInfo scsiInfo = null)
- {
- MediaType mediaType;
- XamlReader.Load(this);
-
- // Defaults
- chkStopOnError.Checked = false;
- chkForce.Checked = false;
- chkPersistent.Checked = true;
- chkResume.Checked = true;
- chkTrack1Pregap.Checked = false;
- chkSidecar.Checked = true;
- chkTrim.Checked = true;
- chkExistingMetadata.Checked = false;
- stpRetries.Value = 5;
- stpSkipped.Value = 512;
-
- if(scsiInfo != null)
- mediaType = scsiInfo.MediaType;
- else
- switch(deviceInfo.Type)
- {
- case DeviceType.SecureDigital:
- mediaType = MediaType.SecureDigital;
-
- break;
- case DeviceType.MMC:
- mediaType = MediaType.MMC;
-
- break;
- default:
- if(deviceInfo.IsPcmcia)
- mediaType = MediaType.PCCardTypeII;
- else if(deviceInfo.IsCompactFlash)
- mediaType = MediaType.CompactFlash;
- else
- mediaType = MediaType.GENERIC_HDD;
-
- break;
- }
-
- ObservableCollection lstPlugins = new ObservableCollection();
- PluginBase plugins = GetPluginBase.Instance;
-
- foreach(IWritableImage plugin in
- plugins.WritableImages.Values.Where(p => p.SupportedMediaTypes.Contains(mediaType)))
- lstPlugins.Add(plugin);
-
- cmbFormat.ItemTextBinding = Binding.Property((IWritableImage p) => p.Name);
- cmbFormat.ItemKeyBinding = Binding.Property((IWritableImage p) => p.Id.ToString());
- cmbFormat.DataStore = lstPlugins;
-
- List encodings = Encoding.GetEncodings().Select(info => new CommonEncodingInfo
- {
- Name = info.Name, DisplayName = info.GetEncoding().EncodingName
- }).ToList();
-
- encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings().Select(info => new CommonEncodingInfo
- {
- Name = info.Name, DisplayName = info.DisplayName
- }));
-
- ObservableCollection lstEncodings = new ObservableCollection();
-
- foreach(CommonEncodingInfo info in encodings.OrderBy(t => t.DisplayName))
- lstEncodings.Add(info);
-
- cmbEncoding.ItemTextBinding = Binding.Property((CommonEncodingInfo p) => p.DisplayName);
- cmbEncoding.ItemKeyBinding = Binding.Property((CommonEncodingInfo p) => p.Name);
- cmbEncoding.DataStore = lstEncodings;
-
- switch(mediaType)
- {
- case MediaType.CD:
- case MediaType.CDDA:
- case MediaType.CDG:
- case MediaType.CDEG:
- case MediaType.CDI:
- case MediaType.CDROM:
- case MediaType.CDROMXA:
- case MediaType.CDPLUS:
- case MediaType.CDMO:
- case MediaType.CDR:
- case MediaType.CDRW:
- case MediaType.CDMRW:
- case MediaType.VCD:
- case MediaType.SVCD:
- case MediaType.PCD:
- case MediaType.DDCD:
- case MediaType.DDCDR:
- case MediaType.DDCDRW:
- case MediaType.DTSCD:
- case MediaType.CDMIDI:
- case MediaType.CDV:
- case MediaType.CDIREADY:
- case MediaType.FMTOWNS:
- case MediaType.PS1CD:
- case MediaType.PS2CD:
- case MediaType.MEGACD:
- case MediaType.SATURNCD:
- case MediaType.GDROM:
- case MediaType.GDR:
- case MediaType.MilCD:
- case MediaType.SuperCDROM2:
- case MediaType.JaguarCD:
- case MediaType.ThreeDO:
- case MediaType.PCFX:
- case MediaType.NeoGeoCD:
- case MediaType.CDTV:
- case MediaType.CD32:
- case MediaType.Playdia:
- case MediaType.Pippin:
- case MediaType.VideoNow:
- case MediaType.VideoNowColor:
- case MediaType.VideoNowXp:
- chkTrack1Pregap.Visible = true;
-
- break;
- default:
- chkTrack1Pregap.Visible = false;
-
- break;
- }
-
- _devicePath = devicePath;
- }
-
- void OnCmbFormatSelectedIndexChanged(object sender, EventArgs e)
- {
- txtDestination.Text = "";
-
- if(!(cmbFormat.SelectedValue is IWritableImage plugin))
- {
- grpOptions.Visible = false;
- btnDestination.Enabled = false;
-
- return;
- }
-
- btnDestination.Enabled = true;
-
- if(!plugin.SupportedOptions.Any())
- {
- grpOptions.Content = null;
- grpOptions.Visible = false;
-
- return;
- }
-
- grpOptions.Visible = true;
-
- var stkOptions = new StackLayout
- {
- Orientation = Orientation.Vertical
- };
-
- foreach((string name, Type type, string description, object @default) option in plugin.SupportedOptions)
- switch(option.type.ToString())
- {
- case "System.Boolean":
- var optBoolean = new CheckBox();
- optBoolean.ID = "opt" + option.name;
- optBoolean.Text = option.description;
- optBoolean.Checked = (bool)option.@default;
- stkOptions.Items.Add(optBoolean);
-
- break;
- case "System.SByte":
- case "System.Int16":
- case "System.Int32":
- case "System.Int64":
- var stkNumber = new StackLayout();
- stkNumber.Orientation = Orientation.Horizontal;
- var optNumber = new NumericStepper();
- optNumber.ID = "opt" + option.name;
- optNumber.Value = Convert.ToDouble(option.@default);
- stkNumber.Items.Add(optNumber);
- var lblNumber = new Label();
- lblNumber.Text = option.description;
- stkNumber.Items.Add(lblNumber);
- stkOptions.Items.Add(stkNumber);
-
- break;
- case "System.Byte":
- case "System.UInt16":
- case "System.UInt32":
- case "System.UInt64":
- var stkUnsigned = new StackLayout();
- stkUnsigned.Orientation = Orientation.Horizontal;
- var optUnsigned = new NumericStepper();
- optUnsigned.ID = "opt" + option.name;
- optUnsigned.MinValue = 0;
- optUnsigned.Value = Convert.ToDouble(option.@default);
- stkUnsigned.Items.Add(optUnsigned);
- var lblUnsigned = new Label();
- lblUnsigned.Text = option.description;
- stkUnsigned.Items.Add(lblUnsigned);
- stkOptions.Items.Add(stkUnsigned);
-
- break;
- case "System.Single":
- case "System.Double":
- var stkFloat = new StackLayout();
- stkFloat.Orientation = Orientation.Horizontal;
- var optFloat = new NumericStepper();
- optFloat.ID = "opt" + option.name;
- optFloat.DecimalPlaces = 2;
- optFloat.Value = Convert.ToDouble(option.@default);
- stkFloat.Items.Add(optFloat);
- var lblFloat = new Label();
- lblFloat.Text = option.description;
- stkFloat.Items.Add(lblFloat);
- stkOptions.Items.Add(stkFloat);
-
- break;
- case "System.Guid":
- // TODO
- break;
- case "System.String":
- var stkString = new StackLayout();
- stkString.Orientation = Orientation.Horizontal;
- var lblString = new Label();
- lblString.Text = option.description;
- stkString.Items.Add(lblString);
- var optString = new TextBox();
- optString.ID = "opt" + option.name;
- optString.Text = (string)option.@default;
- stkString.Items.Add(optString);
- stkOptions.Items.Add(stkString);
-
- break;
- }
-
- grpOptions.Content = stkOptions;
- }
-
- void OnBtnDestinationClick(object sender, EventArgs e)
- {
- if(!(cmbFormat.SelectedValue is IWritableImage plugin))
- return;
-
- var dlgDestination = new SaveFileDialog
- {
- Title = "Choose destination file"
- };
-
- dlgDestination.Filters.Add(new FileFilter(plugin.Name, plugin.KnownExtensions.ToArray()));
-
- DialogResult result = dlgDestination.ShowDialog(this);
-
- if(result != DialogResult.Ok)
- {
- txtDestination.Text = "";
- _outputPrefix = null;
-
- return;
- }
-
- if(string.IsNullOrEmpty(Path.GetExtension(dlgDestination.FileName)))
- dlgDestination.FileName += plugin.KnownExtensions.First();
-
- txtDestination.Text = dlgDestination.FileName;
-
- _outputPrefix = Path.Combine(Path.GetDirectoryName(dlgDestination.FileName),
- Path.GetFileNameWithoutExtension(dlgDestination.FileName));
-
- chkResume.Checked = true;
- }
-
- void OnChkSidecarCheckedChanged(object sender, EventArgs e)
- {
- cmbEncoding.Visible = chkSidecar.Checked.Value;
- lblEncoding.Visible = chkSidecar.Checked.Value;
- }
-
- void OnChkExistingMetadataCheckedChanged(object sender, EventArgs e)
- {
- if(chkExistingMetadata.Checked == false)
- {
- _sidecar = null;
-
- return;
- }
-
- var dlgMetadata = new OpenFileDialog
- {
- Title = "Choose existing metadata sidecar", CheckFileExists = true
- };
-
- dlgMetadata.Filters.Add(new FileFilter("CICM XML metadata", ".xml"));
-
- DialogResult result = dlgMetadata.ShowDialog(this);
-
- if(result != DialogResult.Ok)
- {
- chkExistingMetadata.Checked = false;
-
- return;
- }
-
- var sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
-
- try
- {
- var sr = new StreamReader(dlgMetadata.FileName);
- _sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
- sr.Close();
- }
- catch
- {
- Eto.Forms.MessageBox.Show("Incorrect metadata sidecar file...", MessageBoxType.Error);
- chkExistingMetadata.Checked = false;
- }
- }
-
- void OnChkResumeCheckedChanged(object sender, EventArgs e)
- {
- if(chkResume.Checked == false)
- return;
-
- if(_outputPrefix != null)
- CheckResumeFile();
- }
-
- void CheckResumeFile()
- {
- _resume = null;
- var xs = new XmlSerializer(typeof(Resume));
-
- try
- {
- var sr = new StreamReader(_outputPrefix + ".resume.xml");
- _resume = (Resume)xs.Deserialize(sr);
- sr.Close();
- }
- catch
- {
- Eto.Forms.MessageBox.Show("Incorrect resume file, cannot use it...", MessageBoxType.Error);
- chkResume.Checked = false;
-
- return;
- }
-
- if(_resume == null ||
- _resume.NextBlock <= _resume.LastBlock ||
- (_resume.BadBlocks.Count != 0 && !_resume.Tape))
- return;
-
- Eto.Forms.MessageBox.Show("Media already dumped correctly, please choose another destination...",
- MessageBoxType.Warning);
-
- chkResume.Checked = false;
- }
-
- void OnBtnCloseClick(object sender, EventArgs e) => Close();
-
- void OnBtnStopClick(object sender, EventArgs e)
- {
- btnStop.Enabled = false;
- _dumper.Abort();
- }
-
- void OnBtnDumpClick(object sender, EventArgs e)
- {
- txtLog.Text = "";
- btnClose.Visible = false;
- btnStart.Visible = false;
- btnStop.Visible = true;
- btnStop.Enabled = true;
- stkProgress.Visible = true;
- btnDestination.Visible = false;
- stkOptions.Visible = false;
-
- UpdateStatus("Opening device...");
-
- try
- {
- _dev = new Device(_devicePath);
-
- if(_dev.IsRemote)
- Statistics.AddRemote(_dev.RemoteApplication, _dev.RemoteVersion, _dev.RemoteOperatingSystem,
- _dev.RemoteOperatingSystemVersion, _dev.RemoteArchitecture);
-
- if(_dev.Error)
- {
- StoppingErrorMessage($"Error {_dev.LastError} opening device.");
-
- return;
- }
- }
- catch(Exception exception)
- {
- StoppingErrorMessage($"Exception {exception.Message} opening device.");
-
- return;
- }
-
- Statistics.AddDevice(_dev);
- Statistics.AddCommand("dump-media");
-
- if(!(cmbFormat.SelectedValue is IWritableImage outputFormat))
- {
- StoppingErrorMessage("Cannot open output plugin.");
-
- return;
- }
-
- Encoding encoding = null;
-
- if(cmbEncoding.SelectedValue is CommonEncodingInfo encodingInfo)
- try
- {
- encoding = Claunia.Encoding.Encoding.GetEncoding(encodingInfo.Name);
- }
- catch(ArgumentException)
- {
- StoppingErrorMessage("Specified encoding is not supported.");
-
- return;
- }
-
- Dictionary parsedOptions = new Dictionary();
-
- if(grpOptions.Content is StackLayout stkFormatOptions)
- foreach(Control option in stkFormatOptions.Children)
- {
- string value;
-
- switch(option)
- {
- case CheckBox optBoolean:
- value = optBoolean.Checked?.ToString();
-
- break;
- case NumericStepper optNumber:
- value = optNumber.Value.ToString(CultureInfo.CurrentCulture);
-
- break;
- case TextBox optString:
- value = optString.Text;
-
- break;
- default: continue;
- }
-
- string key = option.ID.Substring(3);
-
- parsedOptions.Add(key, value);
- }
-
- var dumpLog = new DumpLog(_outputPrefix + ".log", _dev, false);
-
- dumpLog.WriteLine("Output image format: {0}.", outputFormat.Name);
-
- _dumper = new Dump(chkResume.Checked == true, _dev, _devicePath, outputFormat,
- (ushort)stpRetries.Value,
- chkForce.Checked == true, false, chkPersistent.Checked == true,
- chkStopOnError.Checked == true, _resume, dumpLog, encoding, _outputPrefix,
- txtDestination.Text, parsedOptions, _sidecar, (uint)stpSkipped.Value,
- chkExistingMetadata.Checked == false, chkTrim.Checked == false,
- chkTrack1Pregap.Checked == true, true, false, DumpSubchannel.Any, 0, false);
-
- new Thread(DoWork).Start();
- }
-
- void DoWork()
- {
- _dumper.UpdateStatus += UpdateStatus;
- _dumper.ErrorMessage += ErrorMessage;
- _dumper.StoppingErrorMessage += StoppingErrorMessage;
- _dumper.PulseProgress += PulseProgress;
- _dumper.InitProgress += InitProgress;
- _dumper.UpdateProgress += UpdateProgress;
- _dumper.EndProgress += EndProgress;
- _dumper.InitProgress2 += InitProgress2;
- _dumper.UpdateProgress2 += UpdateProgress2;
- _dumper.EndProgress2 += EndProgress2;
-
- _dumper.Start();
-
- _dev.Close();
-
- WorkFinished();
- }
-
- void WorkFinished() => Application.Instance.Invoke(() =>
- {
- btnClose.Visible = true;
- btnStop.Visible = false;
- stkProgress1.Visible = false;
- stkProgress2.Visible = false;
- });
-
- void EndProgress2() => Application.Instance.Invoke(() =>
- {
- stkProgress2.Visible = false;
- });
-
- void UpdateProgress2(string text, long current, long maximum) => Application.Instance.Invoke(() =>
- {
- lblProgress2.Text = text;
- prgProgress2.Indeterminate = false;
- prgProgress2.MinValue = 0;
-
- if(maximum > int.MaxValue)
- {
- prgProgress2.MaxValue = (int)(maximum / int.MaxValue);
- prgProgress2.Value = (int)(current / int.MaxValue);
- }
- else
- {
- prgProgress2.MaxValue = (int)maximum;
- prgProgress2.Value = (int)current;
- }
- });
-
- void InitProgress2() => Application.Instance.Invoke(() =>
- {
- stkProgress2.Visible = true;
- });
-
- void EndProgress() => Application.Instance.Invoke(() =>
- {
- stkProgress1.Visible = false;
- });
-
- void UpdateProgress(string text, long current, long maximum) => Application.Instance.Invoke(() =>
- {
- lblProgress.Text = text;
- prgProgress.Indeterminate = false;
- prgProgress.MinValue = 0;
-
- if(maximum > int.MaxValue)
- {
- prgProgress.MaxValue = (int)(maximum / int.MaxValue);
- prgProgress.Value = (int)(current / int.MaxValue);
- }
- else
- {
- prgProgress.MaxValue = (int)maximum;
- prgProgress.Value = (int)current;
- }
- });
-
- void InitProgress() => Application.Instance.Invoke(() =>
- {
- stkProgress1.Visible = true;
- });
-
- void PulseProgress(string text) => Application.Instance.Invoke(() =>
- {
- lblProgress.Text = text;
- prgProgress.Indeterminate = true;
- });
-
- void StoppingErrorMessage(string text) => Application.Instance.Invoke(() =>
- {
- ErrorMessage(text);
- Eto.Forms.MessageBox.Show(text, MessageBoxType.Error);
- WorkFinished();
- });
-
- void ErrorMessage(string text) => Application.Instance.Invoke(() =>
- {
- txtLog.Append(text + Environment.NewLine, true);
- });
-
- void UpdateStatus(string text) => Application.Instance.Invoke(() =>
- {
- txtLog.Append(text + Environment.NewLine, true);
- });
-
- class CommonEncodingInfo
- {
- public string Name { get; set; }
- public string DisplayName { get; set; }
- }
-
- #region XAML IDs
- // ReSharper disable InconsistentNaming
- ComboBox cmbFormat;
- TextBox txtDestination;
- Button btnDestination;
- CheckBox chkStopOnError;
- CheckBox chkForce;
- CheckBox chkPersistent;
- CheckBox chkResume;
- CheckBox chkTrack1Pregap;
- CheckBox chkSidecar;
- CheckBox chkTrim;
- CheckBox chkExistingMetadata;
- ComboBox cmbEncoding;
- GroupBox grpOptions;
- NumericStepper stpRetries;
- NumericStepper stpSkipped;
- Label lblEncoding;
- Button btnClose;
- Button btnStart;
- Button btnStop;
- StackLayout stkProgress;
- Label lblDestinationLabel;
- Label lblDestination;
- TextArea txtLog;
- StackLayout stkProgress1;
- Label lblProgress;
- ProgressBar prgProgress;
- StackLayout stkProgress2;
- Label lblProgress2;
- ProgressBar prgProgress2;
- StackLayout stkOptions;
-
- // ReSharper restore InconsistentNaming
- #endregion
- }
-}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/MediaDumpViewModel.cs b/Aaru.Gui/ViewModels/MediaDumpViewModel.cs
new file mode 100644
index 000000000..0ef52fab3
--- /dev/null
+++ b/Aaru.Gui/ViewModels/MediaDumpViewModel.cs
@@ -0,0 +1,870 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Reactive;
+using System.Text;
+using System.Threading;
+using System.Xml.Serialization;
+using Aaru.CommonTypes;
+using Aaru.CommonTypes.Enums;
+using Aaru.CommonTypes.Interfaces;
+using Aaru.CommonTypes.Metadata;
+using Aaru.Core;
+using Aaru.Core.Devices.Dumping;
+using Aaru.Core.Logging;
+using Aaru.Core.Media.Info;
+using Aaru.Devices;
+using Aaru.Gui.Models;
+using Avalonia.Controls;
+using Avalonia.Threading;
+using DynamicData;
+using MessageBox.Avalonia;
+using MessageBox.Avalonia.Enums;
+using ReactiveUI;
+using Schemas;
+using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo;
+using MediaType = Aaru.CommonTypes.MediaType;
+
+namespace Aaru.Gui.ViewModels
+{
+ public class MediaDumpViewModel : ViewModelBase
+ {
+ readonly string _devicePath;
+ readonly Window _view;
+ bool _closeVisible;
+ string _destination;
+ bool _destinationEnabled;
+ Device _dev;
+ Dump _dumper;
+ string _encodingEnabled;
+ bool _encodingVisible;
+ bool _existingMetadata;
+ bool _force;
+ string _formatReadOnly;
+ string _log;
+ bool _optionsVisible;
+ string _outputPrefix;
+ bool _persistent;
+ bool _progress1Visible;
+ bool _progress2Indeterminate;
+ double _progress2MaxValue;
+ string _progress2Text;
+ double _progress2Value;
+ bool _progress2Visible;
+ bool _progressIndeterminate;
+ double _progressMaxValue;
+ string _progressText;
+ double _progressValue;
+ bool _progressVisible;
+ Resume _resume;
+ double _retries;
+ EncodingModel _selectedEncoding;
+ ImagePluginModel _selectedPlugin;
+ CICMMetadataType _sidecar;
+ double _skipped;
+ bool _startVisible;
+ bool _stopEnabled;
+ bool _stopOnError;
+ bool _stopVisible;
+ bool _track1Pregap;
+ bool _track1PregapVisible;
+ bool _trim;
+ bool _useResume;
+ bool _useSidecar;
+
+ public MediaDumpViewModel(string devicePath, DeviceInfo deviceInfo, Window view, ScsiInfo scsiInfo = null)
+ {
+ _view = view;
+ DestinationEnabled = true;
+ StartVisible = true;
+ CloseVisible = true;
+ OptionsVisible = true;
+ StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
+ CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
+ StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
+ DestinationCommand = ReactiveCommand.Create(ExecuteDestinationCommand);
+ PluginsList = new ObservableCollection();
+ Encodings = new ObservableCollection();
+
+ // Defaults
+ StopOnError = false;
+ Force = false;
+ Persistent = true;
+ Resume = true;
+ Track1Pregap = false;
+ Sidecar = true;
+ Trim = true;
+ ExistingMetadata = false;
+ Retries = 5;
+ Skipped = 512;
+
+ MediaType mediaType;
+
+ if(scsiInfo != null)
+ mediaType = scsiInfo.MediaType;
+ else
+ switch(deviceInfo.Type)
+ {
+ case DeviceType.SecureDigital:
+ mediaType = MediaType.SecureDigital;
+
+ break;
+ case DeviceType.MMC:
+ mediaType = MediaType.MMC;
+
+ break;
+ default:
+ if(deviceInfo.IsPcmcia)
+ mediaType = MediaType.PCCardTypeII;
+ else if(deviceInfo.IsCompactFlash)
+ mediaType = MediaType.CompactFlash;
+ else
+ mediaType = MediaType.GENERIC_HDD;
+
+ break;
+ }
+
+ PluginBase plugins = GetPluginBase.Instance;
+
+ foreach(IWritableImage plugin in
+ plugins.WritableImages.Values.Where(p => p.SupportedMediaTypes.Contains(mediaType)))
+ PluginsList.Add(new ImagePluginModel
+ {
+ Plugin = plugin
+ });
+
+ Encodings.AddRange(Encoding.GetEncodings().Select(info => new EncodingModel
+ {
+ Name = info.Name, DisplayName = info.GetEncoding().EncodingName
+ }));
+
+ Encodings.AddRange(Claunia.Encoding.Encoding.GetEncodings().Select(info => new EncodingModel
+ {
+ Name = info.Name, DisplayName = info.DisplayName
+ }));
+
+ switch(mediaType)
+ {
+ case MediaType.CD:
+ case MediaType.CDDA:
+ case MediaType.CDG:
+ case MediaType.CDEG:
+ case MediaType.CDI:
+ case MediaType.CDROM:
+ case MediaType.CDROMXA:
+ case MediaType.CDPLUS:
+ case MediaType.CDMO:
+ case MediaType.CDR:
+ case MediaType.CDRW:
+ case MediaType.CDMRW:
+ case MediaType.VCD:
+ case MediaType.SVCD:
+ case MediaType.PCD:
+ case MediaType.DDCD:
+ case MediaType.DDCDR:
+ case MediaType.DDCDRW:
+ case MediaType.DTSCD:
+ case MediaType.CDMIDI:
+ case MediaType.CDV:
+ case MediaType.CDIREADY:
+ case MediaType.FMTOWNS:
+ case MediaType.PS1CD:
+ case MediaType.PS2CD:
+ case MediaType.MEGACD:
+ case MediaType.SATURNCD:
+ case MediaType.GDROM:
+ case MediaType.GDR:
+ case MediaType.MilCD:
+ case MediaType.SuperCDROM2:
+ case MediaType.JaguarCD:
+ case MediaType.ThreeDO:
+ case MediaType.PCFX:
+ case MediaType.NeoGeoCD:
+ case MediaType.CDTV:
+ case MediaType.CD32:
+ case MediaType.Playdia:
+ case MediaType.Pippin:
+ case MediaType.VideoNow:
+ case MediaType.VideoNowColor:
+ case MediaType.VideoNowXp:
+ Track1PregapVisible = true;
+
+ break;
+ default:
+ Track1PregapVisible = false;
+
+ break;
+ }
+
+ _devicePath = devicePath;
+ }
+
+ public ReactiveCommand StartCommand { get; }
+ public ReactiveCommand CloseCommand { get; }
+ public ReactiveCommand StopCommand { get; }
+ public ReactiveCommand DestinationCommand { get; }
+
+ public ObservableCollection PluginsList { get; }
+ public ObservableCollection Encodings { get; }
+
+ public string Title { get; }
+
+ public bool OptionsVisible
+ {
+ get => _optionsVisible;
+ set => this.RaiseAndSetIfChanged(ref _optionsVisible, value);
+ }
+
+ public ImagePluginModel SelectedPlugin
+ {
+ get => _selectedPlugin;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _selectedPlugin, value);
+
+ Destination = "";
+
+ if(value is null)
+ {
+ DestinationEnabled = false;
+
+ return;
+ }
+
+ DestinationEnabled = true;
+
+ if(!value.Plugin.SupportedOptions.Any())
+ {
+ // Hide options
+ }
+
+ /* TODO: Plugin options
+ grpOptions.Visible = true;
+
+ var stkOptions = new StackLayout
+ {
+ Orientation = Orientation.Vertical
+ };
+
+ foreach((string name, Type type, string description, object @default) option in plugin.SupportedOptions)
+ switch(option.type.ToString())
+ {
+ case "System.Boolean":
+ var optBoolean = new CheckBox();
+ optBoolean.ID = "opt" + option.name;
+ optBoolean.Text = option.description;
+ optBoolean.Checked = (bool)option.@default;
+ stkOptions.Items.Add(optBoolean);
+
+ break;
+ case "System.SByte":
+ case "System.Int16":
+ case "System.Int32":
+ case "System.Int64":
+ var stkNumber = new StackLayout();
+ stkNumber.Orientation = Orientation.Horizontal;
+ var optNumber = new NumericStepper();
+ optNumber.ID = "opt" + option.name;
+ optNumber.Value = Convert.ToDouble(option.@default);
+ stkNumber.Items.Add(optNumber);
+ var lblNumber = new Label();
+ lblNumber.Text = option.description;
+ stkNumber.Items.Add(lblNumber);
+ stkOptions.Items.Add(stkNumber);
+
+ break;
+ case "System.Byte":
+ case "System.UInt16":
+ case "System.UInt32":
+ case "System.UInt64":
+ var stkUnsigned = new StackLayout();
+ stkUnsigned.Orientation = Orientation.Horizontal;
+ var optUnsigned = new NumericStepper();
+ optUnsigned.ID = "opt" + option.name;
+ optUnsigned.MinValue = 0;
+ optUnsigned.Value = Convert.ToDouble(option.@default);
+ stkUnsigned.Items.Add(optUnsigned);
+ var lblUnsigned = new Label();
+ lblUnsigned.Text = option.description;
+ stkUnsigned.Items.Add(lblUnsigned);
+ stkOptions.Items.Add(stkUnsigned);
+
+ break;
+ case "System.Single":
+ case "System.Double":
+ var stkFloat = new StackLayout();
+ stkFloat.Orientation = Orientation.Horizontal;
+ var optFloat = new NumericStepper();
+ optFloat.ID = "opt" + option.name;
+ optFloat.DecimalPlaces = 2;
+ optFloat.Value = Convert.ToDouble(option.@default);
+ stkFloat.Items.Add(optFloat);
+ var lblFloat = new Label();
+ lblFloat.Text = option.description;
+ stkFloat.Items.Add(lblFloat);
+ stkOptions.Items.Add(stkFloat);
+
+ break;
+ case "System.Guid":
+ // TODO
+ break;
+ case "System.String":
+ var stkString = new StackLayout();
+ stkString.Orientation = Orientation.Horizontal;
+ var lblString = new Label();
+ lblString.Text = option.description;
+ stkString.Items.Add(lblString);
+ var optString = new TextBox();
+ optString.ID = "opt" + option.name;
+ optString.Text = (string)option.@default;
+ stkString.Items.Add(optString);
+ stkOptions.Items.Add(stkString);
+
+ break;
+ }
+
+ grpOptions.Content = stkOptions;
+ */
+ }
+ }
+
+ public string FormatReadOnly
+ {
+ get => _formatReadOnly;
+ set => this.RaiseAndSetIfChanged(ref _formatReadOnly, value);
+ }
+
+ public string Destination
+ {
+ get => _destination;
+ set => this.RaiseAndSetIfChanged(ref _destination, value);
+ }
+
+ public bool DestinationEnabled
+ {
+ get => _destinationEnabled;
+ set => this.RaiseAndSetIfChanged(ref _destinationEnabled, value);
+ }
+
+ public bool StopOnError
+ {
+ get => _stopOnError;
+ set => this.RaiseAndSetIfChanged(ref _stopOnError, value);
+ }
+
+ public bool Force
+ {
+ get => _force;
+ set => this.RaiseAndSetIfChanged(ref _force, value);
+ }
+
+ public double Retries
+ {
+ get => _retries;
+ set => this.RaiseAndSetIfChanged(ref _retries, value);
+ }
+
+ public bool Persistent
+ {
+ get => _persistent;
+ set => this.RaiseAndSetIfChanged(ref _persistent, value);
+ }
+
+ public bool Resume
+ {
+ get => _useResume;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _useResume, value);
+
+ if(value == false)
+ return;
+
+ if(_outputPrefix != null)
+ CheckResumeFile();
+ }
+ }
+
+ public bool Track1Pregap
+ {
+ get => _track1Pregap;
+ set => this.RaiseAndSetIfChanged(ref _track1Pregap, value);
+ }
+
+ public bool Track1PregapVisible
+ {
+ get => _track1PregapVisible;
+ set => this.RaiseAndSetIfChanged(ref _track1PregapVisible, value);
+ }
+
+ public double Skipped
+ {
+ get => _skipped;
+ set => this.RaiseAndSetIfChanged(ref _skipped, value);
+ }
+
+ public bool Sidecar
+ {
+ get => _useSidecar;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _useSidecar, value);
+ EncodingVisible = value;
+ }
+ }
+
+ public bool EncodingVisible
+ {
+ get => _encodingVisible;
+ set => this.RaiseAndSetIfChanged(ref _encodingVisible, value);
+ }
+
+ public bool Trim
+ {
+ get => _trim;
+ set => this.RaiseAndSetIfChanged(ref _trim, value);
+ }
+
+ public bool ExistingMetadata
+ {
+ get => _existingMetadata;
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _existingMetadata, value);
+
+ if(value == false)
+ {
+ _sidecar = null;
+
+ return;
+ }
+
+ var dlgMetadata = new OpenFileDialog
+ {
+ Title = "Choose existing metadata sidecar"
+ };
+
+ dlgMetadata.Filters.Add(new FileDialogFilter
+ {
+ Name = "CICM XML metadata", Extensions = new List(new[]
+ {
+ ".xml"
+ })
+ });
+
+ string[] result = dlgMetadata.ShowAsync(_view).Result;
+
+ if(result?.Length != 1)
+ {
+ ExistingMetadata = false;
+
+ return;
+ }
+
+ var sidecarXs = new XmlSerializer(typeof(CICMMetadataType));
+
+ try
+ {
+ var sr = new StreamReader(result[0]);
+ _sidecar = (CICMMetadataType)sidecarXs.Deserialize(sr);
+ sr.Close();
+ }
+ catch
+ {
+ // ReSharper disable AssignmentIsFullyDiscarded
+ _ = MessageBoxManager.
+
+ // ReSharper restore AssignmentIsFullyDiscarded
+ GetMessageBoxStandardWindow("Error", "Incorrect metadata sidecar file...", ButtonEnum.Ok,
+ Icon.Error).ShowDialog(_view).Result;
+
+ ExistingMetadata = false;
+ }
+ }
+ }
+
+ public EncodingModel SelectedEncoding
+ {
+ get => _selectedEncoding;
+ set => this.RaiseAndSetIfChanged(ref _selectedEncoding, value);
+ }
+
+ public string EncodingEnabled
+ {
+ get => _encodingEnabled;
+ set => this.RaiseAndSetIfChanged(ref _encodingEnabled, value);
+ }
+
+ public bool ProgressVisible
+ {
+ get => _progressVisible;
+ set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
+ }
+
+ public string Log
+ {
+ get => _log;
+ set => this.RaiseAndSetIfChanged(ref _log, value);
+ }
+
+ public bool Progress1Visible
+ {
+ get => _progress1Visible;
+ set => this.RaiseAndSetIfChanged(ref _progress1Visible, value);
+ }
+
+ public string ProgressText
+ {
+ get => _progressText;
+ set => this.RaiseAndSetIfChanged(ref _progressText, value);
+ }
+
+ public double ProgressValue
+ {
+ get => _progressValue;
+ set => this.RaiseAndSetIfChanged(ref _progressValue, value);
+ }
+
+ public double ProgressMaxValue
+ {
+ get => _progressMaxValue;
+ set => this.RaiseAndSetIfChanged(ref _progressMaxValue, value);
+ }
+
+ public bool ProgressIndeterminate
+ {
+ get => _progressIndeterminate;
+ set => this.RaiseAndSetIfChanged(ref _progressIndeterminate, value);
+ }
+
+ public bool Progress2Visible
+ {
+ get => _progress2Visible;
+ set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
+ }
+
+ public string Progress2Text
+ {
+ get => _progress2Text;
+ set => this.RaiseAndSetIfChanged(ref _progress2Text, value);
+ }
+
+ public double Progress2Value
+ {
+ get => _progress2Value;
+ set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
+ }
+
+ public double Progress2MaxValue
+ {
+ get => _progress2MaxValue;
+ set => this.RaiseAndSetIfChanged(ref _progress2MaxValue, value);
+ }
+
+ public bool Progress2Indeterminate
+ {
+ get => _progress2Indeterminate;
+ set => this.RaiseAndSetIfChanged(ref _progress2Indeterminate, value);
+ }
+
+ public bool StartVisible
+ {
+ get => _startVisible;
+ set => this.RaiseAndSetIfChanged(ref _startVisible, value);
+ }
+
+ public bool CloseVisible
+ {
+ get => _closeVisible;
+ set => this.RaiseAndSetIfChanged(ref _closeVisible, value);
+ }
+
+ public bool StopVisible
+ {
+ get => _stopVisible;
+ set => this.RaiseAndSetIfChanged(ref _stopVisible, value);
+ }
+
+ public bool StopEnabled
+ {
+ get => _stopEnabled;
+ set => this.RaiseAndSetIfChanged(ref _stopEnabled, value);
+ }
+
+ async void ExecuteDestinationCommand()
+ {
+ if(SelectedPlugin is null)
+ return;
+
+ var dlgDestination = new SaveFileDialog
+ {
+ Title = "Choose destination file"
+ };
+
+ dlgDestination.Filters.Add(new FileDialogFilter
+ {
+ Name = SelectedPlugin.Plugin.Name, Extensions = SelectedPlugin.Plugin.KnownExtensions.ToList()
+ });
+
+ string result = await dlgDestination.ShowAsync(_view);
+
+ if(result is null)
+ {
+ Destination = "";
+ _outputPrefix = null;
+
+ return;
+ }
+
+ if(string.IsNullOrEmpty(Path.GetExtension(result)))
+ result += SelectedPlugin.Plugin.KnownExtensions.First();
+
+ Destination = result;
+
+ _outputPrefix = Path.Combine(Path.GetDirectoryName(result), Path.GetFileNameWithoutExtension(result));
+
+ Resume = true;
+ }
+
+ async void CheckResumeFile()
+ {
+ _resume = null;
+ var xs = new XmlSerializer(typeof(Resume));
+
+ try
+ {
+ var sr = new StreamReader(_outputPrefix + ".resume.xml");
+ _resume = (Resume)xs.Deserialize(sr);
+ sr.Close();
+ }
+ catch
+ {
+ await MessageBoxManager.
+ GetMessageBoxStandardWindow("Error", "Incorrect resume file, cannot use it...", ButtonEnum.Ok,
+ Icon.Error).ShowDialog(_view);
+
+ Resume = false;
+
+ return;
+ }
+
+ if(_resume == null ||
+ _resume.NextBlock <= _resume.LastBlock ||
+ (_resume.BadBlocks.Count != 0 && !_resume.Tape))
+ return;
+
+ await MessageBoxManager.
+ GetMessageBoxStandardWindow("Warning",
+ "Media already dumped correctly, please choose another destination...",
+ ButtonEnum.Ok, Icon.Warning).ShowDialog(_view);
+
+ Resume = false;
+ }
+
+ void ExecuteCloseCommand() => _view.Close();
+
+ internal void ExecuteStopCommand()
+ {
+ StopEnabled = false;
+ _dumper?.Abort();
+ }
+
+ void ExecuteStartCommand()
+ {
+ Log = "";
+ CloseVisible = false;
+ StartVisible = false;
+ StopVisible = true;
+ StopEnabled = true;
+ ProgressVisible = true;
+ DestinationEnabled = false;
+ OptionsVisible = false;
+
+ UpdateStatus("Opening device...");
+
+ try
+ {
+ _dev = new Device(_devicePath);
+
+ if(_dev.IsRemote)
+ Statistics.AddRemote(_dev.RemoteApplication, _dev.RemoteVersion, _dev.RemoteOperatingSystem,
+ _dev.RemoteOperatingSystemVersion, _dev.RemoteArchitecture);
+
+ if(_dev.Error)
+ {
+ StoppingErrorMessage($"Error {_dev.LastError} opening device.");
+
+ return;
+ }
+ }
+ catch(Exception exception)
+ {
+ StoppingErrorMessage($"Exception {exception.Message} opening device.");
+
+ return;
+ }
+
+ Statistics.AddDevice(_dev);
+ Statistics.AddCommand("dump-media");
+
+ if(SelectedPlugin is null)
+ {
+ StoppingErrorMessage("Cannot open output plugin.");
+
+ return;
+ }
+
+ Encoding encoding = null;
+
+ if(!(SelectedEncoding is null))
+ try
+ {
+ encoding = Claunia.Encoding.Encoding.GetEncoding(SelectedEncoding.Name);
+ }
+ catch(ArgumentException)
+ {
+ StoppingErrorMessage("Specified encoding is not supported.");
+
+ return;
+ }
+
+ Dictionary parsedOptions = new Dictionary();
+
+ /* TODO: Options
+ if(grpOptions.Content is StackLayout stkFormatOptions)
+ foreach(Control option in stkFormatOptions.Children)
+ {
+ string value;
+
+ switch(option)
+ {
+ case CheckBox optBoolean:
+ value = optBoolean.Checked?.ToString();
+
+ break;
+ case NumericStepper optNumber:
+ value = optNumber.Value.ToString(CultureInfo.CurrentCulture);
+
+ break;
+ case TextBox optString:
+ value = optString.Text;
+
+ break;
+ default: continue;
+ }
+
+ string key = option.ID.Substring(3);
+
+ parsedOptions.Add(key, value);
+ }
+ */
+
+ var dumpLog = new DumpLog(_outputPrefix + ".log", _dev, false);
+
+ dumpLog.WriteLine("Output image format: {0}.", SelectedPlugin.Name);
+
+ _dumper = new Dump(Resume, _dev, _devicePath, SelectedPlugin.Plugin, (ushort)Retries, Force, false,
+ Persistent, StopOnError, _resume, dumpLog, encoding, _outputPrefix, Destination,
+ parsedOptions, _sidecar, (uint)Skipped, ExistingMetadata == false, Trim == false,
+ Track1Pregap, true, false, DumpSubchannel.Any, 0, false);
+
+ new Thread(DoWork).Start();
+ }
+
+ void DoWork()
+ {
+ _dumper.UpdateStatus += UpdateStatus;
+ _dumper.ErrorMessage += ErrorMessage;
+ _dumper.StoppingErrorMessage += StoppingErrorMessage;
+ _dumper.PulseProgress += PulseProgress;
+ _dumper.InitProgress += InitProgress;
+ _dumper.UpdateProgress += UpdateProgress;
+ _dumper.EndProgress += EndProgress;
+ _dumper.InitProgress2 += InitProgress2;
+ _dumper.UpdateProgress2 += UpdateProgress2;
+ _dumper.EndProgress2 += EndProgress2;
+
+ _dumper.Start();
+
+ _dev.Close();
+
+ WorkFinished();
+ }
+
+ async void WorkFinished() => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ CloseVisible = true;
+ StopVisible = false;
+ Progress1Visible = false;
+ Progress2Visible = false;
+ });
+
+ async void EndProgress2() => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Visible = false;
+ });
+
+ async void UpdateProgress2(string text, long current, long maximum) =>
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Text = text;
+ Progress2Indeterminate = false;
+
+ Progress2MaxValue = maximum;
+ Progress2Value = current;
+ });
+
+ async void InitProgress2() => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Visible = true;
+ });
+
+ async void EndProgress() => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress1Visible = false;
+ });
+
+ async void UpdateProgress(string text, long current, long maximum) =>
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ ProgressText = text;
+ ProgressIndeterminate = false;
+
+ ProgressMaxValue = maximum;
+ ProgressValue = current;
+ });
+
+ async void InitProgress() => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress1Visible = true;
+ });
+
+ async void PulseProgress(string text) => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ ProgressText = text;
+ ProgressIndeterminate = true;
+ });
+
+ async void StoppingErrorMessage(string text) => await Dispatcher.UIThread.InvokeAsync(async () =>
+ {
+ ErrorMessage(text);
+
+ await MessageBoxManager.GetMessageBoxStandardWindow("Error", $"{text}", ButtonEnum.Ok, Icon.Error).
+ ShowDialog(_view);
+
+ WorkFinished();
+ });
+
+ async void ErrorMessage(string text) => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Log += text + Environment.NewLine;
+ });
+
+ async void UpdateStatus(string text) => await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Log += text + Environment.NewLine;
+ });
+ }
+}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/MediaInfoViewModel.cs b/Aaru.Gui/ViewModels/MediaInfoViewModel.cs
index c01a9dc00..c23316a2c 100644
--- a/Aaru.Gui/ViewModels/MediaInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/MediaInfoViewModel.cs
@@ -336,25 +336,35 @@ namespace Aaru.Gui.ViewModels
void ExecuteSaveMediumSupportCommand() => SaveElement(_scsiInfo.MediaTypeSupport);
- void ExecuteDumpCommand()
+ async void ExecuteDumpCommand()
{
- /* TODO: frmDump
- if(scsiInfo.MediaType == MediaType.GDR ||
- scsiInfo.MediaType == MediaType.GDROM)
+ if(_scsiInfo.MediaType == CommonTypes.MediaType.GDR ||
+ _scsiInfo.MediaType == CommonTypes.MediaType.GDROM)
{
- Eto.Forms.MessageBox.Show("GD-ROM dump support is not yet implemented.", MessageBoxType.Error);
+ await MessageBoxManager.
+ GetMessageBoxStandardWindow("Error", "GD-ROM dump support is not yet implemented.", ButtonEnum.Ok,
+ Icon.Error).ShowDialog(_view);
return;
}
- if((scsiInfo.MediaType == MediaType.XGD || scsiInfo.MediaType == MediaType.XGD2 ||
- scsiInfo.MediaType == MediaType.XGD3) &&
- scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true)
- Eto.Forms.MessageBox.Show("Dumping Xbox discs require a Kreon drive.", MessageBoxType.Error);
+ if((_scsiInfo.MediaType == CommonTypes.MediaType.XGD || _scsiInfo.MediaType == CommonTypes.MediaType.XGD2 ||
+ _scsiInfo.MediaType == CommonTypes.MediaType.XGD3) &&
+ _scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true)
+ {
+ await MessageBoxManager.
+ GetMessageBoxStandardWindow("Error", "Dumping Xbox discs require a Kreon drive.", ButtonEnum.Ok,
+ Icon.Error).ShowDialog(_view);
- var dumpForm = new frmDump(devicePath, scsiInfo.DeviceInfo, scsiInfo);
- dumpForm.Show();
- */
+ return;
+ }
+
+ var mediaDumpWindow = new MediaDumpWindow();
+
+ mediaDumpWindow.DataContext =
+ new MediaDumpViewModel(_devicePath, _scsiInfo.DeviceInfo, mediaDumpWindow, _scsiInfo);
+
+ mediaDumpWindow.Show();
}
async void ExecuteScanCommand()
diff --git a/Aaru.Gui/Views/MediaDumpWindow.xaml b/Aaru.Gui/Views/MediaDumpWindow.xaml
new file mode 100644
index 000000000..a0c5fa9dc
--- /dev/null
+++ b/Aaru.Gui/Views/MediaDumpWindow.xaml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Aaru.Gui/Views/MediaDumpWindow.xaml.cs b/Aaru.Gui/Views/MediaDumpWindow.xaml.cs
new file mode 100644
index 000000000..0a3a694ea
--- /dev/null
+++ b/Aaru.Gui/Views/MediaDumpWindow.xaml.cs
@@ -0,0 +1,27 @@
+using System.ComponentModel;
+using Aaru.Gui.ViewModels;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Aaru.Gui.Views
+{
+ public class MediaDumpWindow : Window
+ {
+ public MediaDumpWindow()
+ {
+ InitializeComponent();
+ #if DEBUG
+ this.AttachDevTools();
+ #endif
+ }
+
+ void InitializeComponent() => AvaloniaXamlLoader.Load(this);
+
+ protected override void OnClosing(CancelEventArgs e)
+ {
+ (DataContext as MediaDumpViewModel)?.ExecuteStopCommand();
+ base.OnClosing(e);
+ }
+ }
+}
\ No newline at end of file