Use subchannel, if available, to set ISRC.

This commit is contained in:
2020-05-05 20:26:18 +01:00
parent 06dfb76728
commit fb947e3d5c
6 changed files with 173 additions and 110 deletions

View File

@@ -31,6 +31,7 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Extents;
@@ -83,7 +84,8 @@ namespace Aaru.Core.Devices.Dumping
ref double minSpeed, out bool newTrim, bool nextData, int offsetBytes, bool read6, bool read10,
bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize,
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel)
Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel,
Dictionary<byte, string> isrcs)
{
ulong sectorSpeedStart = 0; // Used to calculate correct speed
DateTime timeSpeedStart = DateTime.UtcNow; // Time of start for speed calculation
@@ -385,15 +387,8 @@ namespace Aaru.Core.Devices.Dumping
_outputPlugin.WriteSectorsLong(data, i + r, 1);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)
sub = Subchannel.ConvertQToRaw(sub);
_outputPlugin.WriteSectorsTag(sub, i + r, 1, SectorTagType.CdSectorSubchannel);
}
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)(i + r), 1);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i + r, 1, subLog,
isrcs, (byte)track.TrackSequence);
}
else
{
@@ -506,15 +501,8 @@ namespace Aaru.Core.Devices.Dumping
_outputPlugin.WriteSectorsLong(data, i, blocksToRead);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)
sub = Subchannel.ConvertQToRaw(sub);
_outputPlugin.WriteSectorsTag(sub, i, blocksToRead, SectorTagType.CdSectorSubchannel);
}
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, blocksToRead);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, blocksToRead, subLog,
isrcs, (byte)track.TrackSequence);
}
else
{

View File

@@ -113,6 +113,7 @@ namespace Aaru.Core.Devices.Dumping
MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel
MmcSubchannel desiredSubchannel; // User requested subchannel
bool bcdSubchannel = false; // Subchannel positioning is in BCD
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
Dictionary<MediaTagType, byte[]> mediaTags = new Dictionary<MediaTagType, byte[]>(); // Media tags
@@ -834,7 +835,7 @@ namespace Aaru.Core.Devices.Dumping
}
// Set ISRCs
// TODO: Use subchannels
if(supportedSubchannel == MmcSubchannel.None)
foreach(Track trk in tracks)
{
sense = _dev.ReadIsrc((byte)trk.TrackSequence, out string isrc, out _, out _, _dev.Timeout, out _);
@@ -844,12 +845,7 @@ namespace Aaru.Core.Devices.Dumping
isrc == "000000000000")
continue;
if(!_outputPlugin.WriteSectorTag(Encoding.ASCII.GetBytes(isrc), trk.TrackStartSector,
SectorTagType.CdTrackIsrc))
continue;
UpdateStatus?.Invoke($"Setting ISRC for track {trk.TrackSequence} to {isrc}");
_dumpLog.WriteLine("Setting ISRC for track {0} to {1}", trk.TrackSequence, isrc);
isrcs[(byte)trk.TrackSequence] = isrc;
}
if(_resume.NextBlock > 0)
@@ -1019,13 +1015,13 @@ namespace Aaru.Core.Devices.Dumping
ref imageWriteDuration, lastSector, leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed,
out newTrim, tracks[0].TrackType != TrackType.Audio, offsetBytes, read6, read10, read12, read16,
readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors, ref totalDuration,
tracks, subLog, desiredSubchannel);
tracks, subLog, desiredSubchannel, isrcs);
// TODO: Enable when underlying images support lead-outs
/*
DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration,
leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd,
supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel);
supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel, isrcs);
*/
end = DateTime.UtcNow;
@@ -1052,10 +1048,10 @@ namespace Aaru.Core.Devices.Dumping
TrimCdUserData(audioExtents, blockSize, currentTry, extents, newTrim, offsetBytes, read6, read10, read12,
read16, readcd, sectorsForOffset, subSize, supportedSubchannel, supportsLongSectors,
ref totalDuration, subLog, desiredSubchannel);
ref totalDuration, subLog, desiredSubchannel, tracks, isrcs);
RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset,
subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel);
subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks, isrcs);
// Write media tags to image
if(!_aborted)
@@ -1102,6 +1098,19 @@ namespace Aaru.Core.Devices.Dumping
if(_preSidecar != null)
_outputPlugin.SetCicmMetadata(_preSidecar);
foreach(KeyValuePair<byte, string> isrc in isrcs)
{
// TODO: Track tags
Track track = tracks.First(t => t.TrackSequence == isrc.Key);
if(!_outputPlugin.WriteSectorTag(Encoding.ASCII.GetBytes(isrc.Value), track.TrackStartSector,
SectorTagType.CdTrackIsrc))
continue;
UpdateStatus?.Invoke($"Setting ISRC for track {isrc.Key} to {isrc.Value}");
_dumpLog.WriteLine("Setting ISRC for track {0} to {1}", isrc.Key, isrc.Value);
}
_dumpLog.WriteLine("Closing output file.");
UpdateStatus?.Invoke("Closing output file.");
DateTime closeStart = DateTime.Now;

