Add options to fix subchannels on image conversion.

This commit is contained in:
2020-07-14 02:16:53 +01:00
parent f1244d543c
commit 4759a73679
2 changed files with 282 additions and 73 deletions

View File

@@ -36,6 +36,7 @@ using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reactive; using System.Reactive;
using System.Text;
using System.Threading; using System.Threading;
using System.Xml.Serialization; using System.Xml.Serialization;
using Aaru.CommonTypes; using Aaru.CommonTypes;
@@ -45,6 +46,8 @@ using Aaru.CommonTypes.Metadata;
using Aaru.CommonTypes.Structs; using Aaru.CommonTypes.Structs;
using Aaru.Console; using Aaru.Console;
using Aaru.Core; using Aaru.Core;
using Aaru.Core.Media;
using Aaru.Devices;
using Aaru.Gui.Models; using Aaru.Gui.Models;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
@@ -59,30 +62,27 @@ namespace Aaru.Gui.ViewModels.Windows
{ {
public class ImageConvertViewModel : ViewModelBase public class ImageConvertViewModel : ViewModelBase
{ {
readonly Window _view; readonly Window _view;
readonly IMediaImage inputFormat; readonly IMediaImage inputFormat;
bool _cicmXmlFromImageVisible; bool _cicmXmlFromImageVisible;
string _cicmXmlText; string _cicmXmlText;
bool _closeVisible; bool _closeVisible;
string _commentsText; string _commentsText;
bool _commentsVisible; bool _commentsVisible;
string _creatorText; string _creatorText;
bool _creatorVisible;
bool _creatorVisible; bool _destinationEnabled;
bool _destinationEnabled; string _destinationText;
string _destinationText; bool _destinationVisible;
string _driveFirmwareRevisionText;
bool _destinationVisible; bool _driveFirmwareRevisionVisible;
string _driveFirmwareRevisionText; string _driveManufacturerText;
bool _driveFirmwareRevisionVisible; bool _driveManufacturerVisible;
string _driveManufacturerText; string _driveModelText;
bool _driveManufacturerVisible; bool _driveModelVisible;
string _driveModelText; string _driveSerialNumberText;
bool _driveModelVisible; bool _driveSerialNumberVisible;
string _driveSerialNumberText; bool _forceChecked;
bool _driveSerialNumberVisible;
bool _forceChecked;
bool _formatReadOnly; bool _formatReadOnly;
double _lastMediaSequenceValue; double _lastMediaSequenceValue;
bool _lastMediaSequenceVisible; bool _lastMediaSequenceVisible;
@@ -127,49 +127,45 @@ namespace Aaru.Gui.ViewModels.Windows
public ImageConvertViewModel(IMediaImage inputFormat, string imageSource, Window view) public ImageConvertViewModel(IMediaImage inputFormat, string imageSource, Window view)
{ {
_view = view; _view = view;
this.inputFormat = inputFormat; this.inputFormat = inputFormat;
cancel = false; cancel = false;
DestinationCommand = ReactiveCommand.Create(ExecuteDestinationCommand); DestinationCommand = ReactiveCommand.Create(ExecuteDestinationCommand);
CreatorCommand = ReactiveCommand.Create(ExecuteCreatorCommand); CreatorCommand = ReactiveCommand.Create(ExecuteCreatorCommand);
MediaTitleCommand = ReactiveCommand.Create(ExecuteMediaTitleCommand); MediaTitleCommand = ReactiveCommand.Create(ExecuteMediaTitleCommand);
MediaManufacturerCommand = ReactiveCommand.Create(ExecuteMediaManufacturerCommand); MediaManufacturerCommand = ReactiveCommand.Create(ExecuteMediaManufacturerCommand);
MediaModelCommand = ReactiveCommand.Create(ExecuteMediaModelCommand); MediaModelCommand = ReactiveCommand.Create(ExecuteMediaModelCommand);
MediaSerialNumberCommand = ReactiveCommand.Create(ExecuteMediaSerialNumberCommand); MediaSerialNumberCommand = ReactiveCommand.Create(ExecuteMediaSerialNumberCommand);
MediaBarcodeCommand = ReactiveCommand.Create(ExecuteMediaBarcodeCommand); MediaBarcodeCommand = ReactiveCommand.Create(ExecuteMediaBarcodeCommand);
MediaPartNumberCommand = ReactiveCommand.Create(ExecuteMediaPartNumberCommand); MediaPartNumberCommand = ReactiveCommand.Create(ExecuteMediaPartNumberCommand);
MediaSequenceCommand = ReactiveCommand.Create(ExecuteMediaSequenceCommand); MediaSequenceCommand = ReactiveCommand.Create(ExecuteMediaSequenceCommand);
LastMediaSequenceCommand = ReactiveCommand.Create(ExecuteLastMediaSequenceCommand); LastMediaSequenceCommand = ReactiveCommand.Create(ExecuteLastMediaSequenceCommand);
DriveManufacturerCommand = ReactiveCommand.Create(ExecuteDriveManufacturerCommand); DriveManufacturerCommand = ReactiveCommand.Create(ExecuteDriveManufacturerCommand);
DriveModelCommand = ReactiveCommand.Create(ExecuteDriveModelCommand); DriveModelCommand = ReactiveCommand.Create(ExecuteDriveModelCommand);
DriveSerialNumberCommand = ReactiveCommand.Create(ExecuteDriveSerialNumberCommand); DriveSerialNumberCommand = ReactiveCommand.Create(ExecuteDriveSerialNumberCommand);
DriveFirmwareRevisionCommand = ReactiveCommand.Create(ExecuteDriveFirmwareRevisionCommand); DriveFirmwareRevisionCommand = ReactiveCommand.Create(ExecuteDriveFirmwareRevisionCommand);
CommentsCommand = ReactiveCommand.Create(ExecuteCommentsCommand); CommentsCommand = ReactiveCommand.Create(ExecuteCommentsCommand);
CicmXmlFromImageCommand = ReactiveCommand.Create(ExecuteCicmXmlFromImageCommand); CicmXmlFromImageCommand = ReactiveCommand.Create(ExecuteCicmXmlFromImageCommand);
CicmXmlCommand = ReactiveCommand.Create(ExecuteCicmXmlCommand); CicmXmlCommand = ReactiveCommand.Create(ExecuteCicmXmlCommand);
ResumeFileFromImageCommand = ReactiveCommand.Create(ExecuteResumeFileFromImageCommand); ResumeFileFromImageCommand = ReactiveCommand.Create(ExecuteResumeFileFromImageCommand);
ResumeFileCommand = ReactiveCommand.Create(ExecuteResumeFileCommand); ResumeFileCommand = ReactiveCommand.Create(ExecuteResumeFileCommand);
StartCommand = ReactiveCommand.Create(ExecuteStartCommand); StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand); CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
StopCommand = ReactiveCommand.Create(ExecuteStopCommand); StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
SourceText = imageSource;
SourceText = imageSource; CreatorVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Creator);
CreatorVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Creator); MediaTitleVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaTitle);
MediaTitleVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaTitle); CommentsVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Comments);
CommentsVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Comments);
MediaManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaManufacturer); MediaManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaManufacturer);
MediaModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaModel); MediaModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaModel);
MediaSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaSerialNumber); MediaSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaSerialNumber);
MediaBarcodeVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaBarcode); MediaBarcodeVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaBarcode);
MediaPartNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaPartNumber); MediaPartNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaPartNumber);
MediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0; MediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
LastMediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0; LastMediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
DriveManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveManufacturer);
DriveManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveManufacturer); DriveModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveModel);
DriveModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveModel); DriveSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveSerialNumber);
DriveSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveSerialNumber);
DriveFirmwareRevisionVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveFirmwareRevision); DriveFirmwareRevisionVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveFirmwareRevision);
PluginBase plugins = GetPluginBase.Instance; PluginBase plugins = GetPluginBase.Instance;
@@ -1014,6 +1010,47 @@ namespace Aaru.Gui.ViewModels.Windows
Progress2Value = Progress2MaxValue; Progress2Value = Progress2MaxValue;
}); });
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>();
string mcn = null;
HashSet<int> subchannelExtents = new HashSet<int>();
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
Where(t => t == SectorTagType.CdTrackIsrc).OrderBy(t => t))
{
foreach(Track track in inputOptical.Tracks)
{
byte[] isrc = inputFormat.ReadSectorTag(track.TrackSequence, tag);
if(isrc is null)
continue;
isrcs[(byte)track.TrackSequence] = Encoding.UTF8.GetString(isrc);
}
}
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
{
foreach(Track track in inputOptical.Tracks)
{
byte[] flags = inputFormat.ReadSectorTag(track.TrackSequence, tag);
if(flags is null)
continue;
trackFlags[(byte)track.TrackSequence] = 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) foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
{ {
if(!useLong || cancel) if(!useLong || cancel)
@@ -1076,12 +1113,45 @@ namespace Aaru.Gui.ViewModels.Windows
if(sectorsToDo == 1) if(sectorsToDo == 1)
{ {
sector = inputFormat.ReadSectorTag(doneSectors, tag); sector = inputFormat.ReadSectorTag(doneSectors, tag);
result = outputFormat.WriteSectorTag(sector, doneSectors, tag); Track track = tracks.LastOrDefault(t => t.TrackStartSector >= doneSectors);
if(tag == SectorTagType.CdSectorSubchannel &&
track != null)
{
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
MmcSubchannel.Raw, sector, doneSectors, 1, null, isrcs,
(byte)track.TrackSequence, ref mcn, tracks.ToArray(), subchannelExtents, false,
outputFormat, false, false, null, null);
if(indexesChanged)
outputOptical.SetTracks(tracks.ToList());
result = true;
}
else
result = outputFormat.WriteSectorTag(sector, doneSectors, tag);
} }
else else
{ {
sector = inputFormat.ReadSectorsTag(doneSectors, sectorsToDo, tag); sector = inputFormat.ReadSectorsTag(doneSectors, sectorsToDo, tag);
result = outputFormat.WriteSectorsTag(sector, doneSectors, sectorsToDo, tag); Track track = tracks.LastOrDefault(t => t.TrackStartSector >= doneSectors);
if(tag == SectorTagType.CdSectorSubchannel &&
track != null)
{
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
MmcSubchannel.Raw, sector, doneSectors, sectorsToDo, null, isrcs,
(byte)track.TrackSequence, ref mcn, tracks.ToArray(), subchannelExtents, false,
outputFormat, false, false, null, null);
if(indexesChanged)
outputOptical.SetTracks(tracks.ToList());
result = true;
}
else
result = outputFormat.WriteSectorsTag(sector, doneSectors, sectorsToDo, tag);
} }
if(!result) if(!result)
@@ -1118,6 +1188,21 @@ namespace Aaru.Gui.ViewModels.Windows
Progress2Value = Progress2MaxValue; Progress2Value = Progress2MaxValue;
}); });
if(isrcs.Count > 0)
foreach(KeyValuePair<byte, string> isrc in isrcs)
outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
SectorTagType.CdTrackIsrc);
if(trackFlags.Count > 0)
foreach(KeyValuePair<byte, byte> flags in trackFlags)
outputOptical.WriteSectorTag(new[]
{
flags.Value
}, flags.Key, SectorTagType.CdTrackFlags);
if(mcn != null)
outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
} }
} }
else else

