diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs b/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs index f7e7c20cf..43726d2a8 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/CdiReady.cs @@ -285,7 +285,7 @@ partial class Dump imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - _opticalDiscSpiral?.PaintSectorGood(i + r); + _mediaGraph?.PaintSectorGood(i + r); } else { @@ -398,9 +398,7 @@ partial class Dump imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - if(_opticalDiscSpiral is not null) - for(ulong p = 0; p < blocksToRead; p++) - _opticalDiscSpiral?.PaintSectorGood(i + p); + _mediaGraph?.PaintSectorsGood(i, blocksToRead); } else { diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs index a93a313fe..af579315a 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs @@ -555,7 +555,7 @@ partial class Dump } } - _opticalDiscSpiral?.PaintSectorGood(i + r); + _mediaGraph?.PaintSectorGood(i + r); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; } @@ -589,7 +589,7 @@ partial class Dump imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - _opticalDiscSpiral?.PaintSectorBad(i + r); + _mediaGraph?.PaintSectorBad(i + r); _resume.BadBlocks.Add(i + r); @@ -718,9 +718,7 @@ partial class Dump } } - if(_opticalDiscSpiral is not null) - for(int p = 0; p < blocksToRead; p++) - _opticalDiscSpiral?.PaintSectorGood(i + (ulong)p); + _mediaGraph?.PaintSectorsGood(i, blocksToRead); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; } diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index 96d4fe842..d100ede26 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -1121,14 +1121,12 @@ sealed partial class Dump if(discSpiralParameters is not null) { - _opticalDiscSpiral = new Spiral((int)_dimensions, (int)_dimensions, discSpiralParameters, blocks); + _mediaGraph = new Spiral((int)_dimensions, (int)_dimensions, discSpiralParameters, blocks); foreach(Tuple e in extents.ToArray()) - for(ulong b = e.Item1; b <= e.Item2; b++) - _opticalDiscSpiral?.PaintSectorGood(b); + _mediaGraph?.PaintSectorsGood(e.Item1, (uint)(e.Item2 - e.Item1 + 2)); - foreach(ulong b in _resume.BadBlocks) - _opticalDiscSpiral?.PaintSectorBad(b); + _mediaGraph?.PaintSectorsBad(_resume.BadBlocks); } } diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs index 4d4fb9119..021783245 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs @@ -339,7 +339,7 @@ partial class Dump { _resume.BadBlocks.Remove(badSector); extents.Add(badSector); - _opticalDiscSpiral?.PaintSectorGood(badSector); + _mediaGraph?.PaintSectorGood(badSector); UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_sector_0_in_pass_1, badSector, pass)); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Tags.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Tags.cs index d931f664a..77266a291 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Tags.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Tags.cs @@ -77,7 +77,7 @@ partial class Dump tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.CD_ATIP, tmpBuf); - _opticalDiscSpiral?.PaintRecordableInformationGood(); + _mediaGraph?.PaintRecordableInformationGood(); } } @@ -111,7 +111,7 @@ partial class Dump tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.CD_PMA, tmpBuf); - _opticalDiscSpiral?.PaintRecordableInformationGood(); + _mediaGraph?.PaintRecordableInformationGood(); } _dumpLog.WriteLine(Localization.Core.Reading_Session_Information); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs index 3c00878c2..dbd090c7b 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs @@ -223,7 +223,7 @@ partial class Dump { _resume.BadBlocks.Remove(badSector); extents.Add(badSector); - _opticalDiscSpiral?.PaintSectorGood(badSector); + _mediaGraph?.PaintSectorGood(badSector); } // Because one block has been partially used to fix the offset diff --git a/Aaru.Core/Devices/Dumping/Dump.cs b/Aaru.Core/Devices/Dumping/Dump.cs index e2a073bf5..d7e002aff 100644 --- a/Aaru.Core/Devices/Dumping/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Dump.cs @@ -41,7 +41,6 @@ using Aaru.CommonTypes; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Metadata; -using Aaru.Core.Graphics; using Aaru.Core.Logging; using Aaru.Database; using Aaru.Devices; @@ -66,9 +65,11 @@ public enum DumpSubchannel public partial class Dump { + readonly bool _createGraph; readonly bool _debug; readonly Device _dev; readonly string _devicePath; + readonly uint _dimensions; readonly bool _doResume; readonly DumpLog _dumpLog; readonly bool _dumpRaw; @@ -96,14 +97,12 @@ public partial class Dump readonly bool _titleKeys; readonly bool _trim; bool _aborted; - readonly bool _createGraph; AaruContext _ctx; // Main database context Database.Models.Device _dbDev; // Device database entry - readonly uint _dimensions; bool _dumpFirstTrackPregap; bool _fixOffset; uint _maximumReadable; // Maximum number of sectors drive can read at once - Spiral _opticalDiscSpiral; + IMediaGraph _mediaGraph; Resume _resume; Sidecar _sidecarClass; uint _skip; @@ -284,15 +283,10 @@ public partial class Dump _resume.LastWriteDate = DateTime.UtcNow; _resume.BadBlocks.Sort(); - if(_createGraph && _opticalDiscSpiral is not null) + if(_createGraph && _mediaGraph is not null) { - foreach(ulong b in _resume.BadBlocks) - _opticalDiscSpiral?.PaintSectorBad(b); - - string spiralFilename = $"{_outputPrefix}.graph.png"; - var spiralFs = new FileStream(spiralFilename, FileMode.Create); - _opticalDiscSpiral.WriteToStream(spiralFs); - spiralFs.Close(); + _mediaGraph?.PaintSectorsBad(_resume.BadBlocks); + _mediaGraph?.WriteTo($"{_outputPrefix}.graph.png"); } if(File.Exists(_outputPrefix + ".resume.xml")) diff --git a/Aaru.Core/Devices/Dumping/Sbc/Data.cs b/Aaru.Core/Devices/Dumping/Sbc/Data.cs index 58126cf9f..4376c4042 100644 --- a/Aaru.Core/Devices/Dumping/Sbc/Data.cs +++ b/Aaru.Core/Devices/Dumping/Sbc/Data.cs @@ -214,10 +214,7 @@ partial class Dump outputFormat.WriteSectors(buffer, i, blocksToRead); imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; extents.Add(i, blocksToRead, true); - - if(_opticalDiscSpiral is not null) - for(int b = 0; b < blocksToRead; b++) - _opticalDiscSpiral.PaintSectorGood(i + (ulong)b); + _mediaGraph?.PaintSectorsGood(i, blocksToRead); } else { diff --git a/Aaru.Core/Devices/Dumping/Sbc/Dump.cs b/Aaru.Core/Devices/Dumping/Sbc/Dump.cs index 8ab2b22f8..ea2bda299 100644 --- a/Aaru.Core/Devices/Dumping/Sbc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Sbc/Dump.cs @@ -716,14 +716,12 @@ partial class Dump if(discSpiralParameters is not null) { - _opticalDiscSpiral = new Spiral((int)_dimensions, (int)_dimensions, discSpiralParameters, blocks); + _mediaGraph = new Spiral((int)_dimensions, (int)_dimensions, discSpiralParameters, blocks); foreach(Tuple e in extents.ToArray()) - for(ulong b = e.Item1; b <= e.Item2; b++) - _opticalDiscSpiral?.PaintSectorGood(b); + _mediaGraph?.PaintSectorsGood(e.Item1, (uint)(e.Item2 - e.Item1 + 1)); - foreach(ulong b in _resume.BadBlocks) - _opticalDiscSpiral?.PaintSectorBad(b); + _mediaGraph?.PaintSectorsBad(_resume.BadBlocks); } } diff --git a/Aaru.Core/Devices/Dumping/Sbc/Error.cs b/Aaru.Core/Devices/Dumping/Sbc/Error.cs index 7c2cceda3..75a6ab0be 100644 --- a/Aaru.Core/Devices/Dumping/Sbc/Error.cs +++ b/Aaru.Core/Devices/Dumping/Sbc/Error.cs @@ -278,7 +278,7 @@ partial class Dump _resume.BadBlocks.Remove(badSector); extents.Add(badSector); outputFormat.WriteSector(buffer, badSector); - _opticalDiscSpiral?.PaintSectorGood(badSector); + _mediaGraph?.PaintSectorGood(badSector); UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_block_0_in_pass_1, badSector, pass)); diff --git a/Aaru.Core/Devices/Dumping/Sbc/Trim.cs b/Aaru.Core/Devices/Dumping/Sbc/Trim.cs index fe19d7d5c..a900be3db 100644 --- a/Aaru.Core/Devices/Dumping/Sbc/Trim.cs +++ b/Aaru.Core/Devices/Dumping/Sbc/Trim.cs @@ -91,7 +91,7 @@ partial class Dump _resume.BadBlocks.Remove(badSector); extents.Add(badSector); outputFormat.WriteSector(buffer, badSector); - _opticalDiscSpiral?.PaintSectorGood(badSector); + _mediaGraph?.PaintSectorGood(badSector); } if(newBlank) diff --git a/Aaru.Core/Graphics/Spiral.cs b/Aaru.Core/Graphics/Spiral.cs index 0ef50485d..3d9abd325 100644 --- a/Aaru.Core/Graphics/Spiral.cs +++ b/Aaru.Core/Graphics/Spiral.cs @@ -34,12 +34,13 @@ using System; using System.Collections.Generic; using System.IO; using Aaru.CommonTypes; +using Aaru.CommonTypes.Interfaces; using SkiaSharp; namespace Aaru.Core.Graphics; // TODO: HD DVD sectors are a guess -public sealed class Spiral +public sealed class Spiral : IMediaGraph { static readonly DiscParameters _cdParameters = new(120, 15, 33, 46, 50, 116, 0, 0, 360000, SKColors.Silver); static readonly DiscParameters _cdRecordableParameters = @@ -279,6 +280,106 @@ public sealed class Spiral public SKBitmap Bitmap { get; } + /// + /// Paints the segment of the spiral that corresponds to the specified sector in green + /// Sector + public void PaintSectorGood(ulong sector) => PaintSector(sector, SKColors.Green); + + /// + /// Paints the segment of the spiral that corresponds to the specified sector in red + /// Sector + public void PaintSectorBad(ulong sector) => PaintSector(sector, SKColors.Red); + + /// + /// Paints the segment of the spiral that corresponds to the specified sector in yellow + /// Sector + public void PaintSectorUnknown(ulong sector) => PaintSector(sector, SKColors.Yellow); + + /// + /// Paints the segment of the spiral that corresponds to the specified sector in gray + /// Sector + public void PaintSectorUndumped(ulong sector) => PaintSector(sector, SKColors.Gray); + + /// + public void PaintSector(ulong sector, byte red, byte green, byte blue, byte opacity = 255) => + PaintSector(sector, new SKColor(red, green, blue, opacity)); + + /// + public void PaintSectorsUndumped(ulong startingSector, uint length) => + PaintSectors(startingSector, length, SKColors.Gray); + + /// + public void PaintSectorsGood(ulong startingSector, uint length) => + PaintSectors(startingSector, length, SKColors.Green); + + /// + public void PaintSectorsBad(ulong startingSector, uint length) => + PaintSectors(startingSector, length, SKColors.Red); + + /// + public void PaintSectorsUnknown(ulong startingSector, uint length) => + PaintSectors(startingSector, length, SKColors.Yellow); + + /// + public void PaintSectors(ulong startingSector, uint length, byte red, byte green, byte blue, byte opacity = 255) => + PaintSectors(startingSector, length, new SKColor(red, green, blue, opacity)); + + /// + public void PaintSectorsUndumped(IEnumerable sectors) => PaintSectors(sectors, SKColors.Gray); + + /// + public void PaintSectorsGood(IEnumerable sectors) => PaintSectors(sectors, SKColors.Green); + + /// + public void PaintSectorsBad(IEnumerable sectors) => PaintSectors(sectors, SKColors.Red); + + /// + public void PaintSectorsUnknown(IEnumerable sectors) => PaintSectors(sectors, SKColors.Yellow); + + /// + public void PaintSectorsUnknown(IEnumerable sectors, byte red, byte green, byte blue, byte opacity = 255) => + PaintSectors(sectors, new SKColor(red, green, blue, opacity)); + + /// + /// Paints the segment of the spiral that corresponds to the information specific to recordable discs in green + public void PaintRecordableInformationGood() + { + if(_recordableInformationPoints is null) + return; + + var path = new SKPath(); + + path.MoveTo(_recordableInformationPoints[0]); + + foreach(SKPoint point in _recordableInformationPoints) + path.LineTo(point); + + _canvas.DrawPath(path, new SKPaint + { + Style = SKPaintStyle.Stroke, + Color = SKColors.Green, + StrokeWidth = 2 + }); + } + + /// + public void WriteTo(string path) + { + using var fs = new FileStream(path, FileMode.Create); + WriteTo(fs); + fs.Close(); + } + + /// + /// Writes the spiral bitmap as a PNG into the specified stream + /// Stream that will receive the spiral bitmap + public void WriteTo(Stream stream) + { + var image = SKImage.FromBitmap(Bitmap); + SKData data = image.Encode(); + data.SaveTo(stream); + } + public static DiscParameters DiscParametersFromMediaType(MediaType mediaType, bool smallDisc = false) => mediaType switch { @@ -359,47 +460,22 @@ public sealed class Spiral _ => null }; - /// Paints the segment of the spiral that corresponds to the specified sector in green - /// Sector - public void PaintSectorGood(ulong sector) => PaintSector(sector, SKColors.Green); - - /// Paints the segment of the spiral that corresponds to the specified sector in red - /// Sector - public void PaintSectorBad(ulong sector) => PaintSector(sector, SKColors.Red); - - /// Paints the segment of the spiral that corresponds to the specified sector in yellow - /// Sector - public void PaintSectorUnknown(ulong sector) => PaintSector(sector, SKColors.Yellow); - - /// Paints the segment of the spiral that corresponds to the specified sector in gray - /// Sector - public void PaintSectorUndumped(ulong sector) => PaintSector(sector, SKColors.Gray); - - /// Paints the segment of the spiral that corresponds to the information specific to recordable discs in green - public void PaintRecordableInformationGood() + void PaintSectors(ulong startingSector, uint length, SKColor color) { - if(_recordableInformationPoints is null) - return; + for(uint i = 0; i < length; i++) + PaintSector(startingSector + i, color); + } - var path = new SKPath(); - - path.MoveTo(_recordableInformationPoints[0]); - - foreach(SKPoint point in _recordableInformationPoints) - path.LineTo(point); - - _canvas.DrawPath(path, new SKPaint - { - Style = SKPaintStyle.Stroke, - Color = SKColors.Green, - StrokeWidth = 2 - }); + void PaintSectors(IEnumerable sectors, SKColor color) + { + foreach(ulong sector in sectors) + PaintSector(sector, color); } /// Paints the segment of the spiral that corresponds to the specified sector in the specified color /// Sector /// Color to paint the segment - public void PaintSector(ulong sector, SKColor color) + void PaintSector(ulong sector, SKColor color) { long pointsPerSector; long sectorsPerPoint; @@ -537,15 +613,6 @@ public sealed class Spiral _canvas.DrawPath(path, paint); } - /// Writes the spiral bitmap as a PNG into the specified stream - /// Stream that will receive the spiral bitmap - public void WriteToStream(Stream stream) - { - var image = SKImage.FromBitmap(Bitmap); - SKData data = image.Encode(); - data.SaveTo(stream); - } - /// Gets all the points that are needed to draw a spiral with the specified parameters /// Center of the spiral start /// Minimum radius before which the spiral must have no points diff --git a/Aaru/Commands/Image/Verify.cs b/Aaru/Commands/Image/Verify.cs index 2718c6383..d83e3c466 100644 --- a/Aaru/Commands/Image/Verify.cs +++ b/Aaru/Commands/Image/Verify.cs @@ -428,13 +428,7 @@ sealed class VerifyCommand : Command AaruConsole.WriteLine($"[italic]{UI.Total_unknowns}[/] {unknownLbas.Count}"); AaruConsole.WriteLine($"[italic]{UI.Total_errors_plus_unknowns}[/] {failingLbas.Count + unknownLbas.Count}"); - if(spiral is not null) - { - string spiralFilename = $"{Path.GetFileNameWithoutExtension(inputFilter.Filename)}.verify.png"; - var spiralFs = new FileStream(spiralFilename, FileMode.Create); - spiral.WriteToStream(spiralFs); - spiralFs.Close(); - } + spiral?.WriteTo($"{Path.GetFileNameWithoutExtension(inputFilter.Filename)}.verify.png"); if(failingLbas.Count > 0) correctSectors = false;