View File

@@ -32,12 +32,12 @@
using System;
using System.Collections.Generic;
using Aaru.CommonTypes.Enums;
using System.Linq;
using Aaru.CommonTypes.Extents;
using Aaru.CommonTypes.Structs;
using Aaru.CommonTypes.Structs.Devices.SCSI;
using Aaru.Console;
using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Decoders.SCSI;
using Aaru.Devices;
using Schemas;
@@ -53,7 +53,7 @@ namespace Aaru.Core.Devices.Dumping
void RetryCdUserData(ExtentsULong audioExtents, uint blockSize, DumpHardwareType currentTry,
ExtentsULong extents, int offsetBytes, bool readcd, int sectorsForOffset, uint subSize,
MmcSubchannel supportedSubchannel, ref double totalDuration, SubchannelLog subLog,
MmcSubchannel desiredSubchannel)
MmcSubchannel desiredSubchannel, Track[] tracks, Dictionary<byte, string> isrcs)
{
bool sense = true; // Sense indicator
byte[] cmdBuf = null; // Data buffer
@@ -207,6 +207,9 @@ namespace Aaru.Core.Devices.Dumping
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : ""));
Track track = tracks.OrderBy(t => t.TrackStartSector).
LastOrDefault(t => badSector >= t.TrackStartSector);
byte sectorsToReRead = 1;
uint badSectorToReRead = (uint)badSector;
@@ -281,15 +284,8 @@ namespace Aaru.Core.Devices.Dumping
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
_outputPlugin.WriteSectorLong(data, badSector);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)
sub = Subchannel.ConvertQToRaw(sub);
_outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
}
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs,
(byte)track.TrackSequence);
}
else
{
@@ -364,6 +360,9 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trying to get partial data for sector {badSector}");
Track track = tracks.OrderBy(t => t.TrackStartSector).
LastOrDefault(t => badSector >= t.TrackStartSector);
if(readcd)
{
sense = _dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1,
@@ -387,15 +386,8 @@ namespace Aaru.Core.Devices.Dumping
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
_outputPlugin.WriteSectorLong(data, badSector);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)
sub = Subchannel.ConvertQToRaw(sub);
_outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel);
}
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)badSector, 1);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog,
isrcs, (byte)track.TrackSequence);
}
else
{

View File

@@ -31,6 +31,7 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Extents;
using Aaru.Core.Logging;
@@ -225,7 +226,7 @@ namespace Aaru.Core.Devices.Dumping
ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed,
bool read6, bool read10, bool read12, bool read16, bool readcd,
MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration,
SubchannelLog subLog, MmcSubchannel desiredSubchannel)
SubchannelLog subLog, MmcSubchannel desiredSubchannel, Dictionary<byte, string> isrcs)
{
byte[] cmdBuf = null; // Data buffer
const uint sectorSize = 2352; // Full sector size
@@ -308,6 +309,9 @@ namespace Aaru.Core.Devices.Dumping
_outputPlugin.WriteSectorsLong(data, i, _maximumReadable);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, _maximumReadable,
subLog, isrcs, 0xAA);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)

