diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs index c0b2b930e..d91468ea0 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs @@ -85,7 +85,7 @@ namespace Aaru.Core.Devices.Dumping bool read12, bool read16, bool readcd, int sectorsForOffset, uint subSize, MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration, Track[] tracks, SubchannelLog subLog, MmcSubchannel desiredSubchannel, - Dictionary isrcs) + Dictionary isrcs, ref string mcn) { ulong sectorSpeedStart = 0; // Used to calculate correct speed DateTime timeSpeedStart = DateTime.UtcNow; // Time of start for speed calculation @@ -388,7 +388,7 @@ namespace Aaru.Core.Devices.Dumping _outputPlugin.WriteSectorsLong(data, i + r, 1); WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i + r, 1, subLog, - isrcs, (byte)track.TrackSequence); + isrcs, (byte)track.TrackSequence, ref mcn); } else { @@ -502,7 +502,7 @@ namespace Aaru.Core.Devices.Dumping _outputPlugin.WriteSectorsLong(data, i, blocksToRead); WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, blocksToRead, subLog, - isrcs, (byte)track.TrackSequence); + isrcs, (byte)track.TrackSequence, ref mcn); } else { diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index 6c7d5558e..40641bcbf 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -114,6 +114,7 @@ namespace Aaru.Core.Devices.Dumping MmcSubchannel desiredSubchannel; // User requested subchannel bool bcdSubchannel = false; // Subchannel positioning is in BCD Dictionary isrcs = new Dictionary(); + string mcn = null; Dictionary mediaTags = new Dictionary(); // Media tags @@ -822,16 +823,19 @@ namespace Aaru.Core.Devices.Dumping } // Set MCN - // TODO: Use subchannels - sense = _dev.ReadMcn(out string mcn, out _, out _, _dev.Timeout, out _); - - if(!sense && - mcn != null && - mcn != "0000000000000" && - _outputPlugin.WriteMediaTag(Encoding.ASCII.GetBytes(mcn), MediaTagType.CD_MCN)) + if(supportedSubchannel == MmcSubchannel.None) { - UpdateStatus?.Invoke($"Setting disc Media Catalogue Number to {mcn}"); - _dumpLog.WriteLine("Setting disc Media Catalogue Number to {0}", mcn); + sense = _dev.ReadMcn(out mcn, out _, out _, _dev.Timeout, out _); + + if(!sense && + mcn != null && + mcn != "0000000000000") + { + UpdateStatus?.Invoke($"Found Media Catalogue Number: {mcn}"); + _dumpLog.WriteLine("Found Media Catalogue Number: {0}", mcn); + } + else + mcn = null; } // Set ISRCs @@ -846,6 +850,9 @@ namespace Aaru.Core.Devices.Dumping continue; isrcs[(byte)trk.TrackSequence] = isrc; + + UpdateStatus?.Invoke($"Found ISRC for track {trk.TrackSequence}: {mcn}"); + _dumpLog.WriteLine($"Found ISRC for track {trk.TrackSequence}: {mcn}"); } if(_resume.NextBlock > 0) @@ -1015,13 +1022,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, isrcs); + tracks, subLog, desiredSubchannel, isrcs, ref mcn); // 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, isrcs); + supportedSubchannel, subSize, ref totalDuration, subLog, desiredSubchannel, isrcs, ref mcn); */ end = DateTime.UtcNow; @@ -1048,10 +1055,11 @@ 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, tracks, isrcs); + ref totalDuration, subLog, desiredSubchannel, tracks, isrcs, ref mcn); RetryCdUserData(audioExtents, blockSize, currentTry, extents, offsetBytes, readcd, sectorsForOffset, - subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks, isrcs); + subSize, supportedSubchannel, ref totalDuration, subLog, desiredSubchannel, tracks, isrcs, + ref mcn); // Write media tags to image if(!_aborted) @@ -1111,6 +1119,13 @@ namespace Aaru.Core.Devices.Dumping _dumpLog.WriteLine("Setting ISRC for track {0} to {1}", isrc.Key, isrc.Value); } + if(mcn != null && + _outputPlugin.WriteMediaTag(Encoding.ASCII.GetBytes(mcn), MediaTagType.CD_MCN)) + { + UpdateStatus?.Invoke($"Setting disc Media Catalogue Number to {mcn}"); + _dumpLog.WriteLine("Setting disc Media Catalogue Number to {0}", mcn); + } + _dumpLog.WriteLine("Closing output file."); UpdateStatus?.Invoke("Closing output file."); DateTime closeStart = DateTime.Now; diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs index 117da5b9d..9434b68c0 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Error.cs @@ -53,7 +53,8 @@ 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, Track[] tracks, Dictionary isrcs) + MmcSubchannel desiredSubchannel, Track[] tracks, Dictionary isrcs, + ref string mcn) { bool sense = true; // Sense indicator byte[] cmdBuf = null; // Data buffer @@ -285,7 +286,7 @@ namespace Aaru.Core.Devices.Dumping _outputPlugin.WriteSectorLong(data, badSector); WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs, - (byte)track.TrackSequence); + (byte)track.TrackSequence, ref mcn); } else { @@ -387,7 +388,7 @@ namespace Aaru.Core.Devices.Dumping _outputPlugin.WriteSectorLong(data, badSector); WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, - isrcs, (byte)track.TrackSequence); + isrcs, (byte)track.TrackSequence, ref mcn); } else { diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs index a63ae1c32..43cb0b933 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/LeadOuts.cs @@ -35,7 +35,6 @@ using System.Collections.Generic; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Extents; using Aaru.Core.Logging; -using Aaru.Decoders.CD; using Aaru.Devices; using Schemas; @@ -72,7 +71,8 @@ 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) + SubchannelLog subLog, MmcSubchannel desiredSubchannel, Dictionary isrcs, + ref string mcn) { byte[] cmdBuf = null; // Data buffer const uint sectorSize = 2352; // Full sector size @@ -154,10 +154,9 @@ namespace Aaru.Core.Devices.Dumping } _outputPlugin.WriteSectorsLong(data, i, _maximumReadable); - _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, SectorTagType.CdSectorSubchannel); - subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, - _maximumReadable); + WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, i, _maximumReadable, + subLog, isrcs, 0xAA, ref mcn); } else _outputPlugin.WriteSectors(cmdBuf, i, _maximumReadable); @@ -226,7 +225,8 @@ 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, Dictionary isrcs) + SubchannelLog subLog, MmcSubchannel desiredSubchannel, Dictionary isrcs, + ref string mcn) { byte[] cmdBuf = null; // Data buffer const uint sectorSize = 2352; // Full sector size @@ -310,19 +310,7 @@ 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) - sub = Subchannel.ConvertQToRaw(sub); - - _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, - SectorTagType.CdSectorSubchannel); - } - - subLog?.WriteEntry(sub, supportedSubchannel == MmcSubchannel.Raw, (long)i, - _maximumReadable); + subLog, isrcs, 0xAA, ref mcn); } else _outputPlugin.WriteSectors(cmdBuf, i, _maximumReadable); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs index 79ae43afa..b537ea8e7 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Subchannel.cs @@ -68,7 +68,7 @@ namespace Aaru.Core.Devices.Dumping void WriteSubchannelToImage(MmcSubchannel supportedSubchannel, MmcSubchannel desiredSubchannel, byte[] sub, ulong sectorAddress, uint length, SubchannelLog subLog, - Dictionary isrcs, byte currentTrack) + Dictionary isrcs, byte currentTrack, ref string mcn) { if(supportedSubchannel == MmcSubchannel.Q16) sub = Subchannel.ConvertQToRaw(sub); @@ -83,11 +83,12 @@ namespace Aaru.Core.Devices.Dumping // Check subchannel for(int subPos = 0; subPos < deSub.Length; subPos += 96) { + byte[] q = new byte[12]; + Array.Copy(deSub, subPos + 12, q, 0, 12); + // ISRC - if((deSub[subPos + 12] & 0x3) == 3) + if((q[0] & 0x3) == 3) { - byte[] q = new byte[12]; - Array.Copy(deSub, subPos + 12, q, 0, 12); string isrc = Subchannel.DecodeIsrc(q); if(isrc == null || @@ -118,6 +119,36 @@ namespace Aaru.Core.Devices.Dumping isrcs[currentTrack] = isrc; } + else if((q[0] & 0x3) == 2) + { + string newMcn = Subchannel.DecodeMcn(q); + + if(newMcn == null || + newMcn == "0000000000000") + continue; + + if(mcn is null) + { + _dumpLog?.WriteLine($"Found new MCN {newMcn}."); + UpdateStatus?.Invoke($"Found new MCN {newMcn}."); + } + else if(mcn != newMcn) + { + CRC16CCITTContext.Data(q, 10, out byte[] crc); + + if(crc[0] != q[10] || + crc[1] != q[11]) + { + continue; + } + + _dumpLog?.WriteLine($"MCN changed from {mcn} to {newMcn}."); + + UpdateStatus?.Invoke($"MCN changed from {mcn} to {newMcn}."); + } + + mcn = newMcn; + } } } } diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs index 0450e4386..b73fe3042 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Trim.cs @@ -54,7 +54,7 @@ namespace Aaru.Core.Devices.Dumping bool read16, bool readcd, int sectorsForOffset, uint subSize, MmcSubchannel supportedSubchannel, bool supportsLongSectors, ref double totalDuration, SubchannelLog subLog, MmcSubchannel desiredSubchannel, Track[] tracks, - Dictionary isrcs) + Dictionary isrcs, ref string mcn) { DateTime start; DateTime end; @@ -188,7 +188,7 @@ namespace Aaru.Core.Devices.Dumping _outputPlugin.WriteSectorLong(data, badSector); WriteSubchannelToImage(supportedSubchannel, desiredSubchannel, sub, badSector, 1, subLog, isrcs, - (byte)track.TrackSequence); + (byte)track.TrackSequence, ref mcn); if(desiredSubchannel != MmcSubchannel.None) {