diff --git a/Aaru.Gui/ViewModels/Windows/ImageConvertViewModel.cs b/Aaru.Gui/ViewModels/Windows/ImageConvertViewModel.cs index 15b3c44d7..4185b0d26 100644 --- a/Aaru.Gui/ViewModels/Windows/ImageConvertViewModel.cs +++ b/Aaru.Gui/ViewModels/Windows/ImageConvertViewModel.cs @@ -36,19 +36,15 @@ using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using Aaru.CommonTypes; using Aaru.CommonTypes.AaruMetadata; -using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Metadata; using Aaru.Core; -using Aaru.Core.Media; -using Aaru.Devices; using Aaru.Gui.Models; using Aaru.Localization; using Aaru.Logging; @@ -60,9 +56,7 @@ using CommunityToolkit.Mvvm.Input; using MsBox.Avalonia; using MsBox.Avalonia.Enums; using Sentry; -using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo; -using Track = Aaru.CommonTypes.Structs.Track; -using Version = Aaru.CommonTypes.Interop.Version; +using Convert = Aaru.Core.Image.Convert; namespace Aaru.Gui.ViewModels.Windows; @@ -107,7 +101,6 @@ public sealed partial class ImageConvertViewModel : ViewModelBase string _driveSerialNumberText; [ObservableProperty] bool _driveSerialNumberVisible; - List _dumpHardware; [ObservableProperty] bool _forceChecked; [ObservableProperty] @@ -186,6 +179,8 @@ public sealed partial class ImageConvertViewModel : ViewModelBase bool _stopEnabled; [ObservableProperty] bool _stopVisible; + Resume _resume; + Convert _converter; public ImageConvertViewModel([JetBrains.Annotations.NotNull] IMediaImage inputFormat, string imageSource, Window view) @@ -251,10 +246,10 @@ public sealed partial class ImageConvertViewModel : ViewModelBase ResumeFileFromImageVisible = inputFormat.DumpHardware?.Any() == true; _aaruMetadata = inputFormat.AaruMetadata; - _dumpHardware = inputFormat.DumpHardware?.Any() == true ? inputFormat.DumpHardware : null; + List dumpHardware = inputFormat.DumpHardware?.Any() == true ? inputFormat.DumpHardware : null; MetadataJsonText = _aaruMetadata == null ? "" : UI._From_image_; - ResumeFileText = _dumpHardware == null ? "" : UI._From_image_; + ResumeFileText = dumpHardware == null ? "" : UI._From_image_; SelectedPlugin = PluginsList[0]; SectorsValue = 512; @@ -317,21 +312,43 @@ public sealed partial class ImageConvertViewModel : ViewModelBase return; } - var inputOptical = _inputFormat as IOpticalMediaImage; - var outputOptical = outputFormat as IWritableOpticalImage; + Dictionary parsedOptions = []; + uint nominalNegativeSectors = _inputFormat.Info.NegativeSectors; + uint nominalOverflowSectors = _inputFormat.Info.OverflowSectors; + PluginRegister plugins = PluginRegister.Singleton; - List tracks; - - try - { - tracks = inputOptical?.Tracks; - } - catch(Exception ex) - { - SentrySdk.CaptureException(ex); - - tracks = null; - } + _converter = new Convert(_inputFormat, + outputFormat, + _inputFormat.Info.MediaType, + ForceChecked, + DestinationText, + parsedOptions, + nominalNegativeSectors, + nominalOverflowSectors, + CommentsText, + CreatorText, + DriveFirmwareRevisionText, + DriveManufacturerText, + DriveModelText, + DriveSerialNumberText, + (int)LastMediaSequenceValue, + MediaBarcodeText, + MediaManufacturerText, + MediaModelText, + MediaPartNumberText, + (int)MediaSequenceValue, + MediaSerialNumberText, + MediaTitleText, + false, + (uint)SectorsValue, + plugins, + true, + false, + false, + false, + null, + _resume, + _aaruMetadata); // Prepare UI await Dispatcher.UIThread.InvokeAsync(() => @@ -344,1259 +361,63 @@ public sealed partial class ImageConvertViewModel : ViewModelBase StopEnabled = true; FormatReadOnly = true; DestinationVisible = false; - Progress1Visible = true; - Progress2Visible = true; - - ProgressMaxValue = 1d; - ProgressMaxValue += _inputFormat.Info.ReadableMediaTags.Count; - ProgressMaxValue++; - - if(tracks != null) ProgressMaxValue++; - - if(tracks == null) - { - ProgressMaxValue += 2; - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags) - { - switch(tag) - { - case SectorTagType.AppleSonyTag: - case SectorTagType.AppleProfileTag: - case SectorTagType.PriamDataTowerTag: - case SectorTagType.CdSectorSync: - case SectorTagType.CdSectorHeader: - case SectorTagType.CdSectorSubHeader: - case SectorTagType.CdSectorEdc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEcc: - // This tags are inline in long sector - continue; - } - - if(ForceChecked && !outputFormat.SupportedSectorTags.Contains(tag)) continue; - - ProgressMaxValue++; - } - } - else - { - ProgressMaxValue += tracks.Count; - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags.Order()) - { - switch(tag) - { - case SectorTagType.AppleSonyTag: - case SectorTagType.AppleProfileTag: - case SectorTagType.PriamDataTowerTag: - case SectorTagType.CdSectorSync: - case SectorTagType.CdSectorHeader: - case SectorTagType.CdSectorSubHeader: - case SectorTagType.CdSectorEdc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEcc: - // This tags are inline in long sector - continue; - } - - if(ForceChecked && !outputFormat.SupportedSectorTags.Contains(tag)) continue; - - ProgressMaxValue += tracks.Count; - } - } - - if(_dumpHardware != null) ProgressMaxValue++; - - if(_aaruMetadata != null) ProgressMaxValue++; - - ProgressMaxValue++; }); - foreach(MediaTagType mediaTag in _inputFormat.Info.ReadableMediaTags.Where(mediaTag => - !outputFormat.SupportedMediaTags.Contains(mediaTag) && !ForceChecked)) + _converter.UpdateStatus += static text => AaruLogging.WriteLine(text); + + _converter.ErrorMessage += text => { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Converting_image_will_lose_media_tag_0, - mediaTag), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - - bool useLong = _inputFormat.Info.ReadableSectorTags.Count != 0; - - foreach(SectorTagType sectorTag in _inputFormat.Info.ReadableSectorTags.Where(sectorTag => - !outputFormat.SupportedSectorTags.Contains(sectorTag))) - { - if(ForceChecked) - { - if(sectorTag != SectorTagType.CdTrackFlags && - sectorTag != SectorTagType.CdTrackIsrc && - sectorTag != SectorTagType.CdSectorSubchannel) - useLong = false; - - continue; - } - - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Converting_image_will_lose_sector_tag_0, - sectorTag), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - - Dictionary parsedOptions = []; - - /* TODO: - if(grpOptions.Content is StackLayout stkImageOptions) - foreach(Control option in stkImageOptions.Children) - { - if(cancel) - break; - - string value; - - switch(option) - { - case CheckBox optBoolean: - value = optBooleanChecked?.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); - } - */ - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Creating_output_image; - Progress2Text = ""; - Progress2Indeterminate = true; - }); - - // TODO: Get the source image number of negative and overflow sectors to convert them too - if(!outputFormat.Create(DestinationText, - _inputFormat.Info.MediaType, - parsedOptions, - _inputFormat.Info.Sectors, - 0, - 0, - _inputFormat.Info.SectorSize)) - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_creating_output_image, - outputFormat.ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_creating_output_image, outputFormat.ErrorMessage); - - return; - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Setting_image_metadata; - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = true; - }); - - var metadata = new ImageInfo - { - Application = "Aaru", - ApplicationVersion = Version.GetInformationalVersion(), - Comments = CommentsText, - Creator = CreatorText, - DriveFirmwareRevision = DriveFirmwareRevisionText, - DriveManufacturer = DriveManufacturerText, - DriveModel = DriveModelText, - DriveSerialNumber = DriveSerialNumberText, - LastMediaSequence = (int)LastMediaSequenceValue, - MediaBarcode = MediaBarcodeText, - MediaManufacturer = MediaManufacturerText, - MediaModel = MediaModelText, - MediaPartNumber = MediaPartNumberText, - MediaSequence = (int)MediaSequenceValue, - MediaSerialNumber = MediaSerialNumberText, - MediaTitle = MediaTitleText + warning = true; + AaruLogging.Error(text); }; - if(!_cancel) + _converter.StoppingErrorMessage += text => { - if(!outputFormat.SetImageInfo(metadata)) - { - if(!ForceChecked) - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_setting_metadata_not_continuing, - outputFormat.ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); + _ = Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager + .GetMessageBoxStandard(UI.Title_Error, text, icon: Icon.Error) + .ShowWindowDialogAsync(_view)); + }; - AaruLogging.Error(UI.Error_0_setting_metadata_not_continuing, outputFormat.ErrorMessage); - - return; - } - - warning = true; - AaruLogging.Error(Localization.Core.Error_0_setting_metadata, outputFormat.ErrorMessage); - } - } - - if(tracks != null && !_cancel && outputOptical != null) + _converter.UpdateProgress += (text, current, maximum) => { - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Invoke(() => { - ProgressText = UI.Setting_tracks_list; - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = true; + ProgressText = text; + ProgressValue = current; + ProgressMaxValue = maximum; + ProgressIndeterminate = false; }); + }; - if(!outputOptical.SetTracks(tracks)) - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_sending_tracks_list_to_output_image, - outputFormat.ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_sending_tracks_list_to_output_image, outputFormat.ErrorMessage); - - return; - } - } - - ErrorNumber errno; - - foreach(MediaTagType mediaTag in _inputFormat.Info.ReadableMediaTags.TakeWhile(_ => !_cancel)) + _converter.PulseProgress += text => { - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Invoke(() => { - ProgressText = string.Format(UI.Converting_media_tag_0, mediaTag); - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = true; + ProgressText = text; + ProgressIndeterminate = true; }); + }; - if(ForceChecked && !outputFormat.SupportedMediaTags.Contains(mediaTag)) continue; + _converter.InitProgress += () => Dispatcher.UIThread.Invoke(() => Progress1Visible = true); - errno = _inputFormat.ReadMediaTag(mediaTag, out byte[] tag); + _converter.EndProgress += () => Dispatcher.UIThread.Invoke(() => Progress1Visible = false); - if(errno == ErrorNumber.NoError && outputFormat.WriteMediaTag(tag, mediaTag)) continue; + _converter.InitProgress2 += () => Dispatcher.UIThread.Invoke(() => Progress2Visible = true); - if(ForceChecked) - { - warning = true; + _converter.EndProgress2 += () => Dispatcher.UIThread.Invoke(() => Progress2Visible = false); - if(errno == ErrorNumber.NoError) - AaruLogging.Error(UI.Error_0_writing_media_tag, outputFormat.ErrorMessage); - else - AaruLogging.Error(UI.Error_0_reading_media_tag, errno); - } - else - { - if(errno == ErrorNumber.NoError) - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_media_tag_not_continuing, - outputFormat.ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_writing_media_tag_not_continuing, outputFormat.ErrorMessage); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_media_tag_not_continuing, - errno), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_reading_media_tag_not_continuing, errno); - } - - return; - } - } - - ulong doneSectors = 0; - - if(tracks == null && !_cancel) + _converter.UpdateProgress2 += (text, current, maximum) => { - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Invoke(() => { - ProgressText = string.Format(UI.Setting_geometry_to_0_cylinders_1_heads_and_2_sectors_per_track, - _inputFormat.Info.Cylinders, - _inputFormat.Info.Heads, - _inputFormat.Info.SectorsPerTrack); - - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = true; - }); - - if(!outputFormat.SetGeometry(_inputFormat.Info.Cylinders, - _inputFormat.Info.Heads, - _inputFormat.Info.SectorsPerTrack)) - { - warning = true; - - AaruLogging.Error(UI.Error_0_setting_geometry_image_may_be_incorrect_continuing, - outputFormat.ErrorMessage); - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Converting_sectors; - ProgressValue++; - Progress2Text = ""; + Progress2Text = text; + Progress2Value = current; + Progress2MaxValue = maximum; Progress2Indeterminate = false; - Progress2MaxValue = (int)(_inputFormat.Info.Sectors / SectorsValue); }); + }; - while(doneSectors < _inputFormat.Info.Sectors) - { - if(_cancel) break; - - byte[] sector; - - uint sectorsToDo; - - if(_inputFormat.Info.Sectors - doneSectors >= (ulong)SectorsValue) - sectorsToDo = (uint)SectorsValue; - else - sectorsToDo = (uint)(_inputFormat.Info.Sectors - doneSectors); - - ulong sectors = doneSectors; - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_sectors_0_to_1_2_done, - sectors, - sectors + sectorsToDo, - sectors / (double)_inputFormat.Info.Sectors); - - Progress2Value = (int)(sectors / SectorsValue); - }); - - bool result; - SectorStatus sectorStatus = SectorStatus.NotDumped; - var sectorStatusArray = new SectorStatus[1]; - - if(useLong) - { - errno = sectorsToDo == 1 - ? _inputFormat.ReadSectorLong(doneSectors, false, out sector, out sectorStatus) - : _inputFormat.ReadSectorsLong(doneSectors, - false, - sectorsToDo, - out sector, - out sectorStatusArray); - - if(errno == ErrorNumber.NoError) - { - result = sectorsToDo == 1 - ? outputFormat.WriteSectorLong(sector, doneSectors, false, sectorStatus) - : outputFormat.WriteSectorsLong(sector, - doneSectors, - false, - sectorsToDo, - sectorStatusArray); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_reading_sector_1_not_continuing, errno, doneSectors); - - return; - } - } - } - else - { - errno = sectorsToDo == 1 - ? _inputFormat.ReadSector(doneSectors, false, out sector, out sectorStatus) - : _inputFormat.ReadSectors(doneSectors, - false, - sectorsToDo, - out sector, - out sectorStatusArray); - - if(errno == ErrorNumber.NoError) - { - result = sectorsToDo == 1 - ? outputFormat.WriteSector(sector, doneSectors, false, sectorStatus) - : outputFormat.WriteSectors(sector, - doneSectors, - false, - sectorsToDo, - sectorStatusArray); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_reading_sector_1_not_continuing, errno, doneSectors); - - return; - } - } - } - - if(!result) - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_writing_sector_1_continuing, - outputFormat.ErrorMessage, - doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_sector_1_not_continuing, - outputFormat.ErrorMessage, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_writing_sector_1_not_continuing, - outputFormat.ErrorMessage, - doneSectors); - - return; - } - } - - doneSectors += sectorsToDo; - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_sectors_0_to_1_2_done, - _inputFormat.Info.Sectors, - _inputFormat.Info.Sectors, - 1.0); - - Progress2Value = Progress2MaxValue; - }); - - Dictionary isrcs = []; - Dictionary trackFlags = []; - string mcn = null; - HashSet subchannelExtents = []; - Dictionary smallestPregapLbaPerTrack = []; - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags - .Where(static t => t == SectorTagType.CdTrackIsrc) - .Order()) - { - foreach(Track track in inputOptical.Tracks) - { - errno = _inputFormat.ReadSectorTag(track.Sequence, false, tag, out byte[] isrc); - - if(errno != ErrorNumber.NoError) continue; - - isrcs[(byte)track.Sequence] = Encoding.UTF8.GetString(isrc); - } - } - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags - .Where(static t => t == SectorTagType.CdTrackFlags) - .Order()) - { - foreach(Track track in inputOptical.Tracks) - { - errno = _inputFormat.ReadSectorTag(track.Sequence, false, tag, out byte[] flags); - - if(errno != ErrorNumber.NoError) continue; - - trackFlags[(byte)track.Sequence] = flags[0]; - } - } - - for(ulong s = 0; s < _inputFormat.Info.Sectors; s++) - { - if(s > int.MaxValue) break; - - subchannelExtents.Add((int)s); - } - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags.TakeWhile(_ => useLong && !_cancel)) - { - switch(tag) - { - case SectorTagType.AppleSonyTag: - case SectorTagType.AppleProfileTag: - case SectorTagType.PriamDataTowerTag: - case SectorTagType.CdSectorSync: - case SectorTagType.CdSectorHeader: - case SectorTagType.CdSectorSubHeader: - case SectorTagType.CdSectorEdc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEcc: - // This tags are inline in long sector - continue; - } - - if(ForceChecked && !outputFormat.SupportedSectorTags.Contains(tag)) continue; - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = string.Format(UI.Converting_tag_0, tag); - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = false; - Progress2MaxValue = (int)(_inputFormat.Info.Sectors / SectorsValue); - }); - - doneSectors = 0; - - while(doneSectors < _inputFormat.Info.Sectors) - { - if(_cancel) break; - - byte[] sector; - - uint sectorsToDo; - - if(_inputFormat.Info.Sectors - doneSectors >= (ulong)SectorsValue) - sectorsToDo = (uint)SectorsValue; - else - sectorsToDo = (uint)(_inputFormat.Info.Sectors - doneSectors); - - ulong sectors = doneSectors; - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_tag_0_for_sectors_1_to_2_3_done, - sectors / (double)_inputFormat.Info.Sectors, - sectors, - sectors + sectorsToDo, - sectors / (double)_inputFormat.Info.Sectors); - - Progress2Value = (int)(sectors / SectorsValue); - }); - - bool result; - - if(sectorsToDo == 1) - { - errno = _inputFormat.ReadSectorTag(doneSectors, false, tag, out sector); - - if(errno == ErrorNumber.NoError) - { - Track track = tracks.LastOrDefault(t => t.StartSector >= doneSectors); - - if(tag == SectorTagType.CdSectorSubchannel && track != null) - { - bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw, - MmcSubchannel.Raw, - sector, - doneSectors, - 1, - null, - isrcs, - (byte)track.Sequence, - ref mcn, - tracks.ToArray(), - subchannelExtents, - false, - outputFormat as IWritableOpticalImage, - false, - false, - null, - smallestPregapLbaPerTrack, - false, - out _); - - if(indexesChanged) outputOptical.SetTracks(tracks.ToList()); - - result = true; - } - else - result = outputFormat.WriteSectorTag(sector, doneSectors, false, tag); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_reading_sector_1_not_continuing, errno, doneSectors); - - return; - } - } - } - else - { - errno = _inputFormat.ReadSectorsTag(doneSectors, false, sectorsToDo, tag, out sector); - - if(errno == ErrorNumber.NoError) - { - Track track = tracks.LastOrDefault(t => t.StartSector >= doneSectors); - - if(tag == SectorTagType.CdSectorSubchannel && track != null) - - { - bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw, - MmcSubchannel.Raw, - sector, - doneSectors, - sectorsToDo, - null, - isrcs, - (byte)track.Sequence, - ref mcn, - tracks.ToArray(), - subchannelExtents, - false, - outputFormat as IWritableOpticalImage, - false, - false, - null, - smallestPregapLbaPerTrack, - false, - out _); - - if(indexesChanged) outputOptical.SetTracks(tracks.ToList()); - - result = true; - } - else - result = outputFormat.WriteSectorsTag(sector, doneSectors, false, sectorsToDo, tag); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_reading_sector_1_not_continuing, errno, doneSectors); - - return; - } - } - } - - if(!result) - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_writing_sector_1_continuing, - outputFormat.ErrorMessage, - doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_sector_1_not_continuing, - outputFormat.ErrorMessage, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - AaruLogging.Error(UI.Error_0_writing_sector_1_not_continuing, - outputFormat.ErrorMessage, - doneSectors); - - return; - } - } - - doneSectors += sectorsToDo; - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_tag_0_for_sectors_1_to_2_3_done, - tag, - _inputFormat.Info.Sectors, - _inputFormat.Info.Sectors, - 1.0); - - Progress2Value = Progress2MaxValue; - }); - - foreach(KeyValuePair isrc in isrcs) - { - outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), - isrc.Key, - false, - SectorTagType.CdTrackIsrc); - } - - foreach(KeyValuePair flags in trackFlags) - outputOptical.WriteSectorTag([flags.Value], flags.Key, false, SectorTagType.CdTrackFlags); - - if(mcn != null) outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN); - } - } - else - { - foreach(Track track in tracks.TakeWhile(_ => !_cancel)) - { - doneSectors = 0; - ulong trackSectors = track.EndSector - track.StartSector + 1; - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = string.Format(UI.Converting_sectors_in_track_0, track.Sequence); - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = false; - Progress2MaxValue = (int)(trackSectors / SectorsValue); - }); - - while(doneSectors < trackSectors) - { - if(_cancel) break; - - byte[] sector; - - uint sectorsToDo; - - if(trackSectors - doneSectors >= (ulong)SectorsValue) - sectorsToDo = (uint)SectorsValue; - else - sectorsToDo = (uint)(trackSectors - doneSectors); - - ulong sectors = doneSectors; - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_sectors_0_to_1_in_track_2_3_done, - sectors + track.StartSector, - sectors + sectorsToDo + track.StartSector, - track.Sequence, - (sectors + track.StartSector) / - (double)_inputFormat.Info.Sectors); - - Progress2Value = (int)(sectors / SectorsValue); - }); - - bool result; - SectorStatus sectorStatus = SectorStatus.NotDumped; - var sectorStatusArray = new SectorStatus[1]; - - if(useLong) - { - errno = sectorsToDo == 1 - ? _inputFormat.ReadSectorLong(doneSectors + track.StartSector, - false, - out sector, - out sectorStatus) - : _inputFormat.ReadSectorsLong(doneSectors + track.StartSector, - false, - sectorsToDo, - out sector, - out sectorStatusArray); - - if(errno == ErrorNumber.NoError) - { - result = sectorsToDo == 1 - ? outputFormat.WriteSectorLong(sector, - doneSectors + track.StartSector, - false, - sectorStatus) - : outputFormat.WriteSectorsLong(sector, - doneSectors + track.StartSector, - false, - sectorsToDo, - sectorStatusArray); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - } - else - { - errno = sectorsToDo == 1 - ? _inputFormat.ReadSector(doneSectors + track.StartSector, - false, - out sector, - out sectorStatus) - : _inputFormat.ReadSectors(doneSectors + track.StartSector, - false, - sectorsToDo, - out sector, - out sectorStatusArray); - - if(errno == ErrorNumber.NoError) - { - result = sectorsToDo == 1 - ? outputFormat.WriteSector(sector, - doneSectors + track.StartSector, - false, - sectorStatus) - : outputFormat.WriteSectors(sector, - doneSectors + track.StartSector, - false, - sectorsToDo, - sectorStatusArray); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - } - - if(!result) - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_writing_sector_1_continuing, - outputFormat.ErrorMessage, - doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_sector_1_not_continuing, - outputFormat.ErrorMessage, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - - doneSectors += sectorsToDo; - } - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_sectors_0_to_1_in_track_2_3_done, - _inputFormat.Info.Sectors, - _inputFormat.Info.Sectors, - tracks.Count, - 1.0); - - Progress2Value = Progress2MaxValue; - }); - - foreach(SectorTagType tag in _inputFormat.Info.ReadableSectorTags.Order() - .TakeWhile(_ => useLong && !_cancel)) - { - switch(tag) - { - case SectorTagType.AppleSonyTag: - case SectorTagType.AppleProfileTag: - case SectorTagType.PriamDataTowerTag: - case SectorTagType.CdSectorSync: - case SectorTagType.CdSectorHeader: - case SectorTagType.CdSectorSubHeader: - case SectorTagType.CdSectorEdc: - case SectorTagType.CdSectorEccP: - case SectorTagType.CdSectorEccQ: - case SectorTagType.CdSectorEcc: - // This tags are inline in long sector - continue; - } - - if(ForceChecked && !outputFormat.SupportedSectorTags.Contains(tag)) continue; - - foreach(Track track in tracks.TakeWhile(_ => !_cancel)) - { - doneSectors = 0; - ulong trackSectors = track.EndSector - track.StartSector + 1; - byte[] sector; - bool result; - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = $"Converting tag {tag} in track {track.Sequence}."; - ProgressValue++; - Progress2Text = ""; - Progress2Indeterminate = false; - Progress2MaxValue = (int)(trackSectors / SectorsValue); - }); - - switch(tag) - { - case SectorTagType.CdTrackFlags: - case SectorTagType.CdTrackIsrc: - - errno = _inputFormat.ReadSectorTag(track.Sequence, false, tag, out sector); - - if(errno == ErrorNumber.NoError) - result = outputFormat.WriteSectorTag(sector, track.Sequence, false, tag); - else - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_media_tag, errno); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_media_tag_not_continuing, - errno), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - - continue; - } - - if(!result) - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_writing_tag_continuing, outputFormat.ErrorMessage); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_tag_not_continuing, - outputFormat - .ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - - continue; - } - - while(doneSectors < trackSectors) - { - if(_cancel) break; - - uint sectorsToDo; - - if(trackSectors - doneSectors >= (ulong)SectorsValue) - sectorsToDo = (uint)SectorsValue; - else - sectorsToDo = (uint)(trackSectors - doneSectors); - - ulong sectors = doneSectors; - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Text = string.Format(UI.Converting_tag_0_for_sectors_1_to_2_in_track_3_4_done, - tag, - sectors + track.StartSector, - sectors + sectorsToDo + track.StartSector, - track.Sequence, - (sectors + track.StartSector) / - (double)_inputFormat.Info.Sectors); - - Progress2Value = (int)(sectors / SectorsValue); - }); - - errno = sectorsToDo == 1 - ? _inputFormat.ReadSectorTag(doneSectors + track.StartSector, - false, - tag, - out sector) - : _inputFormat.ReadSectorsTag(doneSectors + track.StartSector, - false, - sectorsToDo, - tag, - out sector); - - if(errno == ErrorNumber.NoError) - { - result = sectorsToDo == 1 - ? outputFormat.WriteSectorTag(sector, - doneSectors + track.StartSector, - false, - tag) - : outputFormat.WriteSectorsTag(sector, - doneSectors + track.StartSector, - false, - sectorsToDo, - tag); - } - else - { - result = true; - - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_reading_tag_for_sector_1_continuing, errno, doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_reading_tag_for_sector_1_not_continuing, - errno, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - - if(!result) - { - if(ForceChecked) - { - warning = true; - - AaruLogging.Error(UI.Error_0_writing_tag_for_sector_1_continuing, - outputFormat.ErrorMessage, - doneSectors); - } - else - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_writing_tag_for_sector_1_not_continuing, - outputFormat - .ErrorMessage, - doneSectors), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - } - - doneSectors += sectorsToDo; - } - } - } - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - Progress2Visible = false; - Progress2Visible = false; - }); - - bool ret; - - if(_dumpHardware != null && !_cancel) - { - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Writing_dump_hardware_list; - ProgressValue++; - }); - - ret = outputFormat.SetDumpHardware(_dumpHardware); - - if(!ret) - AaruLogging.WriteLine(UI.Error_0_writing_dump_hardware_list_to_output_image, outputFormat.ErrorMessage); - } - - ret = false; - - if(_aaruMetadata != null && !_cancel) - { - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Writing_Aaru_Metadata_to_output_image; - ProgressValue++; - }); - - outputFormat.SetMetadata(_aaruMetadata); - - if(!ret) AaruLogging.WriteLine(UI.Error_0_writing_Aaru_Metadata_to_output_image, outputFormat.ErrorMessage); - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - ProgressText = UI.Closing_output_image; - ProgressIndeterminate = true; - }); + _converter.Start(); if(_cancel) { @@ -1616,20 +437,6 @@ public sealed partial class ImageConvertViewModel : ViewModelBase return; } - if(!outputFormat.Close()) - { - await Dispatcher.UIThread.InvokeAsync(() => MessageBoxManager - .GetMessageBoxStandard(UI.Title_Error, - string - .Format(UI - .Error_0_closing_output_image_Contents_are_not_correct, - outputFormat.ErrorMessage), - icon: Icon.Error) - .ShowWindowDialogAsync(_view)); - - return; - } - await Dispatcher.UIThread.InvokeAsync(async () => { await MessageBoxManager.GetMessageBoxStandard(warning ? UI.Title_Warning : UI.Title_Conversion_success, @@ -1651,144 +458,11 @@ public sealed partial class ImageConvertViewModel : ViewModelBase internal void Stop() { - _cancel = true; + _cancel = true; + _converter.Abort(); StopEnabled = false; } - /* TODO - void OnCmbFormatSelectedIndexChanged() - { - 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; - } - - chkForce.Visible = false; - - foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags) - { - if(plugin.SupportedMediaTags.Contains(mediaTag)) - continue; - - chkForce.Visible = true; - ForceChecked = true; - - break; - } - - foreach(SectorTagType sectorTag in inputFormat.Info.ReadableSectorTags) - { - if(plugin.SupportedSectorTags.Contains(sectorTag)) - continue; - - chkForce.Visible = true; - ForceChecked = true; - - break; - } - - grpOptions.Visible = true; - - var stkImageOptions = 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; - optBooleanChecked = (bool)option.@default; - stkImageOptions.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); - stkImageOptions.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); - stkImageOptions.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); - stkImageOptions.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); - stkImageOptions.Items.Add(stkString); - - break; - } - - grpOptions.Content = stkImageOptions; - } - */ async Task DestinationAsync() { if(SelectedPlugin is null) return; @@ -1890,12 +564,11 @@ public sealed partial class ImageConvertViewModel : ViewModelBase void ResumeFileFromImage() { ResumeFileText = UI._From_image_; - _dumpHardware = _inputFormat.DumpHardware; } async Task ResumeFileAsync() { - _dumpHardware = null; + _resume = null; ResumeFileText = ""; IReadOnlyList result = await _view.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions @@ -1919,7 +592,7 @@ public sealed partial class ImageConvertViewModel : ViewModelBase if(resume?.Tries?.Any() == false) { - _dumpHardware = resume.Tries; + _resume = resume; ResumeFileText = result[0].Path.LocalPath; } else