View File

@@ -30,7 +30,12 @@
// Copyright © 2011-2020 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using Aaru.Checksums;
using Aaru.CommonTypes.Enums;
using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Devices;
// ReSharper disable JoinDeclarationAndInitializer
@@ -60,5 +65,60 @@ namespace Aaru.Core.Devices.Dumping
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.Q16,
dev.Timeout, out _);
}
void WriteSubchannelToImage(MmcSubchannel supportedSubchannel, MmcSubchannel desiredSubchannel, byte[] sub,
ulong sectorAddress, uint length, SubchannelLog subLog,
Dictionary<byte, string> isrcs, byte currentTrack)
{
if(supportedSubchannel == MmcSubchannel.Q16)
sub = Subchannel.ConvertQToRaw(sub);
if(desiredSubchannel != MmcSubchannel.None)
_outputPlugin.WriteSectorsTag(sub, sectorAddress, 1, SectorTagType.CdSectorSubchannel);
subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)sectorAddress, 1);
byte[] deSub = Subchannel.Deinterleave(sub);
// Check subchannel
for(int subPos = 0; subPos < deSub.Length; subPos += 96)
{
// ISRC
if((deSub[subPos + 12] & 0x3) == 3)
{
byte[] q = new byte[12];
Array.Copy(deSub, subPos + 12, q, 0, 12);
string isrc = Subchannel.DecodeIsrc(q);
if(isrc == null ||
isrc == "000000000000")
continue;
if(!isrcs.ContainsKey(currentTrack))
{
_dumpLog?.WriteLine($"Found new ISRC {isrc} for track {currentTrack}.");
UpdateStatus?.Invoke($"Found new ISRC {isrc} for track {currentTrack}.");
}
else if(isrcs[currentTrack] != isrc)
{
CRC16CCITTContext.Data(q, 10, out byte[] crc);
if(crc[0] != q[10] ||
crc[1] != q[11])
{
continue;
}
_dumpLog?.
WriteLine($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");
UpdateStatus?.
Invoke($"ISRC for track {currentTrack} changed from {isrcs[currentTrack]} to {isrc}.");
}
isrcs[currentTrack] = isrc;
}
}
}
}
}

View File

@@ -31,8 +31,11 @@
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Extents;
using Aaru.CommonTypes.Structs;
using Aaru.Core.Logging;
using Aaru.Decoders.CD;
using Aaru.Devices;
@@ -50,7 +53,8 @@ namespace Aaru.Core.Devices.Dumping
ExtentsULong extents, bool newTrim, int offsetBytes, bool read6, bool read10, bool read12,
bool read16, bool readcd, int sectorsForOffset, uint subSize,
MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration,
SubchannelLog subLog, MmcSubchannel desiredSubchannel)
SubchannelLog subLog, MmcSubchannel desiredSubchannel, Track[] tracks,
Dictionary<byte, string> isrcs)
{
DateTime start;
DateTime end;
@@ -110,6 +114,9 @@ namespace Aaru.Core.Devices.Dumping
PulseProgress?.Invoke($"Trimming sector {badSector}");
Track track = tracks.OrderBy(t => t.TrackStartSector).
LastOrDefault(t => badSector >= t.TrackStartSector);
byte sectorsToTrim = 1;
uint badSectorToRead = (uint)badSector;
@@ -180,6 +187,9 @@ namespace Aaru.Core.Devices.Dumping
Array.Copy(cmdBuf, sectorSize, sub, 0, subSize);
_outputPlugin.WriteSectorLong(data, badSector);
WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs,
(byte)track.TrackSequence);
if(desiredSubchannel != MmcSubchannel.None)
{
if(supportedSubchannel == MmcSubchannel.Q16)