View File

@@ -36,6 +36,7 @@ using System.CommandLine;
using System.CommandLine.Invocation; using System.CommandLine.Invocation;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Xml.Serialization; using System.Xml.Serialization;
using Aaru.CommonTypes; using Aaru.CommonTypes;
using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Enums;
@@ -44,6 +45,8 @@ using Aaru.CommonTypes.Metadata;
using Aaru.CommonTypes.Structs; using Aaru.CommonTypes.Structs;
using Aaru.Console; using Aaru.Console;
using Aaru.Core; using Aaru.Core;
using Aaru.Core.Media;
using Aaru.Devices;
using Schemas; using Schemas;
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo; using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
using MediaType = Aaru.CommonTypes.MediaType; using MediaType = Aaru.CommonTypes.MediaType;
@@ -186,6 +189,30 @@ namespace Aaru.Commands.Image
Argument = new Argument<string>(() => null), Required = false Argument = new Argument<string>(() => null), Required = false
}); });
Add(new Option(new[]
{
"--fix-subchannel-position"
}, "Store subchannel according to the sector they describe.")
{
Argument = new Argument<bool>(() => true), Required = false
});
Add(new Option(new[]
{
"--fix-subchannel"
}, "Try to fix subchannel. Implies fixing subchannel position.")
{
Argument = new Argument<bool>(() => false), Required = false
});
Add(new Option(new[]
{
"--fix-subchannel-crc"
}, "If subchannel looks OK but CRC fails, rewrite it. Implies fixing subchannel.")
{
Argument = new Argument<bool>(() => false), Required = false
});
AddArgument(new Argument<string> AddArgument(new Argument<string>
{ {
Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path" Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path"
@@ -204,7 +231,8 @@ namespace Aaru.Commands.Image
string driveSerialNumber, bool force, string inputPath, int lastMediaSequence, string driveSerialNumber, bool force, string inputPath, int lastMediaSequence,
string mediaBarcode, string mediaManufacturer, string mediaModel, string mediaBarcode, string mediaManufacturer, string mediaModel,
string mediaPartNumber, int mediaSequence, string mediaSerialNumber, string mediaTitle, string mediaPartNumber, int mediaSequence, string mediaSerialNumber, string mediaTitle,
string outputPath, string options, string resumeFile, string format, string geometry) string outputPath, string options, string resumeFile, string format, string geometry,
bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc)
{ {
MainClass.PrintCopyright(); MainClass.PrintCopyright();
@@ -214,6 +242,12 @@ namespace Aaru.Commands.Image
if(verbose) if(verbose)
AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine; AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
if(fixSubchannelCrc)
fixSubchannel = true;
if(fixSubchannel)
fixSubchannelPosition = true;
Statistics.AddCommand("convert-image"); Statistics.AddCommand("convert-image");
AaruConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml); AaruConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
@@ -241,6 +275,9 @@ namespace Aaru.Commands.Image
AaruConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath); AaruConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath);
AaruConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile); AaruConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
AaruConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose); AaruConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel-position={0}", fixSubchannelPosition);
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel={0}", fixSubchannel);
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel-crc={0}", fixSubchannelCrc);
Dictionary<string, string> parsedOptions = Core.Options.Parse(options); Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
AaruConsole.DebugWriteLine("Analyze command", "Parsed options:"); AaruConsole.DebugWriteLine("Analyze command", "Parsed options:");
@@ -449,8 +486,8 @@ namespace Aaru.Commands.Image
// Try name // Try name
else else
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format, candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format,
StringComparison. StringComparison.
InvariantCultureIgnoreCase))); InvariantCultureIgnoreCase)));
if(candidates.Count == 0) if(candidates.Count == 0)
{ {
@@ -613,7 +650,7 @@ namespace Aaru.Commands.Image
sectorsToDo = (uint)(trackSectors - doneSectors); sectorsToDo = (uint)(trackSectors - doneSectors);
AaruConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", AaruConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector, doneSectors + track.TrackStartSector,
doneSectors + sectorsToDo + track.TrackStartSector, doneSectors + sectorsToDo + track.TrackStartSector,
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors, (doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
track.TrackSequence); track.TrackSequence);
@@ -690,6 +727,48 @@ namespace Aaru.Commands.Image
AaruConsole.WriteLine(); AaruConsole.WriteLine();
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>();
string mcn = null;
HashSet<int> subchannelExtents = new HashSet<int>();
Track[] tracks = inputOptical.Tracks.ToArray();
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
Where(t => t == SectorTagType.CdTrackIsrc).OrderBy(t => t))
{
foreach(Track track in inputOptical.Tracks)
{
byte[] isrc = inputFormat.ReadSectorTag(track.TrackSequence, tag);
if(isrc is null)
continue;
isrcs[(byte)track.TrackSequence] = Encoding.UTF8.GetString(isrc);
}
}
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
{
foreach(Track track in inputOptical.Tracks)
{
byte[] flags = inputFormat.ReadSectorTag(track.TrackSequence, tag);
if(flags is null)
continue;
trackFlags[(byte)track.TrackSequence] = 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.OrderBy(t => t)) foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t))
{ {
if(!useLong) if(!useLong)
@@ -755,23 +834,53 @@ namespace Aaru.Commands.Image
sectorsToDo = (uint)(trackSectors - doneSectors); sectorsToDo = (uint)(trackSectors - doneSectors);
AaruConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)", AaruConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
doneSectors + track.TrackStartSector, doneSectors + track.TrackStartSector,
doneSectors + sectorsToDo + track.TrackStartSector, doneSectors + sectorsToDo + track.TrackStartSector,
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors, (doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
track.TrackSequence, tag); track.TrackSequence, tag);
if(sectorsToDo == 1) if(sectorsToDo == 1)
{ {
sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag); sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag);
result = outputFormat.WriteSectorTag(sector, doneSectors + track.TrackStartSector, tag);
if(tag == SectorTagType.CdSectorSubchannel)
{
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector, 1, null,
isrcs, (byte)track.TrackSequence, ref mcn, tracks, subchannelExtents,
fixSubchannelPosition, outputFormat, fixSubchannel, fixSubchannelCrc, null,
null);
if(indexesChanged)
outputOptical.SetTracks(tracks.ToList());
result = true;
}
else
result = outputFormat.WriteSectorTag(sector, doneSectors + track.TrackStartSector,
tag);
} }
else else
{ {
sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo, sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
tag); tag);
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector, if(tag == SectorTagType.CdSectorSubchannel)
sectorsToDo, tag); {
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector,
sectorsToDo, null, isrcs, (byte)track.TrackSequence, ref mcn, tracks,
subchannelExtents, fixSubchannelPosition, outputFormat, fixSubchannel,
fixSubchannelCrc, null, null);
if(indexesChanged)
outputOptical.SetTracks(tracks.ToList());
result = true;
}
else
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
sectorsToDo, tag);
} }
if(!result) if(!result)
@@ -810,6 +919,21 @@ namespace Aaru.Commands.Image
AaruConsole.WriteLine(); AaruConsole.WriteLine();
} }
if(isrcs.Count > 0)
foreach(KeyValuePair<byte, string> isrc in isrcs)
outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
SectorTagType.CdTrackIsrc);
if(trackFlags.Count > 0)
foreach(KeyValuePair<byte, byte> flags in trackFlags)
outputOptical.WriteSectorTag(new[]
{
flags.Value
}, flags.Key, SectorTagType.CdTrackFlags);
if(mcn != null)
outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
} }
else else
{ {