2017-05-19 20:28:49 +01:00
// /***************************************************************************
2015-12-23 23:46:31 +00:00
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : CDRDAO.cs
2016-07-28 18:13:49 +01:00
// Author(s) : Natalia Portillo <claunia@claunia.com>
2015-12-23 23:46:31 +00:00
//
2016-07-28 18:13:49 +01:00
// Component : Disc image plugins.
2015-12-23 23:46:31 +00:00
//
// --[ Description ] ----------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// Manages cdrdao cuesheets (toc/bin).
2015-12-23 23:46:31 +00:00
//
// --[ License ] --------------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
2015-12-23 23:46:31 +00:00
// License, or (at your option) any later version.
//
2016-07-28 18:13:49 +01:00
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
2015-12-23 23:46:31 +00:00
//
2016-07-28 18:13:49 +01:00
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
2015-12-23 23:46:31 +00:00
//
// ----------------------------------------------------------------------------
2017-05-19 20:28:49 +01:00
// Copyright © 2011-2017 Natalia Portillo
2015-12-23 23:46:31 +00:00
// ****************************************************************************/
2016-07-28 18:13:49 +01:00
2015-12-23 23:46:31 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Text.RegularExpressions ;
using DiscImageChef.Console ;
using DiscImageChef.CommonTypes ;
using System.Text ;
2016-09-05 17:37:31 +01:00
using DiscImageChef.Filters ;
2015-12-23 23:46:31 +00:00
namespace DiscImageChef.ImagePlugins
{
// TODO: Doesn't support compositing from several files
// TODO: Doesn't support silences that are not in files
2017-07-01 02:49:09 +01:00
public class CDRDAO : ImagePlugin
2015-12-23 23:46:31 +00:00
{
#region Internal structures
struct CDRDAOTrackFile
{
/// <summary>Track #</summary>
2016-07-28 22:25:26 +01:00
public uint sequence ;
2016-09-05 17:37:31 +01:00
/// <summary>Filter of file containing track</summary>
public Filter datafilter ;
2015-12-23 23:46:31 +00:00
/// <summary>Path of file containing track</summary>
public string datafile ;
/// <summary>Offset of track start in file</summary>
2016-07-28 22:25:26 +01:00
public ulong offset ;
2015-12-23 23:46:31 +00:00
/// <summary>Type of file</summary>
public string filetype ;
}
struct CDRDAOTrack
{
/// <summary>Track #</summary>
2016-07-28 22:25:26 +01:00
public uint sequence ;
2015-12-23 23:46:31 +00:00
/// <summary>Track title (from CD-Text)</summary>
public string title ;
/// <summary>Track genre (from CD-Text)</summary>
public string genre ;
/// <summary>Track arranger (from CD-Text)</summary>
public string arranger ;
/// <summary>Track composer (from CD-Text)</summary>
public string composer ;
/// <summary>Track performer (from CD-Text)</summary>
public string performer ;
/// <summary>Track song writer (from CD-Text)</summary>
public string songwriter ;
/// <summary>Track ISRC</summary>
public string isrc ;
/// <summary>Disk provider's message (from CD-Text)</summary>
public string message ;
/// <summary>File struct for this track</summary>
public CDRDAOTrackFile trackfile ;
/// <summary>Indexes on this track</summary>
2016-07-28 22:25:26 +01:00
public Dictionary < int , ulong > indexes ;
2015-12-23 23:46:31 +00:00
/// <summary>Track pre-gap in sectors</summary>
2016-07-28 22:25:26 +01:00
public ulong pregap ;
2015-12-23 23:46:31 +00:00
/// <summary>Track post-gap in sectors</summary>
2016-07-28 22:25:26 +01:00
public ulong postgap ;
2015-12-23 23:46:31 +00:00
/// <summary>Digical Copy Permitted</summary>
public bool flag_dcp ;
/// <summary>Track is quadraphonic</summary>
public bool flag_4ch ;
/// <summary>Track has preemphasis</summary>
public bool flag_pre ;
/// <summary>Bytes per sector</summary>
2016-07-28 22:25:26 +01:00
public ushort bps ;
2015-12-23 23:46:31 +00:00
/// <summary>Sectors in track</summary>
2016-07-28 22:25:26 +01:00
public ulong sectors ;
2015-12-23 23:46:31 +00:00
/// <summary>Starting sector in track</summary>
2016-07-28 22:25:26 +01:00
public ulong startSector ;
2015-12-23 23:46:31 +00:00
/// <summary>Track type</summary>
public string tracktype ;
public bool subchannel ;
public bool packedsubchannel ;
}
struct CDRDAODisc
{
/// <summary>Disk title (from CD-Text)</summary>
public string title ;
/// <summary>Disk genre (from CD-Text)</summary>
public string genre ;
/// <summary>Disk arranger (from CD-Text)</summary>
public string arranger ;
/// <summary>Disk composer (from CD-Text)</summary>
public string composer ;
/// <summary>Disk performer (from CD-Text)</summary>
public string performer ;
/// <summary>Disk song writer (from CD-Text)</summary>
public string songwriter ;
/// <summary>Disk provider's message (from CD-Text)</summary>
public string message ;
/// <summary>Media catalog number</summary>
public string mcn ;
/// <summary>Disk type</summary>
2016-01-16 03:54:55 +00:00
public MediaType disktype ;
2015-12-23 23:46:31 +00:00
/// <summary>Disk type string</summary>
public string disktypestr ;
/// <summary>Disk CDDB ID</summary>
public string disk_id ;
/// <summary>Disk UPC/EAN</summary>
public string barcode ;
/// <summary>Tracks</summary>
public List < CDRDAOTrack > tracks ;
/// <summary>Disk comment</summary>
public string comment ;
}
#endregion Internal structures
#region Internal consts
/// <summary>Audio track, 2352 bytes/sector</summary>
const string CDRDAOTrackTypeAudio = "AUDIO" ;
/// <summary>Mode 1 track, cooked, 2048 bytes/sector</summary>
const string CDRDAOTrackTypeMode1 = "MODE1" ;
/// <summary>Mode 1 track, raw, 2352 bytes/sector</summary>
const string CDRDAOTrackTypeMode1Raw = "MODE1_RAW" ;
/// <summary>Mode 2 mixed formless, cooked, 2336 bytes/sector</summary>
const string CDRDAOTrackTypeMode2 = "MODE2" ;
/// <summary>Mode 2 form 1 track, cooked, 2048 bytes/sector</summary>
const string CDRDAOTrackTypeMode2Form1 = "MODE2_FORM1" ;
/// <summary>Mode 2 form 2 track, cooked, 2324 bytes/sector</summary>
const string CDRDAOTrackTypeMode2Form2 = "MODE2_FORM2" ;
/// <summary>Mode 2 mixed forms track, cooked, 2336 bytes/sector</summary>
const string CDRDAOTrackTypeMode2Mix = "MODE2_FORM_MIX" ;
/// <summary>Mode 2 track, raw, 2352 bytes/sector</summary>
const string CDRDAOTrackTypeMode2Raw = "MODE2_RAW" ;
#endregion Internal consts
#region Internal variables
2016-09-05 17:37:31 +01:00
Filter imageFilter ;
2015-12-23 23:46:31 +00:00
StreamReader tocStream ;
2016-09-05 17:37:31 +01:00
Stream imageStream ;
2015-12-23 23:46:31 +00:00
/// <summary>Dictionary, index is track #, value is TrackFile</summary>
2016-07-28 22:25:26 +01:00
Dictionary < uint , ulong > offsetmap ;
List < Partition > partitions ;
2015-12-23 23:46:31 +00:00
CDRDAODisc discimage ;
#endregion
#region Parsing regexs
const string CommentRegEx = "^\\s*\\/{2}(?<comment>.+)$" ;
const string DiskTypeRegEx = "^\\s*(?<type>(CD_DA|CD_ROM_XA|CD_ROM|CD_I))" ;
const string MCNRegEx = "^\\s*CATALOG\\s*\"(?<catalog>[\\d]{13,13})\"" ;
const string TrackRegEx = "^\\s*TRACK\\s*(?<type>(AUDIO|MODE1_RAW|MODE1|MODE2_FORM1|MODE2_FORM2|MODE2_FORM_MIX|MODE2_RAW|MODE2))\\s*(?<subchan>(RW_RAW|RW))?" ;
const string CopyRegEx = "^\\s*(?<no>NO)?\\s*COPY" ;
const string EmphasisRegEx = "^\\s*(?<no>NO)?\\s*PRE_EMPHASIS" ;
const string StereoRegEx = "^\\s*(?<num>(TWO|FOUR))_CHANNEL_AUDIO" ;
const string ISRCRegEx = "^\\s*ISRC\\s*\"(?<isrc>[A-Z0-9]{5,5}[0-9]{7,7})\"" ;
const string IndexRegEx = "^\\s*INDEX\\s*(?<address>\\d+:\\d+:\\d+)" ;
const string PregapRegEx = "^\\s*START\\s*(?<address>\\d+:\\d+:\\d+)?" ;
const string ZeroPregapRegEx = "^\\s*PREGAP\\s*(?<length>\\d+:\\d+:\\d+)" ;
const string ZeroDataRegEx = "^\\s*ZERO\\s*(?<length>\\d+:\\d+:\\d+)" ;
const string ZeroAudioRegEx = "^\\s*SILENCE\\s*(?<length>\\d+:\\d+:\\d+)" ;
const string AudioFileRegEx = "^\\s*(AUDIO)?FILE\\s*\"(?<filename>.+)\"\\s*(#(?<base_offset>\\d+))?\\s*((?<start>[\\d]+:[\\d]+:[\\d]+)|(?<start_num>\\d+))\\s*(?<length>[\\d]+:[\\d]+:[\\d]+)?" ;
const string FileRegEx = "^\\s*DATAFILE\\s*\"(?<filename>.+)\"\\s*(#(?<base_offset>\\d+))?\\s*(?<length>[\\d]+:[\\d]+:[\\d]+)?" ;
// CD-Text
const string TitleRegEx = "^\\s*TITLE\\s*\"(?<title>.+)\"" ;
const string PerformerRegEx = "^\\s*PERFORMER\\s*\"(?<performer>.+)\"" ;
const string SongwriterRegEx = "^\\s*SONGWRITER\\s*\"(?<songwriter>.+)\"" ;
const string ComposerRegEx = "^\\s*COMPOSER\\s*\"(?<composer>.+)\"" ;
const string ArrangerRegEx = "^\\s*ARRANGER\\s*\"(?<arranger>.+)\"" ;
const string MessageRegEx = "^\\s*MESSAGE\\s*\"(?<message>.+)\"" ;
const string DiscIDRegEx = "^\\s*DISC_ID\\s*\"(?<discid>.+)\"" ;
const string UPCRegEx = "^\\s*UPC_EAN\\s*\"(?<catalog>[\\d]{13,13})\"" ;
// Unused
const string CDTextRegEx = "^\\s*CD_TEXT\\s*\\{" ;
const string LanguageRegEx = "^\\s*LANGUAGE\\s*(?<code>\\d+)\\s*\\{" ;
const string ClosureRegEx = "^\\s*\\}" ;
const string LanguageMapRegEx = "^\\s*LANGUAGE_MAP\\s*\\{" ;
const string LanguageMappingRegEx = "^\\s*(?<code>\\d+)\\s?\\:\\s?(?<language>\\d+|\\w+)" ;
#endregion
#region Public methods
public CDRDAO ( )
{
Name = "CDRDAO tocfile" ;
PluginUUID = new Guid ( "04D7BA12-1BE8-44D4-97A4-1B48A505463E" ) ;
ImageInfo = new ImageInfo ( ) ;
ImageInfo . readableSectorTags = new List < SectorTagType > ( ) ;
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags = new List < MediaTagType > ( ) ;
2015-12-23 23:46:31 +00:00
ImageInfo . imageHasPartitions = true ;
ImageInfo . imageHasSessions = true ;
ImageInfo . imageVersion = null ;
ImageInfo . imageApplicationVersion = null ;
ImageInfo . imageName = null ;
ImageInfo . imageCreator = null ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaManufacturer = null ;
ImageInfo . mediaModel = null ;
ImageInfo . mediaPartNumber = null ;
ImageInfo . mediaSequence = 0 ;
ImageInfo . lastMediaSequence = 0 ;
2015-12-23 23:46:31 +00:00
ImageInfo . driveManufacturer = null ;
ImageInfo . driveModel = null ;
ImageInfo . driveSerialNumber = null ;
2016-08-18 00:05:24 +01:00
ImageInfo . driveFirmwareRevision = null ;
2015-12-23 23:46:31 +00:00
}
#endregion Public methods
2016-09-05 17:37:31 +01:00
public override bool IdentifyImage ( Filter imageFilter )
2015-12-23 23:46:31 +00:00
{
try
{
2016-09-05 17:37:31 +01:00
imageFilter . GetDataForkStream ( ) . Seek ( 0 , SeekOrigin . Begin ) ;
2016-09-17 21:23:01 +01:00
byte [ ] testArray = new byte [ 512 ] ;
imageFilter . GetDataForkStream ( ) . Read ( testArray , 0 , 512 ) ;
imageFilter . GetDataForkStream ( ) . Seek ( 0 , SeekOrigin . Begin ) ;
// Check for unexpected control characters that shouldn't be present in a text file and can crash this plugin
2017-08-07 16:07:27 +01:00
bool twoConsecutiveNulls = false ;
for ( int i = 0 ; i < 512 ; i + + )
2016-09-17 21:23:01 +01:00
{
2017-08-07 16:07:27 +01:00
if ( i > = imageFilter . GetDataForkStream ( ) . Length )
break ;
if ( testArray [ i ] = = 0 )
{
if ( twoConsecutiveNulls )
return false ;
twoConsecutiveNulls = true ;
}
else
twoConsecutiveNulls = false ;
if ( testArray [ i ] < 0x20 & & testArray [ i ] ! = 0x0A & & testArray [ i ] ! = 0x0D & & testArray [ i ] ! = 0x00 )
2016-09-17 21:23:01 +01:00
return false ;
}
tocStream = new StreamReader ( imageFilter . GetDataForkStream ( ) ) ;
2015-12-23 23:46:31 +00:00
string _line = tocStream . ReadLine ( ) ;
Regex Dr = new Regex ( DiskTypeRegEx ) ;
Match Dm ;
Dm = Dr . Match ( _line ) ;
return Dm . Success ;
}
2016-04-19 02:11:47 +01:00
catch ( Exception ex )
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
DicConsole . ErrorWriteLine ( "Exception trying to identify image file {0}" , this . imageFilter . GetFilename ( ) ) ;
2015-12-23 23:46:31 +00:00
DicConsole . ErrorWriteLine ( "Exception: {0}" , ex . Message ) ;
DicConsole . ErrorWriteLine ( "Stack trace: {0}" , ex . StackTrace ) ;
return false ;
}
}
#region Not implemented methods
2016-09-05 17:37:31 +01:00
public override bool OpenImage ( Filter imageFilter )
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
if ( imageFilter = = null )
2015-12-23 23:46:31 +00:00
return false ;
2016-09-05 17:37:31 +01:00
if ( imageFilter = = null )
2015-12-23 23:46:31 +00:00
return false ;
2016-09-05 17:37:31 +01:00
this . imageFilter = imageFilter ;
2015-12-23 23:46:31 +00:00
try
{
2016-09-05 17:37:31 +01:00
imageFilter . GetDataForkStream ( ) . Seek ( 0 , SeekOrigin . Begin ) ;
tocStream = new StreamReader ( imageFilter . GetDataForkStream ( ) ) ;
2015-12-23 23:46:31 +00:00
int line = 0 ;
bool intrack = false ;
// Initialize all RegExs
Regex RegexComment = new Regex ( CommentRegEx ) ;
Regex RegexDiskType = new Regex ( DiskTypeRegEx ) ;
Regex RegexMCN = new Regex ( MCNRegEx ) ;
Regex RegexTrack = new Regex ( TrackRegEx ) ;
Regex RegexCopy = new Regex ( CopyRegEx ) ;
Regex RegexEmphasis = new Regex ( EmphasisRegEx ) ;
Regex RegexStereo = new Regex ( StereoRegEx ) ;
Regex RegexISRC = new Regex ( ISRCRegEx ) ;
Regex RegexIndex = new Regex ( IndexRegEx ) ;
Regex RegexPregap = new Regex ( PregapRegEx ) ;
Regex RegexZeroPregap = new Regex ( ZeroPregapRegEx ) ;
Regex RegexZeroData = new Regex ( ZeroDataRegEx ) ;
Regex RegexZeroAudio = new Regex ( ZeroAudioRegEx ) ;
Regex RegexAudioFile = new Regex ( AudioFileRegEx ) ;
Regex RegexFile = new Regex ( FileRegEx ) ;
Regex RegexTitle = new Regex ( TitleRegEx ) ;
Regex RegexPerformer = new Regex ( PerformerRegEx ) ;
Regex RegexSongwriter = new Regex ( SongwriterRegEx ) ;
Regex RegexComposer = new Regex ( ComposerRegEx ) ;
Regex RegexArranger = new Regex ( ArrangerRegEx ) ;
Regex RegexMessage = new Regex ( MessageRegEx ) ;
Regex RegexDiscID = new Regex ( DiscIDRegEx ) ;
Regex RegexUPC = new Regex ( UPCRegEx ) ;
Regex RegexCDText = new Regex ( CDTextRegEx ) ;
Regex RegexLanguage = new Regex ( LanguageRegEx ) ;
Regex RegexClosure = new Regex ( ClosureRegEx ) ;
Regex RegexLanguageMap = new Regex ( LanguageMapRegEx ) ;
Regex RegexLanguageMapping = new Regex ( LanguageMappingRegEx ) ;
// Initialize all RegEx matches
Match MatchComment ;
Match MatchDiskType ;
Match MatchMCN ;
Match MatchTrack ;
Match MatchCopy ;
Match MatchEmphasis ;
Match MatchStereo ;
Match MatchISRC ;
Match MatchIndex ;
Match MatchPregap ;
Match MatchZeroPregap ;
Match MatchZeroData ;
Match MatchZeroAudio ;
Match MatchAudioFile ;
Match MatchFile ;
Match MatchTitle ;
Match MatchPerformer ;
Match MatchSongwriter ;
Match MatchComposer ;
Match MatchArranger ;
Match MatchMessage ;
Match MatchDiscID ;
Match MatchUPC ;
Match MatchCDText ;
Match MatchLanguage ;
Match MatchClosure ;
Match MatchLanguageMap ;
Match MatchLanguageMapping ;
// Initialize disc
discimage = new CDRDAODisc ( ) ;
discimage . tracks = new List < CDRDAOTrack > ( ) ;
discimage . comment = "" ;
CDRDAOTrack currenttrack = new CDRDAOTrack ( ) ;
uint currentTrackNumber = 0 ;
currenttrack . indexes = new Dictionary < int , ulong > ( ) ;
currenttrack . pregap = 0 ;
ulong currentSector = 0 ;
int nextindex = 2 ;
StringBuilder commentBuilder = new StringBuilder ( ) ;
2016-09-05 17:37:31 +01:00
tocStream = new StreamReader ( this . imageFilter . GetDataForkStream ( ) ) ;
2015-12-23 23:46:31 +00:00
string _line = tocStream . ReadLine ( ) ;
MatchDiskType = RegexDiskType . Match ( _line ) ;
2016-04-19 02:11:47 +01:00
if ( ! MatchDiskType . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Not a CDRDAO TOC or TOC type not in first line." ) ;
return false ;
}
2016-09-05 17:37:31 +01:00
tocStream = new StreamReader ( this . imageFilter . GetDataForkStream ( ) ) ;
FiltersList filtersList = new FiltersList ( ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
while ( tocStream . Peek ( ) > = 0 )
2015-12-23 23:46:31 +00:00
{
line + + ;
_line = tocStream . ReadLine ( ) ;
MatchComment = RegexComment . Match ( _line ) ;
MatchDiskType = RegexDiskType . Match ( _line ) ;
MatchMCN = RegexMCN . Match ( _line ) ;
MatchTrack = RegexTrack . Match ( _line ) ;
MatchCopy = RegexCopy . Match ( _line ) ;
MatchEmphasis = RegexEmphasis . Match ( _line ) ;
MatchStereo = RegexStereo . Match ( _line ) ;
MatchISRC = RegexISRC . Match ( _line ) ;
MatchIndex = RegexIndex . Match ( _line ) ;
MatchPregap = RegexPregap . Match ( _line ) ;
MatchZeroPregap = RegexZeroPregap . Match ( _line ) ;
MatchZeroData = RegexZeroData . Match ( _line ) ;
MatchZeroAudio = RegexZeroAudio . Match ( _line ) ;
MatchAudioFile = RegexAudioFile . Match ( _line ) ;
MatchFile = RegexFile . Match ( _line ) ;
MatchTitle = RegexTitle . Match ( _line ) ;
MatchPerformer = RegexPerformer . Match ( _line ) ;
MatchSongwriter = RegexSongwriter . Match ( _line ) ;
MatchComposer = RegexComposer . Match ( _line ) ;
MatchArranger = RegexArranger . Match ( _line ) ;
MatchMessage = RegexMessage . Match ( _line ) ;
MatchDiscID = RegexDiscID . Match ( _line ) ;
MatchUPC = RegexUPC . Match ( _line ) ;
MatchCDText = RegexCDText . Match ( _line ) ;
MatchLanguage = RegexLanguage . Match ( _line ) ;
MatchClosure = RegexClosure . Match ( _line ) ;
MatchLanguageMap = RegexLanguageMap . Match ( _line ) ;
MatchLanguageMapping = RegexLanguageMapping . Match ( _line ) ;
2016-04-19 02:11:47 +01:00
if ( MatchComment . Success )
2015-12-23 23:46:31 +00:00
{
// Ignore "// Track X" comments
2016-04-19 02:11:47 +01:00
if ( ! MatchComment . Groups [ "comment" ] . Value . StartsWith ( " Track " , StringComparison . Ordinal ) )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found comment \"{1}\" at line {0}" , line , MatchComment . Groups [ "comment" ] . Value . Trim ( ) ) ;
commentBuilder . AppendLine ( MatchComment . Groups [ "comment" ] . Value . Trim ( ) ) ;
}
}
2016-04-19 02:11:47 +01:00
else if ( MatchDiskType . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found {1} at line {0}" , line , MatchDiskType . Groups [ "type" ] . Value ) ;
discimage . disktypestr = MatchDiskType . Groups [ "type" ] . Value ;
2016-04-19 02:11:47 +01:00
switch ( MatchDiskType . Groups [ "type" ] . Value )
2015-12-23 23:46:31 +00:00
{
case "CD_DA" :
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . CDDA ;
2015-12-23 23:46:31 +00:00
break ;
case "CD_ROM" :
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . CDROM ;
2015-12-23 23:46:31 +00:00
break ;
case "CD_ROM_XA" :
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . CDROMXA ;
2015-12-23 23:46:31 +00:00
break ;
case "CD_I" :
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . CDI ;
2015-12-23 23:46:31 +00:00
break ;
default :
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . CD ;
2015-12-23 23:46:31 +00:00
break ;
}
}
2016-04-19 02:11:47 +01:00
else if ( MatchMCN . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found CATALOG \"{1}\" at line {0}" , line , MatchMCN . Groups [ "catalog" ] . Value ) ;
discimage . mcn = MatchMCN . Groups [ "catalog" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchTrack . Success )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( MatchTrack . Groups [ "subchan" ] . Value = = "" )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found TRACK type \"{1}\" with no subchannel at line {0}" , line , MatchTrack . Groups [ "type" ] . Value ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found TRACK type \"{1}\" subchannel {2} at line {0}" , line , MatchTrack . Groups [ "type" ] . Value , MatchTrack . Groups [ "subchan" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
{
currentSector + = currenttrack . sectors ;
if ( currenttrack . pregap ! = currenttrack . sectors & & ! currenttrack . indexes . ContainsKey ( 1 ) )
currenttrack . indexes . Add ( 1 , currenttrack . startSector + currenttrack . pregap ) ;
discimage . tracks . Add ( currenttrack ) ;
currenttrack = new CDRDAOTrack ( ) ;
currenttrack . indexes = new Dictionary < int , ulong > ( ) ;
currenttrack . pregap = 0 ;
nextindex = 2 ;
}
currentTrackNumber + + ;
intrack = true ;
2016-04-19 02:11:47 +01:00
switch ( MatchTrack . Groups [ "type" ] . Value )
2015-12-23 23:46:31 +00:00
{
case "AUDIO" :
case "MODE1_RAW" :
case "MODE2_RAW" :
currenttrack . bps = 2352 ;
break ;
case "MODE1" :
case "MODE2_FORM1" :
currenttrack . bps = 2048 ;
break ;
case "MODE2_FORM2" :
currenttrack . bps = 2324 ;
break ;
case "MODE2" :
case "MODE2_FORM_MIX" :
currenttrack . bps = 2336 ;
break ;
default :
2016-07-28 22:25:26 +01:00
throw new NotSupportedException ( string . Format ( "Track mode {0} is unsupported" , MatchTrack . Groups [ "type" ] . Value ) ) ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
switch ( MatchTrack . Groups [ "subchan" ] . Value )
2015-12-23 23:46:31 +00:00
{
case "" :
break ;
case "RW" :
currenttrack . packedsubchannel = true ;
goto case "RW_RAW" ;
case "RW_RAW" :
currenttrack . bps + = 96 ;
currenttrack . subchannel = true ;
break ;
default :
2016-07-28 22:25:26 +01:00
throw new NotSupportedException ( string . Format ( "Track subchannel mode {0} is unsupported" , MatchTrack . Groups [ "subchan" ] . Value ) ) ;
2015-12-23 23:46:31 +00:00
}
currenttrack . tracktype = MatchTrack . Groups [ "type" ] . Value ;
currenttrack . sequence = currentTrackNumber ;
currenttrack . startSector = currentSector ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchCopy . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found {1} COPY at line {0}" , line , MatchCopy . Groups [ "no" ] . Value ) ;
currenttrack . flag_dcp | = intrack & & MatchCopy . Groups [ "no" ] . Value = = "" ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchEmphasis . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found {1} PRE_EMPHASIS at line {0}" , line , MatchEmphasis . Groups [ "no" ] . Value ) ;
currenttrack . flag_pre | = intrack & & MatchCopy . Groups [ "no" ] . Value = = "" ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchStereo . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found {1}_CHANNEL_AUDIO at line {0}" , line , MatchStereo . Groups [ "num" ] . Value ) ;
currenttrack . flag_4ch | = intrack & & MatchCopy . Groups [ "num" ] . Value = = "FOUR" ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchISRC . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found ISRC \"{1}\" at line {0}" , line , MatchISRC . Groups [ "isrc" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . isrc = MatchISRC . Groups [ "isrc" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchIndex . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found INDEX \"{1}\" at line {0}" , line , MatchIndex . Groups [ "address" ] . Value ) ;
string [ ] lengthString = MatchFile . Groups [ "length" ] . Value . Split ( new char [ ] { ':' } ) ;
ulong nextIndexPos = ulong . Parse ( lengthString [ 0 ] ) * 60 * 75 + ulong . Parse ( lengthString [ 1 ] ) * 75 + ulong . Parse ( lengthString [ 2 ] ) ;
currenttrack . indexes . Add ( nextindex , nextIndexPos + currenttrack . pregap + currenttrack . startSector ) ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchPregap . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found START \"{1}\" at line {0}" , line , MatchPregap . Groups [ "address" ] . Value ) ;
currenttrack . indexes . Add ( 0 , currenttrack . startSector ) ;
if ( MatchPregap . Groups [ "address" ] . Value ! = "" )
{
string [ ] lengthString = MatchPregap . Groups [ "address" ] . Value . Split ( new char [ ] { ':' } ) ;
currenttrack . pregap = ulong . Parse ( lengthString [ 0 ] ) * 60 * 75 + ulong . Parse ( lengthString [ 1 ] ) * 75 + ulong . Parse ( lengthString [ 2 ] ) ;
}
else
currenttrack . pregap = currenttrack . sectors ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchZeroPregap . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found PREGAP \"{1}\" at line {0}" , line , MatchZeroPregap . Groups [ "length" ] . Value ) ;
currenttrack . indexes . Add ( 0 , currenttrack . startSector ) ;
string [ ] lengthString = MatchZeroPregap . Groups [ "length" ] . Value . Split ( new char [ ] { ':' } ) ;
currenttrack . pregap = ulong . Parse ( lengthString [ 0 ] ) * 60 * 75 + ulong . Parse ( lengthString [ 1 ] ) * 75 + ulong . Parse ( lengthString [ 2 ] ) ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchZeroData . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found ZERO \"{1}\" at line {0}" , line , MatchZeroData . Groups [ "length" ] . Value ) ;
// Seems can be ignored as the data is still in the image
}
2016-04-19 02:11:47 +01:00
else if ( MatchZeroAudio . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found SILENCE \"{1}\" at line {0}" , line , MatchZeroAudio . Groups [ "length" ] . Value ) ;
// Seems can be ignored as the data is still in the image
}
2016-04-19 02:11:47 +01:00
else if ( MatchAudioFile . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found AUDIOFILE \"{1}\" at line {0}" , line , MatchAudioFile . Groups [ "filename" ] . Value ) ;
currenttrack . trackfile = new CDRDAOTrackFile ( ) ;
2016-09-05 17:37:31 +01:00
currenttrack . trackfile . datafilter = filtersList . GetFilter ( Path . Combine ( imageFilter . GetParentFolder ( ) , MatchAudioFile . Groups [ "filename" ] . Value ) ) ;
2015-12-23 23:46:31 +00:00
currenttrack . trackfile . datafile = MatchAudioFile . Groups [ "filename" ] . Value ;
currenttrack . trackfile . offset = MatchAudioFile . Groups [ "base_offset" ] . Value ! = "" ? ulong . Parse ( MatchAudioFile . Groups [ "base_offset" ] . Value ) : 0 ;
currenttrack . trackfile . filetype = "BINARY" ;
currenttrack . trackfile . sequence = currentTrackNumber ;
ulong startSectors = 0 ;
2016-08-08 18:44:08 +01:00
if ( MatchAudioFile . Groups [ "start" ] . Value ! = "" )
2015-12-23 23:46:31 +00:00
{
string [ ] startString = MatchAudioFile . Groups [ "start" ] . Value . Split ( new char [ ] { ':' } ) ;
startSectors = ulong . Parse ( startString [ 0 ] ) * 60 * 75 + ulong . Parse ( startString [ 1 ] ) * 75 + ulong . Parse ( startString [ 2 ] ) ;
}
currenttrack . trackfile . offset + = ( startSectors * currenttrack . bps ) ;
2016-08-08 18:44:08 +01:00
if ( MatchAudioFile . Groups [ "length" ] . Value ! = "" )
2015-12-23 23:46:31 +00:00
{
string [ ] lengthString = MatchAudioFile . Groups [ "length" ] . Value . Split ( new char [ ] { ':' } ) ;
currenttrack . sectors = ulong . Parse ( lengthString [ 0 ] ) * 60 * 75 + ulong . Parse ( lengthString [ 1 ] ) * 75 + ulong . Parse ( lengthString [ 2 ] ) ;
}
else
2016-09-05 17:37:31 +01:00
currenttrack . sectors = ( ( ulong ) currenttrack . trackfile . datafilter . GetDataForkLength ( ) - currenttrack . trackfile . offset ) / currenttrack . bps ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
else if ( MatchFile . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found DATAFILE \"{1}\" at line {0}" , line , MatchFile . Groups [ "filename" ] . Value ) ;
currenttrack . trackfile = new CDRDAOTrackFile ( ) ;
2016-09-05 17:37:31 +01:00
currenttrack . trackfile . datafilter = filtersList . GetFilter ( Path . Combine ( imageFilter . GetParentFolder ( ) , MatchAudioFile . Groups [ "filename" ] . Value ) ) ;
currenttrack . trackfile . datafile = MatchAudioFile . Groups [ "filename" ] . Value ;
2015-12-23 23:46:31 +00:00
currenttrack . trackfile . offset = MatchFile . Groups [ "base_offset" ] . Value ! = "" ? ulong . Parse ( MatchFile . Groups [ "base_offset" ] . Value ) : 0 ;
currenttrack . trackfile . filetype = "BINARY" ;
currenttrack . trackfile . sequence = currentTrackNumber ;
2016-04-19 02:11:47 +01:00
if ( MatchFile . Groups [ "length" ] . Value ! = "" )
2015-12-23 23:46:31 +00:00
{
string [ ] lengthString = MatchFile . Groups [ "length" ] . Value . Split ( new char [ ] { ':' } ) ;
currenttrack . sectors = ulong . Parse ( lengthString [ 0 ] ) * 60 * 75 + ulong . Parse ( lengthString [ 1 ] ) * 75 + ulong . Parse ( lengthString [ 2 ] ) ;
}
else
2016-09-05 17:37:31 +01:00
currenttrack . sectors = ( ( ulong ) currenttrack . trackfile . datafilter . GetDataForkLength ( ) - currenttrack . trackfile . offset ) / currenttrack . bps ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
else if ( MatchTitle . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found TITLE \"{1}\" at line {0}" , line , MatchTitle . Groups [ "title" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . title = MatchTitle . Groups [ "title" ] . Value ;
else
discimage . title = MatchTitle . Groups [ "title" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchPerformer . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found PERFORMER \"{1}\" at line {0}" , line , MatchPerformer . Groups [ "performer" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . performer = MatchPerformer . Groups [ "performer" ] . Value ;
else
discimage . performer = MatchPerformer . Groups [ "performer" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchSongwriter . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found SONGWRITER \"{1}\" at line {0}" , line , MatchSongwriter . Groups [ "songwriter" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . songwriter = MatchSongwriter . Groups [ "songwriter" ] . Value ;
else
discimage . songwriter = MatchSongwriter . Groups [ "songwriter" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchComposer . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found COMPOSER \"{1}\" at line {0}" , line , MatchComposer . Groups [ "composer" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . composer = MatchComposer . Groups [ "composer" ] . Value ;
else
discimage . composer = MatchComposer . Groups [ "composer" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchArranger . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found ARRANGER \"{1}\" at line {0}" , line , MatchArranger . Groups [ "arranger" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . arranger = MatchArranger . Groups [ "arranger" ] . Value ;
else
discimage . arranger = MatchArranger . Groups [ "arranger" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchMessage . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found MESSAGE \"{1}\" at line {0}" , line , MatchMessage . Groups [ "message" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( intrack )
2015-12-23 23:46:31 +00:00
currenttrack . message = MatchMessage . Groups [ "message" ] . Value ;
else
discimage . message = MatchMessage . Groups [ "message" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchDiscID . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found DISC_ID \"{1}\" at line {0}" , line , MatchDiscID . Groups [ "discid" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( ! intrack )
2015-12-23 23:46:31 +00:00
discimage . disk_id = MatchDiscID . Groups [ "discid" ] . Value ;
}
2016-04-19 02:11:47 +01:00
else if ( MatchUPC . Success )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Found UPC_EAN \"{1}\" at line {0}" , line , MatchUPC . Groups [ "catalog" ] . Value ) ;
2016-04-19 02:11:47 +01:00
if ( ! intrack )
2015-12-23 23:46:31 +00:00
discimage . barcode = MatchUPC . Groups [ "catalog" ] . Value ;
}
// Ignored fields
2016-04-19 02:11:47 +01:00
else if ( MatchCDText . Success | | MatchLanguage . Success | | MatchClosure . Success | |
MatchLanguageMap . Success | | MatchLanguageMapping . Success )
2015-12-23 23:46:31 +00:00
{
}
2016-04-19 02:11:47 +01:00
else if ( _line = = "" ) // Empty line, ignore it
2015-12-23 23:46:31 +00:00
{
}
// TODO: Regex CD-TEXT SIZE_INFO
/ *
else // Non-empty unknown field
{
2016-07-28 22:25:26 +01:00
throw new FeatureUnsupportedImageException ( string . Format ( "Found unknown field defined at line {0}: \"{1}\"" , line , _line ) ) ;
2015-12-23 23:46:31 +00:00
}
* /
}
2016-04-19 02:11:47 +01:00
if ( currenttrack . sequence ! = 0 )
2015-12-23 23:46:31 +00:00
{
if ( currenttrack . pregap ! = currenttrack . sectors & & ! currenttrack . indexes . ContainsKey ( 1 ) )
currenttrack . indexes . Add ( 1 , currenttrack . startSector + currenttrack . pregap ) ;
2016-04-19 02:11:47 +01:00
2015-12-23 23:46:31 +00:00
discimage . tracks . Add ( currenttrack ) ;
}
discimage . comment = commentBuilder . ToString ( ) ;
// DEBUG information
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Disc image parsing results" ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Disc CD-TEXT:" ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . arranger = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tArranger is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tArranger: {0}" , discimage . arranger ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . composer = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tComposer is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tComposer: {0}" , discimage . composer ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . performer = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPerformer is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPerformer: {0}" , discimage . performer ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . songwriter = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tSongwriter is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tSongwriter: {0}" , discimage . songwriter ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . title = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tTitle is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tTitle: {0}" , discimage . title ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Disc information:" ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tGuessed disk type: {0}" , discimage . disktype ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . barcode = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tBarcode not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tBarcode: {0}" , discimage . barcode ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . disk_id = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tDisc ID not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tDisc ID: {0}" , discimage . disk_id ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . mcn = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tMCN not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tMCN: {0}" , discimage . mcn ) ;
2016-04-19 02:11:47 +01:00
if ( string . IsNullOrEmpty ( discimage . comment ) )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tComment not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tComment: \"{0}\"" , discimage . comment ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Track information:" ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tDisc contains {0} tracks" , discimage . tracks . Count ) ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < discimage . tracks . Count ; i + + )
2015-12-23 23:46:31 +00:00
{
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tTrack {0} information:" , discimage . tracks [ i ] . sequence ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\t{0} bytes per sector" , discimage . tracks [ i ] . bps ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tPregap: {0} sectors" , discimage . tracks [ i ] . pregap ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tData: {0} sectors starting at sector {1}" , discimage . tracks [ i ] . sectors , discimage . tracks [ i ] . startSector ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tPostgap: {0} sectors" , discimage . tracks [ i ] . postgap ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . flag_4ch )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTrack is flagged as quadraphonic" ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . flag_dcp )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTrack allows digital copy" ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . flag_pre )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTrack has pre-emphasis applied" ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTrack resides in file {0}, type defined as {1}, starting at byte {2}" ,
2016-09-05 17:37:31 +01:00
discimage . tracks [ i ] . trackfile . datafilter , discimage . tracks [ i ] . trackfile . filetype , discimage . tracks [ i ] . trackfile . offset ) ;
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tIndexes:" ) ;
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < int , ulong > kvp in discimage . tracks [ i ] . indexes )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\t\tIndex {0} starts at sector {1}" , kvp . Key , kvp . Value ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . isrc = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tISRC is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tISRC: {0}" , discimage . tracks [ i ] . isrc ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . arranger = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tArranger is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tArranger: {0}" , discimage . tracks [ i ] . arranger ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . composer = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tComposer is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tComposer: {0}" , discimage . tracks [ i ] . composer ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . performer = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tPerformer is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tPerformer: {0}" , discimage . tracks [ i ] . performer ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . songwriter = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tSongwriter is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tSongwriter: {0}" , discimage . tracks [ i ] . songwriter ) ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . title = = null )
2015-12-23 23:46:31 +00:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTitle is not set." ) ;
else
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\t\tTitle: {0}" , discimage . tracks [ i ] . title ) ;
}
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Building offset map" ) ;
partitions = new List < Partition > ( ) ;
offsetmap = new Dictionary < uint , ulong > ( ) ;
ulong byte_offset = 0 ;
ulong partitionSequence = 0 ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < discimage . tracks . Count ; i + + )
2015-12-23 23:46:31 +00:00
{
ulong index0_len = 0 ;
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . sequence = = 1 & & i ! = 0 )
2015-12-23 23:46:31 +00:00
throw new ImageNotSupportedException ( "Unordered tracks" ) ;
Partition partition = new Partition ( ) ;
// Index 01
2017-07-19 16:37:11 +01:00
partition . Description = string . Format ( "Track {0}." , discimage . tracks [ i ] . sequence ) ;
partition . Name = discimage . tracks [ i ] . title ;
partition . Start = discimage . tracks [ i ] . startSector ;
partition . Size = ( discimage . tracks [ i ] . sectors - index0_len ) * discimage . tracks [ i ] . bps ;
partition . Length = ( discimage . tracks [ i ] . sectors - index0_len ) ;
partition . Sequence = partitionSequence ;
partition . Offset = byte_offset ;
partition . Type = discimage . tracks [ i ] . tracktype ;
byte_offset + = partition . Size ;
2015-12-23 23:46:31 +00:00
partitionSequence + + ;
2016-04-19 02:11:47 +01:00
if ( ! offsetmap . ContainsKey ( discimage . tracks [ i ] . sequence ) )
2017-07-19 16:37:11 +01:00
offsetmap . Add ( discimage . tracks [ i ] . sequence , partition . Start ) ;
2015-12-23 23:46:31 +00:00
else
{
ulong old_start ;
offsetmap . TryGetValue ( discimage . tracks [ i ] . sequence , out old_start ) ;
2017-07-19 16:37:11 +01:00
if ( partition . Start < old_start )
2015-12-23 23:46:31 +00:00
{
offsetmap . Remove ( discimage . tracks [ i ] . sequence ) ;
2017-07-19 16:37:11 +01:00
offsetmap . Add ( discimage . tracks [ i ] . sequence , partition . Start ) ;
2015-12-23 23:46:31 +00:00
}
}
partitions . Add ( partition ) ;
partition = new Partition ( ) ;
}
// Print partition map
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "printing partition map" ) ;
2016-04-19 02:11:47 +01:00
foreach ( Partition partition in partitions )
2015-12-23 23:46:31 +00:00
{
2017-07-19 16:37:11 +01:00
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "Partition sequence: {0}" , partition . Sequence ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition name: {0}" , partition . Name ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition description: {0}" , partition . Description ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition type: {0}" , partition . Type ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition starting sector: {0}" , partition . Start ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition sectors: {0}" , partition . Length ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition starting offset: {0}" , partition . Offset ) ;
DicConsole . DebugWriteLine ( "CDRDAO plugin" , "\tPartition size in bytes: {0}" , partition . Size ) ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
ImageInfo . imageSize + = track . bps * track . sectors ;
ImageInfo . sectors + = track . sectors ;
}
2016-04-19 02:11:47 +01:00
if ( discimage . disktype = = MediaType . CDG | | discimage . disktype = = MediaType . CDEG | | discimage . disktype = = MediaType . CDMIDI )
2015-12-23 23:46:31 +00:00
ImageInfo . sectorSize = 2448 ; // CD+G subchannels ARE user data, as CD+G are useless without them
2016-04-19 02:11:47 +01:00
else if ( discimage . disktype ! = MediaType . CDROMXA & & discimage . disktype ! = MediaType . CDDA & & discimage . disktype ! = MediaType . CDI & & discimage . disktype ! = MediaType . CDPLUS )
2015-12-23 23:46:31 +00:00
ImageInfo . sectorSize = 2048 ; // Only data tracks
else
ImageInfo . sectorSize = 2352 ; // All others
2016-04-19 02:11:47 +01:00
if ( discimage . mcn ! = null )
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags . Add ( MediaTagType . CD_MCN ) ;
2015-12-23 23:46:31 +00:00
ImageInfo . imageApplication = "CDRDAO" ;
2016-09-05 17:37:31 +01:00
ImageInfo . imageCreationTime = imageFilter . GetCreationTime ( ) ;
ImageInfo . imageLastModificationTime = imageFilter . GetLastWriteTime ( ) ;
2015-12-23 23:46:31 +00:00
ImageInfo . imageComments = discimage . comment ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaSerialNumber = discimage . mcn ;
ImageInfo . mediaBarcode = discimage . barcode ;
ImageInfo . mediaType = discimage . disktype ;
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDTrackFlags ) ;
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( track . subchannel )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSubchannel ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSubchannel ) ;
}
2016-04-19 02:11:47 +01:00
switch ( track . tracktype )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeAudio :
{
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDTrackISRC ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDTrackISRC ) ;
break ;
}
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
{
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSubHeader ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSubHeader ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorEDC ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorEDC ) ;
break ;
}
case CDRDAOTrackTypeMode2Raw :
{
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSync ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSync ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorHeader ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorHeader ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSubHeader ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSubHeader ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorEDC ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorEDC ) ;
break ;
}
case CDRDAOTrackTypeMode1Raw :
{
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSync ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSync ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorHeader ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorHeader ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorSubHeader ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorSubHeader ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorECC ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorECC ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorECC_P ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorECC_P ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorECC_Q ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorECC_Q ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDSectorEDC ) )
2015-12-23 23:46:31 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDSectorEDC ) ;
break ;
}
}
}
ImageInfo . xmlMediaType = XmlMediaType . OpticalDisc ;
2016-08-21 17:35:35 +01:00
DicConsole . VerboseWriteLine ( "CDRDAO image describes a disc of type {0}" , ImageInfo . mediaType ) ;
if ( ! string . IsNullOrEmpty ( ImageInfo . imageComments ) )
DicConsole . VerboseWriteLine ( "CDRDAO comments: {0}" , ImageInfo . imageComments ) ;
2015-12-23 23:46:31 +00:00
return true ;
}
2016-04-19 02:11:47 +01:00
catch ( Exception ex )
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
DicConsole . ErrorWriteLine ( "Exception trying to identify image file {0}" , imageFilter ) ;
2015-12-23 23:46:31 +00:00
DicConsole . ErrorWriteLine ( "Exception: {0}" , ex . Message ) ;
DicConsole . ErrorWriteLine ( "Stack trace: {0}" , ex . StackTrace ) ;
return false ;
}
}
public override bool ImageHasPartitions ( )
{
return ImageInfo . imageHasPartitions ;
}
2016-07-28 22:25:26 +01:00
public override ulong GetImageSize ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageSize ;
}
2016-07-28 22:25:26 +01:00
public override ulong GetSectors ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . sectors ;
}
2016-07-28 22:25:26 +01:00
public override uint GetSectorSize ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . sectorSize ;
}
2016-01-16 03:54:55 +00:00
public override byte [ ] ReadDiskTag ( MediaTagType tag )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
case MediaTagType . CD_MCN :
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( discimage . mcn ! = null )
2015-12-23 23:46:31 +00:00
{
return Encoding . ASCII . GetBytes ( discimage . mcn ) ;
}
throw new FeatureNotPresentImageException ( "Image does not contain MCN information." ) ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Feature not supported by image format" ) ;
}
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress )
2015-12-23 23:46:31 +00:00
{
return ReadSectors ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , SectorTagType tag )
2015-12-23 23:46:31 +00:00
{
return ReadSectorsTag ( sectorAddress , 1 , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress , uint track )
2015-12-23 23:46:31 +00:00
{
return ReadSectors ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , uint track , SectorTagType tag )
2015-12-23 23:46:31 +00:00
{
return ReadSectorsTag ( sectorAddress , 1 , track , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = kvp . Key )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < cdrdao_track . sectors )
2015-12-23 23:46:31 +00:00
return ReadSectors ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , string . Format ( "Sector address {0} not found" , sectorAddress ) ) ;
2015-12-23 23:46:31 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , SectorTagType tag )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = kvp . Key )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < cdrdao_track . sectors )
2015-12-23 23:46:31 +00:00
return ReadSectorsTag ( ( sectorAddress - kvp . Value ) , length , kvp . Key , tag ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , string . Format ( "Sector address {0} not found" , sectorAddress ) ) ;
2015-12-23 23:46:31 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length , uint track )
2015-12-23 23:46:31 +00:00
{
CDRDAOTrack _track = new CDRDAOTrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = track )
2015-12-23 23:46:31 +00:00
{
_track = cdrdao_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
if ( length > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-23 23:46:31 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode2Form1 :
{
sector_offset = 0 ;
sector_size = 2048 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode2Form2 :
{
sector_offset = 0 ;
sector_size = 2324 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
{
sector_offset = 0 ;
sector_size = 2336 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeAudio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode1Raw :
{
sector_offset = 16 ;
sector_size = 2048 ;
sector_skip = 288 ;
break ;
}
case CDRDAOTrackTypeMode2Raw :
{
sector_offset = 16 ;
sector_size = 2336 ;
sector_skip = 0 ;
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
2016-04-19 02:11:47 +01:00
if ( _track . subchannel )
2015-12-23 23:46:31 +00:00
sector_skip + = 96 ;
byte [ ] buffer = new byte [ sector_size * length ] ;
2016-09-05 17:37:31 +01:00
imageStream = _track . trackfile . datafilter . GetDataForkStream ( ) ;
BinaryReader br = new BinaryReader ( imageStream ) ;
br . BaseStream . Seek ( ( long ) _track . trackfile . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
if ( sector_offset = = 0 & & sector_skip = = 0 )
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
2015-12-23 23:46:31 +00:00
}
}
return buffer ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , uint track , SectorTagType tag )
2015-12-23 23:46:31 +00:00
{
CDRDAOTrack _track = new CDRDAOTrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = track )
2015-12-23 23:46:31 +00:00
{
_track = cdrdao_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
if ( length > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-23 23:46:31 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip = 0 ;
2016-04-19 02:11:47 +01:00
if ( ! _track . subchannel & & tag = = SectorTagType . CDSectorSubchannel )
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "No tags in image for requested track" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
switch ( tag )
2015-12-23 23:46:31 +00:00
{
case SectorTagType . CDSectorECC :
case SectorTagType . CDSectorECC_P :
case SectorTagType . CDSectorECC_Q :
case SectorTagType . CDSectorEDC :
case SectorTagType . CDSectorHeader :
case SectorTagType . CDSectorSubchannel :
case SectorTagType . CDSectorSubHeader :
case SectorTagType . CDSectorSync :
break ;
case SectorTagType . CDTrackFlags :
{
byte [ ] flags = new byte [ 1 ] ;
2016-04-19 02:11:47 +01:00
if ( _track . tracktype ! = CDRDAOTrackTypeAudio )
2015-12-23 23:46:31 +00:00
flags [ 0 ] + = 0x40 ;
2016-04-19 02:11:47 +01:00
if ( _track . flag_dcp )
2015-12-23 23:46:31 +00:00
flags [ 0 ] + = 0x20 ;
2016-04-19 02:11:47 +01:00
if ( _track . flag_pre )
2015-12-23 23:46:31 +00:00
flags [ 0 ] + = 0x10 ;
2016-04-19 02:11:47 +01:00
if ( _track . flag_4ch )
2015-12-23 23:46:31 +00:00
flags [ 0 ] + = 0x80 ;
return flags ;
}
case SectorTagType . CDTrackISRC :
return Encoding . UTF8 . GetBytes ( _track . isrc ) ;
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode2Form1 :
2016-04-19 02:11:47 +01:00
if ( tag = = SectorTagType . CDSectorSubchannel )
2015-12-23 23:46:31 +00:00
{
sector_offset = 2048 ;
sector_size = 96 ;
break ;
}
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "No tags in image for requested track" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
case CDRDAOTrackTypeMode2Form2 :
case CDRDAOTrackTypeMode2Mix :
2016-04-19 02:11:47 +01:00
if ( tag = = SectorTagType . CDSectorSubchannel )
2015-12-23 23:46:31 +00:00
{
sector_offset = 2336 ;
sector_size = 96 ;
break ;
}
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "No tags in image for requested track" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
case CDRDAOTrackTypeAudio :
2016-04-19 02:11:47 +01:00
if ( tag = = SectorTagType . CDSectorSubchannel )
2015-12-23 23:46:31 +00:00
{
sector_offset = 2352 ;
sector_size = 96 ;
break ;
}
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "No tags in image for requested track" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
case CDRDAOTrackTypeMode1Raw :
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2015-12-23 23:46:31 +00:00
{
case SectorTagType . CDSectorSync :
{
sector_offset = 0 ;
sector_size = 12 ;
sector_skip = 2340 ;
break ;
}
case SectorTagType . CDSectorHeader :
{
sector_offset = 12 ;
sector_size = 4 ;
sector_skip = 2336 ;
break ;
}
case SectorTagType . CDSectorSubchannel :
{
sector_offset = 2352 ;
sector_size = 96 ;
break ;
}
case SectorTagType . CDSectorSubHeader :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
case SectorTagType . CDSectorECC :
{
sector_offset = 2076 ;
sector_size = 276 ;
sector_skip = 0 ;
break ;
}
case SectorTagType . CDSectorECC_P :
{
sector_offset = 2076 ;
sector_size = 172 ;
sector_skip = 104 ;
break ;
}
case SectorTagType . CDSectorECC_Q :
{
sector_offset = 2248 ;
sector_size = 104 ;
sector_skip = 0 ;
break ;
}
case SectorTagType . CDSectorEDC :
{
sector_offset = 2064 ;
sector_size = 4 ;
sector_skip = 284 ;
break ;
}
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2015-12-23 23:46:31 +00:00
}
break ;
}
case CDRDAOTrackTypeMode2Raw : // Requires reading sector
if ( tag = = SectorTagType . CDSectorSubchannel )
{
sector_offset = 2352 ;
sector_size = 96 ;
break ;
}
throw new FeatureSupportedButNotImplementedImageException ( "Feature not yet implemented" ) ;
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
byte [ ] buffer = new byte [ sector_size * length ] ;
2016-09-05 17:37:31 +01:00
imageStream = _track . trackfile . datafilter . GetDataForkStream ( ) ;
BinaryReader br = new BinaryReader ( imageStream ) ;
br . BaseStream . Seek ( ( long ) _track . trackfile . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
if ( sector_offset = = 0 & & sector_skip = = 0 )
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-23 23:46:31 +00:00
{
2016-09-05 17:37:31 +01:00
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
2015-12-23 23:46:31 +00:00
}
}
return buffer ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress )
2015-12-23 23:46:31 +00:00
{
return ReadSectorsLong ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress , uint track )
2015-12-23 23:46:31 +00:00
{
return ReadSectorsLong ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = kvp . Key )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < cdrdao_track . sectors )
2015-12-23 23:46:31 +00:00
return ReadSectorsLong ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , "Sector address not found" ) ;
2015-12-23 23:46:31 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length , uint track )
2015-12-23 23:46:31 +00:00
{
CDRDAOTrack _track = new CDRDAOTrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdrdao_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
if ( cdrdao_track . sequence = = track )
2015-12-23 23:46:31 +00:00
{
_track = cdrdao_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
if ( length > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-23 23:46:31 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode2Form1 :
{
sector_offset = 0 ;
sector_size = 2048 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode2Form2 :
{
sector_offset = 0 ;
sector_size = 2324 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
{
sector_offset = 0 ;
sector_size = 2336 ;
sector_skip = 0 ;
break ;
}
case CDRDAOTrackTypeMode1Raw :
case CDRDAOTrackTypeMode2Raw :
case CDRDAOTrackTypeAudio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
2016-04-19 02:11:47 +01:00
if ( _track . subchannel )
2015-12-23 23:46:31 +00:00
sector_skip + = 96 ;
byte [ ] buffer = new byte [ sector_size * length ] ;
2016-09-05 17:37:31 +01:00
imageStream = _track . trackfile . datafilter . GetDataForkStream ( ) ;
2015-12-23 23:46:31 +00:00
BinaryReader br = new BinaryReader ( imageStream ) ;
br . BaseStream . Seek ( ( long ) _track . trackfile . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2015-12-23 23:46:31 +00:00
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-23 23:46:31 +00:00
{
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
}
}
return buffer ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageFormat ( )
2015-12-23 23:46:31 +00:00
{
return "CDRDAO tocfile" ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageVersion ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageVersion ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageApplication ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageApplication ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageApplicationVersion ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageApplicationVersion ;
}
public override DateTime GetImageCreationTime ( )
{
return ImageInfo . imageCreationTime ;
}
public override DateTime GetImageLastModificationTime ( )
{
return ImageInfo . imageLastModificationTime ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageComments ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageComments ;
}
2016-01-16 03:54:55 +00:00
public override string GetMediaSerialNumber ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaSerialNumber ;
2015-12-23 23:46:31 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaBarcode ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaBarcode ;
2015-12-23 23:46:31 +00:00
}
2016-01-16 03:54:55 +00:00
public override MediaType GetMediaType ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaType ;
2015-12-23 23:46:31 +00:00
}
public override List < Partition > GetPartitions ( )
{
return partitions ;
}
public override List < Track > GetTracks ( )
{
List < Track > tracks = new List < Track > ( ) ;
2016-04-19 02:11:47 +01:00
foreach ( CDRDAOTrack cdr_track in discimage . tracks )
2015-12-23 23:46:31 +00:00
{
Track _track = new Track ( ) ;
_track . Indexes = cdr_track . indexes ;
_track . TrackDescription = cdr_track . title ;
2016-04-19 02:11:47 +01:00
if ( ! cdr_track . indexes . TryGetValue ( 0 , out _track . TrackStartSector ) )
2015-12-23 23:46:31 +00:00
cdr_track . indexes . TryGetValue ( 1 , out _track . TrackStartSector ) ;
_track . TrackStartSector = cdr_track . startSector ;
_track . TrackEndSector = _track . TrackStartSector + cdr_track . sectors - 1 ;
_track . TrackPregap = cdr_track . pregap ;
_track . TrackSession = 1 ;
_track . TrackSequence = cdr_track . sequence ;
_track . TrackType = CDRDAOTrackTypeToTrackType ( cdr_track . tracktype ) ;
2016-09-05 17:37:31 +01:00
_track . TrackFilter = cdr_track . trackfile . datafilter ;
_track . TrackFile = cdr_track . trackfile . datafilter . GetFilename ( ) ;
2015-12-23 23:46:31 +00:00
_track . TrackFileOffset = cdr_track . trackfile . offset ;
_track . TrackFileType = cdr_track . trackfile . filetype ;
_track . TrackRawBytesPerSector = cdr_track . bps ;
_track . TrackBytesPerSector = CDRDAOTrackTypeToCookedBytesPerSector ( cdr_track . tracktype ) ;
2016-04-19 02:11:47 +01:00
if ( cdr_track . subchannel )
2015-12-23 23:46:31 +00:00
{
_track . TrackSubchannelType = cdr_track . packedsubchannel ? TrackSubchannelType . PackedInterleaved : TrackSubchannelType . RawInterleaved ;
2016-09-05 17:37:31 +01:00
_track . TrackSubchannelFilter = cdr_track . trackfile . datafilter ;
_track . TrackSubchannelFile = cdr_track . trackfile . datafilter . GetFilename ( ) ;
2015-12-23 23:46:31 +00:00
_track . TrackSubchannelOffset = cdr_track . trackfile . offset ;
}
else
_track . TrackSubchannelType = TrackSubchannelType . None ;
tracks . Add ( _track ) ;
}
return tracks ;
}
public override List < Track > GetSessionTracks ( Session session )
{
return GetSessionTracks ( session . SessionSequence ) ;
}
public override List < Track > GetSessionTracks ( ushort session )
{
2016-04-19 02:11:47 +01:00
if ( session = = 1 )
2015-12-23 23:46:31 +00:00
return GetTracks ( ) ;
throw new ImageNotSupportedException ( "Session does not exist in disc image" ) ;
}
public override List < Session > GetSessions ( )
{
// TODO
throw new NotImplementedException ( ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress )
2015-12-23 23:46:31 +00:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress , uint track )
2015-12-23 23:46:31 +00:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress , track ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2015-12-23 23:46:31 +00:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-23 23:46:31 +00:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2015-12-23 23:46:31 +00:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2015-12-23 23:46:31 +00:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2015-12-23 23:46:31 +00:00
return false ;
return true ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , uint track , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2015-12-23 23:46:31 +00:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length , track ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2015-12-23 23:46:31 +00:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-23 23:46:31 +00:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2015-12-23 23:46:31 +00:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2015-12-23 23:46:31 +00:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2015-12-23 23:46:31 +00:00
return false ;
return true ;
}
2016-01-16 03:54:55 +00:00
public override bool? VerifyMediaImage ( )
2015-12-23 23:46:31 +00:00
{
return null ;
}
#endregion
#region Private methods
2016-07-28 22:25:26 +01:00
static ushort CDRDAOTrackTypeToBytesPerSector ( string trackType )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
switch ( trackType )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode2Form1 :
return 2048 ;
case CDRDAOTrackTypeMode2Form2 :
return 2324 ;
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
return 2336 ;
case CDRDAOTrackTypeAudio :
case CDRDAOTrackTypeMode1Raw :
case CDRDAOTrackTypeMode2Raw :
return 2352 ;
default :
return 0 ;
}
}
2016-07-28 22:25:26 +01:00
static ushort CDRDAOTrackTypeToCookedBytesPerSector ( string trackType )
2015-12-23 23:46:31 +00:00
{
2016-04-19 02:11:47 +01:00
switch ( trackType )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode2Form1 :
case CDRDAOTrackTypeMode1Raw :
return 2048 ;
case CDRDAOTrackTypeMode2Form2 :
return 2324 ;
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
case CDRDAOTrackTypeMode2Raw :
return 2336 ;
case CDRDAOTrackTypeAudio :
return 2352 ;
default :
return 0 ;
}
}
static TrackType CDRDAOTrackTypeToTrackType ( string trackType )
{
2016-04-19 02:11:47 +01:00
switch ( trackType )
2015-12-23 23:46:31 +00:00
{
case CDRDAOTrackTypeMode1 :
case CDRDAOTrackTypeMode1Raw :
return TrackType . CDMode1 ;
case CDRDAOTrackTypeMode2Form1 :
return TrackType . CDMode2Form1 ;
case CDRDAOTrackTypeMode2Form2 :
return TrackType . CDMode2Form2 ;
case CDRDAOTrackTypeMode2 :
case CDRDAOTrackTypeMode2Mix :
case CDRDAOTrackTypeMode2Raw :
return TrackType . CDMode2Formless ;
case CDRDAOTrackTypeAudio :
return TrackType . Audio ;
default :
return TrackType . Data ;
}
}
#endregion
#region Unsupported features
2016-04-19 02:11:47 +01:00
public override int GetMediaSequence ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaSequence ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
public override int GetLastDiskSequence ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . lastMediaSequence ;
2015-12-23 23:46:31 +00:00
}
public override string GetDriveManufacturer ( )
{
return ImageInfo . driveManufacturer ;
}
public override string GetDriveModel ( )
{
return ImageInfo . driveModel ;
}
public override string GetDriveSerialNumber ( )
{
return ImageInfo . driveSerialNumber ;
}
2016-01-16 03:54:55 +00:00
public override string GetMediaPartNumber ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaPartNumber ;
2015-12-23 23:46:31 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaManufacturer ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaManufacturer ;
2015-12-23 23:46:31 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaModel ( )
2015-12-23 23:46:31 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaModel ;
2015-12-23 23:46:31 +00:00
}
2016-04-19 02:11:47 +01:00
public override string GetImageName ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageName ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageCreator ( )
2015-12-23 23:46:31 +00:00
{
return ImageInfo . imageCreator ;
}
#endregion
}
}