Preliminary support for CDTOC tag

This commit is contained in:
Grigory Chudov
2013-04-21 19:52:36 -04:00
parent 6643b4e7f1
commit aecd23d001
3 changed files with 108 additions and 25 deletions

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Globalization;
namespace CUETools.CDImage namespace CUETools.CDImage
{ {
@@ -437,6 +438,21 @@ namespace CUETools.CDImage
} }
} }
public string TAG
{
get
{
StringBuilder mbSB = new StringBuilder();
mbSB.AppendFormat(CultureInfo.InvariantCulture, "{0:X}", AudioTracks);
for (int iTrack = _firstAudio; iTrack < TrackCount; iTrack++)
mbSB.AppendFormat("+{0:X}", _tracks[iTrack].Start + 150);
mbSB.AppendFormat("+{0:X}", Length + 150);
for (int iTrack = 0; iTrack < _firstAudio; iTrack++)
mbSB.AppendFormat("+X{0:X}", _tracks[iTrack].Start + 150);
return mbSB.ToString();
}
}
public static CDImageLayout FromString(string str) public static CDImageLayout FromString(string str)
{ {
var ids = str.Split(':'); var ids = str.Split(':');
@@ -453,6 +469,44 @@ namespace CUETools.CDImage
return new CDImageLayout(trackcount, audiotracks, firstaudio, string.Join(" ", ids)); return new CDImageLayout(trackcount, audiotracks, firstaudio, string.Join(" ", ids));
} }
public static CDImageLayout FromTag(string str)
{
var ids = str.Split('+');
int audiotracks;
int firstaudio = 1;
int trackcount = ids.Length - 2;
int offs;
var ids2 = new List<string>();
if (!int.TryParse(ids[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out audiotracks))
return null;
if (trackcount > audiotracks && ids[ids.Length - 1][0] == 'X')
{
firstaudio = 1 + trackcount - audiotracks;
for (int i = 0; i < trackcount - audiotracks; i++)
{
if (!int.TryParse(ids[i + 2 + audiotracks].Substring(1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offs))
return null;
ids2.Add((offs - 150).ToString());
}
for (int i = 0; i <= audiotracks; i++)
{
if (!int.TryParse(ids[i + 1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offs))
return null;
ids2.Add((offs - 150).ToString());
}
}
else
{
for (int i = 0; i <= trackcount; i++)
{
if (!int.TryParse(ids[i + 1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offs))
return null;
ids2.Add((offs - 150).ToString());
}
}
return new CDImageLayout(trackcount, audiotracks, firstaudio, string.Join(" ", ids2.ToArray()));
}
public override string ToString() public override string ToString()
{ {
StringBuilder mbSB = new StringBuilder(); StringBuilder mbSB = new StringBuilder();

View File

@@ -87,5 +87,8 @@ namespace CUETools.Processor
[DefaultValue(false), Category("Tagging"), DisplayName("Use id3v2.4 instead of id3v2.3")] [DefaultValue(false), Category("Tagging"), DisplayName("Use id3v2.4 instead of id3v2.3")]
public bool UseId3v24 { get; set; } public bool UseId3v24 { get; set; }
[DefaultValue(true), Category("Tagging"), DisplayName("Write CDTOC tag")]
public bool WriteCDTOCTag { get; set; }
} }
} }

View File

@@ -1549,21 +1549,31 @@ namespace CUETools.Processor
} }
} }
if (tocFromLog == null)
{
var tocTag = GetCommonMiscTag("CDTOC");
if (tocTag != null)
{
tocFromLog = CDImageLayout.FromTag(tocTag);
if (tocFromLog != null && tocFromLog.TOCID != _toc.TOCID)
tocFromLog = null;
}
}
// use pregaps from log // use pregaps from log
if (tocFromLog != null) if (tocFromLog != null)
{ {
//int srcNo = (int) _toc[_toc.FirstAudio].LastIndex - (PreGapLength == 0 ? 1 : 0);
if (PreGapLength < tocFromLog.Pregap)
{
PreGapLength = tocFromLog.Pregap;
//srcNo ++;
}
int trNo; int trNo;
for (trNo = 1; trNo < tocFromLog.AudioTracks && trNo < _toc.AudioTracks; trNo++) for (trNo = 0; trNo < tocFromLog.AudioTracks && trNo < _toc.AudioTracks; trNo++)
{ {
if (_toc[_toc.FirstAudio + trNo].Pregap < tocFromLog[tocFromLog.FirstAudio + trNo].Pregap) if (_toc[_toc.FirstAudio + trNo].Pregap < tocFromLog[tocFromLog.FirstAudio + trNo].Pregap)
{
if (_toc.FirstAudio + trNo == 1)
PreGapLength = tocFromLog[tocFromLog.FirstAudio + trNo].Pregap;
else
_toc[_toc.FirstAudio + trNo].Pregap = tocFromLog[tocFromLog.FirstAudio + trNo].Pregap; _toc[_toc.FirstAudio + trNo].Pregap = tocFromLog[tocFromLog.FirstAudio + trNo].Pregap;
} }
}
//if (_toc[_toc.FirstAudio].Length > tocFromLog[tocFromLog.FirstAudio].Length) //if (_toc[_toc.FirstAudio].Length > tocFromLog[tocFromLog.FirstAudio].Length)
//{ //{
// uint offs = _toc[_toc.FirstAudio].Length - tocFromLog[tocFromLog.FirstAudio].Length; // uint offs = _toc[_toc.FirstAudio].Length - tocFromLog[tocFromLog.FirstAudio].Length;
@@ -1613,26 +1623,31 @@ namespace CUETools.Processor
_toc[_toc.TrackCount][0].Start = tocFromLog[_toc.TrackCount].Start; _toc[_toc.TrackCount][0].Start = tocFromLog[_toc.TrackCount].Start;
_toc[_toc.TrackCount][1].Start = tocFromLog[_toc.TrackCount].Start; _toc[_toc.TrackCount][1].Start = tocFromLog[_toc.TrackCount].Start;
} }
if (_toc.TrackCount == _toc.AudioTracks if (_toc.TrackCount == _toc.AudioTracks
&& tocFromLog.TrackCount == tocFromLog.AudioTracks && tocFromLog.TrackCount == tocFromLog.AudioTracks
&& tocFromLog.TrackCount > _toc.TrackCount) && tocFromLog.TrackCount > _toc.TrackCount)
{ {
int dtracks = tocFromLog.TrackCount - _toc.TrackCount; int dtracks = tocFromLog.TrackCount - _toc.TrackCount;
bool matches = true; var toc2 = new CDImageLayout(tocFromLog);
for (int iTrack = 1; iTrack <= _toc.TrackCount; iTrack++)
if (tocFromLog[iTrack + dtracks].Length != _toc[iTrack].Length)
matches = false;
if (matches)
{
for (int iTrack = 1; iTrack <= dtracks; iTrack++) for (int iTrack = 1; iTrack <= dtracks; iTrack++)
toc2[iTrack].IsAudio = false;
toc2.FirstAudio += dtracks;
toc2.AudioTracks -= (uint)dtracks;
if (toc2.TOCID == _toc.TOCID)
tocFromLog = toc2;
}
if (tocFromLog.AudioTracks == _toc.AudioTracks
// && tocFromLog.TOCID == _toc.TOCID
&& _toc.TrackCount == _toc.AudioTracks
&& tocFromLog.FirstAudio > 1
&& tocFromLog.TrackCount == tocFromLog.FirstAudio + tocFromLog.AudioTracks - 1)
{ {
for (int iTrack = 1; iTrack < tocFromLog.FirstAudio; iTrack++)
_toc.InsertTrack(new CDTrack((uint)iTrack, 0, 0, false, false)); _toc.InsertTrack(new CDTrack((uint)iTrack, 0, 0, false, false));
tocFromLog[iTrack].IsAudio = false;
}
tocFromLog.FirstAudio += dtracks;
tocFromLog.AudioTracks -= (uint)dtracks;
}
} }
if (tocFromLog.AudioTracks == _toc.AudioTracks if (tocFromLog.AudioTracks == _toc.AudioTracks
&& tocFromLog.TrackCount == _toc.TrackCount && tocFromLog.TrackCount == _toc.TrackCount
&& tocFromLog.FirstAudio == _toc.FirstAudio && tocFromLog.FirstAudio == _toc.FirstAudio
@@ -3101,6 +3116,9 @@ namespace CUETools.Processor
_arVerify.ExceptionStatus == WebExceptionStatus.Success) _arVerify.ExceptionStatus == WebExceptionStatus.Success)
GenerateAccurateRipTags(destTags, bestOffset, iTrack); GenerateAccurateRipTags(destTags, bestOffset, iTrack);
if (_config.advanced.WriteCDTOCTag)
destTags.Add("CDTOC", _toc.TAG);
return destTags; return destTags;
} }
@@ -4096,6 +4114,7 @@ namespace CUETools.Processor
uint number = 0; uint number = 0;
string album = null; string album = null;
string cueFound = null; string cueFound = null;
CDImageLayout tocFound = null;
TimeSpan dur = TimeSpan.Zero; TimeSpan dur = TimeSpan.Zero;
TagLib.UserDefined.AdditionalFileTypes.Config = _config; TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.File.IFileAbstraction fileAbsraction = new TagLib.File.LocalFileAbstraction(file.FullName); TagLib.File.IFileAbstraction fileAbsraction = new TagLib.File.LocalFileAbstraction(file.FullName);
@@ -4106,7 +4125,10 @@ namespace CUETools.Processor
album = fileInfo.Tag.Album; album = fileInfo.Tag.Album;
number = fileInfo.Tag.Track; number = fileInfo.Tag.Track;
dur = fileInfo.Properties.Duration; dur = fileInfo.Properties.Duration;
cueFound = fmt.allowEmbed ? Tagging.Analyze(fileInfo).Get("CUESHEET") : null; var tags = Tagging.Analyze(fileInfo);
cueFound = fmt.allowEmbed ? tags.Get("CUESHEET") : null;
var toc = tags.Get("CDTOC");
if (toc != null) tocFound = CDImageLayout.FromTag(toc);
} }
catch { } catch { }
if (cueFound != null) if (cueFound != null)
@@ -4117,13 +4139,14 @@ namespace CUETools.Processor
fileGroups.Add(group); fileGroups.Add(group);
continue; continue;
} }
disc = Math.Min(5, Math.Max(1, disc)); disc = Math.Min(50, Math.Max(1, disc));
FileGroupInfo groupFound = null; FileGroupInfo groupFound = null;
foreach (FileGroupInfo fileGroup in fileGroups) foreach (FileGroupInfo fileGroup in fileGroups)
{ {
if (fileGroup.type == FileGroupInfoType.TrackFiles if (fileGroup.type == FileGroupInfoType.TrackFiles
&& fileGroup.discNo == disc && fileGroup.discNo == disc
&& fileGroup.album == album && fileGroup.album == album
&& (fileGroup.TOC == null ? "" : fileGroup.TOC.ToString()) == (tocFound == null ? "" : tocFound.ToString())
&& fileGroup.main.Extension.ToLower() == ext) && fileGroup.main.Extension.ToLower() == ext)
{ {
groupFound = fileGroup; groupFound = fileGroup;
@@ -4135,6 +4158,7 @@ namespace CUETools.Processor
groupFound = new FileGroupInfo(file, FileGroupInfoType.TrackFiles); groupFound = new FileGroupInfo(file, FileGroupInfoType.TrackFiles);
groupFound.discNo = disc; groupFound.discNo = disc;
groupFound.album = album; groupFound.album = album;
groupFound.TOC = tocFound;
groupFound.durations = new Dictionary<FileSystemInfo, TimeSpan>(); groupFound.durations = new Dictionary<FileSystemInfo, TimeSpan>();
fileGroups.Add(groupFound); fileGroups.Add(groupFound);
} }
@@ -4143,7 +4167,9 @@ namespace CUETools.Processor
if (dur != TimeSpan.Zero) groupFound.durations.Add(file, dur); if (dur != TimeSpan.Zero) groupFound.durations.Add(file, dur);
} }
} }
fileGroups.RemoveAll(group => group.type == FileGroupInfoType.TrackFiles && group.files.Count < 2); fileGroups.RemoveAll(group => group.type == FileGroupInfoType.TrackFiles && (
(group.TOC == null && group.files.Count < 2) ||
(group.TOC != null && group.TOC.AudioTracks != group.files.Count)));
// tracks must be sorted according to tracknumer (or filename if missing) // tracks must be sorted according to tracknumer (or filename if missing)
foreach (FileGroupInfo group in fileGroups) foreach (FileGroupInfo group in fileGroups)
if (group.type == FileGroupInfoType.TrackFiles) if (group.type == FileGroupInfoType.TrackFiles)