Files
cuetools.net/CUETools.CDImage/CDImage.cs
chudov 3d94188f92 1) Fixed crash on source files that contain zero length tags
2) Fixed a glitch in filename corrector - it sometimes didn't replace underscores with spaces.
3) Fixed a bug when a broken cue sheet was created if artist, title or genre contained comma character.
3) Added .zip archive support
4) Added support for cue sheets which start with data track (mixed mode or "playstation type" cds)
2009-01-28 04:53:13 +00:00

392 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace CUETools.CDImage
{
public class CDTrackIndex
{
public CDTrackIndex(uint index, uint start)
{
_start = start;
_index = index;
}
public CDTrackIndex(CDTrackIndex src)
{
_start = src._start;
_index = src._index;
}
public uint Start
{
get
{
return _start;
}
set
{
_start = value;
}
}
public uint Index
{
get
{
return _index;
}
}
public string MSF
{
get
{
return CDImageLayout.TimeToString(_start);
}
}
uint _start, _index;
}
public class CDTrack : ICloneable
{
public CDTrack(uint number, uint start, uint length, bool isAudio, bool preEmpasis)
{
_number = number;
_start = start;
_length = length;
_isAudio = isAudio;
_preEmphasis = preEmpasis;
_indexes = new List<CDTrackIndex>();
_indexes.Add(new CDTrackIndex(0, start));
_indexes.Add(new CDTrackIndex(1, start));
}
public CDTrack(CDTrack src)
{
_number = src._number;
_start = src._start;
_length = src._length;
_isAudio = src._isAudio;
_preEmphasis = src._preEmphasis;
_indexes = new List<CDTrackIndex>();
for (int i = 0; i < src._indexes.Count; i++)
_indexes.Add(new CDTrackIndex(src._indexes[i]));
}
public object Clone()
{
return new CDTrack(this);
}
public uint Start
{
get
{
return _start;
}
set
{
_start = value;
}
}
public string StartMSF
{
get
{
return CDImageLayout.TimeToString(_start);
}
}
public uint Length
{
get
{
return _length;
}
set
{
_length = value;
}
}
public string LengthMSF
{
get
{
return CDImageLayout.TimeToString(_length);
}
}
public string ISRC
{
get
{
return _isrc;
}
set
{
_isrc = value;
}
}
public uint End
{
get
{
return _start + _length - 1;
}
}
public string EndMSF
{
get
{
return CDImageLayout.TimeToString(End);
}
}
public uint Number
{
get
{
return _number;
}
}
public uint Pregap
{
get
{
return _start - _indexes[0].Start;
}
}
public CDTrackIndex this[int key]
{
get
{
return _indexes[key];
}
}
public uint LastIndex
{
get
{
return (uint) _indexes.Count - 1;
}
}
public bool IsAudio
{
get
{
return _isAudio;
}
}
public bool PreEmphasis
{
get
{
return _preEmphasis;
}
set
{
_preEmphasis = value;
}
}
public bool DCP
{
get
{
return _dcp;
}
set
{
_dcp = value;
}
}
public void AddIndex(CDTrackIndex index)
{
if (index.Index < 2)
_indexes[(int)index.Index] = index;
else
_indexes.Add(index);
}
IList<CDTrackIndex> _indexes;
string _isrc;
bool _isAudio;
bool _preEmphasis, _dcp;
uint _start;
uint _length;
uint _number;
}
public class CDImageLayout : ICloneable
{
public CDImageLayout()
{
_tracks = new List<CDTrack>();
}
public CDImageLayout(CDImageLayout src)
{
_catalog = src._catalog;
_audioTracks = src._audioTracks;
_firstAudio = src._firstAudio;
_tracks = new List<CDTrack>();
for (int i = 0; i < src.TrackCount; i++)
_tracks.Add(new CDTrack(src._tracks[i]));
}
public object Clone()
{
return new CDImageLayout(this);
}
public uint Length
{
get
{
return TrackCount > 0 ? _tracks[TrackCount - 1].End + 1U : 0U;
}
}
public CDTrack this[int key]
{
get
{
return _tracks[key - 1];
}
}
public int TrackCount
{
get
{
return _tracks.Count;
}
}
public uint Pregap
{
get
{
return _tracks[0].Pregap;
}
}
public uint AudioTracks
{
get
{
return (uint) _audioTracks;
}
}
public int FirstAudio
{
get
{
return _firstAudio + 1;
}
}
public uint AudioLength
{
get
{
return AudioTracks > 0 ? _tracks[_firstAudio + _audioTracks - 1].End + 1U - _tracks[_firstAudio].Start + _tracks[_firstAudio].Pregap : 0U;
}
}
public string Catalog
{
get
{
return _catalog;
}
set
{
_catalog = value;
}
}
public string MusicBrainzId
{
get
{
StringBuilder mbSB = new StringBuilder();
mbSB.AppendFormat("{0:X2}{1:X2}{2:X8}", 1, AudioTracks, _tracks[(int)AudioTracks-1].End + 1 + 150);
for (int iTrack = 0; iTrack < AudioTracks; iTrack++)
mbSB.AppendFormat("{0:X8}", _tracks[iTrack].Start + 150);
mbSB.Append(new string('0', (99 - (int)AudioTracks) * 8));
byte[] hashBytes = (new SHA1CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(mbSB.ToString()));
return Convert.ToBase64String(hashBytes).Replace('+', '.').Replace('/', '_').Replace('=', '-');
}
}
public void AddTrack(CDTrack track)
{
_tracks.Add(track);
if (track.IsAudio)
{
_audioTracks++;
if (!_tracks[_firstAudio].IsAudio)
_firstAudio = _tracks.Count - 1;
}
}
public uint IndexLength(int iTrack, int iIndex)
{
if (iIndex < _tracks[iTrack - 1].LastIndex)
return _tracks[iTrack - 1][iIndex + 1].Start - _tracks[iTrack - 1][iIndex].Start;
if (iTrack < AudioTracks)
return _tracks[iTrack][0].Start - _tracks[iTrack - 1][iIndex].Start;
return _tracks[iTrack - 1].End + 1 - _tracks[iTrack - 1][iIndex].Start;
}
public static int TimeFromString(string s)
{
string[] n = s.Split(':');
if (n.Length != 3)
{
throw new Exception("Invalid timestamp.");
}
int min, sec, frame;
min = Int32.Parse(n[0]);
sec = Int32.Parse(n[1]);
frame = Int32.Parse(n[2]);
return frame + (sec * 75) + (min * 60 * 75);
}
public static string TimeToString(uint t)
{
uint min, sec, frame;
frame = t % 75;
t /= 75;
sec = t % 60;
t /= 60;
min = t;
return String.Format("{0:00}:{1:00}:{2:00}", min, sec, frame);
}
string _catalog;
IList<CDTrack> _tracks;
int _audioTracks;
int _firstAudio;
}
}