2008-12-07 23:38:00 +00:00
// ****************************************************************************
//
// CUE Tools
// Copyright (C) 2006-2007 Moitah (moitah@yahoo.com)
2010-02-08 01:29:31 +00:00
// Copyright (C) 2008-2010 Gregory S. Chudov (gchudov@gmail.com)
2008-12-07 23:38:00 +00:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// ****************************************************************************
using System ;
2009-08-06 13:03:02 +00:00
using System.ComponentModel ;
2008-12-09 07:25:48 +00:00
using System.Collections ;
2008-12-07 23:38:00 +00:00
using System.Collections.Generic ;
using System.Collections.Specialized ;
using System.Text ;
using System.Globalization ;
using System.IO ;
using System.Net ;
2010-02-06 23:17:07 +00:00
using System.Security.Policy ;
2008-12-07 23:38:00 +00:00
using System.Security.Cryptography ;
using System.Threading ;
using System.Xml ;
2009-05-01 15:16:26 +00:00
using System.Drawing ;
using System.Drawing.Drawing2D ;
using System.Drawing.Imaging ;
2010-02-06 23:17:07 +00:00
using System.Reflection ;
using System.Runtime.InteropServices ;
2008-12-07 23:38:00 +00:00
using CUETools.Codecs ;
using CUETools.CDImage ;
using CUETools.AccurateRip ;
2010-02-23 15:15:08 +00:00
//using CUETools.CDRepair;
using CUETools.CTDB ;
2010-02-08 01:29:31 +00:00
using CUETools.Ripper ;
using CUETools.Compression ;
2008-12-09 07:25:48 +00:00
using MusicBrainz ;
2009-01-17 04:09:38 +00:00
using Freedb ;
2009-05-01 15:16:26 +00:00
using CSScriptLibrary ;
2008-12-07 23:38:00 +00:00
namespace CUETools.Processor
{
2009-05-01 15:16:26 +00:00
public enum AudioEncoderType
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
Lossless ,
Hybrid ,
Lossy ,
/// <summary>
/// No Audio
/// </summary>
2009-02-19 04:09:59 +00:00
NoAudio ,
2008-12-07 23:38:00 +00:00
}
2009-03-22 16:59:05 +00:00
public enum CUEAction
2008-12-09 07:25:48 +00:00
{
2009-08-08 16:14:06 +00:00
Encode = 0 ,
Verify = 1 ,
CreateDummyCUE = 2 ,
CorrectFilenames = 3
2008-12-09 07:25:48 +00:00
}
public enum CUEStyle
{
2009-05-01 15:16:26 +00:00
/// <summary>
/// Single file with embedded CUE
/// </summary>
2008-12-09 07:25:48 +00:00
SingleFileWithCUE ,
2009-05-01 15:16:26 +00:00
/// <summary>
/// Single file with external CUE
/// </summary>
2008-12-09 07:25:48 +00:00
SingleFile ,
2009-05-01 15:16:26 +00:00
/// <summary>
/// Gaps prepended file-per-track
/// </summary>
2008-12-09 07:25:48 +00:00
GapsPrepended ,
2009-05-01 15:16:26 +00:00
/// <summary>
/// Gaps appended (noncompliant) file-per-track
/// </summary>
2008-12-09 07:25:48 +00:00
GapsAppended ,
2009-05-01 15:16:26 +00:00
/// <summary>
/// Gaps left out file-per-track
/// </summary>
2008-12-09 07:25:48 +00:00
GapsLeftOut
}
2008-12-07 23:38:00 +00:00
public static class General {
public static CUELine FindCUELine ( List < CUELine > list , string command ) {
command = command . ToUpper ( ) ;
foreach ( CUELine line in list ) {
if ( line . Params [ 0 ] . ToUpper ( ) = = command ) {
return line ;
}
}
return null ;
}
public static CUELine FindCUELine ( List < CUELine > list , string command , string command2 )
{
command = command . ToUpper ( ) ;
command2 = command2 . ToUpper ( ) ;
foreach ( CUELine line in list )
{
if ( line . Params . Count > 1 & & line . Params [ 0 ] . ToUpper ( ) = = command & & line . Params [ 1 ] . ToUpper ( ) = = command2 )
{
return line ;
}
}
return null ;
}
2009-01-17 04:09:38 +00:00
//public static CUELine FindCUELine(List<CUELine> list, string [] commands)
//{
// foreach (CUELine line in list)
// {
// if (line.Params.Count < commands.Length)
// continue;
// for (int i = 0; i < commands.Length; i++)
// {
// if (line.Params[i].ToUpper() != commands[i].ToUpper())
// break;
// if (i == commands.Length - 1)
// return line;
// }
// }
// return null;
//}
2008-12-07 23:38:00 +00:00
public static void SetCUELine ( List < CUELine > list , string command , string value , bool quoted )
{
CUELine line = General . FindCUELine ( list , command ) ;
if ( line = = null )
{
line = new CUELine ( ) ;
line . Params . Add ( command ) ; line . IsQuoted . Add ( false ) ;
2008-12-09 07:25:48 +00:00
line . Params . Add ( value ) ; line . IsQuoted . Add ( quoted ) ;
2008-12-07 23:38:00 +00:00
list . Add ( line ) ;
}
else
{
2009-03-22 16:59:05 +00:00
while ( line . Params . Count > 1 )
{
line . Params . RemoveAt ( 1 ) ;
line . IsQuoted . RemoveAt ( 1 ) ;
}
line . Params . Add ( value ) ; line . IsQuoted . Add ( quoted ) ;
2008-12-07 23:38:00 +00:00
}
}
public static void SetCUELine ( List < CUELine > list , string command , string command2 , string value , bool quoted )
{
CUELine line = General . FindCUELine ( list , command , command2 ) ;
if ( line = = null )
{
line = new CUELine ( ) ;
line . Params . Add ( command ) ; line . IsQuoted . Add ( false ) ;
line . Params . Add ( command2 ) ; line . IsQuoted . Add ( false ) ;
2008-12-09 07:25:48 +00:00
line . Params . Add ( value ) ; line . IsQuoted . Add ( quoted ) ;
2008-12-07 23:38:00 +00:00
list . Add ( line ) ;
}
else
{
2009-03-22 16:59:05 +00:00
while ( line . Params . Count > 2 )
{
line . Params . RemoveAt ( 2 ) ;
line . IsQuoted . RemoveAt ( 2 ) ;
}
line . Params . Add ( value ) ; line . IsQuoted . Add ( quoted ) ;
2008-12-07 23:38:00 +00:00
}
}
2009-01-17 04:09:38 +00:00
public static void DelCUELine ( List < CUELine > list , string command , string command2 )
{
CUELine line = General . FindCUELine ( list , command , command2 ) ;
if ( line = = null )
return ;
list . Remove ( line ) ;
}
public static void DelCUELine ( List < CUELine > list , string command )
{
CUELine line = General . FindCUELine ( list , command ) ;
if ( line = = null )
return ;
list . Remove ( line ) ;
}
2009-06-24 19:40:23 +00:00
class TitleFormatFunctionInfo
{
public string func ;
public List < int > positions ;
public List < bool > found ;
public TitleFormatFunctionInfo ( string _func , int position )
{
func = _func ;
positions = new List < int > ( ) ;
found = new List < bool > ( ) ;
NextArg ( position ) ;
}
public void Found ( )
{
found [ found . Count - 1 ] = true ;
}
public void NextArg ( int position )
{
positions . Add ( position ) ;
found . Add ( false ) ;
}
public string GetArg ( StringBuilder sb , int no )
{
return sb . ToString ( ) . Substring ( positions [ no ] ,
( ( no = = positions . Count - 1 ) ? sb . Length : positions [ no + 1 ] ) - positions [ no ] ) ;
}
public int GetIntArg ( StringBuilder sb , int no )
{
int res ;
return int . TryParse ( GetArg ( sb , no ) , out res ) ? res : 0 ;
}
void Returns ( StringBuilder sb , string res )
{
sb . Length = positions [ 0 ] ;
sb . Append ( res ) ;
}
public bool Finalise ( StringBuilder sb )
{
switch ( func )
{
case "[" :
if ( positions . Count ! = 1 )
return false ;
if ( ! found [ 0 ] )
sb . Length = positions [ 0 ] ;
return true ;
case "if" :
if ( positions . Count ! = 3 )
return false ;
Returns ( sb , GetArg ( sb , found [ 0 ] ? 1 : 2 ) ) ;
return true ;
case "if2" :
if ( positions . Count ! = 2 )
return false ;
Returns ( sb , GetArg ( sb , found [ 0 ] ? 0 : 1 ) ) ;
return true ;
case "if3" :
if ( positions . Count < 1 )
return false ;
for ( int argno = 0 ; argno < positions . Count ; argno + + )
if ( found [ argno ] | | argno = = positions . Count - 1 )
{
Returns ( sb , GetArg ( sb , argno ) ) ;
return true ;
}
return false ;
case "ifgreater" :
if ( positions . Count ! = 4 )
return false ;
Returns ( sb , GetArg ( sb , ( GetIntArg ( sb , 0 ) > GetIntArg ( sb , 1 ) ) ? 2 : 3 ) ) ;
return true ;
case "iflonger" :
if ( positions . Count ! = 4 )
return false ;
Returns ( sb , GetArg ( sb , ( GetArg ( sb , 0 ) . Length > GetIntArg ( sb , 1 ) ) ? 2 : 3 ) ) ;
return true ;
case "ifequal" :
if ( positions . Count ! = 4 )
return false ;
Returns ( sb , GetArg ( sb , ( GetIntArg ( sb , 0 ) = = GetIntArg ( sb , 1 ) ) ? 2 : 3 ) ) ;
return true ;
case "len" :
if ( positions . Count ! = 1 )
return false ;
Returns ( sb , GetArg ( sb , 0 ) . Length . ToString ( ) ) ;
return true ;
case "max" :
if ( positions . Count ! = 2 )
return false ;
Returns ( sb , Math . Max ( GetIntArg ( sb , 0 ) , GetIntArg ( sb , 1 ) ) . ToString ( ) ) ;
return true ;
2009-08-06 13:03:02 +00:00
case "directory" :
if ( positions . Count ! = 1 & & positions . Count ! = 2 & & positions . Count ! = 3 )
return false ;
try
{
int arg3 = positions . Count > 1 ? GetIntArg ( sb , 1 ) : 1 ;
int arg2 = positions . Count > 2 ? GetIntArg ( sb , 2 ) : arg3 ;
Returns ( sb , General . GetDirectoryElements ( Path . GetDirectoryName ( GetArg ( sb , 0 ) ) , - arg2 , - arg3 ) ) ;
}
catch { return false ; }
return true ;
case "directory_path" :
if ( positions . Count ! = 1 )
return false ;
try { Returns ( sb , Path . GetDirectoryName ( GetArg ( sb , 0 ) ) ) ; }
catch { return false ; }
return true ;
case "ext" :
if ( positions . Count ! = 1 )
return false ;
try { Returns ( sb , Path . GetExtension ( GetArg ( sb , 0 ) ) ) ; }
catch { return false ; }
return true ;
case "filename" :
if ( positions . Count ! = 1 )
return false ;
try { Returns ( sb , Path . GetFileNameWithoutExtension ( GetArg ( sb , 0 ) ) ) ; }
catch { return false ; }
return true ;
2009-06-24 19:40:23 +00:00
}
return false ;
}
2009-08-06 13:03:02 +00:00
}
public static string GetDirectoryElements ( string dir , int first , int last )
{
if ( dir = = null )
return "" ;
string [ ] dirSplit = dir . Split ( Path . DirectorySeparatorChar ,
Path . AltDirectorySeparatorChar ) ;
int count = dirSplit . Length ;
if ( ( first = = 0 ) & & ( last = = 0 ) )
{
first = 1 ;
last = count ;
}
if ( first < 0 ) first = ( count + 1 ) + first ;
if ( last < 0 ) last = ( count + 1 ) + last ;
if ( ( first < 1 ) & & ( last < 1 ) )
{
return String . Empty ;
}
else if ( ( first > count ) & & ( last > count ) )
{
return String . Empty ;
}
else
{
int i ;
StringBuilder sb = new StringBuilder ( ) ;
if ( first < 1 ) first = 1 ;
if ( first > count ) first = count ;
if ( last < 1 ) last = 1 ;
if ( last > count ) last = count ;
if ( last > = first )
{
for ( i = first ; i < = last ; i + + )
{
sb . Append ( dirSplit [ i - 1 ] ) ;
sb . Append ( Path . DirectorySeparatorChar ) ;
}
}
else
{
for ( i = first ; i > = last ; i - - )
{
sb . Append ( dirSplit [ i - 1 ] ) ;
sb . Append ( Path . DirectorySeparatorChar ) ;
}
}
return sb . ToString ( 0 , sb . Length - 1 ) ;
}
}
public static string ReplaceMultiple ( string s , NameValueCollection tags )
{
List < string > find = new List < string > ( ) ;
List < string > replace = new List < string > ( ) ;
foreach ( string tag in tags . AllKeys )
{
string key = '%' + tag . ToLower ( ) + '%' ;
string val = tags [ tag ] ;
if ( ! find . Contains ( key ) & & val ! = null & & val ! = "" )
{
find . Add ( key ) ;
replace . Add ( val ) ;
}
}
2009-06-24 19:40:23 +00:00
2009-08-06 13:03:02 +00:00
return ReplaceMultiple ( s , find , replace ) ;
2009-06-24 19:40:23 +00:00
}
2009-08-08 16:14:06 +00:00
public delegate bool CheckIfExists ( string output ) ;
public static string ReplaceMultiple ( string fmt , NameValueCollection tags , string unique_key , CheckIfExists exists )
{
string result = ReplaceMultiple ( fmt , tags ) ;
if ( result = = String . Empty | | result = = null )
return result ;
int unique = 1 ;
try
{
while ( exists ( result ) )
{
tags [ unique_key ] = unique . ToString ( ) ;
string new_result = ReplaceMultiple ( fmt , tags ) ;
if ( new_result = = result | | new_result = = String . Empty | | new_result = = null )
break ;
result = new_result ;
unique + + ;
}
}
catch { }
return result ;
}
2008-12-07 23:38:00 +00:00
public static string ReplaceMultiple ( string s , List < string > find , List < string > replace )
{
if ( find . Count ! = replace . Count )
{
throw new ArgumentException ( ) ;
}
StringBuilder sb ;
int iChar , iFind ;
string f ;
bool found ;
2009-06-24 19:40:23 +00:00
List < TitleFormatFunctionInfo > formatFunctions = new List < TitleFormatFunctionInfo > ( ) ;
bool quote = false ;
2008-12-07 23:38:00 +00:00
sb = new StringBuilder ( ) ;
for ( iChar = 0 ; iChar < s . Length ; iChar + + )
{
found = false ;
2009-06-24 19:40:23 +00:00
if ( quote )
{
if ( s [ iChar ] = = '\'' )
{
if ( iChar > 0 & & s [ iChar - 1 ] = = '\'' )
sb . Append ( s [ iChar ] ) ;
quote = false ;
continue ;
}
sb . Append ( s [ iChar ] ) ;
continue ;
}
if ( s [ iChar ] = = '\'' )
{
quote = true ;
continue ;
}
if ( s [ iChar ] = = '[' )
{
formatFunctions . Add ( new TitleFormatFunctionInfo ( "[" , sb . Length ) ) ;
continue ;
}
if ( s [ iChar ] = = '$' )
{
int funcEnd = s . IndexOf ( '(' , iChar + 1 ) ;
if ( funcEnd < 0 )
return null ;
formatFunctions . Add ( new TitleFormatFunctionInfo ( s . Substring ( iChar + 1 , funcEnd - iChar - 1 ) , sb . Length ) ) ;
iChar = funcEnd ;
continue ;
}
if ( s [ iChar ] = = ',' )
{
if ( formatFunctions . Count < 1 )
return null ;
formatFunctions [ formatFunctions . Count - 1 ] . NextArg ( sb . Length ) ;
continue ;
}
if ( s [ iChar ] = = ']' )
{
if ( formatFunctions . Count < 1 | |
formatFunctions [ formatFunctions . Count - 1 ] . func ! = "["
| | ! formatFunctions [ formatFunctions . Count - 1 ] . Finalise ( sb ) )
return null ;
formatFunctions . RemoveAt ( formatFunctions . Count - 1 ) ;
continue ;
}
if ( s [ iChar ] = = ')' )
{
if ( formatFunctions . Count < 1 | |
formatFunctions [ formatFunctions . Count - 1 ] . func = = "["
| | ! formatFunctions [ formatFunctions . Count - 1 ] . Finalise ( sb ) )
return null ;
formatFunctions . RemoveAt ( formatFunctions . Count - 1 ) ;
continue ;
}
2008-12-07 23:38:00 +00:00
for ( iFind = 0 ; iFind < find . Count ; iFind + + )
{
f = find [ iFind ] ;
if ( ( f . Length < = ( s . Length - iChar ) ) & & ( s . Substring ( iChar , f . Length ) = = f ) )
{
2009-06-24 19:40:23 +00:00
if ( formatFunctions . Count > 0 )
2008-12-07 23:38:00 +00:00
{
2009-06-24 19:40:23 +00:00
if ( replace [ iFind ] ! = null )
{
formatFunctions [ formatFunctions . Count - 1 ] . Found ( ) ;
sb . Append ( replace [ iFind ] ) ;
}
}
else
{
if ( replace [ iFind ] ! = null )
sb . Append ( replace [ iFind ] ) ;
else
return null ;
2008-12-07 23:38:00 +00:00
}
iChar + = f . Length - 1 ;
found = true ;
break ;
}
}
if ( ! found )
{
sb . Append ( s [ iChar ] ) ;
}
}
return sb . ToString ( ) ;
}
public static string EmptyStringToNull ( string s )
{
return ( ( s ! = null ) & & ( s . Length = = 0 ) ) ? null : s ;
}
}
2009-05-01 15:16:26 +00:00
public enum CUEToolsTagger
{
TagLibSharp = 0 ,
APEv2 = 1 ,
ID3v2 = 2 ,
}
public class CUEToolsFormat
{
public CUEToolsFormat (
string _extension ,
CUEToolsTagger _tagger ,
bool _allowLossless ,
bool _allowLossy ,
bool _allowLossyWAV ,
bool _allowEmbed ,
bool _builtin ,
2009-08-06 13:03:02 +00:00
CUEToolsUDC _encoderLossless ,
CUEToolsUDC _encoderLossy ,
2009-05-01 15:16:26 +00:00
string _decoder )
{
extension = _extension ;
tagger = _tagger ;
allowLossless = _allowLossless ;
allowLossy = _allowLossy ;
allowLossyWAV = _allowLossyWAV ;
allowEmbed = _allowEmbed ;
builtin = _builtin ;
encoderLossless = _encoderLossless ;
encoderLossy = _encoderLossy ;
decoder = _decoder ;
}
2010-03-22 06:37:43 +00:00
public string DotExtension
{
get
{
return "." + extension ;
}
}
2009-05-01 15:16:26 +00:00
public override string ToString ( )
{
return extension ;
}
public string extension ;
2009-08-06 13:03:02 +00:00
public CUEToolsUDC encoderLossless ;
public CUEToolsUDC encoderLossy ;
2009-05-01 15:16:26 +00:00
public string decoder ;
public CUEToolsTagger tagger ;
public bool allowLossless , allowLossy , allowLossyWAV , allowEmbed , builtin ;
}
2009-08-06 13:03:02 +00:00
public class CUEToolsUDC : INotifyPropertyChanged
2009-05-01 15:16:26 +00:00
{
2009-08-06 13:03:02 +00:00
public event PropertyChangedEventHandler PropertyChanged ;
2009-05-01 15:16:26 +00:00
public CUEToolsUDC (
string _name ,
string _extension ,
bool _lossless ,
2009-06-24 19:40:23 +00:00
string _supported_modes ,
string _default_mode ,
2009-05-01 15:16:26 +00:00
string _path ,
string _parameters
)
{
name = _name ;
extension = _extension ;
lossless = _lossless ;
2009-06-24 19:40:23 +00:00
supported_modes = _supported_modes ;
default_mode = _default_mode ;
2010-02-08 01:29:31 +00:00
priority = 0 ;
2009-05-01 15:16:26 +00:00
path = _path ;
parameters = _parameters ;
2010-02-06 23:17:07 +00:00
type = null ;
2009-05-01 15:16:26 +00:00
}
2010-02-06 23:17:07 +00:00
public CUEToolsUDC ( AudioEncoderClass enc , Type enctype )
2009-05-01 15:16:26 +00:00
{
2010-02-06 23:17:07 +00:00
name = enc . EncoderName ;
extension = enc . Extension ;
lossless = enc . Lossless ;
supported_modes = enc . SupportedModes ;
default_mode = enc . DefaultMode ;
priority = enc . Priority ;
2009-05-01 15:16:26 +00:00
path = null ;
parameters = null ;
2010-02-06 23:17:07 +00:00
type = enctype ;
}
2010-02-08 01:29:31 +00:00
public CUEToolsUDC ( AudioDecoderClass dec , Type dectype )
2010-02-06 23:17:07 +00:00
{
2010-02-08 01:29:31 +00:00
name = dec . DecoderName ;
extension = dec . Extension ;
2010-02-06 23:17:07 +00:00
lossless = true ;
supported_modes = "" ;
default_mode = "" ;
2010-02-08 01:29:31 +00:00
priority = 1 ;
2010-02-06 23:17:07 +00:00
path = null ;
parameters = null ;
type = dectype ;
2009-05-01 15:16:26 +00:00
}
public override string ToString ( )
{
return name ;
}
2009-08-06 13:03:02 +00:00
public string name = "" ;
public string extension = "wav" ;
public string path = "" ;
public string parameters = "" ;
2010-02-06 23:17:07 +00:00
public Type type = null ;
2009-08-06 13:03:02 +00:00
public string supported_modes = "" ;
public string default_mode = "" ;
public bool lossless = false ;
2010-02-06 23:17:07 +00:00
public int priority = 0 ;
2009-08-06 13:03:02 +00:00
public string Name
{
get { return name ; }
set { name = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "Name" ) ) ; }
}
public string Path
{
get { return path ; }
set { path = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "Path" ) ) ; }
}
public string Parameters
{
get { return parameters ; }
set { parameters = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "Parameters" ) ) ; }
}
public bool Lossless
{
get { return lossless ; }
set { lossless = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "Lossless" ) ) ; }
}
public string Extension
{
get { return extension ; }
set { extension = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "Extension" ) ) ; }
}
public string DotExtension
{
get { return "." + extension ; }
}
public string SupportedModesStr
{
get { return supported_modes ; }
set { supported_modes = value ; if ( PropertyChanged ! = null ) PropertyChanged ( this , new PropertyChangedEventArgs ( "SupportedModesStr" ) ) ; }
}
2009-06-24 19:40:23 +00:00
public string [ ] SupportedModes
{
get
{
return supported_modes . Split ( ' ' ) ;
}
}
public int DefaultModeIndex
{
get
{
string [ ] modes = supported_modes . Split ( ' ' ) ;
if ( modes = = null | | modes . Length < 2 )
return - 1 ;
for ( int i = 0 ; i < modes . Length ; i + + )
if ( modes [ i ] = = default_mode )
return i ;
return - 1 ;
}
}
2009-08-06 13:03:02 +00:00
public bool CanBeDeleted
{
get
{
return path ! = null ;
}
}
2009-05-01 15:16:26 +00:00
}
public class CUEToolsScript
{
public CUEToolsScript ( string _name , bool _builtin , IEnumerable < CUEAction > _conditions , string _code )
{
name = _name ;
builtin = _builtin ;
conditions = new List < CUEAction > ( ) ;
foreach ( CUEAction condition in _conditions )
conditions . Add ( condition ) ;
code = _code ;
}
public override string ToString ( )
{
return name ;
}
public string name ;
public bool builtin ;
public List < CUEAction > conditions ;
public string code ;
}
2009-08-06 13:03:02 +00:00
public class CUEToolsUDCList : BindingList < CUEToolsUDC >
{
public CUEToolsUDCList ( ) : base ( )
{
AddingNew + = OnAddingNew ;
}
private void OnAddingNew ( object sender , AddingNewEventArgs e )
{
string name = "new" ;
CUEToolsUDC temp ;
while ( TryGetValue ( name , out temp ) )
name + = "(1)" ;
e . NewObject = new CUEToolsUDC ( name , "wav" , true , "" , "" , "" , "" ) ;
}
public bool TryGetValue ( string name , out CUEToolsUDC result )
{
foreach ( CUEToolsUDC udc in this )
if ( udc . name = = name )
{
result = udc ;
return true ;
}
result = null ;
return false ;
}
2010-02-06 23:17:07 +00:00
public CUEToolsUDC GetDefault ( string extension , bool lossless )
{
CUEToolsUDC result = null ;
foreach ( CUEToolsUDC udc in this )
if ( udc . extension = = extension & & udc . lossless = = lossless & & ( result = = null | | result . priority < udc . priority ) )
result = udc ;
return result ;
}
2009-08-06 13:03:02 +00:00
public CUEToolsUDC this [ string name ]
{
get
{
CUEToolsUDC udc ;
if ( ! TryGetValue ( name , out udc ) )
throw new Exception ( "CUEToolsUDCList: member not found" ) ;
return udc ;
}
}
}
2010-02-08 01:29:31 +00:00
public static class CUEProcessorPlugins
{
static public List < Type > encs ;
static public List < Type > decs ;
static public List < Type > arcp ;
static public List < string > arcp_fmt ;
static public Type hdcd ;
static public Type ripper ;
static CUEProcessorPlugins ( )
{
encs = new List < Type > ( ) ;
decs = new List < Type > ( ) ;
arcp = new List < Type > ( ) ;
arcp_fmt = new List < string > ( ) ;
encs . Add ( typeof ( CUETools . Codecs . WAVWriter ) ) ;
decs . Add ( typeof ( CUETools . Codecs . WAVReader ) ) ;
//ApplicationSecurityInfo asi = new ApplicationSecurityInfo(AppDomain.CurrentDomain.ActivationContext);
//string arch = asi.ApplicationId.ProcessorArchitecture;
//ActivationContext is null most of the time :(
2010-02-08 05:06:48 +00:00
string arch = Marshal . SizeOf ( typeof ( IntPtr ) ) = = 8 ? "x64" : "Win32" ;
2010-03-20 07:09:07 +00:00
string plugins_path = Path . Combine ( Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) , "Plugins (" + arch + ")" ) ;
2010-02-08 01:29:31 +00:00
if ( Directory . Exists ( plugins_path ) )
AddPluginDirectory ( plugins_path ) ;
2010-03-20 07:09:07 +00:00
plugins_path = Path . Combine ( Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) , "Plugins" ) ;
2010-02-08 01:29:31 +00:00
if ( Directory . Exists ( plugins_path ) )
AddPluginDirectory ( plugins_path ) ;
}
private static void AddPluginDirectory ( string plugins_path )
{
foreach ( string plugin_path in Directory . GetFiles ( plugins_path , "*.dll" , SearchOption . TopDirectoryOnly ) )
{
try
{
AssemblyName name = AssemblyName . GetAssemblyName ( plugin_path ) ;
2010-03-25 05:04:45 +00:00
Assembly assembly = Assembly . Load ( name , Assembly . GetEntryAssembly ( ) . Evidence ) ;
System . Diagnostics . Trace . WriteLine ( "Loaded " + assembly . FullName ) ;
2010-02-08 01:29:31 +00:00
foreach ( Type type in assembly . GetExportedTypes ( ) )
{
try
{
if ( Attribute . GetCustomAttribute ( type , typeof ( AudioDecoderClass ) ) ! = null )
decs . Add ( type ) ;
//if (type.IsClass && !type.IsAbstract && typeof(IAudioDest).IsAssignableFrom(type))
if ( Attribute . GetCustomAttribute ( type , typeof ( AudioEncoderClass ) ) ! = null )
encs . Add ( type ) ;
CompressionProviderClass archclass = Attribute . GetCustomAttribute ( type , typeof ( CompressionProviderClass ) ) as CompressionProviderClass ;
if ( archclass ! = null )
{
arcp . Add ( type ) ;
if ( ! arcp_fmt . Contains ( archclass . Extension ) )
arcp_fmt . Add ( archclass . Extension ) ;
}
if ( type . Name = = "HDCDDotNet" )
hdcd = type ;
if ( type . IsClass & & ! type . IsAbstract & & typeof ( ICDRipper ) . IsAssignableFrom ( type ) )
ripper = type ;
}
catch ( Exception ex )
{
2010-03-25 05:04:45 +00:00
System . Diagnostics . Trace . WriteLine ( ex . Message ) ;
2010-02-08 01:29:31 +00:00
}
}
}
catch ( Exception ex )
{
2010-03-25 05:04:45 +00:00
System . Diagnostics . Trace . WriteLine ( ex . Message ) ;
2010-02-08 01:29:31 +00:00
}
}
}
}
2008-12-07 23:38:00 +00:00
public class CUEConfig {
2009-05-01 15:16:26 +00:00
public uint fixOffsetMinimumConfidence ;
public uint fixOffsetMinimumTracksPercent ;
2008-12-07 23:38:00 +00:00
public uint encodeWhenConfidence ;
public uint encodeWhenPercent ;
public bool encodeWhenZeroOffset ;
public bool writeArTagsOnVerify ;
public bool writeArLogOnVerify ;
2009-08-08 16:14:06 +00:00
public bool writeArTagsOnEncode ;
2008-12-07 23:38:00 +00:00
public bool writeArLogOnConvert ;
public bool fixOffset ;
public bool noUnverifiedOutput ;
public bool autoCorrectFilenames ;
public bool flacVerify ;
2009-12-24 16:17:42 +00:00
public bool flaCudaVerify ;
public bool flaCudaGPUOnly ;
2010-02-06 23:17:07 +00:00
public bool flaCudaThreads ;
2008-12-07 23:38:00 +00:00
public bool preserveHTOA ;
public int wvExtraMode ;
public bool wvStoreMD5 ;
public bool keepOriginalFilenames ;
public string trackFilenameFormat ;
public string singleFilenameFormat ;
public bool removeSpecial ;
public string specialExceptions ;
public bool replaceSpaces ;
public bool embedLog ;
2009-01-17 04:09:38 +00:00
public bool extractLog ;
2008-12-07 23:38:00 +00:00
public bool fillUpCUE ;
2009-01-17 04:09:38 +00:00
public bool overwriteCUEData ;
2008-12-07 23:38:00 +00:00
public bool filenamesANSISafe ;
public bool bruteForceDTL ;
2009-03-04 21:30:56 +00:00
public bool createEACLOG ;
2008-12-07 23:38:00 +00:00
public bool detectHDCD ;
public bool decodeHDCD ;
public bool wait750FramesForHDCD ;
public bool createM3U ;
public bool createTOC ;
public bool createCUEFileWhenEmbedded ;
public bool truncate4608ExtraSamples ;
public int lossyWAVQuality ;
public bool decodeHDCDtoLW16 ;
public bool decodeHDCDto24bit ;
2009-03-04 21:30:56 +00:00
public bool disableAsm ;
2009-03-22 16:59:05 +00:00
public bool oneInstance ;
2009-06-24 19:40:23 +00:00
public bool checkForUpdates ;
2009-03-28 03:57:49 +00:00
public string language ;
2009-05-01 15:16:26 +00:00
public Dictionary < string , CUEToolsFormat > formats ;
2009-08-06 13:03:02 +00:00
public CUEToolsUDCList encoders ;
2009-05-01 15:16:26 +00:00
public Dictionary < string , CUEToolsUDC > decoders ;
public Dictionary < string , CUEToolsScript > scripts ;
public string defaultVerifyScript ;
2009-08-08 16:14:06 +00:00
public string defaultEncodeScript ;
2009-05-01 15:16:26 +00:00
public bool writeBasicTagsFromCUEData ;
public bool copyBasicTags ;
public bool copyUnknownTags ;
public bool copyAlbumArt ;
public bool embedAlbumArt ;
2009-05-13 16:07:53 +00:00
public bool extractAlbumArt ;
2009-05-01 15:16:26 +00:00
public bool arLogToSourceFolder ;
public bool arLogVerbose ;
public bool fixOffsetToNearest ;
public int maxAlbumArtSize ;
2009-08-06 13:03:02 +00:00
public string arLogFilenameFormat , alArtFilenameFormat ;
2009-06-24 19:40:23 +00:00
public CUEStyle gapsHandling ;
2010-02-23 15:15:08 +00:00
public bool separateDecodingThread ;
public bool useSystemProxySettings ;
2008-12-07 23:38:00 +00:00
2009-08-06 13:03:02 +00:00
public bool CopyAlbumArt { get { return copyAlbumArt ; } set { copyAlbumArt = value ; } }
2010-02-06 23:17:07 +00:00
public bool FlaCudaThreads { get { return flaCudaThreads ; } set { flaCudaThreads = value ; } }
public bool FlaCudaGPUOnly { get { return flaCudaGPUOnly ; } set { flaCudaGPUOnly = value ; } }
public bool FlaCudaVerify { get { return flaCudaVerify ; } set { flaCudaVerify = value ; } }
2009-08-08 16:14:06 +00:00
public string ArLogFilenameFormat { get { return arLogFilenameFormat ; } set { arLogFilenameFormat = value ; } }
public string AlArtFilenameFormat { get { return alArtFilenameFormat ; } set { alArtFilenameFormat = value ; } }
2009-08-06 13:03:02 +00:00
public CUEToolsUDCList Encoders
{
get { return encoders ; }
}
2008-12-07 23:38:00 +00:00
public CUEConfig ( )
{
2009-05-01 15:16:26 +00:00
fixOffsetMinimumConfidence = 2 ;
fixOffsetMinimumTracksPercent = 51 ;
2008-12-07 23:38:00 +00:00
encodeWhenConfidence = 2 ;
encodeWhenPercent = 100 ;
encodeWhenZeroOffset = false ;
fixOffset = false ;
noUnverifiedOutput = false ;
2009-08-08 16:14:06 +00:00
writeArTagsOnEncode = true ;
2008-12-07 23:38:00 +00:00
writeArLogOnConvert = true ;
writeArTagsOnVerify = false ;
writeArLogOnVerify = true ;
autoCorrectFilenames = true ;
flacVerify = false ;
2009-12-24 16:17:42 +00:00
flaCudaVerify = false ;
flaCudaGPUOnly = false ;
2010-02-06 23:17:07 +00:00
flaCudaThreads = true ;
2008-12-07 23:38:00 +00:00
preserveHTOA = true ;
wvExtraMode = 0 ;
wvStoreMD5 = false ;
2009-05-01 15:16:26 +00:00
keepOriginalFilenames = false ;
2009-08-08 16:14:06 +00:00
trackFilenameFormat = "%tracknumber%. %title%" ;
singleFilenameFormat = "%filename%" ;
2008-12-07 23:38:00 +00:00
removeSpecial = false ;
specialExceptions = "-()" ;
2008-12-09 07:25:48 +00:00
replaceSpaces = false ;
2008-12-07 23:38:00 +00:00
embedLog = true ;
2009-01-17 04:09:38 +00:00
extractLog = true ;
2008-12-07 23:38:00 +00:00
fillUpCUE = true ;
2009-01-17 04:09:38 +00:00
overwriteCUEData = false ;
2008-12-07 23:38:00 +00:00
filenamesANSISafe = true ;
bruteForceDTL = false ;
2010-02-28 21:04:34 +00:00
createEACLOG = true ;
2008-12-07 23:38:00 +00:00
detectHDCD = true ;
wait750FramesForHDCD = true ;
decodeHDCD = false ;
createM3U = false ;
createTOC = false ;
2009-01-17 04:09:38 +00:00
createCUEFileWhenEmbedded = true ;
2008-12-07 23:38:00 +00:00
truncate4608ExtraSamples = true ;
lossyWAVQuality = 5 ;
decodeHDCDtoLW16 = false ;
decodeHDCDto24bit = true ;
2009-02-19 04:09:59 +00:00
2009-03-04 21:30:56 +00:00
disableAsm = false ;
2009-03-22 16:59:05 +00:00
oneInstance = true ;
2009-06-24 19:40:23 +00:00
checkForUpdates = true ;
2009-03-28 03:57:49 +00:00
2009-05-01 15:16:26 +00:00
writeBasicTagsFromCUEData = true ;
copyBasicTags = true ;
copyUnknownTags = true ;
copyAlbumArt = true ;
embedAlbumArt = true ;
2009-05-13 16:07:53 +00:00
extractAlbumArt = true ;
2009-05-01 15:16:26 +00:00
maxAlbumArtSize = 300 ;
arLogToSourceFolder = false ;
arLogVerbose = true ;
fixOffsetToNearest = true ;
2009-08-08 16:14:06 +00:00
arLogFilenameFormat = "%filename%.accurip" ;
2009-08-06 13:03:02 +00:00
alArtFilenameFormat = "folder.jpg" ;
2009-05-01 15:16:26 +00:00
2010-02-23 15:15:08 +00:00
separateDecodingThread = true ;
useSystemProxySettings = true ;
2009-06-24 19:40:23 +00:00
gapsHandling = CUEStyle . GapsAppended ;
2009-03-28 03:57:49 +00:00
language = Thread . CurrentThread . CurrentUICulture . Name ;
2009-05-01 15:16:26 +00:00
2009-08-06 13:03:02 +00:00
encoders = new CUEToolsUDCList ( ) ;
2010-02-08 01:29:31 +00:00
foreach ( Type type in CUEProcessorPlugins . encs )
2010-02-06 23:17:07 +00:00
{
AudioEncoderClass enc = Attribute . GetCustomAttribute ( type , typeof ( AudioEncoderClass ) ) as AudioEncoderClass ;
//if (!encoders.TryGetValue(enc.EncoderName))
encoders . Add ( new CUEToolsUDC ( enc , type ) ) ;
}
2009-05-01 15:16:26 +00:00
decoders = new Dictionary < string , CUEToolsUDC > ( ) ;
2010-02-08 01:29:31 +00:00
foreach ( Type type in CUEProcessorPlugins . decs )
2010-02-06 23:17:07 +00:00
{
AudioDecoderClass dec = Attribute . GetCustomAttribute ( type , typeof ( AudioDecoderClass ) ) as AudioDecoderClass ;
decoders . Add ( dec . DecoderName , new CUEToolsUDC ( dec , type ) ) ;
}
2010-02-08 01:29:31 +00:00
if ( Type . GetType ( "Mono.Runtime" , false ) = = null )
{
2010-02-28 21:04:34 +00:00
encoders . Add ( new CUEToolsUDC ( "flake" , "flac" , true , "0 1 2 3 4 5 6 7 8 9 10 11 12" , "8" , "flake.exe" , "-%M - -o %O -p %P" ) ) ;
2010-02-08 01:29:31 +00:00
encoders . Add ( new CUEToolsUDC ( "takc" , "tak" , true , "0 1 2 2e 2m 3 3e 3m 4 4e 4m" , "2" , "takc.exe" , "-e -p%M -overwrite - %O" ) ) ;
encoders . Add ( new CUEToolsUDC ( "ffmpeg alac" , "m4a" , true , "" , "" , "ffmpeg.exe" , "-i - -f ipod -acodec alac -y %O" ) ) ;
encoders . Add ( new CUEToolsUDC ( "lame vbr" , "mp3" , false , "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0" , "V2" , "lame.exe" , "--vbr-new -%M - %O" ) ) ;
encoders . Add ( new CUEToolsUDC ( "lame cbr" , "mp3" , false , "96 128 192 256 320" , "256" , "lame.exe" , "-m s -q 0 -b %M --noreplaygain - %O" ) ) ;
encoders . Add ( new CUEToolsUDC ( "oggenc" , "ogg" , false , "-1 -0.5 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8" , "3" , "oggenc.exe" , "-q %M - -o %O" ) ) ;
encoders . Add ( new CUEToolsUDC ( "nero aac" , "m4a" , false , "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9" , "0.4" , "neroAacEnc.exe" , "-q %M -if - -of %O" ) ) ;
decoders . Add ( "takc" , new CUEToolsUDC ( "takc" , "tak" , true , "" , "" , "takc.exe" , "-d %I -" ) ) ;
decoders . Add ( "ffmpeg alac" , new CUEToolsUDC ( "ffmpeg alac" , "m4a" , true , "" , "" , "ffmpeg.exe" , "%I -f wav -" ) ) ;
}
else
{
// !!!
}
2009-05-01 15:16:26 +00:00
2009-08-06 13:03:02 +00:00
formats = new Dictionary < string , CUEToolsFormat > ( ) ;
2010-02-08 01:29:31 +00:00
formats . Add ( "flac" , new CUEToolsFormat ( "flac" , CUEToolsTagger . TagLibSharp , true , false , true , true , true , encoders . GetDefault ( "flac" , true ) , null , GetDefaultDecoder ( "flac" ) ) ) ;
formats . Add ( "wv" , new CUEToolsFormat ( "wv" , CUEToolsTagger . TagLibSharp , true , false , true , true , true , encoders . GetDefault ( "wv" , true ) , null , GetDefaultDecoder ( "wv" ) ) ) ;
formats . Add ( "ape" , new CUEToolsFormat ( "ape" , CUEToolsTagger . TagLibSharp , true , false , false , true , true , encoders . GetDefault ( "ape" , true ) , null , GetDefaultDecoder ( "ape" ) ) ) ;
formats . Add ( "tta" , new CUEToolsFormat ( "tta" , CUEToolsTagger . APEv2 , true , false , false , false , true , encoders . GetDefault ( "tta" , true ) , null , GetDefaultDecoder ( "tta" ) ) ) ;
formats . Add ( "wav" , new CUEToolsFormat ( "wav" , CUEToolsTagger . TagLibSharp , true , false , true , false , true , encoders . GetDefault ( "wav" , true ) , null , GetDefaultDecoder ( "wav" ) ) ) ;
formats . Add ( "m4a" , new CUEToolsFormat ( "m4a" , CUEToolsTagger . TagLibSharp , true , true , false , false , true , encoders . GetDefault ( "m4a" , true ) , encoders . GetDefault ( "m4a" , false ) , GetDefaultDecoder ( "m4a" ) ) ) ;
2010-02-06 23:17:07 +00:00
formats . Add ( "tak" , new CUEToolsFormat ( "tak" , CUEToolsTagger . APEv2 , true , false , true , true , true , encoders . GetDefault ( "tak" , true ) , null , "takc" ) ) ;
formats . Add ( "mp3" , new CUEToolsFormat ( "mp3" , CUEToolsTagger . TagLibSharp , false , true , false , false , true , null , encoders . GetDefault ( "mp3" , false ) , null ) ) ;
formats . Add ( "ogg" , new CUEToolsFormat ( "ogg" , CUEToolsTagger . TagLibSharp , false , true , false , false , true , null , encoders . GetDefault ( "ogg" , false ) , null ) ) ;
2009-08-06 13:03:02 +00:00
2009-05-01 15:16:26 +00:00
scripts = new Dictionary < string , CUEToolsScript > ( ) ;
scripts . Add ( "default" , new CUEToolsScript ( "default" , true ,
2009-08-08 16:14:06 +00:00
new CUEAction [ ] { CUEAction . Verify , CUEAction . Encode } ,
2009-05-01 15:16:26 +00:00
"return processor.Go();" ) ) ;
scripts . Add ( "only if found" , new CUEToolsScript ( "only if found" , true ,
new CUEAction [ ] { CUEAction . Verify } ,
@ "if (processor.ArVerify.AccResult != HttpStatusCode.OK)
return processor . WriteReport ( ) ;
return processor . Go ( ) ; "));
scripts . Add ( "fix offset" , new CUEToolsScript ( "fix offset" , true ,
2009-08-08 16:14:06 +00:00
new CUEAction [ ] { CUEAction . Encode } ,
2009-05-01 15:16:26 +00:00
@ "if (processor.ArVerify.AccResult != HttpStatusCode.OK)
return processor . WriteReport ( ) ;
processor . WriteOffset = 0 ;
processor . Action = CUEAction . Verify ;
string status = processor . Go ( ) ;
uint tracksMatch ;
int bestOffset ;
processor . FindBestOffset ( processor . Config . fixOffsetMinimumConfidence , ! processor . Config . fixOffsetToNearest , out tracksMatch , out bestOffset ) ;
if ( tracksMatch * 100 < processor . Config . fixOffsetMinimumTracksPercent * processor . TrackCount )
return status ;
processor . WriteOffset = bestOffset ;
2009-08-08 16:14:06 +00:00
processor . Action = CUEAction . Encode ;
2009-05-01 15:16:26 +00:00
//MessageBox.Show(null, processor.AccurateRipLog, " + "\"Done\"" + @"MessageBoxButtons.OK, MessageBoxIcon.Information);
return processor . Go ( ) ;
"));
scripts . Add ( "encode if verified" , new CUEToolsScript ( "encode if verified" , true ,
2009-08-08 16:14:06 +00:00
new CUEAction [ ] { CUEAction . Encode } ,
2009-05-01 15:16:26 +00:00
@ "if (processor.ArVerify.AccResult != HttpStatusCode.OK)
return processor . WriteReport ( ) ;
processor . Action = CUEAction . Verify ;
string status = processor . Go ( ) ;
uint tracksMatch ;
int bestOffset ;
processor . FindBestOffset ( processor . Config . encodeWhenConfidence , false , out tracksMatch , out bestOffset ) ;
if ( tracksMatch * 100 < processor . Config . encodeWhenPercent * processor . TrackCount | | ( processor . Config . encodeWhenZeroOffset & & bestOffset ! = 0 ) )
return status ;
2009-08-08 16:14:06 +00:00
processor . Action = CUEAction . Encode ;
2009-05-01 15:16:26 +00:00
return processor . Go ( ) ;
"));
2010-02-23 15:15:08 +00:00
scripts . Add ( "repair" , new CUEToolsScript ( "repair" , true ,
new CUEAction [ ] { CUEAction . Encode } ,
@ "
processor . UseCUEToolsDB ( ) ;
processor . Action = CUEAction . Verify ;
if ( processor . CTDB . DBStatus ! = null )
return CTDB . DBStatus ;
processor . Go ( ) ;
processor . CTDB . DoVerify ( ) ;
if ( ! processor . CTDB . Verify . HasErrors )
return "" nothing to fix "" ;
if ( ! processor . CTDB . Verify . CanRecover )
return "" cannot fix "" ;
processor . _useCUEToolsDBFix = true ;
processor . Action = CUEAction . Encode ;
return processor . Go ( ) ;
"));
scripts . Add ( "submit" , new CUEToolsScript ( "submit" , true ,
new CUEAction [ ] { CUEAction . Verify } ,
@ "
string status = processor . Go ( ) ;
"));
2009-05-01 15:16:26 +00:00
defaultVerifyScript = "default" ;
2009-08-08 16:14:06 +00:00
defaultEncodeScript = "default" ;
2008-12-07 23:38:00 +00:00
}
public void Save ( SettingsWriter sw )
{
2009-06-24 19:40:23 +00:00
sw . Save ( "Version" , 203 ) ;
2009-05-01 15:16:26 +00:00
sw . Save ( "ArFixWhenConfidence" , fixOffsetMinimumConfidence ) ;
sw . Save ( "ArFixWhenPercent" , fixOffsetMinimumTracksPercent ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "ArEncodeWhenConfidence" , encodeWhenConfidence ) ;
sw . Save ( "ArEncodeWhenPercent" , encodeWhenPercent ) ;
sw . Save ( "ArEncodeWhenZeroOffset" , encodeWhenZeroOffset ) ;
sw . Save ( "ArNoUnverifiedOutput" , noUnverifiedOutput ) ;
sw . Save ( "ArFixOffset" , fixOffset ) ;
2009-08-08 16:14:06 +00:00
sw . Save ( "ArWriteCRC" , writeArTagsOnEncode ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "ArWriteLog" , writeArLogOnConvert ) ;
sw . Save ( "ArWriteTagsOnVerify" , writeArTagsOnVerify ) ;
sw . Save ( "ArWriteLogOnVerify" , writeArLogOnVerify ) ;
sw . Save ( "PreserveHTOA" , preserveHTOA ) ;
sw . Save ( "AutoCorrectFilenames" , autoCorrectFilenames ) ;
sw . Save ( "FLACVerify" , flacVerify ) ;
2009-12-24 16:17:42 +00:00
sw . Save ( "FlaCudaVerify" , flaCudaVerify ) ;
sw . Save ( "FlaCudaGPUOnly" , flaCudaGPUOnly ) ;
2010-02-06 23:17:07 +00:00
sw . Save ( "FlaCudaThreads" , flaCudaThreads ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "WVExtraMode" , wvExtraMode ) ;
sw . Save ( "WVStoreMD5" , wvStoreMD5 ) ;
sw . Save ( "KeepOriginalFilenames" , keepOriginalFilenames ) ;
sw . Save ( "SingleFilenameFormat" , singleFilenameFormat ) ;
sw . Save ( "TrackFilenameFormat" , trackFilenameFormat ) ;
sw . Save ( "RemoveSpecialCharacters" , removeSpecial ) ;
sw . Save ( "SpecialCharactersExceptions" , specialExceptions ) ;
sw . Save ( "ReplaceSpaces" , replaceSpaces ) ;
sw . Save ( "EmbedLog" , embedLog ) ;
2009-01-17 04:09:38 +00:00
sw . Save ( "ExtractLog" , extractLog ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "FillUpCUE" , fillUpCUE ) ;
2009-01-17 04:09:38 +00:00
sw . Save ( "OverwriteCUEData" , overwriteCUEData ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "FilenamesANSISafe" , filenamesANSISafe ) ;
2009-03-04 21:30:56 +00:00
if ( bruteForceDTL ) sw . Save ( "BruteForceDTL" , bruteForceDTL ) ;
2010-02-28 21:04:34 +00:00
sw . Save ( "CreateEACLOG" , createEACLOG ) ;
2008-12-07 23:38:00 +00:00
sw . Save ( "DetectHDCD" , detectHDCD ) ;
sw . Save ( "Wait750FramesForHDCD" , wait750FramesForHDCD ) ;
sw . Save ( "DecodeHDCD" , decodeHDCD ) ;
sw . Save ( "CreateM3U" , createM3U ) ;
sw . Save ( "CreateTOC" , createTOC ) ;
sw . Save ( "CreateCUEFileWhenEmbedded" , createCUEFileWhenEmbedded ) ;
sw . Save ( "Truncate4608ExtraSamples" , truncate4608ExtraSamples ) ;
sw . Save ( "LossyWAVQuality" , lossyWAVQuality ) ;
sw . Save ( "DecodeHDCDToLossyWAV16" , decodeHDCDtoLW16 ) ;
sw . Save ( "DecodeHDCDTo24bit" , decodeHDCDto24bit ) ;
2009-03-04 21:30:56 +00:00
sw . Save ( "DisableAsm" , disableAsm ) ;
2009-03-22 16:59:05 +00:00
sw . Save ( "OneInstance" , oneInstance ) ;
2009-06-24 19:40:23 +00:00
sw . Save ( "CheckForUpdates" , checkForUpdates ) ;
2009-03-28 03:57:49 +00:00
sw . Save ( "Language" , language ) ;
2009-05-01 15:16:26 +00:00
2010-02-23 15:15:08 +00:00
sw . Save ( "SeparateDecodingThread" , separateDecodingThread ) ;
sw . Save ( "UseSystemProxySettings" , useSystemProxySettings ) ;
2009-05-01 15:16:26 +00:00
sw . Save ( "WriteBasicTagsFromCUEData" , writeBasicTagsFromCUEData ) ;
sw . Save ( "CopyBasicTags" , copyBasicTags ) ;
sw . Save ( "CopyUnknownTags" , copyUnknownTags ) ;
sw . Save ( "CopyAlbumArt" , copyAlbumArt ) ;
sw . Save ( "EmbedAlbumArt" , embedAlbumArt ) ;
2009-05-13 16:07:53 +00:00
sw . Save ( "ExtractAlbumArt" , extractAlbumArt ) ;
2009-05-01 15:16:26 +00:00
sw . Save ( "MaxAlbumArtSize" , maxAlbumArtSize ) ;
sw . Save ( "ArLogToSourceFolder" , arLogToSourceFolder ) ;
sw . Save ( "ArLogVerbose" , arLogVerbose ) ;
sw . Save ( "FixOffsetToNearest" , fixOffsetToNearest ) ;
2009-08-06 13:03:02 +00:00
sw . Save ( "ArLogFilenameFormat" , arLogFilenameFormat ) ;
sw . Save ( "AlArtFilenameFormat" , alArtFilenameFormat ) ;
2009-05-01 15:16:26 +00:00
int nEncoders = 0 ;
2009-08-06 13:03:02 +00:00
foreach ( CUEToolsUDC encoder in encoders )
{
sw . Save ( string . Format ( "ExternalEncoder{0}Name" , nEncoders ) , encoder . name ) ;
sw . Save ( string . Format ( "ExternalEncoder{0}Modes" , nEncoders ) , encoder . supported_modes ) ;
sw . Save ( string . Format ( "ExternalEncoder{0}Mode" , nEncoders ) , encoder . default_mode ) ;
if ( encoder . path ! = null )
2009-05-01 15:16:26 +00:00
{
2009-08-06 13:03:02 +00:00
sw . Save ( string . Format ( "ExternalEncoder{0}Extension" , nEncoders ) , encoder . extension ) ;
sw . Save ( string . Format ( "ExternalEncoder{0}Path" , nEncoders ) , encoder . path ) ;
sw . Save ( string . Format ( "ExternalEncoder{0}Parameters" , nEncoders ) , encoder . parameters ) ;
sw . Save ( string . Format ( "ExternalEncoder{0}Lossless" , nEncoders ) , encoder . lossless ) ;
2009-05-01 15:16:26 +00:00
}
2009-08-06 13:03:02 +00:00
nEncoders + + ;
}
2009-05-01 15:16:26 +00:00
sw . Save ( "ExternalEncoders" , nEncoders ) ;
int nDecoders = 0 ;
foreach ( KeyValuePair < string , CUEToolsUDC > decoder in decoders )
if ( decoder . Value . path ! = null )
{
sw . Save ( string . Format ( "ExternalDecoder{0}Name" , nDecoders ) , decoder . Key ) ;
sw . Save ( string . Format ( "ExternalDecoder{0}Extension" , nDecoders ) , decoder . Value . extension ) ;
sw . Save ( string . Format ( "ExternalDecoder{0}Path" , nDecoders ) , decoder . Value . path ) ;
sw . Save ( string . Format ( "ExternalDecoder{0}Parameters" , nDecoders ) , decoder . Value . parameters ) ;
nDecoders + + ;
}
sw . Save ( "ExternalDecoders" , nDecoders ) ;
int nFormats = 0 ;
foreach ( KeyValuePair < string , CUEToolsFormat > format in formats )
{
sw . Save ( string . Format ( "CustomFormat{0}Name" , nFormats ) , format . Key ) ;
2009-08-06 13:03:02 +00:00
sw . Save ( string . Format ( "CustomFormat{0}EncoderLossless" , nFormats ) , format . Value . encoderLossless = = null ? "" : format . Value . encoderLossless . Name ) ;
sw . Save ( string . Format ( "CustomFormat{0}EncoderLossy" , nFormats ) , format . Value . encoderLossy = = null ? "" : format . Value . encoderLossy . Name ) ;
2009-05-01 15:16:26 +00:00
sw . Save ( string . Format ( "CustomFormat{0}Decoder" , nFormats ) , format . Value . decoder ) ;
sw . Save ( string . Format ( "CustomFormat{0}Tagger" , nFormats ) , ( int ) format . Value . tagger ) ;
sw . Save ( string . Format ( "CustomFormat{0}AllowLossless" , nFormats ) , format . Value . allowLossless ) ;
sw . Save ( string . Format ( "CustomFormat{0}AllowLossy" , nFormats ) , format . Value . allowLossy ) ;
sw . Save ( string . Format ( "CustomFormat{0}AllowLossyWAV" , nFormats ) , format . Value . allowLossyWAV ) ;
sw . Save ( string . Format ( "CustomFormat{0}AllowEmbed" , nFormats ) , format . Value . allowEmbed ) ;
nFormats + + ;
}
sw . Save ( "CustomFormats" , nFormats ) ;
int nScripts = 0 ;
foreach ( KeyValuePair < string , CUEToolsScript > script in scripts )
{
sw . Save ( string . Format ( "CustomScript{0}Name" , nScripts ) , script . Key ) ;
sw . SaveText ( string . Format ( "CustomScript{0}Code" , nScripts ) , script . Value . code ) ;
int nCondition = 0 ;
foreach ( CUEAction action in script . Value . conditions )
sw . Save ( string . Format ( "CustomScript{0}Condition{1}" , nScripts , nCondition + + ) , ( int ) action ) ;
sw . Save ( string . Format ( "CustomScript{0}Conditions" , nScripts ) , nCondition ) ;
nScripts + + ;
}
sw . Save ( "CustomScripts" , nScripts ) ;
sw . Save ( "DefaultVerifyScript" , defaultVerifyScript ) ;
2009-08-08 16:14:06 +00:00
sw . Save ( "DefaultVerifyAndConvertScript" , defaultEncodeScript ) ;
2009-06-24 19:40:23 +00:00
sw . Save ( "GapsHandling" , ( int ) gapsHandling ) ;
2008-12-07 23:38:00 +00:00
}
public void Load ( SettingsReader sr )
{
2009-06-24 19:40:23 +00:00
int version = sr . LoadInt32 ( "Version" , null , null ) ? ? 202 ;
2009-05-01 15:16:26 +00:00
fixOffsetMinimumConfidence = sr . LoadUInt32 ( "ArFixWhenConfidence" , 1 , 1000 ) ? ? 2 ;
fixOffsetMinimumTracksPercent = sr . LoadUInt32 ( "ArFixWhenPercent" , 1 , 100 ) ? ? 51 ;
2008-12-07 23:38:00 +00:00
encodeWhenConfidence = sr . LoadUInt32 ( "ArEncodeWhenConfidence" , 1 , 1000 ) ? ? 2 ;
encodeWhenPercent = sr . LoadUInt32 ( "ArEncodeWhenPercent" , 1 , 100 ) ? ? 100 ;
encodeWhenZeroOffset = sr . LoadBoolean ( "ArEncodeWhenZeroOffset" ) ? ? false ;
noUnverifiedOutput = sr . LoadBoolean ( "ArNoUnverifiedOutput" ) ? ? false ;
fixOffset = sr . LoadBoolean ( "ArFixOffset" ) ? ? false ;
2009-08-08 16:14:06 +00:00
writeArTagsOnEncode = sr . LoadBoolean ( "ArWriteCRC" ) ? ? true ;
2008-12-07 23:38:00 +00:00
writeArLogOnConvert = sr . LoadBoolean ( "ArWriteLog" ) ? ? true ;
writeArTagsOnVerify = sr . LoadBoolean ( "ArWriteTagsOnVerify" ) ? ? false ;
writeArLogOnVerify = sr . LoadBoolean ( "ArWriteLogOnVerify" ) ? ? true ;
preserveHTOA = sr . LoadBoolean ( "PreserveHTOA" ) ? ? true ;
autoCorrectFilenames = sr . LoadBoolean ( "AutoCorrectFilenames" ) ? ? true ;
flacVerify = sr . LoadBoolean ( "FLACVerify" ) ? ? false ;
2009-12-24 16:17:42 +00:00
flaCudaVerify = sr . LoadBoolean ( "FlaCudaVerify" ) ? ? false ;
flaCudaGPUOnly = sr . LoadBoolean ( "FlaCudaGPUOnly" ) ? ? false ;
2010-02-06 23:17:07 +00:00
flaCudaThreads = sr . LoadBoolean ( "FlaCudaThreads" ) ? ? true ;
2008-12-07 23:38:00 +00:00
wvExtraMode = sr . LoadInt32 ( "WVExtraMode" , 0 , 6 ) ? ? 0 ;
wvStoreMD5 = sr . LoadBoolean ( "WVStoreMD5" ) ? ? false ;
2009-05-01 15:16:26 +00:00
keepOriginalFilenames = sr . LoadBoolean ( "KeepOriginalFilenames" ) ? ? false ;
2009-08-08 16:14:06 +00:00
singleFilenameFormat = sr . Load ( "SingleFilenameFormat" ) ? ? singleFilenameFormat ;
trackFilenameFormat = sr . Load ( "TrackFilenameFormat" ) ? ? trackFilenameFormat ;
2008-12-07 23:38:00 +00:00
removeSpecial = sr . LoadBoolean ( "RemoveSpecialCharacters" ) ? ? false ;
specialExceptions = sr . Load ( "SpecialCharactersExceptions" ) ? ? "-()" ;
2008-12-09 07:25:48 +00:00
replaceSpaces = sr . LoadBoolean ( "ReplaceSpaces" ) ? ? false ;
2008-12-07 23:38:00 +00:00
embedLog = sr . LoadBoolean ( "EmbedLog" ) ? ? true ;
2009-01-17 04:09:38 +00:00
extractLog = sr . LoadBoolean ( "ExtractLog" ) ? ? true ;
2008-12-07 23:38:00 +00:00
fillUpCUE = sr . LoadBoolean ( "FillUpCUE" ) ? ? true ;
2009-01-17 04:09:38 +00:00
overwriteCUEData = sr . LoadBoolean ( "OverwriteCUEData" ) ? ? false ;
2008-12-07 23:38:00 +00:00
filenamesANSISafe = sr . LoadBoolean ( "FilenamesANSISafe" ) ? ? true ;
bruteForceDTL = sr . LoadBoolean ( "BruteForceDTL" ) ? ? false ;
2010-02-28 21:04:34 +00:00
createEACLOG = sr . LoadBoolean ( "CreateEACLOG" ) ? ? createEACLOG ;
2008-12-07 23:38:00 +00:00
detectHDCD = sr . LoadBoolean ( "DetectHDCD" ) ? ? true ;
wait750FramesForHDCD = sr . LoadBoolean ( "Wait750FramesForHDCD" ) ? ? true ;
decodeHDCD = sr . LoadBoolean ( "DecodeHDCD" ) ? ? false ;
createM3U = sr . LoadBoolean ( "CreateM3U" ) ? ? false ;
createTOC = sr . LoadBoolean ( "CreateTOC" ) ? ? false ;
2009-01-17 04:09:38 +00:00
createCUEFileWhenEmbedded = sr . LoadBoolean ( "CreateCUEFileWhenEmbedded" ) ? ? true ;
2008-12-07 23:38:00 +00:00
truncate4608ExtraSamples = sr . LoadBoolean ( "Truncate4608ExtraSamples" ) ? ? true ;
lossyWAVQuality = sr . LoadInt32 ( "LossyWAVQuality" , 0 , 10 ) ? ? 5 ;
decodeHDCDtoLW16 = sr . LoadBoolean ( "DecodeHDCDToLossyWAV16" ) ? ? false ;
decodeHDCDto24bit = sr . LoadBoolean ( "DecodeHDCDTo24bit" ) ? ? true ;
2009-02-19 04:09:59 +00:00
2009-03-04 21:30:56 +00:00
disableAsm = sr . LoadBoolean ( "DisableAsm" ) ? ? false ;
2009-03-22 16:59:05 +00:00
oneInstance = sr . LoadBoolean ( "OneInstance" ) ? ? true ;
2009-06-24 19:40:23 +00:00
checkForUpdates = sr . LoadBoolean ( "CheckForUpdates" ) ? ? true ;
2009-03-04 21:30:56 +00:00
2009-05-01 15:16:26 +00:00
writeBasicTagsFromCUEData = sr . LoadBoolean ( "WriteBasicTagsFromCUEData" ) ? ? true ;
copyBasicTags = sr . LoadBoolean ( "CopyBasicTags" ) ? ? true ;
copyUnknownTags = sr . LoadBoolean ( "CopyUnknownTags" ) ? ? true ;
copyAlbumArt = sr . LoadBoolean ( "CopyAlbumArt" ) ? ? true ;
embedAlbumArt = sr . LoadBoolean ( "EmbedAlbumArt" ) ? ? true ;
2009-05-13 16:07:53 +00:00
extractAlbumArt = sr . LoadBoolean ( "ExtractAlbumArt" ) ? ? true ;
maxAlbumArtSize = sr . LoadInt32 ( "MaxAlbumArtSize" , 100 , 10000 ) ? ? maxAlbumArtSize ;
2009-05-01 15:16:26 +00:00
arLogToSourceFolder = sr . LoadBoolean ( "ArLogToSourceFolder" ) ? ? arLogToSourceFolder ;
arLogVerbose = sr . LoadBoolean ( "ArLogVerbose" ) ? ? arLogVerbose ;
fixOffsetToNearest = sr . LoadBoolean ( "FixOffsetToNearest" ) ? ? fixOffsetToNearest ;
2009-08-06 13:03:02 +00:00
arLogFilenameFormat = sr . Load ( "ArLogFilenameFormat" ) ? ? arLogFilenameFormat ;
alArtFilenameFormat = sr . Load ( "AlArtFilenameFormat" ) ? ? alArtFilenameFormat ;
2009-05-01 15:16:26 +00:00
2010-02-23 15:15:08 +00:00
separateDecodingThread = sr . LoadBoolean ( "SeparateDecodingThread" ) ? ? separateDecodingThread ;
useSystemProxySettings = sr . LoadBoolean ( "UseSystemProxySettings" ) ? ? useSystemProxySettings ;
2009-05-01 15:16:26 +00:00
int totalEncoders = sr . LoadInt32 ( "ExternalEncoders" , 0 , null ) ? ? 0 ;
for ( int nEncoders = 0 ; nEncoders < totalEncoders ; nEncoders + + )
{
string name = sr . Load ( string . Format ( "ExternalEncoder{0}Name" , nEncoders ) ) ;
string extension = sr . Load ( string . Format ( "ExternalEncoder{0}Extension" , nEncoders ) ) ;
string path = sr . Load ( string . Format ( "ExternalEncoder{0}Path" , nEncoders ) ) ;
string parameters = sr . Load ( string . Format ( "ExternalEncoder{0}Parameters" , nEncoders ) ) ;
bool lossless = sr . LoadBoolean ( string . Format ( "ExternalEncoder{0}Lossless" , nEncoders ) ) ? ? true ;
2009-06-24 19:40:23 +00:00
string supported_modes = sr . Load ( string . Format ( "ExternalEncoder{0}Modes" , nEncoders ) ) ? ? "" ;
string default_mode = sr . Load ( string . Format ( "ExternalEncoder{0}Mode" , nEncoders ) ) ? ? "" ;
2009-05-01 15:16:26 +00:00
CUEToolsUDC encoder ;
2009-08-06 13:03:02 +00:00
if ( name = = null ) continue ;
2009-05-01 15:16:26 +00:00
if ( ! encoders . TryGetValue ( name , out encoder ) )
2009-08-06 13:03:02 +00:00
{
if ( path = = null | | parameters = = null | | extension = = null ) continue ;
encoders . Add ( new CUEToolsUDC ( name , extension , lossless , supported_modes , default_mode , path , parameters ) ) ;
}
2009-06-24 19:40:23 +00:00
else if ( version = = 203 )
2009-05-01 15:16:26 +00:00
{
if ( encoder . path ! = null )
{
2009-08-06 13:03:02 +00:00
if ( path = = null | | parameters = = null | | extension = = null ) continue ;
2009-05-01 15:16:26 +00:00
encoder . extension = extension ;
encoder . path = path ;
encoder . parameters = parameters ;
encoder . lossless = lossless ;
}
2009-06-24 19:40:23 +00:00
encoder . supported_modes = supported_modes ;
encoder . default_mode = default_mode ;
2009-05-01 15:16:26 +00:00
}
}
int totalDecoders = sr . LoadInt32 ( "ExternalDecoders" , 0 , null ) ? ? 0 ;
for ( int nDecoders = 0 ; nDecoders < totalDecoders ; nDecoders + + )
{
string name = sr . Load ( string . Format ( "ExternalDecoder{0}Name" , nDecoders ) ) ;
string extension = sr . Load ( string . Format ( "ExternalDecoder{0}Extension" , nDecoders ) ) ;
string path = sr . Load ( string . Format ( "ExternalDecoder{0}Path" , nDecoders ) ) ;
string parameters = sr . Load ( string . Format ( "ExternalDecoder{0}Parameters" , nDecoders ) ) ;
CUEToolsUDC decoder ;
if ( ! decoders . TryGetValue ( name , out decoder ) )
2009-06-24 19:40:23 +00:00
decoders . Add ( name , new CUEToolsUDC ( name , extension , true , "" , "" , path , parameters ) ) ;
2009-05-01 15:16:26 +00:00
else
{
decoder . extension = extension ;
decoder . path = path ;
decoder . parameters = parameters ;
}
}
int totalFormats = sr . LoadInt32 ( "CustomFormats" , 0 , null ) ? ? 0 ;
for ( int nFormats = 0 ; nFormats < totalFormats ; nFormats + + )
{
string extension = sr . Load ( string . Format ( "CustomFormat{0}Name" , nFormats ) ) ;
2009-08-06 13:03:02 +00:00
string encoderLossless = sr . Load ( string . Format ( "CustomFormat{0}EncoderLossless" , nFormats ) ) ? ? "" ;
string encoderLossy = sr . Load ( string . Format ( "CustomFormat{0}EncoderLossy" , nFormats ) ) ? ? "" ;
2009-05-01 15:16:26 +00:00
string decoder = sr . Load ( string . Format ( "CustomFormat{0}Decoder" , nFormats ) ) ;
CUEToolsTagger tagger = ( CUEToolsTagger ) ( sr . LoadInt32 ( string . Format ( "CustomFormat{0}Tagger" , nFormats ) , 0 , 2 ) ? ? 0 ) ;
bool allowLossless = sr . LoadBoolean ( string . Format ( "CustomFormat{0}AllowLossless" , nFormats ) ) ? ? false ;
bool allowLossy = sr . LoadBoolean ( string . Format ( "CustomFormat{0}AllowLossy" , nFormats ) ) ? ? false ;
bool allowLossyWav = sr . LoadBoolean ( string . Format ( "CustomFormat{0}AllowLossyWAV" , nFormats ) ) ? ? false ;
bool allowEmbed = sr . LoadBoolean ( string . Format ( "CustomFormat{0}AllowEmbed" , nFormats ) ) ? ? false ;
CUEToolsFormat format ;
2009-08-06 13:03:02 +00:00
CUEToolsUDC udcLossless , udcLossy ;
if ( encoderLossless = = "" | | ! encoders . TryGetValue ( encoderLossless , out udcLossless ) )
udcLossless = null ;
if ( encoderLossy = = "" | | ! encoders . TryGetValue ( encoderLossy , out udcLossy ) )
udcLossy = null ;
2009-05-01 15:16:26 +00:00
if ( ! formats . TryGetValue ( extension , out format ) )
2009-08-06 13:03:02 +00:00
formats . Add ( extension , new CUEToolsFormat ( extension , tagger , allowLossless , allowLossy , allowLossyWav , allowEmbed , false , udcLossless , udcLossy , decoder ) ) ;
2009-05-01 15:16:26 +00:00
else
{
2009-08-06 13:03:02 +00:00
format . encoderLossless = udcLossless ;
format . encoderLossy = udcLossy ;
2009-05-01 15:16:26 +00:00
format . decoder = decoder ;
if ( ! format . builtin )
{
format . tagger = tagger ;
format . allowLossless = allowLossless ;
format . allowLossy = allowLossy ;
format . allowLossyWAV = allowLossyWav ;
format . allowEmbed = allowEmbed ;
}
}
}
int totalScripts = sr . LoadInt32 ( "CustomScripts" , 0 , null ) ? ? 0 ;
for ( int nScripts = 0 ; nScripts < totalScripts ; nScripts + + )
{
string name = sr . Load ( string . Format ( "CustomScript{0}Name" , nScripts ) ) ;
string code = sr . Load ( string . Format ( "CustomScript{0}Code" , nScripts ) ) ;
List < CUEAction > conditions = new List < CUEAction > ( ) ;
int totalConditions = sr . LoadInt32 ( string . Format ( "CustomScript{0}Conditions" , nScripts ) , 0 , null ) ? ? 0 ;
for ( int nCondition = 0 ; nCondition < totalConditions ; nCondition + + )
conditions . Add ( ( CUEAction ) sr . LoadInt32 ( string . Format ( "CustomScript{0}Condition{1}" , nScripts , nCondition ) , 0 , null ) ) ;
CUEToolsScript script ;
if ( ! scripts . TryGetValue ( name , out script ) )
scripts . Add ( name , new CUEToolsScript ( name , false , conditions , code ) ) ;
else
{
if ( ! script . builtin )
{
script . code = code ;
script . conditions = conditions ;
}
}
}
defaultVerifyScript = sr . Load ( "DefaultVerifyScript" ) ? ? "default" ;
2009-08-08 16:14:06 +00:00
defaultEncodeScript = sr . Load ( "DefaultVerifyAndConvertScript" ) ? ? "default" ;
2009-03-28 03:57:49 +00:00
2009-06-24 19:40:23 +00:00
gapsHandling = ( CUEStyle ? ) sr . LoadInt32 ( "GapsHandling" , null , null ) ? ? gapsHandling ;
2009-03-28 03:57:49 +00:00
language = sr . Load ( "Language" ) ? ? Thread . CurrentThread . CurrentUICulture . Name ;
2009-08-08 16:14:06 +00:00
if ( arLogFilenameFormat . Contains ( "%F" ) )
arLogFilenameFormat = "%filename%.accurip" ;
if ( singleFilenameFormat . Contains ( "%F" ) )
singleFilenameFormat = "%filename%" ;
if ( trackFilenameFormat . Contains ( "%N" ) )
trackFilenameFormat = "%tracknumber%. %title%" ;
2008-12-07 23:38:00 +00:00
}
2010-02-08 01:29:31 +00:00
public string GetDefaultDecoder ( string extension )
{
CUEToolsUDC result = null ;
foreach ( KeyValuePair < string , CUEToolsUDC > decoder in decoders )
if ( decoder . Value . Extension = = extension & & ( result = = null | | result . priority < decoder . Value . priority ) )
result = decoder . Value ;
return result = = null ? null : result . Name ;
}
2008-12-07 23:38:00 +00:00
public string CleanseString ( string s )
{
StringBuilder sb = new StringBuilder ( ) ;
char [ ] invalid = Path . GetInvalidFileNameChars ( ) ;
if ( filenamesANSISafe )
s = Encoding . Default . GetString ( Encoding . Default . GetBytes ( s ) ) ;
for ( int i = 0 ; i < s . Length ; i + + )
{
char ch = s [ i ] ;
if ( filenamesANSISafe & & removeSpecial & & specialExceptions . IndexOf ( ch ) < 0 & & ! (
( ( ch > = 'a' ) & & ( ch < = 'z' ) ) | |
( ( ch > = 'A' ) & & ( ch < = 'Z' ) ) | |
( ( ch > = '0' ) & & ( ch < = '9' ) ) | |
( ch = = ' ' ) | | ( ch = = '_' ) ) )
ch = '_' ;
if ( ( Array . IndexOf ( invalid , ch ) > = 0 ) | | ( replaceSpaces & & ch = = ' ' ) )
sb . Append ( "_" ) ;
else
sb . Append ( ch ) ;
}
return sb . ToString ( ) ;
}
}
2009-08-06 13:03:02 +00:00
public class CUEToolsProfile
{
public CUEToolsProfile ( string name )
{
_config = new CUEConfig ( ) ;
_name = name ;
switch ( name )
{
case "verify" :
_action = CUEAction . Verify ;
_script = "only if found" ;
break ;
case "convert" :
2009-08-08 16:14:06 +00:00
_action = CUEAction . Encode ;
2009-08-06 13:03:02 +00:00
break ;
case "fix" :
2009-08-08 16:14:06 +00:00
_action = CUEAction . Encode ;
2009-08-06 13:03:02 +00:00
_script = "fix offset" ;
break ;
}
}
public void Load ( SettingsReader sr )
{
_config . Load ( sr ) ;
_useFreeDb = sr . LoadBoolean ( "FreedbLookup" ) ? ? _useFreeDb ;
_useMusicBrainz = sr . LoadBoolean ( "MusicBrainzLookup" ) ? ? _useMusicBrainz ;
_useAccurateRip = sr . LoadBoolean ( "AccurateRipLookup" ) ? ? _useAccurateRip ;
2010-02-23 15:15:08 +00:00
_useCUEToolsDB = sr . LoadBoolean ( "CUEToolsDBLookup" ) ? ? _useCUEToolsDB ;
2009-08-06 13:03:02 +00:00
_outputAudioType = ( AudioEncoderType ? ) sr . LoadInt32 ( "OutputAudioType" , null , null ) ? ? _outputAudioType ;
_outputAudioFormat = sr . Load ( "OutputAudioFmt" ) ? ? _outputAudioFormat ;
2009-08-08 16:14:06 +00:00
_action = ( CUEAction ? ) sr . LoadInt32 ( "AccurateRipMode" , ( int ) CUEAction . Encode , ( int ) CUEAction . CorrectFilenames ) ? ? _action ;
2009-08-06 13:03:02 +00:00
_CUEStyle = ( CUEStyle ? ) sr . LoadInt32 ( "CUEStyle" , null , null ) ? ? _CUEStyle ;
_writeOffset = sr . LoadInt32 ( "WriteOffset" , null , null ) ? ? 0 ;
_outputTemplate = sr . Load ( "OutputPathTemplate" ) ? ? _outputTemplate ;
_script = sr . Load ( "Script" ) ? ? _script ;
}
public void Save ( SettingsWriter sw )
{
_config . Save ( sw ) ;
sw . Save ( "FreedbLookup" , _useFreeDb ) ;
sw . Save ( "MusicBrainzLookup" , _useMusicBrainz ) ;
sw . Save ( "AccurateRipLookup" , _useAccurateRip ) ;
2010-02-23 15:15:08 +00:00
sw . Save ( "CUEToolsDBLookup" , _useCUEToolsDB ) ;
2009-08-06 13:03:02 +00:00
sw . Save ( "OutputAudioType" , ( int ) _outputAudioType ) ;
sw . Save ( "OutputAudioFmt" , _outputAudioFormat ) ;
sw . Save ( "AccurateRipMode" , ( int ) _action ) ;
sw . Save ( "CUEStyle" , ( int ) _CUEStyle ) ;
sw . Save ( "WriteOffset" , ( int ) _writeOffset ) ;
sw . Save ( "OutputPathTemplate" , _outputTemplate ) ;
sw . Save ( "Script" , _script ) ;
}
public CUEConfig _config ;
public AudioEncoderType _outputAudioType = AudioEncoderType . Lossless ;
public string _outputAudioFormat = "flac" , _outputTemplate = null , _script = "default" ;
2009-08-08 16:14:06 +00:00
public CUEAction _action = CUEAction . Encode ;
2009-08-06 13:03:02 +00:00
public CUEStyle _CUEStyle = CUEStyle . SingleFileWithCUE ;
public int _writeOffset = 0 ;
2010-02-23 15:15:08 +00:00
public bool _useFreeDb = true , _useMusicBrainz = true , _useAccurateRip = true , _useCUEToolsDB = true ;
2009-08-06 13:03:02 +00:00
public string _name ;
}
2010-02-08 01:29:31 +00:00
public class CUEToolsProgressEventArgs : EventArgs
2008-12-07 23:38:00 +00:00
{
public string status = string . Empty ;
2008-12-09 07:25:48 +00:00
public double percentTrck = 0 ;
2008-12-07 23:38:00 +00:00
public double percentDisk = 0.0 ;
2009-08-21 03:26:12 +00:00
public int offset = 0 ;
2008-12-07 23:38:00 +00:00
public string input = string . Empty ;
public string output = string . Empty ;
}
2010-02-08 01:29:31 +00:00
public class CUEToolsSelectionEventArgs : EventArgs
2008-12-07 23:38:00 +00:00
{
2010-02-08 01:29:31 +00:00
public object [ ] choices ;
public int selection = - 1 ;
2008-12-07 23:38:00 +00:00
}
2009-02-22 07:47:56 +00:00
public class CUEToolsSourceFile
{
public string path ;
public string contents ;
2010-02-23 15:15:08 +00:00
public object data ;
2009-02-22 07:47:56 +00:00
2010-02-23 15:15:08 +00:00
public CUEToolsSourceFile ( string _path , TextReader reader )
2009-02-22 07:47:56 +00:00
{
path = _path ;
contents = reader . ReadToEnd ( ) ;
reader . Close ( ) ;
}
}
2008-12-07 23:38:00 +00:00
public class CUESheet {
private bool _stop , _pause ;
private List < CUELine > _attributes ;
private List < TrackInfo > _tracks ;
private List < SourceInfo > _sources ;
private List < string > _sourcePaths , _trackFilenames ;
private string _htoaFilename , _singleFilename ;
2008-12-09 07:25:48 +00:00
private bool _hasHTOAFilename = false , _hasTrackFilenames = false , _hasSingleFilename = false , _appliedWriteOffset ;
2008-12-07 23:38:00 +00:00
private bool _hasEmbeddedCUESheet ;
private bool _paddedToFrame , _truncated4608 , _usePregapForFirstTrackInSingleFile ;
private int _writeOffset ;
2009-03-22 16:59:05 +00:00
private CUEAction _action ;
2009-08-08 16:14:06 +00:00
private bool _useAccurateRip = false ;
2010-02-23 15:15:08 +00:00
private bool _useCUEToolsDB = false ;
private bool _useCUEToolsDBFix = false ;
private bool _useCUEToolsDBSibmit = false ;
private bool _processed = false ;
2008-12-07 23:38:00 +00:00
private uint? _minDataTrackLength ;
private string _accurateRipId ;
private string _eacLog ;
2009-05-01 15:16:26 +00:00
private string _inputPath , _inputDir ;
private string _outputPath ;
2009-05-10 18:34:49 +00:00
private string [ ] _destPaths ;
2009-02-19 04:09:59 +00:00
private TagLib . File _fileInfo ;
2008-12-07 23:38:00 +00:00
private const int _arOffsetRange = 5 * 588 - 1 ;
2010-02-08 01:29:31 +00:00
private IAudioDest hdcdDecoder ;
2009-05-01 15:16:26 +00:00
private AudioEncoderType _audioEncoderType = AudioEncoderType . Lossless ;
2008-12-07 23:38:00 +00:00
private bool _outputLossyWAV = false ;
2009-05-01 15:16:26 +00:00
private string _outputFormat = "wav" ;
private CUEStyle _outputStyle = CUEStyle . SingleFile ;
2008-12-09 07:25:48 +00:00
private CUEConfig _config ;
private string _cddbDiscIdTag ;
private bool _isCD ;
2009-03-04 21:30:56 +00:00
private string _ripperLog ;
2010-02-08 01:29:31 +00:00
private ICDRipper _ripper ;
2008-12-07 23:38:00 +00:00
private bool _isArchive ;
private List < string > _archiveContents ;
private string _archiveCUEpath ;
2010-02-08 01:29:31 +00:00
private ICompressionProvider _archive ;
2008-12-07 23:38:00 +00:00
private string _archivePassword ;
private CUEToolsProgressEventArgs _progress ;
private AccurateRipVerify _arVerify ;
2010-02-23 15:15:08 +00:00
private CUEToolsDB _CUEToolsDB ;
2008-12-09 07:25:48 +00:00
private CDImageLayout _toc ;
2009-08-06 13:03:02 +00:00
private string _arLogFileName , _alArtFileName ;
private TagLib . IPicture [ ] _albumArt ;
2009-08-08 16:14:06 +00:00
private int _padding = 8192 ;
2010-02-23 15:15:08 +00:00
private IWebProxy proxy ;
2008-12-07 23:38:00 +00:00
2010-02-08 01:29:31 +00:00
public event EventHandler < CompressionPasswordRequiredEventArgs > PasswordRequired ;
public event EventHandler < CUEToolsProgressEventArgs > CUEToolsProgress ;
public event EventHandler < CUEToolsSelectionEventArgs > CUEToolsSelection ;
2008-12-07 23:38:00 +00:00
public CUESheet ( CUEConfig config )
{
_config = config ;
_progress = new CUEToolsProgressEventArgs ( ) ;
_attributes = new List < CUELine > ( ) ;
_tracks = new List < TrackInfo > ( ) ;
2008-12-09 07:25:48 +00:00
_trackFilenames = new List < string > ( ) ;
_toc = new CDImageLayout ( ) ;
2008-12-07 23:38:00 +00:00
_sources = new List < SourceInfo > ( ) ;
_sourcePaths = new List < string > ( ) ;
_stop = false ;
_pause = false ;
2009-05-01 15:16:26 +00:00
_outputPath = null ;
2008-12-07 23:38:00 +00:00
_paddedToFrame = false ;
_truncated4608 = false ;
_usePregapForFirstTrackInSingleFile = false ;
2009-08-08 16:14:06 +00:00
_action = CUEAction . Encode ;
2008-12-07 23:38:00 +00:00
_appliedWriteOffset = false ;
_minDataTrackLength = null ;
hdcdDecoder = null ;
_hasEmbeddedCUESheet = false ;
_isArchive = false ;
2008-12-09 07:25:48 +00:00
_isCD = false ;
2009-08-06 13:03:02 +00:00
_albumArt = null ;
2010-02-23 15:15:08 +00:00
proxy = _config . useSystemProxySettings ? WebRequest . GetSystemWebProxy ( ) : null ;
2008-12-07 23:38:00 +00:00
}
2010-02-08 01:29:31 +00:00
public void OpenCD ( ICDRipper ripper )
2008-12-07 23:38:00 +00:00
{
2008-12-10 06:48:38 +00:00
_ripper = ripper ;
_toc = ( CDImageLayout ) _ripper . TOC . Clone ( ) ;
2008-12-09 07:25:48 +00:00
for ( int iTrack = 0 ; iTrack < _toc . AudioTracks ; iTrack + + )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
_trackFilenames . Add ( string . Format ( "{0:00}.wav" , iTrack + 1 ) ) ;
_tracks . Add ( new TrackInfo ( ) ) ;
}
2010-02-23 15:15:08 +00:00
_arVerify = new AccurateRipVerify ( _toc , proxy ) ;
2008-12-10 06:48:38 +00:00
_isCD = true ;
SourceInfo cdInfo ;
cdInfo . Path = _ripper . ARName ;
cdInfo . Offset = 0 ;
cdInfo . Length = _toc . AudioLength * 588 ;
_sources . Add ( cdInfo ) ;
2010-03-20 07:09:07 +00:00
// Causes memory leak, so had to disable!
//_ripper.ReadProgress += new EventHandler<ReadProgressArgs>(CDReadProgress);
2010-03-03 23:52:46 +00:00
_padding + = TrackCount * 200 ;
_padding + = _config . embedLog ? 500 + TrackCount * 200 : 0 ;
2008-12-10 06:48:38 +00:00
}
public void Close ( )
{
2010-02-08 01:29:31 +00:00
if ( _archive ! = null )
_archive . Close ( ) ;
_archive = null ;
2008-12-10 06:48:38 +00:00
if ( _ripper ! = null )
2010-03-20 07:09:07 +00:00
{
//_ripper.ReadProgress -= new EventHandler<ReadProgressArgs>(CDReadProgress);
2008-12-10 06:48:38 +00:00
_ripper . Close ( ) ;
2010-03-20 07:09:07 +00:00
}
2008-12-10 06:48:38 +00:00
_ripper = null ;
}
public AccurateRipVerify ArVerify
{
get
{
return _arVerify ;
}
}
2010-02-23 15:15:08 +00:00
public CUEToolsDB CTDB
{
get
{
return _CUEToolsDB ;
}
}
2010-02-08 01:29:31 +00:00
public ICDRipper CDRipper
2009-05-10 18:34:49 +00:00
{
get
{
return _ripper ;
}
set
{
_ripper = value ;
}
}
2010-02-06 23:17:07 +00:00
public void CopyMetadata ( CUESheet metadata )
{
TotalDiscs = metadata . TotalDiscs ;
DiscNumber = metadata . DiscNumber ;
Year = metadata . Year ;
Genre = metadata . Genre ;
Artist = metadata . Artist ;
Title = metadata . Title ;
for ( int i = 0 ; i < Tracks . Count ; i + + )
{
Tracks [ i ] . Title = metadata . Tracks [ i ] . Title ;
Tracks [ i ] . Artist = metadata . Tracks [ i ] . Artist ;
}
}
2009-01-17 04:09:38 +00:00
public void FillFromMusicBrainz ( MusicBrainz . Release release )
2008-12-10 06:48:38 +00:00
{
2010-03-20 07:09:07 +00:00
string date = release . GetEvents ( ) . Count > 0 ? release . GetEvents ( ) [ 0 ] . Date : null ;
Year = date = = null ? "" : date . Substring ( 0 , 4 ) ;
2008-12-10 06:48:38 +00:00
Artist = release . GetArtist ( ) ;
Title = release . GetTitle ( ) ;
2010-02-06 23:17:07 +00:00
// How to get Genre: http://mm.musicbrainz.org/ws/1/release/6fe1e218-2aee-49ac-94f0-7910ba2151df.html?type=xml&inc=tags
2009-01-17 04:09:38 +00:00
//Catalog = release.GetEvents().Count > 0 ? release.GetEvents()[0].Barcode : "";
2008-12-10 06:48:38 +00:00
for ( int i = 1 ; i < = _toc . AudioTracks ; i + + )
{
2009-01-28 04:53:13 +00:00
MusicBrainz . Track track = release . GetTracks ( ) [ ( int ) _toc [ i ] . Number - 1 ] ; // !!!!!! - _toc.FirstAudio
2008-12-10 06:48:38 +00:00
Tracks [ i - 1 ] . Title = track . GetTitle ( ) ;
Tracks [ i - 1 ] . Artist = track . GetArtist ( ) ;
}
2008-12-09 07:25:48 +00:00
}
2009-01-17 04:09:38 +00:00
public void FillFromFreedb ( Freedb . CDEntry cdEntry )
{
Year = cdEntry . Year ;
Genre = cdEntry . Genre ;
Artist = cdEntry . Artist ;
Title = cdEntry . Title ;
for ( int i = 0 ; i < _toc . AudioTracks ; i + + )
2009-03-04 21:30:56 +00:00
{
2010-03-20 07:09:07 +00:00
Tracks [ i ] . Title = cdEntry . Tracks [ i + _toc . FirstAudio - 1 ] . Title ;
2009-03-04 21:30:56 +00:00
Tracks [ i ] . Artist = cdEntry . Artist ;
}
2009-01-17 04:09:38 +00:00
}
2009-08-06 13:03:02 +00:00
public List < object > LookupAlbumInfo ( bool useFreedb , bool useMusicBrainz )
2009-01-17 04:09:38 +00:00
{
List < object > Releases = new List < object > ( ) ;
2009-08-06 13:03:02 +00:00
if ( useFreedb )
{
2009-08-21 03:26:12 +00:00
ShowProgress ( "Looking up album via Freedb..." , 0.0 , 0.0 , null , null ) ;
2009-03-04 21:30:56 +00:00
2009-08-06 13:03:02 +00:00
FreedbHelper m_freedb = new FreedbHelper ( ) ;
2009-01-17 04:09:38 +00:00
2009-08-06 13:03:02 +00:00
m_freedb . UserName = "gchudov" ;
m_freedb . Hostname = "gmail.com" ;
m_freedb . ClientName = "CUETools" ;
2010-03-25 01:05:26 +00:00
m_freedb . Version = "2.0.7" ;
2009-08-06 13:03:02 +00:00
m_freedb . SetDefaultSiteAddress ( "freedb.org" ) ;
2009-01-17 04:09:38 +00:00
2009-08-06 13:03:02 +00:00
QueryResult queryResult ;
QueryResultCollection coll ;
string code = string . Empty ;
try
2009-01-17 04:09:38 +00:00
{
2009-08-06 13:03:02 +00:00
CDEntry cdEntry = null ;
code = m_freedb . Query ( AccurateRipVerify . CalculateCDDBQuery ( _toc ) , out queryResult , out coll ) ;
if ( code = = FreedbHelper . ResponseCodes . CODE_200 )
2009-01-17 04:09:38 +00:00
{
2010-03-20 07:09:07 +00:00
ShowProgress ( "Looking up album via Freedb... " + queryResult . Discid , 0.5 , 0.0 , null , null ) ;
2009-08-06 13:03:02 +00:00
code = m_freedb . Read ( queryResult , out cdEntry ) ;
if ( code = = FreedbHelper . ResponseCodes . CODE_210 )
Releases . Add ( cdEntry ) ;
}
else
if ( code = = FreedbHelper . ResponseCodes . CODE_210 | |
code = = FreedbHelper . ResponseCodes . CODE_211 )
2009-01-17 04:09:38 +00:00
{
2009-08-06 13:03:02 +00:00
int i = 0 ;
foreach ( QueryResult qr in coll )
{
2010-03-20 07:09:07 +00:00
ShowProgress ( "Looking up album via freedb... " + qr . Discid , 0.0 , ( + + i + 0.0 ) / coll . Count , null , null ) ;
2009-08-06 13:03:02 +00:00
CheckStop ( ) ;
code = m_freedb . Read ( qr , out cdEntry ) ;
if ( code = = FreedbHelper . ResponseCodes . CODE_210 )
Releases . Add ( cdEntry ) ;
}
2009-01-17 04:09:38 +00:00
}
2009-08-06 13:03:02 +00:00
}
catch ( Exception ex )
{
if ( ex is StopException )
throw ex ;
}
2009-01-17 04:09:38 +00:00
}
2009-02-27 14:41:55 +00:00
2009-08-06 13:03:02 +00:00
if ( useMusicBrainz )
2009-02-27 14:41:55 +00:00
{
2009-08-21 03:26:12 +00:00
ShowProgress ( "Looking up album via MusicBrainz..." , 0.0 , 0.0 , null , null ) ;
2009-08-06 13:03:02 +00:00
StringCollection DiscIds = new StringCollection ( ) ;
DiscIds . Add ( _toc . MusicBrainzId ) ;
//if (_tocFromLog != null && !DiscIds.Contains(_tocFromLog.MusicBrainzId))
// DiscIds.Add(_tocFromLog.MusicBrainzId);
foreach ( CDEntry cdEntry in Releases )
{
CDImageLayout toc = TocFromCDEntry ( cdEntry ) ;
if ( ! DiscIds . Contains ( toc . MusicBrainzId ) )
DiscIds . Add ( toc . MusicBrainzId ) ;
}
2009-02-27 14:41:55 +00:00
2009-08-06 13:03:02 +00:00
MusicBrainzService . XmlRequest + = new EventHandler < XmlRequestEventArgs > ( MusicBrainz_LookupProgress ) ;
foreach ( string DiscId in DiscIds )
2009-02-27 14:41:55 +00:00
{
2009-08-06 13:03:02 +00:00
ReleaseQueryParameters p = new ReleaseQueryParameters ( ) ;
p . DiscId = DiscId ;
Query < Release > results = Release . Query ( p ) ;
try
2009-02-27 14:41:55 +00:00
{
2009-08-06 13:03:02 +00:00
foreach ( MusicBrainz . Release release in results )
2009-02-27 14:41:55 +00:00
{
2009-08-06 13:03:02 +00:00
release . GetEvents ( ) ;
release . GetTracks ( ) ;
try
{
foreach ( MusicBrainz . Track track in release . GetTracks ( ) )
;
}
catch { }
try
{
foreach ( MusicBrainz . Event ev in release . GetEvents ( ) )
;
}
catch { }
Releases . Add ( release ) ;
2009-02-27 14:41:55 +00:00
}
}
2009-08-06 13:03:02 +00:00
catch { }
2009-02-27 14:41:55 +00:00
}
2009-08-06 13:03:02 +00:00
MusicBrainzService . XmlRequest - = new EventHandler < XmlRequestEventArgs > ( MusicBrainz_LookupProgress ) ;
//if (release != null)
//{
// FillFromMusicBrainz(release);
// return;
//}
//if (cdEntry != null)
// FillFromFreedb(cdEntry);
2009-02-27 14:41:55 +00:00
}
2009-01-17 04:09:38 +00:00
return Releases ;
}
2009-02-27 14:41:55 +00:00
public CDImageLayout TocFromCDEntry ( CDEntry cdEntry )
{
CDImageLayout tocFromCDEntry = new CDImageLayout ( ) ;
for ( int i = 0 ; i < cdEntry . Tracks . Count ; i + + )
{
if ( i > = _toc . TrackCount )
break ;
tocFromCDEntry . AddTrack ( new CDTrack ( ( uint ) i + 1 ,
( uint ) cdEntry . Tracks [ i ] . FrameOffset - 150 ,
( i + 1 < cdEntry . Tracks . Count ) ? ( uint ) ( cdEntry . Tracks [ i + 1 ] . FrameOffset - cdEntry . Tracks [ i ] . FrameOffset ) : _toc [ i + 1 ] . Length ,
_toc [ i + 1 ] . IsAudio ,
false /*preEmphasis*/ ) ) ;
}
if ( tocFromCDEntry . TrackCount > 0 & & tocFromCDEntry [ 1 ] . IsAudio )
tocFromCDEntry [ 1 ] [ 0 ] . Start = 0 ;
return tocFromCDEntry ;
}
public CDImageLayout TocFromLog ( string eacLog )
{
CDImageLayout tocFromLog = new CDImageLayout ( ) ;
using ( StringReader sr = new StringReader ( eacLog ) )
{
bool isEACLog = false ;
bool iscdda2wavlog = false ;
string lineStr ;
int prevTrNo = 1 , prevTrStart = 0 ;
2009-05-01 15:16:26 +00:00
uint firstPreGap = 0 ;
2009-02-27 14:41:55 +00:00
while ( ( lineStr = sr . ReadLine ( ) ) ! = null )
{
if ( isEACLog )
{
string [ ] n = lineStr . Split ( '|' ) ;
uint trNo , trStart , trEnd ;
if ( n . Length = = 5 & & uint . TryParse ( n [ 0 ] , out trNo ) & & uint . TryParse ( n [ 3 ] , out trStart ) & & uint . TryParse ( n [ 4 ] , out trEnd ) & & trNo = = tocFromLog . TrackCount + 1 )
{
bool isAudio = true ;
if ( tocFromLog . TrackCount > = _toc . TrackCount & &
trStart = = tocFromLog [ tocFromLog . TrackCount ] . End + 1 U + 152 U * 75 U
)
isAudio = false ;
if ( tocFromLog . TrackCount < _toc . TrackCount & &
! _toc [ tocFromLog . TrackCount + 1 ] . IsAudio
)
isAudio = false ;
tocFromLog . AddTrack ( new CDTrack ( trNo , trStart , trEnd + 1 - trStart , isAudio , false ) ) ;
}
2009-05-01 15:16:26 +00:00
else
{
string [ ] sepTrack = { "Track" } ;
string [ ] sepGap = { "Pre-gap length" } ;
string [ ] partsTrack = lineStr . Split ( sepTrack , StringSplitOptions . None ) ;
if ( partsTrack . Length = = 2 & & uint . TryParse ( partsTrack [ 1 ] , out trNo ) )
{
prevTrNo = ( int ) trNo ;
continue ;
}
string [ ] partsGap = lineStr . Split ( sepGap , StringSplitOptions . None ) ;
if ( partsGap . Length = = 2 )
{
string [ ] n1 = partsGap [ 1 ] . Split ( ':' , '.' ) ;
int h , m , s , f ;
if ( n1 . Length = = 4 & & int . TryParse ( n1 [ 0 ] , out h ) & & int . TryParse ( n1 [ 1 ] , out m ) & & int . TryParse ( n1 [ 2 ] , out s ) & & int . TryParse ( n1 [ 3 ] , out f ) )
{
uint gap = ( uint ) ( ( f * 3 + 2 ) / 4 + 75 * ( s + 60 * ( m + 60 * h ) ) ) ;
if ( prevTrNo = = 1 )
gap - = 150 ;
if ( prevTrNo = = 1 )
firstPreGap = gap - _toc [ 1 ] . Start ;
//else
//firstPreGap += gap;
while ( prevTrNo > tocFromLog . TrackCount & & _toc . TrackCount > tocFromLog . TrackCount )
{
tocFromLog . AddTrack ( new CDTrack ( ( uint ) tocFromLog . TrackCount + 1 ,
_toc [ tocFromLog . TrackCount + 1 ] . Start + firstPreGap ,
_toc [ tocFromLog . TrackCount + 1 ] . Length ,
_toc [ tocFromLog . TrackCount + 1 ] . IsAudio , false ) ) ;
}
if ( prevTrNo < = tocFromLog . TrackCount )
tocFromLog [ prevTrNo ] . Pregap = gap ;
}
}
}
2009-02-27 14:41:55 +00:00
}
else if ( iscdda2wavlog )
{
foreach ( string entry in lineStr . Split ( ',' ) )
{
string [ ] n = entry . Split ( '(' ) ;
if ( n . Length < 2 ) continue ;
// assert n.Length == 2;
string key = n [ 0 ] . Trim ( ' ' , '.' ) ;
int trStart = int . Parse ( n [ 1 ] . Trim ( ' ' , ')' ) ) ;
bool isAudio = true ; // !!!
if ( key ! = "1" )
tocFromLog . AddTrack ( new CDTrack ( ( uint ) prevTrNo , ( uint ) prevTrStart , ( uint ) ( trStart - prevTrStart ) , isAudio , false ) ) ;
if ( key = = "lead-out" )
{
iscdda2wavlog = false ;
break ;
}
prevTrNo = int . Parse ( key ) ;
prevTrStart = trStart ;
}
}
else if ( lineStr . StartsWith ( "TOC of the extracted CD" )
| | lineStr . StartsWith ( "Exact Audio Copy" )
| | lineStr . StartsWith ( "EAC extraction logfile" )
| | lineStr . StartsWith ( "CUERipper" ) )
isEACLog = true ;
else if ( lineStr . StartsWith ( "Table of Contents: starting sectors" ) )
iscdda2wavlog = true ;
}
}
2009-03-04 21:30:56 +00:00
if ( tocFromLog . TrackCount = = 0 )
return null ;
tocFromLog [ 1 ] [ 0 ] . Start = 0 ;
2009-02-27 14:41:55 +00:00
return tocFromLog ;
}
2008-12-09 07:25:48 +00:00
public void Open ( string pathIn )
{
2009-05-01 15:16:26 +00:00
_inputPath = pathIn ;
_inputDir = Path . GetDirectoryName ( _inputPath ) ? ? _inputPath ;
if ( _inputDir = = "" ) _inputDir = "." ;
2010-02-08 01:29:31 +00:00
if ( _inputDir = = pathIn & & CUEProcessorPlugins . ripper ! = null )
2008-12-09 07:25:48 +00:00
{
2010-02-08 01:29:31 +00:00
ICDRipper ripper = Activator . CreateInstance ( CUEProcessorPlugins . ripper ) as ICDRipper ;
2009-03-22 16:59:05 +00:00
try
2008-12-09 07:25:48 +00:00
{
2009-03-22 16:59:05 +00:00
ripper . Open ( pathIn [ 0 ] ) ;
if ( ripper . TOC . AudioTracks > 0 )
{
OpenCD ( ripper ) ;
int driveOffset ;
if ( ! AccurateRipVerify . FindDriveReadOffset ( _ripper . ARName , out driveOffset ) )
throw new Exception ( "Failed to find drive read offset for drive" + _ripper . ARName ) ;
_ripper . DriveOffset = driveOffset ;
2009-08-06 13:03:02 +00:00
//LookupAlbumInfo();
2009-03-22 16:59:05 +00:00
return ;
}
}
catch
{
ripper . Dispose ( ) ;
_ripper = null ;
throw ;
2008-12-09 07:25:48 +00:00
}
2008-12-07 23:38:00 +00:00
}
TextReader sr ;
if ( Directory . Exists ( pathIn ) )
2009-03-28 03:57:49 +00:00
throw new Exception ( "is a directory" ) ;
//{
// if (cueDir + Path.DirectorySeparatorChar != pathIn && cueDir != pathIn)
// throw new Exception("Input directory must end on path separator character.");
// string cueSheet = null;
// string[] audioExts = new string[] { "*.wav", "*.flac", "*.wv", "*.ape", "*.m4a", "*.tta" };
// for (i = 0; i < audioExts.Length && cueSheet == null; i++)
// cueSheet = CUESheet.CreateDummyCUESheet(pathIn, audioExts[i]);
// if (_config.udc1Extension != null && cueSheet == null)
// cueSheet = CUESheet.CreateDummyCUESheet(pathIn, "*." + _config.udc1Extension);
// if (cueSheet == null)
// throw new Exception("Input directory doesn't contain supported audio files.");
// sr = new StringReader(cueSheet);
// List<CUEToolsSourceFile> logFiles = new List<CUEToolsSourceFile>();
// foreach (string logPath in Directory.GetFiles(pathIn, "*.log"))
// logFiles.Add(new CUEToolsSourceFile(logPath, new StreamReader(logPath, CUESheet.Encoding)));
// CUEToolsSourceFile selectedLogFile = ChooseFile(logFiles, null, false);
// _eacLog = selectedLogFile != null ? selectedLogFile.contents : null;
//}
2010-02-08 01:29:31 +00:00
else if ( CUEProcessorPlugins . arcp_fmt . Contains ( Path . GetExtension ( pathIn ) . ToLower ( ) . Trim ( '.' ) ) )
2009-05-01 15:16:26 +00:00
{
2010-02-08 01:29:31 +00:00
_archive = null ;
foreach ( Type type in CUEProcessorPlugins . arcp )
2009-01-28 04:53:13 +00:00
{
2010-02-08 01:29:31 +00:00
CompressionProviderClass archclass = Attribute . GetCustomAttribute ( type , typeof ( CompressionProviderClass ) ) as CompressionProviderClass ;
if ( archclass . Extension = = Path . GetExtension ( pathIn ) . ToLower ( ) . Trim ( '.' ) )
2009-01-28 04:53:13 +00:00
{
2010-02-08 01:29:31 +00:00
_archive = Activator . CreateInstance ( type , pathIn ) as ICompressionProvider ;
break ;
2009-01-28 04:53:13 +00:00
}
}
2010-02-08 01:29:31 +00:00
if ( _archive = = null )
throw new Exception ( "archive type not supported." ) ;
_isArchive = true ;
_archiveContents = new List < string > ( ) ;
_archive . PasswordRequired + = new EventHandler < CompressionPasswordRequiredEventArgs > ( unzip_PasswordRequired ) ;
_archive . ExtractionProgress + = new EventHandler < CompressionExtractionProgressEventArgs > ( unzip_ExtractionProgress ) ;
foreach ( string f in _archive . Contents )
_archiveContents . Add ( f ) ;
2009-01-28 04:53:13 +00:00
2009-02-22 07:47:56 +00:00
List < CUEToolsSourceFile > logFiles = new List < CUEToolsSourceFile > ( ) ;
List < CUEToolsSourceFile > cueFiles = new List < CUEToolsSourceFile > ( ) ;
2009-01-17 04:09:38 +00:00
foreach ( string s in _archiveContents )
{
2009-02-22 07:47:56 +00:00
if ( Path . GetExtension ( s ) . ToLower ( ) = = ".cue" | | Path . GetExtension ( s ) . ToLower ( ) = = ".log" )
{
Stream archiveStream = OpenArchive ( s , false ) ;
CUEToolsSourceFile sourceFile = new CUEToolsSourceFile ( s , new StreamReader ( archiveStream , CUESheet . Encoding ) ) ;
archiveStream . Close ( ) ;
if ( Path . GetExtension ( s ) . ToLower ( ) = = ".cue" )
cueFiles . Add ( sourceFile ) ;
else
logFiles . Add ( sourceFile ) ;
}
2009-01-17 04:09:38 +00:00
}
2009-02-22 07:47:56 +00:00
CUEToolsSourceFile selectedCUEFile = ChooseFile ( cueFiles , null , true ) ;
if ( selectedCUEFile = = null | | selectedCUEFile . contents = = "" )
throw new Exception ( "Input archive doesn't contain a usable cue sheet." ) ;
CUEToolsSourceFile selectedLogFile = ChooseFile ( logFiles , Path . GetFileNameWithoutExtension ( selectedCUEFile . path ) , true ) ;
_eacLog = selectedLogFile ! = null ? selectedLogFile . contents : null ;
_archiveCUEpath = Path . GetDirectoryName ( selectedCUEFile . path ) ;
string cueText = selectedCUEFile . contents ;
2009-01-17 04:09:38 +00:00
if ( _config . autoCorrectFilenames )
2009-05-01 15:16:26 +00:00
{
string extension ;
cueText = CorrectAudioFilenames ( _config , _archiveCUEpath , cueText , false , _archiveContents , out extension ) ;
}
2008-12-07 23:38:00 +00:00
sr = new StringReader ( cueText ) ;
}
else if ( Path . GetExtension ( pathIn ) . ToLower ( ) = = ".cue" )
{
if ( _config . autoCorrectFilenames )
2009-05-01 15:16:26 +00:00
sr = new StringReader ( CorrectAudioFilenames ( _config , pathIn , false ) ) ;
2008-12-07 23:38:00 +00:00
else
2009-05-01 15:16:26 +00:00
sr = new StreamReader ( pathIn , CUESheet . Encoding ) ;
2008-12-07 23:38:00 +00:00
2009-02-22 07:47:56 +00:00
List < CUEToolsSourceFile > logFiles = new List < CUEToolsSourceFile > ( ) ;
2009-05-01 15:16:26 +00:00
foreach ( string logPath in Directory . GetFiles ( _inputDir , "*.log" ) )
2009-08-08 16:14:06 +00:00
try { logFiles . Add ( new CUEToolsSourceFile ( logPath , new StreamReader ( logPath , CUESheet . Encoding ) ) ) ; }
catch { }
2009-02-22 07:47:56 +00:00
CUEToolsSourceFile selectedLogFile = ChooseFile ( logFiles , Path . GetFileNameWithoutExtension ( pathIn ) , false ) ;
_eacLog = selectedLogFile ! = null ? selectedLogFile . contents : null ;
}
else
2008-12-07 23:38:00 +00:00
{
2009-03-28 03:57:49 +00:00
string extension = Path . GetExtension ( pathIn ) . ToLower ( ) ;
sr = null ;
2009-05-01 15:16:26 +00:00
CUEToolsFormat fmt ;
if ( ! extension . StartsWith ( "." ) | | ! _config . formats . TryGetValue ( extension . Substring ( 1 ) , out fmt ) | | ! fmt . allowLossless )
throw new Exception ( "Unknown input format." ) ;
if ( fmt . allowEmbed )
2009-03-28 03:57:49 +00:00
{
string cuesheetTag = null ;
TagLib . File fileInfo ;
GetSampleLength ( pathIn , out fileInfo ) ;
NameValueCollection tags = Tagging . Analyze ( fileInfo ) ;
cuesheetTag = tags . Get ( "CUESHEET" ) ;
_accurateRipId = tags . Get ( "ACCURATERIPID" ) ;
_eacLog = tags . Get ( "LOG" ) ;
if ( _eacLog = = null ) _eacLog = tags . Get ( "LOGFILE" ) ;
if ( _eacLog = = null ) _eacLog = tags . Get ( "EACLOG" ) ;
if ( cuesheetTag ! = null )
{
sr = new StringReader ( cuesheetTag ) ;
_hasEmbeddedCUESheet = true ;
}
}
if ( ! _hasEmbeddedCUESheet )
{
string cueSheet = CUESheet . CreateDummyCUESheet ( _config , pathIn ) ;
if ( cueSheet = = null )
throw new Exception ( "Input file doesn't seem to contain a cue sheet or be part of an album." ) ;
sr = new StringReader ( cueSheet ) ;
List < CUEToolsSourceFile > logFiles = new List < CUEToolsSourceFile > ( ) ;
2009-05-01 15:16:26 +00:00
foreach ( string logPath in Directory . GetFiles ( _inputDir , "*.log" ) )
2009-08-08 16:14:06 +00:00
try { logFiles . Add ( new CUEToolsSourceFile ( logPath , new StreamReader ( logPath , CUESheet . Encoding ) ) ) ; }
catch { }
2009-03-28 03:57:49 +00:00
CUEToolsSourceFile selectedLogFile = ChooseFile ( logFiles , null , false ) ;
_eacLog = selectedLogFile ! = null ? selectedLogFile . contents : null ;
}
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
OpenCUE ( sr ) ;
}
public void OpenCUE ( TextReader sr )
{
string pathAudio = null ;
string lineStr , command , fileType ;
bool fileIsBinary = false ;
int timeRelativeToFileStart , absoluteFileStartTime = 0 ;
int fileTimeLengthSamples = 0 , fileTimeLengthFrames = 0 , i ;
TagLib . File _trackFileInfo = null ;
bool seenFirstFileIndex = false ;
bool isAudioTrack = true ;
List < IndexInfo > indexes = new List < IndexInfo > ( ) ;
IndexInfo indexInfo ;
SourceInfo sourceInfo ;
TrackInfo trackInfo = null ;
int trackNumber = 0 ;
using ( sr )
{
2008-12-07 23:38:00 +00:00
while ( ( lineStr = sr . ReadLine ( ) ) ! = null ) {
2009-05-01 15:16:26 +00:00
CUELine line = new CUELine ( lineStr ) ;
2008-12-07 23:38:00 +00:00
if ( line . Params . Count > 0 ) {
command = line . Params [ 0 ] . ToUpper ( ) ;
if ( command = = "FILE" ) {
fileType = line . Params [ 2 ] . ToUpper ( ) ;
2010-02-06 23:17:07 +00:00
fileIsBinary = ( fileType = = "BINARY" ) | | ( fileType = = "MOTOROLA" ) ;
if ( fileIsBinary )
{
if ( ! _hasEmbeddedCUESheet & & _sourcePaths . Count = = 0 )
{
try
{
if ( _isArchive )
pathAudio = LocateFile ( _archiveCUEpath , line . Params [ 1 ] , _archiveContents ) ;
else
pathAudio = LocateFile ( _inputDir , line . Params [ 1 ] , null ) ;
fileIsBinary = ( pathAudio = = null ) ;
}
catch { }
}
}
if ( ! fileIsBinary )
2009-01-28 04:53:13 +00:00
{
2008-12-07 23:38:00 +00:00
if ( ! _hasEmbeddedCUESheet )
{
if ( _isArchive )
pathAudio = LocateFile ( _archiveCUEpath , line . Params [ 1 ] , _archiveContents ) ;
2010-02-06 23:17:07 +00:00
else
2009-05-01 15:16:26 +00:00
pathAudio = LocateFile ( _inputDir , line . Params [ 1 ] , null ) ;
2010-02-06 23:17:07 +00:00
}
else
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
pathAudio = _inputPath ;
2010-02-06 23:17:07 +00:00
if ( _sourcePaths . Count > 0 )
2008-12-07 23:38:00 +00:00
throw new Exception ( "Extra file in embedded CUE sheet: \"" + line . Params [ 1 ] + "\"." ) ;
}
_sourcePaths . Add ( pathAudio ) ;
absoluteFileStartTime + = fileTimeLengthFrames ;
2009-06-24 19:40:23 +00:00
if ( pathAudio = = null )
2008-12-07 23:38:00 +00:00
{
2009-06-24 19:40:23 +00:00
throw new Exception ( "Unable to locate file \"" + line . Params [ 1 ] + "\"." ) ;
//fileTimeLengthFrames = 75 * 60 * 70;;
//fileTimeLengthSamples = fileTimeLengthFrames * 588;
//if (_hasEmbeddedCUESheet)
// _fileInfo = null;
//else
// _trackFileInfo = null;
2008-12-07 23:38:00 +00:00
}
else
2009-06-24 19:40:23 +00:00
{
TagLib . File fileInfo ;
fileTimeLengthSamples = GetSampleLength ( pathAudio , out fileInfo ) ;
if ( ( fileTimeLengthSamples % 588 ) = = 492 & & _config . truncate4608ExtraSamples )
{
_truncated4608 = true ;
fileTimeLengthSamples - = 4608 ;
}
fileTimeLengthFrames = ( int ) ( ( fileTimeLengthSamples + 587 ) / 588 ) ;
if ( _hasEmbeddedCUESheet )
_fileInfo = fileInfo ;
else
_trackFileInfo = fileInfo ;
}
2008-12-07 23:38:00 +00:00
seenFirstFileIndex = false ;
}
}
2009-01-28 04:53:13 +00:00
else if ( command = = "TRACK" )
{
isAudioTrack = line . Params [ 2 ] . ToUpper ( ) = = "AUDIO" ;
trackNumber = int . Parse ( line . Params [ 1 ] ) ;
if ( trackNumber ! = _toc . TrackCount + 1 )
throw new Exception ( "Invalid track number." ) ;
_toc . AddTrack ( new CDTrack ( ( uint ) trackNumber , 0 , 0 , isAudioTrack , false ) ) ;
if ( isAudioTrack )
{
2008-12-07 23:38:00 +00:00
trackInfo = new TrackInfo ( ) ;
_tracks . Add ( trackInfo ) ;
}
}
2009-01-28 04:53:13 +00:00
else if ( command = = "INDEX" )
{
2008-12-07 23:38:00 +00:00
timeRelativeToFileStart = CDImageLayout . TimeFromString ( line . Params [ 2 ] ) ;
if ( ! seenFirstFileIndex )
{
if ( timeRelativeToFileStart ! = 0 )
throw new Exception ( "First index must start at file beginning." ) ;
seenFirstFileIndex = true ;
2009-01-28 04:53:13 +00:00
if ( isAudioTrack )
2008-12-07 23:38:00 +00:00
{
2009-02-19 04:09:59 +00:00
if ( _tracks . Count > 0 & & _trackFileInfo ! = null )
_tracks [ _tracks . Count - 1 ] . _fileInfo = _trackFileInfo ;
_trackFileInfo = null ;
2009-01-28 04:53:13 +00:00
sourceInfo . Path = pathAudio ;
2008-12-07 23:38:00 +00:00
sourceInfo . Offset = 0 ;
2009-01-28 04:53:13 +00:00
sourceInfo . Length = ( uint ) fileTimeLengthSamples ;
2008-12-07 23:38:00 +00:00
_sources . Add ( sourceInfo ) ;
2009-01-28 04:53:13 +00:00
if ( ( fileTimeLengthSamples % 588 ) ! = 0 )
{
sourceInfo . Path = null ;
sourceInfo . Offset = 0 ;
sourceInfo . Length = ( uint ) ( ( fileTimeLengthFrames * 588 ) - fileTimeLengthSamples ) ;
_sources . Add ( sourceInfo ) ;
_paddedToFrame = true ;
}
2008-12-07 23:38:00 +00:00
}
}
2009-05-10 18:34:49 +00:00
else
2009-01-28 04:53:13 +00:00
{
2009-05-10 18:34:49 +00:00
if ( fileIsBinary )
{
fileTimeLengthFrames = timeRelativeToFileStart + 150 ;
sourceInfo . Path = null ;
sourceInfo . Offset = 0 ;
sourceInfo . Length = 150 * 588 ;
_sources . Add ( sourceInfo ) ;
2010-03-03 23:52:46 +00:00
//throw new Exception("unexpected BINARY directive");
2009-05-10 18:34:49 +00:00
}
else
{
if ( timeRelativeToFileStart > fileTimeLengthFrames )
throw new Exception ( string . Format ( "TRACK {0} INDEX {1} is at {2}, which is past {3} - the end of source file {4}" , trackNumber , line . Params [ 1 ] , CDImageLayout . TimeToString ( ( uint ) timeRelativeToFileStart ) , CDImageLayout . TimeToString ( ( uint ) fileTimeLengthFrames ) , pathAudio ) ) ;
}
2009-01-28 04:53:13 +00:00
}
2008-12-07 23:38:00 +00:00
indexInfo . Track = trackNumber ;
indexInfo . Index = Int32 . Parse ( line . Params [ 1 ] ) ;
indexInfo . Time = absoluteFileStartTime + timeRelativeToFileStart ;
indexes . Add ( indexInfo ) ;
}
2009-01-28 04:53:13 +00:00
else if ( ! isAudioTrack )
{
// Ignore lines belonging to data tracks
}
else if ( command = = "PREGAP" )
{
if ( seenFirstFileIndex )
2008-12-07 23:38:00 +00:00
throw new Exception ( "Pregap must occur at the beginning of a file." ) ;
int pregapLength = CDImageLayout . TimeFromString ( line . Params [ 1 ] ) ;
indexInfo . Track = trackNumber ;
indexInfo . Index = 0 ;
indexInfo . Time = absoluteFileStartTime ;
indexes . Add ( indexInfo ) ;
sourceInfo . Path = null ;
sourceInfo . Offset = 0 ;
sourceInfo . Length = ( uint ) pregapLength * 588 ;
_sources . Add ( sourceInfo ) ;
absoluteFileStartTime + = pregapLength ;
}
else if ( command = = "POSTGAP" ) {
throw new Exception ( "POSTGAP command isn't supported." ) ;
}
2009-03-28 03:57:49 +00:00
//else if ((command == "REM") &&
// (line.Params.Count >= 3) &&
// (line.Params[1].Length >= 10) &&
// (line.Params[1].Substring(0, 10).ToUpper() == "REPLAYGAIN"))
//{
// // Remove ReplayGain lines
//}
2008-12-07 23:38:00 +00:00
else if ( ( command = = "REM" ) & &
( line . Params . Count = = 3 ) & &
( line . Params [ 1 ] . ToUpper ( ) = = "ACCURATERIPID" ) )
{
_accurateRipId = line . Params [ 2 ] ;
}
//else if ((command == "REM") &&
// (line.Params.Count == 3) &&
// (line.Params[1].ToUpper() == "SHORTEN"))
//{
// fileTimeLengthFrames -= General.TimeFromString(line.Params[2]);
//}
//else if ((command == "REM") &&
// (line.Params.Count == 3) &&
// (line.Params[1].ToUpper() == "LENGTHEN"))
//{
// fileTimeLengthFrames += General.TimeFromString(line.Params[2]);
//}
else
{
if ( trackInfo ! = null )
{
trackInfo . Attributes . Add ( line ) ;
}
else
{
2009-01-28 04:53:13 +00:00
if ( line . Params . Count > 2 & & ! line . IsQuoted [ 1 ] & &
( line . Params [ 0 ] . ToUpper ( ) = = "TITLE" | | line . Params [ 0 ] . ToUpper ( ) = = "ARTIST" | |
( line . Params [ 0 ] . ToUpper ( ) = = "REM" & & line . Params [ 1 ] . ToUpper ( ) = = "GENRE" & & line . Params . Count > 3 & & ! line . IsQuoted [ 2 ] ) ) )
{
CUELine modline = new CUELine ( ) ;
int nParams = line . Params [ 0 ] . ToUpper ( ) = = "REM" ? 2 : 1 ;
for ( int iParam = 0 ; iParam < nParams ; iParam + + )
{
modline . Params . Add ( line . Params [ iParam ] ) ;
modline . IsQuoted . Add ( false ) ;
}
string s = line . Params [ nParams ] ;
for ( int iParam = nParams + 1 ; iParam < line . Params . Count ; iParam + + )
s + = " " + line . Params [ iParam ] ;
modline . Params . Add ( s ) ;
modline . IsQuoted . Add ( true ) ;
line = modline ;
}
2008-12-07 23:38:00 +00:00
_attributes . Add ( line ) ;
}
}
}
}
sr . Close ( ) ;
}
2009-01-28 04:53:13 +00:00
if ( _tracks . Count = = 0 )
2008-12-07 23:38:00 +00:00
throw new Exception ( "File must contain at least one audio track." ) ;
2009-01-28 04:53:13 +00:00
// Add dummy index 01 for data track
if ( ! _toc [ _toc . TrackCount ] . IsAudio & & indexes [ indexes . Count - 1 ] . Index = = 0 )
{
2009-03-22 16:59:05 +00:00
fileTimeLengthFrames + = 152 * 75 ;
2009-01-28 04:53:13 +00:00
indexInfo . Track = trackNumber ;
indexInfo . Index = 1 ;
indexInfo . Time = absoluteFileStartTime + fileTimeLengthFrames ;
indexes . Add ( indexInfo ) ;
2008-12-07 23:38:00 +00:00
}
// Add dummy track for calculation purposes
indexInfo . Track = trackNumber + 1 ;
indexInfo . Index = 1 ;
indexInfo . Time = absoluteFileStartTime + fileTimeLengthFrames ;
indexes . Add ( indexInfo ) ;
// Calculate the length of each index
for ( i = 0 ; i < indexes . Count - 1 ; i + + )
{
2008-12-09 07:25:48 +00:00
if ( indexes [ i + 1 ] . Time - indexes [ i ] . Time < 0 )
throw new Exception ( "Indexes must be in chronological order." ) ;
if ( ( indexes [ i + 1 ] . Track ! = indexes [ i ] . Track | | indexes [ i + 1 ] . Index ! = indexes [ i ] . Index + 1 ) & &
( indexes [ i + 1 ] . Track ! = indexes [ i ] . Track + 1 | | indexes [ i ] . Index < 1 | | indexes [ i + 1 ] . Index > 1 ) )
2008-12-07 23:38:00 +00:00
throw new Exception ( "Indexes must be in chronological order." ) ;
2008-12-09 07:25:48 +00:00
if ( indexes [ i ] . Index = = 1 & & ( i = = 0 | | indexes [ i - 1 ] . Index ! = 0 ) )
_toc [ indexes [ i ] . Track ] . AddIndex ( new CDTrackIndex ( 0 U , ( uint ) indexes [ i ] . Time ) ) ;
_toc [ indexes [ i ] . Track ] . AddIndex ( new CDTrackIndex ( ( uint ) indexes [ i ] . Index , ( uint ) indexes [ i ] . Time ) ) ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
// Calculate the length of each track
2009-01-28 04:53:13 +00:00
for ( int iTrack = 1 ; iTrack < = _toc . TrackCount ; iTrack + + )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
_toc [ iTrack ] . Start = _toc [ iTrack ] [ 1 ] . Start ;
2009-03-22 16:59:05 +00:00
_toc [ iTrack ] . Length = iTrack = = _toc . TrackCount
? ( uint ) indexes [ indexes . Count - 1 ] . Time - _toc [ iTrack ] . Start
: _toc [ iTrack + 1 ] . IsAudio
? _toc [ iTrack + 1 ] [ 1 ] . Start - _toc [ iTrack ] . Start
: _toc [ iTrack + 1 ] [ 0 ] . Start - _toc [ iTrack ] . Start ;
2008-12-07 23:38:00 +00:00
}
// Store the audio filenames, generating generic names if necessary
2009-03-04 21:30:56 +00:00
_hasSingleFilename = _sourcePaths . Count = = 1 ;
2008-12-07 23:38:00 +00:00
_singleFilename = _hasSingleFilename ? Path . GetFileName ( _sourcePaths [ 0 ] ) :
"Range.wav" ;
_hasHTOAFilename = ( _sourcePaths . Count = = ( TrackCount + 1 ) ) ;
_htoaFilename = _hasHTOAFilename ? Path . GetFileName ( _sourcePaths [ 0 ] ) : "01.00.wav" ;
2009-03-04 21:30:56 +00:00
_hasTrackFilenames = ! _hasEmbeddedCUESheet & & ! _hasSingleFilename & & ( _sourcePaths . Count = = TrackCount | | _hasHTOAFilename ) ;
2008-12-07 23:38:00 +00:00
for ( i = 0 ; i < TrackCount ; i + + ) {
_trackFilenames . Add ( _hasTrackFilenames ? Path . GetFileName (
_sourcePaths [ i + ( _hasHTOAFilename ? 1 : 0 ) ] ) : String . Format ( "{0:00}.wav" , i + 1 ) ) ;
}
if ( ! _hasEmbeddedCUESheet & & _hasSingleFilename )
{
2009-02-19 04:09:59 +00:00
_fileInfo = _tracks [ 0 ] . _fileInfo ;
_tracks [ 0 ] . _fileInfo = null ;
2008-12-07 23:38:00 +00:00
}
if ( _config . fillUpCUE )
{
2009-02-19 04:09:59 +00:00
if ( _config . overwriteCUEData | | General . FindCUELine ( _attributes , "PERFORMER" ) = = null )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . JoinedAlbumArtists ; } ) ;
if ( value = = null )
value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . JoinedPerformers ; } ) ;
2009-05-01 15:16:26 +00:00
if ( value ! = null & & value ! = "" )
2009-02-19 04:09:59 +00:00
General . SetCUELine ( _attributes , "PERFORMER" , value , true ) ;
}
if ( _config . overwriteCUEData | | General . FindCUELine ( _attributes , "TITLE" ) = = null )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . Album ; } ) ;
if ( value ! = null )
General . SetCUELine ( _attributes , "TITLE" , value , true ) ;
}
if ( _config . overwriteCUEData | | General . FindCUELine ( _attributes , "REM" , "DATE" ) = = null )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . Year ! = 0 ? file . Tag . Year . ToString ( ) : null ; } ) ;
if ( value ! = null )
General . SetCUELine ( _attributes , "REM" , "DATE" , value , false ) ;
}
if ( _config . overwriteCUEData | | General . FindCUELine ( _attributes , "REM" , "GENRE" ) = = null )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . JoinedGenres ; } ) ;
if ( value ! = null )
General . SetCUELine ( _attributes , "REM" , "GENRE" , value , true ) ;
}
2009-06-24 19:40:23 +00:00
if ( _config . overwriteCUEData | | TotalDiscs = = "" )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . DiscCount ! = 0 ? file . Tag . DiscCount . ToString ( ) : null ; } ) ;
if ( value ! = null )
TotalDiscs = value ;
}
if ( _config . overwriteCUEData | | DiscNumber = = "" )
{
string value = GetCommonTag ( delegate ( TagLib . File file ) { return file . Tag . Disc ! = 0 ? file . Tag . Disc . ToString ( ) : null ; } ) ;
if ( value ! = null )
DiscNumber = value ;
}
2009-01-17 04:09:38 +00:00
for ( i = 0 ; i < TrackCount ; i + + )
{
TrackInfo track = _tracks [ i ] ;
2009-06-24 19:40:23 +00:00
string artist = _hasTrackFilenames & & track . _fileInfo ! = null ? track . _fileInfo . Tag . JoinedPerformers :
_hasEmbeddedCUESheet & & _fileInfo ! = null ? Tagging . TagListToSingleValue ( Tagging . GetMiscTag ( _fileInfo , String . Format ( "cue_track{0:00}_ARTIST" , i + 1 ) ) ) :
2009-02-19 04:09:59 +00:00
null ;
2009-06-24 19:40:23 +00:00
string title = _hasTrackFilenames & & track . _fileInfo ! = null ? track . _fileInfo . Tag . Title :
_hasEmbeddedCUESheet & & _fileInfo ! = null ? Tagging . TagListToSingleValue ( Tagging . GetMiscTag ( _fileInfo , String . Format ( "cue_track{0:00}_TITLE" , i + 1 ) ) ) :
2009-02-19 04:09:59 +00:00
null ;
2009-05-01 15:16:26 +00:00
if ( ( _config . overwriteCUEData | | track . Artist = = "" ) & & artist ! = null & & artist ! = "" )
2009-01-17 04:09:38 +00:00
track . Artist = artist ;
if ( ( _config . overwriteCUEData | | track . Title = = "" ) & & title ! = null )
track . Title = title ;
}
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
CUELine cddbDiscIdLine = General . FindCUELine ( _attributes , "REM" , "DISCID" ) ;
_cddbDiscIdTag = cddbDiscIdLine ! = null & & cddbDiscIdLine . Params . Count = = 3 ? cddbDiscIdLine . Params [ 2 ] : null ;
2009-02-19 04:09:59 +00:00
if ( _cddbDiscIdTag = = null )
_cddbDiscIdTag = GetCommonMiscTag ( "DISCID" ) ;
2008-12-09 07:25:48 +00:00
2008-12-07 23:38:00 +00:00
if ( _accurateRipId = = null )
2009-02-19 04:09:59 +00:00
_accurateRipId = GetCommonMiscTag ( "ACCURATERIPID" ) ;
2008-12-07 23:38:00 +00:00
2009-02-27 14:41:55 +00:00
CDImageLayout tocFromLog = _eacLog = = null ? null : TocFromLog ( _eacLog ) ;
2009-05-01 15:16:26 +00:00
// use pregaps from log
if ( tocFromLog ! = null )
{
2009-06-24 19:40:23 +00:00
//int srcNo = (int) _toc[_toc.FirstAudio].LastIndex - (PreGapLength == 0 ? 1 : 0);
2009-05-01 15:16:26 +00:00
if ( PreGapLength < tocFromLog . Pregap )
2009-06-24 19:40:23 +00:00
{
2009-05-01 15:16:26 +00:00
PreGapLength = tocFromLog . Pregap ;
2009-06-24 19:40:23 +00:00
//srcNo ++;
}
2009-05-01 15:16:26 +00:00
int trNo ;
2009-05-10 18:34:49 +00:00
for ( trNo = 1 ; trNo < tocFromLog . AudioTracks & & trNo < _toc . AudioTracks ; trNo + + )
2009-06-24 19:40:23 +00:00
{
2009-05-10 18:34:49 +00:00
if ( _toc [ _toc . FirstAudio + trNo ] . Pregap < tocFromLog [ tocFromLog . FirstAudio + trNo ] . Pregap )
_toc [ _toc . FirstAudio + trNo ] . Pregap = tocFromLog [ tocFromLog . FirstAudio + trNo ] . Pregap ;
2009-06-24 19:40:23 +00:00
}
//if (_toc[_toc.FirstAudio].Length > tocFromLog[tocFromLog.FirstAudio].Length)
//{
// uint offs = _toc[_toc.FirstAudio].Length - tocFromLog[tocFromLog.FirstAudio].Length;
// _toc[_toc.FirstAudio].Length -= offs;
// sourceInfo = _sources[srcNo];
// sourceInfo.Length -= offs * 588;
// _sources[srcNo] = sourceInfo;
// for (i = _toc.FirstAudio + 1; i <= _toc.TrackCount; i++)
// {
// _toc[i].Start -= offs;
// for (int j = 0; j <= _toc[i].LastIndex; j++)
// if (i != _toc.FirstAudio + 1 || j != 0 || _toc[i][0].Start == _toc[i][1].Start)
// _toc[i][j].Start -= offs;
// }
//}
//for (trNo = 1; trNo < tocFromLog.AudioTracks && trNo < _toc.AudioTracks; trNo++)
//{
// srcNo ++;
// if (_toc[_toc.FirstAudio + trNo].Length > tocFromLog[tocFromLog.FirstAudio + trNo].Length)
// {
// uint offs = _toc[_toc.FirstAudio + trNo].Length - tocFromLog[tocFromLog.FirstAudio + trNo].Length;
// _toc[_toc.FirstAudio + trNo].Length -= offs;
// sourceInfo = _sources[srcNo];
// sourceInfo.Length -= offs * 588;
// _sources[srcNo] = sourceInfo;
// for (i = _toc.FirstAudio + trNo + 1; i <= _toc.TrackCount; i++)
// {
// _toc[i].Start -= offs;
// for (int j = 0; j <= _toc[i].LastIndex; j++)
// if (i != _toc.FirstAudio + trNo + 1 || j != 0 || _toc[i][0].Start == _toc[i][1].Start)
// _toc[i][j].Start -= offs;
// }
// }
//}
2009-05-01 15:16:26 +00:00
}
2009-02-27 14:41:55 +00:00
2009-03-22 16:59:05 +00:00
// use data track length from log
if ( tocFromLog ! = null & & tocFromLog . AudioTracks = = _toc . AudioTracks & & tocFromLog . TrackCount = = tocFromLog . AudioTracks + 1 )
2008-12-07 23:38:00 +00:00
{
2009-03-22 16:59:05 +00:00
if ( ! tocFromLog [ tocFromLog . TrackCount ] . IsAudio )
2008-12-09 07:25:48 +00:00
{
2009-03-22 16:59:05 +00:00
DataTrackLength = tocFromLog [ tocFromLog . TrackCount ] . Length ;
_toc [ _toc . TrackCount ] . Start = tocFromLog [ _toc . TrackCount ] . Start ;
_toc [ _toc . TrackCount ] [ 0 ] . Start = tocFromLog [ _toc . TrackCount ] . Start ;
_toc [ _toc . TrackCount ] [ 1 ] . Start = tocFromLog [ _toc . TrackCount ] . Start ;
} else
DataTrackLength = tocFromLog [ 1 ] . Length ;
}
2009-02-27 14:41:55 +00:00
2010-03-20 07:09:07 +00:00
// use data track length from log
if ( tocFromLog ! = null
& & _toc . TrackCount = = _toc . AudioTracks
& & tocFromLog . TrackCount = = tocFromLog . AudioTracks
& & tocFromLog . TrackCount = = _toc . TrackCount + 1 )
{
bool matches = true ;
for ( int iTrack = 1 ; iTrack < = _toc . TrackCount ; iTrack + + )
if ( tocFromLog [ iTrack + 1 ] . Length ! = _toc [ iTrack ] . Length )
matches = false ;
if ( matches )
{
_toc . InsertTrack ( new CDTrack ( 1 , 0 , 0 , false , false ) ) ;
DataTrackLength = tocFromLog [ 1 ] . Length ;
}
}
2009-03-22 16:59:05 +00:00
// use data track length range from cddbId
if ( DataTrackLength = = 0 & & _cddbDiscIdTag ! = null )
{
uint cddbDiscIdNum ;
if ( uint . TryParse ( _cddbDiscIdTag , NumberStyles . HexNumber , CultureInfo . InvariantCulture , out cddbDiscIdNum ) & & ( cddbDiscIdNum & 0xff ) = = _toc . AudioTracks + 1 )
{
if ( _toc . TrackCount = = _toc . AudioTracks )
_toc . AddTrack ( new CDTrack ( ( uint ) _toc . TrackCount , _toc . Length + 152 * 75 , 0 , false , false ) ) ;
uint lengthFromTag = ( ( cddbDiscIdNum > > 8 ) & 0xffff ) ;
_minDataTrackLength = ( lengthFromTag + _toc [ 1 ] . Start / 75 ) * 75 - _toc . Length ;
2008-12-09 07:25:48 +00:00
}
2008-12-07 23:38:00 +00:00
}
2010-02-23 15:15:08 +00:00
_arVerify = new AccurateRipVerify ( _toc , proxy ) ;
2008-12-07 23:38:00 +00:00
2009-01-28 04:53:13 +00:00
if ( _eacLog ! = null )
{
sr = new StringReader ( _eacLog ) ;
bool isEACLog = false ;
int trNo = 1 ;
while ( ( lineStr = sr . ReadLine ( ) ) ! = null )
{
if ( isEACLog & & trNo < = TrackCount )
{
string [ ] s = { "Copy CRC " , "CRC <20> <> <EFBFBD> <EFBFBD> <EFBFBD> " } ;
2009-02-23 03:59:50 +00:00
string [ ] s1 = { "CRC" } ;
2009-01-28 04:53:13 +00:00
string [ ] n = lineStr . Split ( s , StringSplitOptions . None ) ;
uint crc ;
2009-02-23 03:59:50 +00:00
if ( n . Length = = 2 & & uint . TryParse ( n [ 1 ] , NumberStyles . HexNumber , CultureInfo . InvariantCulture , out crc ) )
2009-01-28 04:53:13 +00:00
_arVerify . CRCLOG ( trNo + + , crc ) ;
2009-02-23 03:59:50 +00:00
else if ( n . Length = = 1 )
{
n = lineStr . Split ( s1 , StringSplitOptions . None ) ;
if ( n . Length = = 2 & & n [ 0 ] . Trim ( ) = = "" & & uint . TryParse ( n [ 1 ] , NumberStyles . HexNumber , CultureInfo . InvariantCulture , out crc ) )
_arVerify . CRCLOG ( trNo + + , crc ) ;
}
2009-01-28 04:53:13 +00:00
}
else
2009-02-23 03:59:50 +00:00
if ( lineStr . StartsWith ( "Exact Audio Copy" )
| | lineStr . StartsWith ( "EAC extraction logfile" ) )
2009-01-28 04:53:13 +00:00
isEACLog = true ;
}
if ( trNo = = 2 )
{
_arVerify . CRCLOG ( 0 , _arVerify . CRCLOG ( 1 ) ) ;
if ( TrackCount > 1 )
_arVerify . CRCLOG ( 1 , 0 ) ;
}
}
2009-08-06 13:03:02 +00:00
LoadAlbumArt ( _tracks [ 0 ] . _fileInfo ? ? _fileInfo ) ;
2009-08-08 16:14:06 +00:00
ResizeAlbumArt ( ) ;
if ( ( _config . embedAlbumArt | | _config . copyAlbumArt ) & & _albumArt ! = null & & _albumArt . Length > 0 )
_padding + = _albumArt [ 0 ] . Data . Count ;
if ( _config . embedLog & & _eacLog ! = null )
_padding + = _eacLog . Length ;
2009-03-22 16:59:05 +00:00
}
2009-01-28 04:53:13 +00:00
2010-02-28 21:04:34 +00:00
public void UseCUEToolsDB ( bool submit , string userAgent )
2010-02-23 15:15:08 +00:00
{
ShowProgress ( ( string ) "Contacting CUETools database..." , 0 , 0 , null , null ) ;
2010-03-20 07:09:07 +00:00
_CUEToolsDB = new CUEToolsDB ( _toc , proxy ) ;
_CUEToolsDB . UploadHelper . onProgress + = new EventHandler < Krystalware . UploadHelper . UploadProgressEventArgs > ( UploadProgress ) ;
_CUEToolsDB . ContactDB ( userAgent ) ;
2010-02-23 15:15:08 +00:00
ShowProgress ( "" , 0.0 , 0.0 , null , null ) ;
_useCUEToolsDB = true ;
2010-02-28 21:04:34 +00:00
_useCUEToolsDBSibmit = submit ;
2010-02-23 15:15:08 +00:00
}
2009-08-08 16:14:06 +00:00
public void UseAccurateRip ( )
2009-03-22 16:59:05 +00:00
{
2009-08-08 16:14:06 +00:00
ShowProgress ( ( string ) "Contacting AccurateRip database..." , 0 , 0 , null , null ) ;
if ( ! _toc [ _toc . TrackCount ] . IsAudio & & DataTrackLength = = 0 & & _minDataTrackLength . HasValue & & _accurateRipId = = null & & _config . bruteForceDTL )
2009-03-22 16:59:05 +00:00
{
2009-08-08 16:14:06 +00:00
uint minDTL = _minDataTrackLength . Value ;
CDImageLayout toc2 = new CDImageLayout ( _toc ) ;
for ( uint dtl = minDTL ; dtl < minDTL + 75 ; dtl + + )
2009-03-22 16:59:05 +00:00
{
2009-08-08 16:14:06 +00:00
toc2 [ toc2 . TrackCount ] . Length = dtl ;
_arVerify . ContactAccurateRip ( AccurateRipVerify . CalculateAccurateRipId ( toc2 ) ) ;
if ( _arVerify . AccResult ! = HttpStatusCode . NotFound )
2009-03-22 16:59:05 +00:00
{
2009-08-08 16:14:06 +00:00
DataTrackLength = dtl ;
break ;
}
ShowProgress ( ( string ) "Contacting AccurateRip database..." , 0 , ( dtl - minDTL ) / 75.0 , null , null ) ;
CheckStop ( ) ;
lock ( this )
{
Monitor . Wait ( this , 500 ) ;
2009-03-22 16:59:05 +00:00
}
}
}
2009-08-08 16:14:06 +00:00
else
{
_arVerify . ContactAccurateRip ( _accurateRipId ? ? AccurateRipVerify . CalculateAccurateRipId ( _toc ) ) ;
}
_useAccurateRip = true ;
2008-12-07 23:38:00 +00:00
}
public static Encoding Encoding {
get {
return Encoding . Default ;
}
}
2009-02-22 07:47:56 +00:00
internal CUEToolsSourceFile ChooseFile ( List < CUEToolsSourceFile > sourceFiles , string defaultFileName , bool quietIfSingle )
{
if ( sourceFiles . Count < = 0 )
return null ;
if ( defaultFileName ! = null )
{
CUEToolsSourceFile defaultFile = null ;
foreach ( CUEToolsSourceFile file in sourceFiles )
if ( Path . GetFileNameWithoutExtension ( file . path ) . ToLower ( ) = = defaultFileName . ToLower ( ) )
{
if ( defaultFile ! = null )
{
defaultFile = null ;
break ;
}
defaultFile = file ;
}
if ( defaultFile ! = null )
return defaultFile ;
}
if ( quietIfSingle & & sourceFiles . Count = = 1 )
return sourceFiles [ 0 ] ;
if ( CUEToolsSelection = = null )
return null ;
CUEToolsSelectionEventArgs e = new CUEToolsSelectionEventArgs ( ) ;
e . choices = sourceFiles . ToArray ( ) ;
CUEToolsSelection ( this , e ) ;
if ( e . selection = = - 1 )
return null ;
return sourceFiles [ e . selection ] ;
}
2009-02-19 04:09:59 +00:00
internal Stream OpenArchive ( string fileName , bool showProgress )
2009-01-28 04:53:13 +00:00
{
2010-02-08 01:29:31 +00:00
if ( _archive = = null )
throw new Exception ( "Unknown archive type." ) ;
return _archive . Decompress ( fileName ) ;
2009-01-28 04:53:13 +00:00
}
2008-12-09 07:25:48 +00:00
private void ShowProgress ( string status , double percentTrack , double percentDisk , string input , string output )
2008-12-07 23:38:00 +00:00
{
if ( this . CUEToolsProgress = = null )
return ;
_progress . status = status ;
2008-12-09 07:25:48 +00:00
_progress . percentTrck = percentTrack ;
2008-12-07 23:38:00 +00:00
_progress . percentDisk = percentDisk ;
2009-08-21 03:26:12 +00:00
_progress . offset = 0 ;
_progress . input = input ;
_progress . output = output ;
this . CUEToolsProgress ( this , _progress ) ;
}
private void ShowProgress ( string status , double percentTrack , int diskOffset , int diskLength , string input , string output )
{
if ( this . CUEToolsProgress = = null )
return ;
_progress . status = status ;
_progress . percentTrck = percentTrack ;
_progress . percentDisk = ( double ) diskOffset / diskLength ;
_progress . offset = diskOffset ;
2008-12-07 23:38:00 +00:00
_progress . input = input ;
_progress . output = output ;
this . CUEToolsProgress ( this , _progress ) ;
}
2010-02-23 15:15:08 +00:00
private void UploadProgress ( object sender , Krystalware . UploadHelper . UploadProgressEventArgs e )
{
CheckStop ( ) ;
if ( this . CUEToolsProgress = = null )
return ;
2010-02-23 23:24:54 +00:00
_progress . percentDisk = 0 ;
2010-02-23 15:15:08 +00:00
_progress . percentTrck = e . percent ;
_progress . offset = 0 ;
_progress . status = e . uri ;
this . CUEToolsProgress ( this , _progress ) ;
}
2008-12-09 07:25:48 +00:00
private void CDReadProgress ( object sender , ReadProgressArgs e )
{
2009-02-22 07:47:56 +00:00
CheckStop ( ) ;
2008-12-09 07:25:48 +00:00
if ( this . CUEToolsProgress = = null )
return ;
2010-02-08 01:29:31 +00:00
ICDRipper audioSource = ( ICDRipper ) sender ;
2008-12-09 07:25:48 +00:00
int processed = e . Position - e . PassStart ;
TimeSpan elapsed = DateTime . Now - e . PassTime ;
double speed = elapsed . TotalSeconds > 0 ? processed / elapsed . TotalSeconds / 75 : 1.0 ;
_progress . percentDisk = ( double ) ( e . PassStart + ( processed + e . Pass * ( e . PassEnd - e . PassStart ) ) / ( audioSource . CorrectionQuality + 1 ) ) / audioSource . TOC . AudioLength ;
_progress . percentTrck = ( double ) ( e . Position - e . PassStart ) / ( e . PassEnd - e . PassStart ) ;
2009-08-21 03:26:12 +00:00
_progress . offset = 0 ;
2008-12-09 07:25:48 +00:00
_progress . status = string . Format ( "Ripping @{0:00.00}x {1}" , speed , e . Pass > 0 ? " (Retry " + e . Pass . ToString ( ) + ")" : "" ) ;
this . CUEToolsProgress ( this , _progress ) ;
}
private void MusicBrainz_LookupProgress ( object sender , XmlRequestEventArgs e )
{
if ( this . CUEToolsProgress = = null )
return ;
_progress . percentDisk = ( 1.0 + _progress . percentDisk ) / 2 ;
_progress . percentTrck = 0 ;
2009-08-21 03:26:12 +00:00
_progress . offset = 0 ;
2008-12-09 07:25:48 +00:00
_progress . input = e . Uri . ToString ( ) ;
_progress . output = null ;
_progress . status = "Looking up album via MusicBrainz" ;
this . CUEToolsProgress ( this , _progress ) ;
}
2010-02-08 01:29:31 +00:00
private void unzip_ExtractionProgress ( object sender , CompressionExtractionProgressEventArgs e )
2009-02-22 07:47:56 +00:00
{
CheckStop ( ) ;
if ( this . CUEToolsProgress = = null )
return ;
_progress . percentTrck = e . PercentComplete / 100 ;
this . CUEToolsProgress ( this , _progress ) ;
}
2010-02-08 01:29:31 +00:00
private void unzip_PasswordRequired ( object sender , CompressionPasswordRequiredEventArgs e )
2009-02-22 07:47:56 +00:00
{
if ( _archivePassword ! = null )
{
e . ContinueOperation = true ;
e . Password = _archivePassword ;
return ;
}
if ( this . PasswordRequired ! = null )
2010-02-08 01:29:31 +00:00
{
this . PasswordRequired ( this , e ) ;
if ( e . ContinueOperation & & e . Password ! = "" )
2009-02-22 07:47:56 +00:00
{
2010-02-08 01:29:31 +00:00
_archivePassword = e . Password ;
2009-02-22 07:47:56 +00:00
return ;
}
}
throw new IOException ( "Password is required for extraction." ) ;
}
2009-02-19 04:09:59 +00:00
public delegate string GetStringTagProvider ( TagLib . File file ) ;
public string GetCommonTag ( GetStringTagProvider provider )
2008-12-07 23:38:00 +00:00
{
if ( _hasEmbeddedCUESheet | | _hasSingleFilename )
2010-02-06 23:17:07 +00:00
return _fileInfo = = null ? null : General . EmptyStringToNull ( provider ( _fileInfo ) ) ;
2008-12-07 23:38:00 +00:00
if ( _hasTrackFilenames )
{
string tagValue = null ;
bool commonValue = true ;
for ( int i = 0 ; i < TrackCount ; i + + )
{
TrackInfo track = _tracks [ i ] ;
2009-06-24 19:40:23 +00:00
string newValue = track . _fileInfo = = null ? null :
General . EmptyStringToNull ( provider ( track . _fileInfo ) ) ;
2008-12-07 23:38:00 +00:00
if ( tagValue = = null )
tagValue = newValue ;
else
commonValue = ( newValue = = null | | tagValue = = newValue ) ;
}
return commonValue ? tagValue : null ;
}
return null ;
}
2009-02-19 04:09:59 +00:00
public string GetCommonMiscTag ( string tagName )
{
return GetCommonTag ( delegate ( TagLib . File file ) { return Tagging . TagListToSingleValue ( Tagging . GetMiscTag ( file , tagName ) ) ; } ) ;
}
2010-02-06 23:17:07 +00:00
private static string LocateFile ( string dir , string file , List < string > contents )
{
2008-12-07 23:38:00 +00:00
List < string > dirList , fileList ;
2009-01-28 04:53:13 +00:00
string altDir ;
2008-12-07 23:38:00 +00:00
dirList = new List < string > ( ) ;
fileList = new List < string > ( ) ;
altDir = Path . GetDirectoryName ( file ) ;
file = Path . GetFileName ( file ) ;
dirList . Add ( dir ) ;
if ( altDir . Length ! = 0 ) {
dirList . Add ( Path . IsPathRooted ( altDir ) ? altDir : Path . Combine ( dir , altDir ) ) ;
}
fileList . Add ( file ) ;
fileList . Add ( file . Replace ( ' ' , '_' ) ) ;
fileList . Add ( file . Replace ( '_' , ' ' ) ) ;
for ( int iDir = 0 ; iDir < dirList . Count ; iDir + + ) {
for ( int iFile = 0 ; iFile < fileList . Count ; iFile + + ) {
2009-01-28 04:53:13 +00:00
string path = Path . Combine ( dirList [ iDir ] , fileList [ iFile ] ) ;
2009-02-19 04:09:59 +00:00
if ( ( contents = = null & & System . IO . File . Exists ( path ) )
2009-01-28 04:53:13 +00:00
| | ( contents ! = null & & contents . Contains ( path ) ) )
return path ;
path = dirList [ iDir ] + '/' + fileList [ iFile ] ;
if ( contents ! = null & & contents . Contains ( path ) )
2008-12-07 23:38:00 +00:00
return path ;
}
}
return null ;
}
2009-08-06 13:03:02 +00:00
private static bool IsCDROM ( string pathIn )
{
return pathIn . Length = = 3 & & pathIn . Substring ( 1 ) = = ":\\" & & new DriveInfo ( pathIn ) . DriveType = = DriveType . CDRom ;
}
2009-08-08 16:14:06 +00:00
public string GenerateUniqueOutputPath ( string format , string ext , CUEAction action , string pathIn )
2009-08-06 13:03:02 +00:00
{
2009-08-08 16:14:06 +00:00
return GenerateUniqueOutputPath ( _config , format , ext , action , new NameValueCollection ( ) , pathIn , this ) ;
2009-08-06 13:03:02 +00:00
}
public static string GenerateUniqueOutputPath ( CUEConfig _config , string format , string ext , CUEAction action , NameValueCollection vars , string pathIn , CUESheet cueSheet )
{
2009-08-08 16:14:06 +00:00
if ( pathIn = = "" | | ( pathIn = = null & & action ! = CUEAction . Encode ) | | ( pathIn ! = null & & ! IsCDROM ( pathIn ) & & ! File . Exists ( pathIn ) & & ! Directory . Exists ( pathIn ) ) )
2009-08-06 13:03:02 +00:00
return String . Empty ;
if ( action = = CUEAction . Verify & & _config . arLogToSourceFolder )
return Path . ChangeExtension ( pathIn , ".cue" ) ;
if ( action = = CUEAction . CreateDummyCUE )
return Path . ChangeExtension ( pathIn , ".cue" ) ;
if ( action = = CUEAction . CorrectFilenames )
return pathIn ;
if ( _config . detectHDCD & & _config . decodeHDCD & & ( ! ext . StartsWith ( ".lossy." ) | | ! _config . decodeHDCDtoLW16 ) )
{
if ( _config . decodeHDCDto24bit )
ext = ".24bit" + ext ;
else
ext = ".20bit" + ext ;
}
2009-08-08 16:14:06 +00:00
if ( pathIn ! = null )
{
vars . Add ( "path" , pathIn ) ;
try
{
vars . Add ( "filename" , Path . GetFileNameWithoutExtension ( pathIn ) ) ;
vars . Add ( "filename_ext" , Path . GetFileName ( pathIn ) ) ;
vars . Add ( "directoryname" , General . EmptyStringToNull ( Path . GetDirectoryName ( pathIn ) ) ) ;
}
catch { }
2009-08-06 13:03:02 +00:00
}
vars . Add ( "music" , Environment . GetFolderPath ( Environment . SpecialFolder . MyMusic ) ) ;
string artist = cueSheet = = null ? "Artist" : cueSheet . Artist = = "" ? "Unknown Artist" : cueSheet . Artist ;
string album = cueSheet = = null ? "Album" : cueSheet . Title = = "" ? "Unknown Title" : cueSheet . Title ;
2009-08-08 16:14:06 +00:00
vars . Add ( "artist" , General . EmptyStringToNull ( _config . CleanseString ( artist ) ) ) ;
vars . Add ( "album" , General . EmptyStringToNull ( _config . CleanseString ( album ) ) ) ;
2009-08-06 13:03:02 +00:00
if ( cueSheet ! = null )
{
vars . Add ( "year" , General . EmptyStringToNull ( cueSheet . Year ) ) ;
vars . Add ( "catalog" , General . EmptyStringToNull ( cueSheet . Catalog ) ) ;
vars . Add ( "discnumber" , General . EmptyStringToNull ( cueSheet . DiscNumber ) ) ;
vars . Add ( "totaldiscs" , General . EmptyStringToNull ( cueSheet . TotalDiscs ) ) ;
NameValueCollection tags = cueSheet . Tags ;
2009-08-08 16:14:06 +00:00
if ( tags ! = null )
foreach ( string tag in tags . AllKeys )
{
string key = tag . ToLower ( ) ;
string val = tags [ tag ] ;
if ( vars . Get ( key ) = = null & & val ! = null & & val ! = "" )
vars . Add ( key , _config . CleanseString ( val ) ) ;
}
2009-08-06 13:03:02 +00:00
}
vars . Add ( "unique" , null ) ;
2009-08-08 16:14:06 +00:00
string outputPath = General . ReplaceMultiple ( format , vars , "unique" ,
( General . CheckIfExists ) delegate ( string pathOut ) {
return File . Exists ( Path . ChangeExtension ( pathOut , ext ) ) ;
} ) ;
if ( outputPath = = "" | | outputPath = = null )
return "" ;
try { outputPath = Path . ChangeExtension ( outputPath , ext ) ; }
catch { outputPath = "" ; }
2009-08-06 13:03:02 +00:00
return outputPath ;
}
2009-08-08 16:14:06 +00:00
private bool CheckIfFileExists ( string output )
{
return File . Exists ( Path . Combine ( OutputDir , output ) ) ;
}
2009-05-01 15:16:26 +00:00
public void GenerateFilenames ( AudioEncoderType audioEncoderType , string format , string outputPath )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
_audioEncoderType = audioEncoderType ;
_outputLossyWAV = format . StartsWith ( "lossy." ) ;
2009-01-28 04:53:13 +00:00
_outputFormat = format ;
2009-05-01 15:16:26 +00:00
_outputPath = outputPath ;
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
string extension = "." + format ;
2008-12-07 23:38:00 +00:00
string filename ;
int iTrack ;
2009-08-08 16:14:06 +00:00
NameValueCollection vars = new NameValueCollection ( ) ;
vars . Add ( "unique" , null ) ;
vars . Add ( "album artist" , General . EmptyStringToNull ( _config . CleanseString ( Artist ) ) ) ;
vars . Add ( "artist" , General . EmptyStringToNull ( _config . CleanseString ( Artist ) ) ) ;
vars . Add ( "album" , General . EmptyStringToNull ( _config . CleanseString ( Title ) ) ) ;
vars . Add ( "year" , General . EmptyStringToNull ( _config . CleanseString ( Year ) ) ) ;
vars . Add ( "catalog" , General . EmptyStringToNull ( _config . CleanseString ( Catalog ) ) ) ;
vars . Add ( "discnumber" , General . EmptyStringToNull ( _config . CleanseString ( DiscNumber ) ) ) ;
vars . Add ( "totaldiscs" , General . EmptyStringToNull ( _config . CleanseString ( TotalDiscs ) ) ) ;
vars . Add ( "filename" , Path . GetFileNameWithoutExtension ( outputPath ) ) ;
vars . Add ( "tracknumber" , null ) ;
vars . Add ( "title" , null ) ;
2008-12-07 23:38:00 +00:00
if ( _config . detectHDCD & & _config . decodeHDCD & & ( ! _outputLossyWAV | | ! _config . decodeHDCDtoLW16 ) )
{
if ( _config . decodeHDCDto24bit )
extension = ".24bit" + extension ;
else
extension = ".20bit" + extension ;
}
2009-08-08 16:14:06 +00:00
ArLogFileName = General . ReplaceMultiple ( _config . arLogFilenameFormat , vars , "unique" , CheckIfFileExists )
? ? vars [ "%filename%" ] + ".accurip" ;
AlArtFileName = General . ReplaceMultiple ( _config . alArtFilenameFormat , vars , "unique" , CheckIfFileExists )
? ? "folder.jpg" ;
2009-08-06 13:03:02 +00:00
2009-08-08 16:14:06 +00:00
if ( OutputStyle = = CUEStyle . SingleFileWithCUE )
SingleFilename = Path . ChangeExtension ( Path . GetFileName ( outputPath ) , extension ) ;
else if ( _config . keepOriginalFilenames & & HasSingleFilename )
2008-12-07 23:38:00 +00:00
SingleFilename = Path . ChangeExtension ( SingleFilename , extension ) ;
else
2009-08-08 16:14:06 +00:00
SingleFilename = ( General . ReplaceMultiple ( _config . singleFilenameFormat , vars ) ? ? "range" ) + extension ;
2008-12-07 23:38:00 +00:00
for ( iTrack = - 1 ; iTrack < TrackCount ; iTrack + + )
{
bool htoa = ( iTrack = = - 1 ) ;
if ( _config . keepOriginalFilenames & & htoa & & HasHTOAFilename )
{
HTOAFilename = Path . ChangeExtension ( HTOAFilename , extension ) ;
}
else if ( _config . keepOriginalFilenames & & ! htoa & & HasTrackFilenames )
{
TrackFilenames [ iTrack ] = Path . ChangeExtension (
TrackFilenames [ iTrack ] , extension ) ;
}
else
{
string trackStr = htoa ? "01.00" : String . Format ( "{0:00}" , iTrack + 1 ) ;
string artist = Tracks [ htoa ? 0 : iTrack ] . Artist ;
string title = htoa ? "(HTOA)" : Tracks [ iTrack ] . Title ;
2009-08-08 16:14:06 +00:00
vars [ "tracknumber" ] = trackStr ;
vars [ "artist" ] = General . EmptyStringToNull ( _config . CleanseString ( artist ) ) ? ? vars [ "album artist" ] ;
vars [ "title" ] = General . EmptyStringToNull ( _config . CleanseString ( title ) ) ;
2008-12-07 23:38:00 +00:00
2009-08-08 16:14:06 +00:00
filename = ( General . ReplaceMultiple ( _config . trackFilenameFormat , vars ) ? ? vars [ "tracknumber" ] ) + extension ;
2008-12-07 23:38:00 +00:00
if ( htoa )
HTOAFilename = filename ;
else
TrackFilenames [ iTrack ] = filename ;
}
}
2009-05-10 18:34:49 +00:00
if ( OutputStyle = = CUEStyle . SingleFile | | OutputStyle = = CUEStyle . SingleFileWithCUE )
{
_destPaths = new string [ 1 ] ;
_destPaths [ 0 ] = Path . Combine ( OutputDir , _singleFilename ) ;
}
else
{
bool htoaToFile = ( ( OutputStyle = = CUEStyle . GapsAppended ) & & _config . preserveHTOA & &
( _toc . Pregap ! = 0 ) ) ;
_destPaths = new string [ TrackCount + ( htoaToFile ? 1 : 0 ) ] ;
if ( htoaToFile )
_destPaths [ 0 ] = Path . Combine ( OutputDir , _htoaFilename ) ;
for ( int i = 0 ; i < TrackCount ; i + + )
_destPaths [ i + ( htoaToFile ? 1 : 0 ) ] = Path . Combine ( OutputDir , _trackFilenames [ i ] ) ;
}
2008-12-07 23:38:00 +00:00
}
2009-08-08 16:14:06 +00:00
public bool OutputExists ( )
{
bool outputExists = false ;
bool outputCUE = Action = = CUEAction . Encode & & ( OutputStyle ! = CUEStyle . SingleFileWithCUE | | _config . createCUEFileWhenEmbedded ) ;
bool outputAudio = Action = = CUEAction . Encode & & _audioEncoderType ! = AudioEncoderType . NoAudio ;
if ( outputCUE )
outputExists = File . Exists ( _outputPath ) ;
if ( _useAccurateRip & & (
( Action = = CUEAction . Encode & & _config . writeArLogOnConvert ) | |
( Action = = CUEAction . Verify & & _config . writeArLogOnVerify ) ) )
outputExists | = File . Exists ( Path . Combine ( OutputDir , ArLogFileName ) ) ;
if ( outputAudio )
{
if ( _config . extractAlbumArt & & AlbumArt ! = null & & AlbumArt . Length ! = 0 )
outputExists | = File . Exists ( Path . Combine ( OutputDir , AlArtFileName ) ) ;
if ( OutputStyle = = CUEStyle . SingleFile | | OutputStyle = = CUEStyle . SingleFileWithCUE )
outputExists | = File . Exists ( Path . Combine ( OutputDir , SingleFilename ) ) ;
else
{
if ( OutputStyle = = CUEStyle . GapsAppended & & _config . preserveHTOA )
outputExists | = File . Exists ( Path . Combine ( OutputDir , HTOAFilename ) ) ;
for ( int i = 0 ; i < TrackCount ; i + + )
outputExists | = File . Exists ( Path . Combine ( OutputDir , TrackFilenames [ i ] ) ) ;
}
}
return outputExists ;
}
2009-02-19 04:09:59 +00:00
private int GetSampleLength ( string path , out TagLib . File fileInfo )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
ShowProgress ( "Analyzing input file..." , 0.0 , 0.0 , path , null ) ;
2010-02-06 23:17:07 +00:00
if ( Path . GetExtension ( path ) = = ".dummy" | | Path . GetExtension ( path ) = = ".bin" )
{
fileInfo = null ;
2010-02-23 15:15:08 +00:00
}
else
2010-02-06 23:17:07 +00:00
{
TagLib . UserDefined . AdditionalFileTypes . Config = _config ;
TagLib . File . IFileAbstraction file = _isArchive
? ( TagLib . File . IFileAbstraction ) new ArchiveFileAbstraction ( this , path )
: ( TagLib . File . IFileAbstraction ) new TagLib . File . LocalFileAbstraction ( path ) ;
fileInfo = TagLib . File . Create ( file ) ;
}
2008-12-07 23:38:00 +00:00
2009-02-19 04:09:59 +00:00
IAudioSource audioSource = AudioReadWrite . GetAudioSource ( path , _isArchive ? OpenArchive ( path , true ) : null , _config ) ;
2010-02-23 15:15:08 +00:00
try
{
if ( ! audioSource . PCM . IsRedBook | |
audioSource . Length < = 0 | |
audioSource . Length > = Int32 . MaxValue )
throw new Exception ( "Audio format is invalid." ) ;
return ( int ) audioSource . Length ;
}
finally
2008-12-07 23:38:00 +00:00
{
audioSource . Close ( ) ;
}
}
2009-03-04 21:30:56 +00:00
public static void WriteText ( string path , string text , Encoding encoding )
2008-12-07 23:38:00 +00:00
{
2009-03-04 21:30:56 +00:00
StreamWriter sw1 = new StreamWriter ( path , false , encoding ) ;
2008-12-09 07:25:48 +00:00
sw1 . Write ( text ) ;
2008-12-07 23:38:00 +00:00
sw1 . Close ( ) ;
}
2009-03-04 21:30:56 +00:00
public static void WriteText ( string path , string text )
2008-12-07 23:38:00 +00:00
{
2009-03-04 21:30:56 +00:00
bool utf8Required = CUESheet . Encoding . GetString ( CUESheet . Encoding . GetBytes ( text ) ) ! = text ;
WriteText ( path , text , utf8Required ? Encoding . UTF8 : CUESheet . Encoding ) ;
}
public string LOGContents
{
get
{
return _ripperLog ;
}
}
2010-02-28 21:04:34 +00:00
public bool PrintErrors ( StringWriter logWriter , uint tr_start , uint len )
{
uint tr_end = ( len + 74 ) / 75 ;
int errCount = 0 ;
for ( uint iSecond = 0 ; iSecond < tr_end ; iSecond + + )
{
uint sec_start = tr_start + iSecond * 75 ;
uint sec_end = Math . Min ( sec_start + 74 , tr_start + len - 1 ) ;
bool fError = false ;
for ( uint iSector = sec_start ; iSector < = sec_end ; iSector + + )
2010-03-20 07:09:07 +00:00
if ( _ripper . Errors [ ( int ) iSector - ( int ) _toc [ _toc . FirstAudio ] [ 0 ] . Start ] )
2010-02-28 21:04:34 +00:00
fError = true ;
if ( fError )
{
2010-03-20 07:09:07 +00:00
uint end = tr_end - 1 ;
2010-02-28 21:04:34 +00:00
for ( uint jSecond = iSecond + 1 ; jSecond < tr_end ; jSecond + + )
{
uint jsec_start = tr_start + jSecond * 75 ;
uint jsec_end = Math . Min ( jsec_start + 74 , tr_start + len - 1 ) ;
bool jfError = false ;
for ( uint jSector = jsec_start ; jSector < = jsec_end ; jSector + + )
2010-03-20 07:09:07 +00:00
if ( _ripper . Errors [ ( int ) jSector - ( int ) _toc [ _toc . FirstAudio ] [ 0 ] . Start ] )
2010-02-28 21:04:34 +00:00
jfError = true ;
2010-03-20 07:09:07 +00:00
if ( ! jfError )
{
end = jSecond - 1 ;
break ;
}
2010-02-28 21:04:34 +00:00
}
if ( errCount = = 0 )
logWriter . WriteLine ( ) ;
if ( errCount + + > 20 )
break ;
//"Suspicious position 0:02:20"
//" Suspicious position 0:02:23 - 0:02:24"
string s1 = CDImageLayout . TimeToString ( "0:{0:00}:{1:00}" , iSecond * 75 ) ;
string s2 = CDImageLayout . TimeToString ( "0:{0:00}:{1:00}" , end * 75 ) ;
if ( iSecond = = end )
logWriter . WriteLine ( " Suspicious position {0}" , s1 ) ;
else
logWriter . WriteLine ( " Suspicious position {0} - {1}" , s1 , s2 ) ;
2010-03-20 07:09:07 +00:00
iSecond = end + 1 ;
2010-02-28 21:04:34 +00:00
}
}
return errCount > 0 ;
}
2009-05-10 18:34:49 +00:00
public void CreateExactAudioCopyLOG ( )
2009-03-04 21:30:56 +00:00
{
StringWriter logWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
string eacHeader = "Exact Audio Copy V0.99 prebeta 4 from 23. January 2008\r\n" +
"\r\n" +
"EAC extraction logfile from {0:d'.' MMMM yyyy', 'H':'mm}\r\n" +
"\r\n" +
"{1} / {2}\r\n" +
"\r\n" +
"Used drive : {3} Adapter: 1 ID: 0\r\n" +
"\r\n" +
"Read mode : {4}\r\n" +
"Utilize accurate stream : Yes\r\n" +
"Defeat audio cache : Yes\r\n" +
"Make use of C2 pointers : No\r\n" +
"\r\n" +
"Read offset correction : {5}\r\n" +
"Overread into Lead-In and Lead-Out : No\r\n" +
"Fill up missing offset samples with silence : Yes\r\n" +
"Delete leading and trailing silent blocks : No\r\n" +
"Null samples used in CRC calculations : Yes\r\n" +
"Used interface : Native Win32 interface for Win NT & 2000\r\n" +
2010-02-28 21:04:34 +00:00
"{6}" +
2009-03-04 21:30:56 +00:00
"\r\n" +
2009-05-10 18:34:49 +00:00
"Used output format : Internal WAV Routines\r\n" +
"Sample format : 44.100 Hz; 16 Bit; Stereo\r\n" ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( eacHeader ,
DateTime . Now ,
Artist , Title ,
_ripper . EACName ,
_ripper . CorrectionQuality > 0 ? "Secure" : "Burst" ,
2010-02-28 21:04:34 +00:00
_ripper . DriveOffset ,
2010-03-20 07:09:07 +00:00
( OutputStyle = = CUEStyle . SingleFile | | OutputStyle = = CUEStyle . SingleFileWithCUE ) ? "" :
"Gap handling : " +
( _ripper . GapsDetected ? "Appended to previous track\r\n" : "Not detected, thus appended to previous track\r\n" ) ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "TOC of the extracted CD" ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( " Track | Start | Length | Start sector | End sector " ) ;
logWriter . WriteLine ( " ---------------------------------------------------------" ) ;
for ( int track = 1 ; track < = _toc . TrackCount ; track + + )
logWriter . WriteLine ( "{0,9} | {1,8} | {2,8} | {3,8} | {4,8} " ,
_toc [ track ] . Number ,
CDImageLayout . TimeToString ( "{0,2}:{1:00}.{2:00}" , _toc [ track ] . Start ) ,
CDImageLayout . TimeToString ( "{0,2}:{1:00}.{2:00}" , _toc [ track ] . Length ) ,
_toc [ track ] . Start ,
_toc [ track ] . End ) ;
logWriter . WriteLine ( ) ;
2009-05-10 18:34:49 +00:00
bool htoaToFile = ( ( OutputStyle = = CUEStyle . GapsAppended ) & & _config . preserveHTOA & &
2009-03-04 21:30:56 +00:00
( _toc . Pregap ! = 0 ) ) ;
int accurateTracks = 0 , knownTracks = 0 ;
2010-02-28 21:04:34 +00:00
bool wereErrors = false ;
2009-05-10 18:34:49 +00:00
if ( OutputStyle ! = CUEStyle . SingleFile & & OutputStyle ! = CUEStyle . SingleFileWithCUE )
2009-03-04 21:30:56 +00:00
{
logWriter . WriteLine ( ) ;
for ( int track = 0 ; track < _toc . AudioTracks ; track + + )
{
logWriter . WriteLine ( "Track {0,2}" , track + 1 ) ;
logWriter . WriteLine ( ) ;
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( " Filename {0}" , Path . ChangeExtension ( Path . GetFullPath ( _destPaths [ track + ( htoaToFile ? 1 : 0 ) ] ) , ".wav" ) ) ;
2009-03-04 21:30:56 +00:00
if ( _toc [ track + _toc . FirstAudio ] . Pregap > 0 | | track + _toc . FirstAudio = = 1 )
{
logWriter . WriteLine ( ) ;
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( " Pre-gap length 0:{0}.{1:00}" , CDImageLayout . TimeToString ( "{0:00}:{1:00}" , _toc [ track + _toc . FirstAudio ] . Pregap + ( track + _toc . FirstAudio = = 1 ? 150 U : 0 U ) ) , ( _toc [ track + _toc . FirstAudio ] . Pregap % 75 ) * 100 / 75 ) ;
2009-03-04 21:30:56 +00:00
}
2010-02-23 15:15:08 +00:00
2010-02-28 21:04:34 +00:00
wereErrors | = PrintErrors ( logWriter , _toc [ track + _toc . FirstAudio ] . Start , _toc [ track + _toc . FirstAudio ] . Length ) ;
2010-02-23 15:15:08 +00:00
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
2010-03-20 07:09:07 +00:00
logWriter . WriteLine ( " Peak level {0:F1} %" , ( _arVerify . PeakLevel ( track + 1 ) * 1000 / 65535 ) * 0.1 ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( " Track quality 100.0 %" ) ;
logWriter . WriteLine ( " Test CRC {0:X8}" , _arVerify . CRC32 ( track + 1 ) ) ;
logWriter . WriteLine ( " Copy CRC {0:X8}" , _arVerify . CRC32 ( track + 1 ) ) ;
if ( _arVerify . Total ( track ) = = 0 )
logWriter . WriteLine ( " Track not present in AccurateRip database" ) ;
else
{
knownTracks + + ;
if ( _arVerify . Confidence ( track ) = = 0 )
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( " Cannot be verified as accurate (confidence {0}) [{1:X8}], AccurateRip returned [{2:X8}]" , _arVerify . Total ( track ) , _arVerify . CRC ( track ) , _arVerify . DBCRC ( track ) ) ;
2009-03-04 21:30:56 +00:00
else
{
logWriter . WriteLine ( " Accurately ripped (confidence {0}) [{1:X8}]" , _arVerify . Confidence ( track ) , _arVerify . CRC ( track ) ) ;
accurateTracks + + ;
}
}
logWriter . WriteLine ( " Copy OK" ) ;
logWriter . WriteLine ( ) ;
}
}
else
{
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "Range status and errors" ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "Selected range" ) ;
logWriter . WriteLine ( ) ;
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( " Filename {0}" , Path . ChangeExtension ( Path . GetFullPath ( _destPaths [ 0 ] ) , ".wav" ) ) ;
2010-02-28 21:04:34 +00:00
wereErrors = PrintErrors ( logWriter , _toc [ _toc . FirstAudio ] [ 0 ] . Start , _toc . AudioLength ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
2010-03-20 07:09:07 +00:00
logWriter . WriteLine ( " Peak level {0:F1} %" , ( _arVerify . PeakLevel ( ) * 1000 / 65535 ) * 0.1 ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( " Range quality 100.0 %" ) ;
logWriter . WriteLine ( " Test CRC {0:X8}" , _arVerify . CRC32 ( 0 ) ) ;
logWriter . WriteLine ( " Copy CRC {0:X8}" , _arVerify . CRC32 ( 0 ) ) ;
logWriter . WriteLine ( " Copy OK" ) ;
logWriter . WriteLine ( ) ;
2010-02-28 21:04:34 +00:00
if ( wereErrors )
logWriter . WriteLine ( "There were errors" ) ;
else
logWriter . WriteLine ( "No errors occurred" ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "AccurateRip summary" ) ;
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( ) ;
for ( int track = 0 ; track < _toc . AudioTracks ; track + + )
2009-03-04 21:30:56 +00:00
{
2009-05-10 18:34:49 +00:00
if ( _arVerify . Total ( track ) = = 0 )
logWriter . WriteLine ( "Track {0,2} not present in database" , track + 1 ) ;
2009-03-04 21:30:56 +00:00
else
{
knownTracks + + ;
2009-05-10 18:34:49 +00:00
if ( _arVerify . Confidence ( track ) = = 0 )
logWriter . WriteLine ( "Track {3,2} cannot be verified as accurate (confidence {0}) [{1:X8}], AccurateRip returned [{2:X8}]" , _arVerify . Total ( track ) , _arVerify . CRC ( track ) , _arVerify . DBCRC ( track ) , track + 1 ) ;
2009-03-04 21:30:56 +00:00
else
{
2009-05-10 18:34:49 +00:00
logWriter . WriteLine ( "Track {2,2} accurately ripped (confidence {0}) [{1:X8}]" , _arVerify . Confidence ( track ) , _arVerify . CRC ( track ) , track + 1 ) ;
2009-03-04 21:30:56 +00:00
accurateTracks + + ;
}
}
}
}
logWriter . WriteLine ( ) ;
if ( knownTracks = = 0 )
logWriter . WriteLine ( "None of the tracks are present in the AccurateRip database" ) ;
else if ( accurateTracks = = 0 )
2009-05-10 18:34:49 +00:00
{
logWriter . WriteLine ( "No tracks could be verified as accurate" ) ;
logWriter . WriteLine ( "You may have a different pressing from the one(s) in the database" ) ;
}
2009-03-04 21:30:56 +00:00
else if ( accurateTracks = = TrackCount )
logWriter . WriteLine ( "All tracks accurately ripped" ) ;
else
{
logWriter . WriteLine ( "{0,2} track(s) accurately ripped" , accurateTracks ) ;
if ( TrackCount - knownTracks > 0 )
logWriter . WriteLine ( "{0,2} track(s) not present in the AccurateRip database" , TrackCount - knownTracks ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "Some tracks could not be verified as accurate" ) ;
}
logWriter . WriteLine ( ) ;
2009-05-10 18:34:49 +00:00
if ( OutputStyle ! = CUEStyle . SingleFile & & OutputStyle ! = CUEStyle . SingleFileWithCUE )
2009-03-04 21:30:56 +00:00
{
2010-02-28 21:04:34 +00:00
if ( wereErrors )
logWriter . WriteLine ( "There were errors" ) ;
else
logWriter . WriteLine ( "No errors occurred" ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
}
logWriter . WriteLine ( "End of status report" ) ;
logWriter . Close ( ) ;
_ripperLog = logWriter . ToString ( ) ;
}
2009-05-10 18:34:49 +00:00
public void CreateRipperLOG ( )
2009-03-04 21:30:56 +00:00
{
if ( ! _isCD | | _ripper = = null | | _ripperLog ! = null )
return ;
if ( _config . createEACLOG )
{
2009-05-10 18:34:49 +00:00
CreateExactAudioCopyLOG ( ) ;
2009-03-04 21:30:56 +00:00
return ;
}
2010-03-20 07:09:07 +00:00
StringWriter logWriter = new StringWriter ( CultureInfo . InvariantCulture ) ;
2010-02-08 01:29:31 +00:00
logWriter . WriteLine ( "{0}" , _ripper . RipperVersion ) ;
2008-12-09 07:25:48 +00:00
logWriter . WriteLine ( "Extraction logfile from : {0}" , DateTime . Now ) ;
2008-12-10 06:48:38 +00:00
logWriter . WriteLine ( "Used drive : {0}" , _ripper . ARName ) ;
logWriter . WriteLine ( "Read offset correction : {0}" , _ripper . DriveOffset ) ;
logWriter . WriteLine ( "Read command : {0}" , _ripper . CurrentReadCommand ) ;
logWriter . WriteLine ( "Secure mode : {0}" , _ripper . CorrectionQuality ) ;
logWriter . WriteLine ( "Disk length : {0}" , CDImageLayout . TimeToString ( _toc . AudioLength ) ) ;
logWriter . WriteLine ( "AccurateRip : {0}" , _arVerify . ARStatus = = null ? "ok" : _arVerify . ARStatus ) ;
2010-02-08 01:29:31 +00:00
if ( hdcdDecoder ! = null & & string . Format ( "{0:s}" , hdcdDecoder ) ! = "" )
logWriter . WriteLine ( "HDCD : {0:f}" , hdcdDecoder ) ;
2008-12-09 07:25:48 +00:00
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "TOC of the extracted CD" ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( " Track | Start | Length | Start sector | End sector" ) ;
logWriter . WriteLine ( " ---------------------------------------------------------" ) ;
for ( int track = 1 ; track < = _toc . TrackCount ; track + + )
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( "{0,9} | {1,8} | {2,8} | {3,8} | {4,8}" ,
2008-12-09 07:25:48 +00:00
_toc [ track ] . Number ,
_toc [ track ] . StartMSF ,
_toc [ track ] . LengthMSF ,
_toc [ track ] . Start ,
_toc [ track ] . End ) ;
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( " Track | Pregap | Indexes" ) ;
logWriter . WriteLine ( " ---------------------------------------------------------" ) ;
for ( int track = 1 ; track < = _toc . TrackCount ; track + + )
logWriter . WriteLine ( "{0,9} | {1,8} | {2,2}" ,
_toc [ track ] . Number ,
CDImageLayout . TimeToString ( _toc [ track ] . Pregap + ( track = = 1 ? 150 U : 0 U ) ) ,
_toc [ track ] . LastIndex ) ;
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "Destination files" ) ;
2009-05-10 18:34:49 +00:00
foreach ( string path in _destPaths )
2009-03-04 21:30:56 +00:00
logWriter . WriteLine ( " {0}" , path ) ;
2010-02-28 21:04:34 +00:00
bool wereErrors = PrintErrors ( logWriter , _toc [ _toc . FirstAudio ] [ 0 ] . Start , _toc . AudioLength ) ;
if ( wereErrors )
2008-12-09 07:25:48 +00:00
{
2010-02-28 21:04:34 +00:00
logWriter . WriteLine ( ) ;
if ( wereErrors )
logWriter . WriteLine ( "There were errors" ) ;
else
logWriter . WriteLine ( "No errors occurred" ) ;
}
if ( _useCUEToolsDB )
{
logWriter . WriteLine ( ) ;
GenerateCTDBLog ( logWriter ) ;
2008-12-07 23:38:00 +00:00
}
2009-08-08 16:14:06 +00:00
if ( _useAccurateRip )
2008-12-09 07:25:48 +00:00
{
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "AccurateRip summary" ) ;
logWriter . WriteLine ( ) ;
2009-05-01 15:16:26 +00:00
_arVerify . GenerateFullLog ( logWriter , true ) ;
2008-12-09 07:25:48 +00:00
}
logWriter . WriteLine ( ) ;
logWriter . WriteLine ( "End of status report" ) ;
logWriter . Close ( ) ;
2009-03-04 21:30:56 +00:00
_ripperLog = logWriter . ToString ( ) ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
public string M3UContents ( CUEStyle style )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
StringWriter sw = new StringWriter ( ) ;
if ( style = = CUEStyle . GapsAppended & & _config . preserveHTOA & & _toc . Pregap ! = 0 )
WriteLine ( sw , 0 , _htoaFilename ) ;
for ( int iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
WriteLine ( sw , 0 , _trackFilenames [ iTrack ] ) ;
2008-12-07 23:38:00 +00:00
sw . Close ( ) ;
2008-12-09 07:25:48 +00:00
return sw . ToString ( ) ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
public string TOCContents ( )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
StringWriter sw = new StringWriter ( ) ;
2009-01-28 04:53:13 +00:00
for ( int iTrack = 1 ; iTrack < = _toc . TrackCount ; iTrack + + )
sw . WriteLine ( "\t{0}" , _toc [ iTrack ] . Start + 150 ) ;
2008-12-07 23:38:00 +00:00
sw . Close ( ) ;
2008-12-09 07:25:48 +00:00
return sw . ToString ( ) ;
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
public string CUESheetContents ( )
{
CUEStyle style = _hasEmbeddedCUESheet ? CUEStyle . SingleFile
: _hasSingleFilename ? CUEStyle . SingleFileWithCUE
: CUEStyle . GapsAppended ;
bool htoaToFile = _hasHTOAFilename ;
return CUESheetContents ( style , htoaToFile ) ;
}
public string CUESheetContents ( CUEStyle style )
{
return CUESheetContents ( style , ( style = = CUEStyle . GapsAppended & & _config . preserveHTOA & & _toc . Pregap ! = 0 ) ) ;
}
public string CUESheetContents ( CUEStyle style , bool htoaToFile )
2008-12-09 07:25:48 +00:00
{
StringWriter sw = new StringWriter ( ) ;
2008-12-07 23:38:00 +00:00
int i , iTrack , iIndex ;
uint timeRelativeToFileStart = 0 ;
2008-12-09 07:25:48 +00:00
using ( sw )
{
2009-08-08 16:14:06 +00:00
if ( _config . writeArTagsOnEncode )
2009-03-22 16:59:05 +00:00
WriteLine ( sw , 0 , "REM ACCURATERIPID " + ( _accurateRipId ? ? AccurateRipVerify . CalculateAccurateRipId ( _toc ) ) ) ;
2008-12-07 23:38:00 +00:00
2008-12-09 07:25:48 +00:00
for ( i = 0 ; i < _attributes . Count ; i + + )
2008-12-07 23:38:00 +00:00
WriteLine ( sw , 0 , _attributes [ i ] ) ;
2008-12-09 07:25:48 +00:00
if ( style = = CUEStyle . SingleFile | | style = = CUEStyle . SingleFileWithCUE )
2008-12-07 23:38:00 +00:00
WriteLine ( sw , 0 , String . Format ( "FILE \"{0}\" WAVE" , _singleFilename ) ) ;
2008-12-09 07:25:48 +00:00
if ( htoaToFile )
WriteLine ( sw , 0 , String . Format ( "FILE \"{0}\" WAVE" , _htoaFilename ) ) ;
2008-12-07 23:38:00 +00:00
2008-12-09 07:25:48 +00:00
for ( iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
{
2008-12-07 23:38:00 +00:00
if ( ( style = = CUEStyle . GapsPrepended ) | |
( style = = CUEStyle . GapsLeftOut ) | |
( ( style = = CUEStyle . GapsAppended ) & &
2009-01-28 04:53:13 +00:00
( ( _toc [ _toc . FirstAudio + iTrack ] . Pregap = = 0 ) | | ( ( iTrack = = 0 ) & & ! htoaToFile ) ) ) )
2008-12-07 23:38:00 +00:00
{
WriteLine ( sw , 0 , String . Format ( "FILE \"{0}\" WAVE" , _trackFilenames [ iTrack ] ) ) ;
timeRelativeToFileStart = 0 ;
}
WriteLine ( sw , 1 , String . Format ( "TRACK {0:00} AUDIO" , iTrack + 1 ) ) ;
2008-12-09 07:25:48 +00:00
for ( i = 0 ; i < _tracks [ iTrack ] . Attributes . Count ; i + + )
WriteLine ( sw , 2 , _tracks [ iTrack ] . Attributes [ i ] ) ;
2008-12-07 23:38:00 +00:00
2009-01-28 04:53:13 +00:00
if ( _toc [ _toc . FirstAudio + iTrack ] . Pregap ! = 0 )
2008-12-09 07:25:48 +00:00
{
if ( ( ( style = = CUEStyle . GapsLeftOut ) | |
( ( style = = CUEStyle . GapsAppended ) & & ( iTrack = = 0 ) & & ! htoaToFile ) | |
( ( style = = CUEStyle . SingleFile | | style = = CUEStyle . SingleFileWithCUE ) & & ( iTrack = = 0 ) & & _usePregapForFirstTrackInSingleFile ) ) )
2009-01-28 04:53:13 +00:00
WriteLine ( sw , 2 , "PREGAP " + CDImageLayout . TimeToString ( _toc [ _toc . FirstAudio + iTrack ] . Pregap ) ) ;
2008-12-09 07:25:48 +00:00
else
{
WriteLine ( sw , 2 , String . Format ( "INDEX 00 {0}" , CDImageLayout . TimeToString ( timeRelativeToFileStart ) ) ) ;
2009-01-28 04:53:13 +00:00
timeRelativeToFileStart + = _toc [ _toc . FirstAudio + iTrack ] . Pregap ;
2008-12-09 07:25:48 +00:00
if ( style = = CUEStyle . GapsAppended )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
WriteLine ( sw , 0 , String . Format ( "FILE \"{0}\" WAVE" , _trackFilenames [ iTrack ] ) ) ;
timeRelativeToFileStart = 0 ;
2008-12-07 23:38:00 +00:00
}
}
}
2009-01-28 04:53:13 +00:00
for ( iIndex = 1 ; iIndex < = _toc [ _toc . FirstAudio + iTrack ] . LastIndex ; iIndex + + )
2008-12-09 07:25:48 +00:00
{
WriteLine ( sw , 2 , String . Format ( "INDEX {0:00} {1}" , iIndex , CDImageLayout . TimeToString ( timeRelativeToFileStart ) ) ) ;
2009-01-28 04:53:13 +00:00
timeRelativeToFileStart + = _toc . IndexLength ( _toc . FirstAudio + iTrack , iIndex ) ;
2008-12-07 23:38:00 +00:00
}
}
}
2008-12-09 07:25:48 +00:00
sw . Close ( ) ;
return sw . ToString ( ) ;
2008-12-07 23:38:00 +00:00
}
2010-02-28 21:04:34 +00:00
public void GenerateCTDBLog ( TextWriter sw )
{
2010-03-20 07:09:07 +00:00
sw . WriteLine ( "[CTDB TOCID: {0}] {1}." , _toc . TOCID , _CUEToolsDB . DBStatus ? ? "found" ) ;
if ( ! _processed )
return ;
2010-02-28 21:04:34 +00:00
if ( _CUEToolsDB . SubStatus ! = null )
sw . WriteLine ( "CUETools DB: {0}." , _CUEToolsDB . SubStatus ) ;
if ( _CUEToolsDB . DBStatus = = null )
sw . WriteLine ( " [ CTDBID ] Status" ) ;
foreach ( DBEntry entry in _CUEToolsDB . Entries )
{
string confFormat = ( _CUEToolsDB . Total < 10 ) ? "{0:0}/{1:0}" :
( _CUEToolsDB . Total < 100 ) ? "{0:00}/{1:00}" : "{0:000}/{1:000}" ;
string conf = string . Format ( confFormat , entry . conf , _CUEToolsDB . Total ) ;
2010-03-20 07:09:07 +00:00
string dataTrackInfo = ! entry . toc [ entry . toc . TrackCount ] . IsAudio ? string . Format ( "Is an Enhanced CD, data track length {0}" , entry . toc [ entry . toc . TrackCount ] . LengthMSF ) :
! entry . toc [ 1 ] . IsAudio ? string . Format ( "Playstation type data track length {0}" , entry . toc [ 1 ] . LengthMSF ) : "" ;
2010-02-28 21:04:34 +00:00
string status =
2010-03-20 07:09:07 +00:00
entry . toc . Pregap ! = _toc . Pregap ? string . Format ( "Has pregap length {0}" , CDImageLayout . TimeToString ( entry . toc . Pregap ) ) :
entry . toc . AudioLength ! = _toc . AudioLength ? string . Format ( "Has audio length {0}" , CDImageLayout . TimeToString ( entry . toc . AudioLength ) ) :
( ( entry . toc . TrackOffsets ! = _toc . TrackOffsets ) ? dataTrackInfo + ", " : "" ) +
( ( ! entry . hasErrors ) ? "Accurately ripped" :
entry . canRecover ? string . Format ( "Differs in {0} samples" , entry . repair . CorrectableErrors ) :
( entry . httpStatus = = 0 | | entry . httpStatus = = HttpStatusCode . OK ) ? "No match" :
entry . httpStatus . ToString ( ) ) ;
2010-02-28 21:04:34 +00:00
sw . WriteLine ( " [{0:x8}] ({1}) {2}" , entry . crc , conf , status ) ;
}
}
2008-12-07 23:38:00 +00:00
public void GenerateAccurateRipLog ( TextWriter sw )
{
2008-12-09 07:25:48 +00:00
sw . WriteLine ( "[Verification date: {0}]" , DateTime . Now ) ;
2010-03-20 07:09:07 +00:00
sw . WriteLine ( "[AccurateRip ID: {0}] {1}." , _accurateRipId ? ? AccurateRipVerify . CalculateAccurateRipId ( _toc ) , _arVerify . ARStatus ? ? "found" ) ;
2009-02-27 14:41:55 +00:00
if ( PreGapLength ! = 0 )
sw . WriteLine ( "Pregap length {0}." , PreGapLengthMSF ) ;
2009-03-22 16:59:05 +00:00
if ( ! _toc [ 1 ] . IsAudio )
sw . WriteLine ( "Playstation type data track length {0}." , _toc [ 1 ] . LengthMSF ) ;
if ( ! _toc [ _toc . TrackCount ] . IsAudio )
sw . WriteLine ( "CD-Extra data track length {0}." ,
_toc [ _toc . TrackCount ] . Length = = 0 & & _minDataTrackLength . HasValue ?
CDImageLayout . TimeToString ( _minDataTrackLength . Value ) + " - " + CDImageLayout . TimeToString ( _minDataTrackLength . Value + 74 ) :
_toc [ _toc . TrackCount ] . LengthMSF ) ;
if ( _cddbDiscIdTag ! = null & & AccurateRipVerify . CalculateCDDBId ( _toc ) . ToUpper ( ) ! = _cddbDiscIdTag . ToUpper ( ) & & ! _minDataTrackLength . HasValue )
sw . WriteLine ( "CDDBId mismatch: {0} vs {1}" , _cddbDiscIdTag . ToUpper ( ) , AccurateRipVerify . CalculateCDDBId ( _toc ) . ToUpper ( ) ) ;
if ( _accurateRipId ! = null & & AccurateRipVerify . CalculateAccurateRipId ( _toc ) ! = _accurateRipId )
sw . WriteLine ( "Using preserved id, actual id is {0}." , AccurateRipVerify . CalculateAccurateRipId ( _toc ) ) ;
if ( _truncated4608 )
sw . WriteLine ( "Truncated 4608 extra samples in some input files." ) ;
if ( _paddedToFrame )
sw . WriteLine ( "Padded some input files to a frame boundary." ) ;
2010-03-20 07:09:07 +00:00
if ( ! _processed )
{
if ( _useCUEToolsDB ) GenerateCTDBLog ( sw ) ;
return ;
}
2010-02-08 01:29:31 +00:00
if ( hdcdDecoder ! = null & & string . Format ( "{0:s}" , hdcdDecoder ) ! = "" )
sw . WriteLine ( "HDCD: {0:f}" , hdcdDecoder ) ;
2008-12-09 07:25:48 +00:00
if ( 0 ! = _writeOffset )
sw . WriteLine ( "Offset applied: {0}" , _writeOffset ) ;
2010-02-23 15:15:08 +00:00
if ( _useCUEToolsDBFix ) // && _CUEToolsDB.SelectedEntry != null)
sw . WriteLine ( "CUETools DB: corrected {0} errors." , _CUEToolsDB . SelectedEntry . repair . CorrectableErrors ) ;
else if ( _useCUEToolsDB )
2010-02-28 21:04:34 +00:00
GenerateCTDBLog ( sw ) ;
2009-05-01 15:16:26 +00:00
_arVerify . GenerateFullLog ( sw , _config . arLogVerbose ) ;
2008-12-07 23:38:00 +00:00
}
2009-03-28 03:57:49 +00:00
public string GenerateAccurateRipStatus ( )
{
string prefix = "" ;
2010-02-08 01:29:31 +00:00
if ( hdcdDecoder ! = null & & string . Format ( "{0:s}" , hdcdDecoder ) ! = "" )
prefix + = string . Format ( "{0:s}, " , hdcdDecoder ) ;
2009-08-08 16:14:06 +00:00
if ( _useAccurateRip )
2009-03-28 03:57:49 +00:00
{
if ( _arVerify . ARStatus ! = null )
prefix + = _arVerify . ARStatus ;
else
{
uint tracksMatch = 0 ;
int bestOffset = 0 ;
FindBestOffset ( 1 , false , out tracksMatch , out bestOffset ) ;
if ( bestOffset ! = 0 )
prefix + = string . Format ( "offset {0}, " , bestOffset ) ;
if ( tracksMatch = = TrackCount )
prefix + = string . Format ( "rip accurate ({0}/{1})" , _arVerify . WorstConfidence ( ) , _arVerify . WorstTotal ( ) ) ;
else
prefix + = "rip not accurate" ;
}
} else
prefix + = "done" ;
return prefix ;
}
2009-05-01 15:16:26 +00:00
public void GenerateAccurateRipTagsForTrack ( NameValueCollection tags , int bestOffset , int iTrack , string prefix )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
tags . Add ( String . Format ( "{0}ACCURATERIPCRC" , prefix ) , String . Format ( "{0:x8}" , _arVerify . CRC ( iTrack , 0 ) ) ) ;
2009-03-22 16:59:05 +00:00
tags . Add ( String . Format ( "{0}AccurateRipDiscId" , prefix ) , String . Format ( "{0:000}-{1}-{2:00}" , TrackCount , _accurateRipId ? ? AccurateRipVerify . CalculateAccurateRipId ( _toc ) , iTrack + 1 ) ) ;
2009-05-01 15:16:26 +00:00
tags . Add ( String . Format ( "{0}ACCURATERIPCOUNT" , prefix ) , String . Format ( "{0}" , _arVerify . Confidence ( iTrack , 0 ) ) ) ;
2009-03-28 03:57:49 +00:00
tags . Add ( String . Format ( "{0}ACCURATERIPCOUNTALLOFFSETS" , prefix ) , String . Format ( "{0}" , _arVerify . SumConfidence ( iTrack ) ) ) ;
tags . Add ( String . Format ( "{0}ACCURATERIPTOTAL" , prefix ) , String . Format ( "{0}" , _arVerify . Total ( iTrack ) ) ) ;
2009-05-01 15:16:26 +00:00
if ( bestOffset ! = 0 )
2009-03-28 03:57:49 +00:00
tags . Add ( String . Format ( "{0}ACCURATERIPCOUNTWITHOFFSET" , prefix ) , String . Format ( "{0}" , _arVerify . Confidence ( iTrack , bestOffset ) ) ) ;
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
public void GenerateAccurateRipTags ( NameValueCollection tags , int bestOffset , int iTrack )
2008-12-07 23:38:00 +00:00
{
2009-03-22 16:59:05 +00:00
tags . Add ( "ACCURATERIPID" , _accurateRipId ? ? AccurateRipVerify . CalculateAccurateRipId ( _toc ) ) ;
2009-05-01 15:16:26 +00:00
if ( bestOffset ! = 0 )
tags . Add ( "ACCURATERIPOFFSET" , String . Format ( "{1}{0}" , bestOffset , bestOffset > 0 ? "+" : "" ) ) ;
2008-12-07 23:38:00 +00:00
if ( iTrack ! = - 1 )
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTagsForTrack ( tags , bestOffset , iTrack , "" ) ;
2008-12-07 23:38:00 +00:00
else
for ( iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
{
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTagsForTrack ( tags , bestOffset , iTrack ,
2008-12-07 23:38:00 +00:00
String . Format ( "cue_track{0:00}_" , iTrack + 1 ) ) ;
}
}
public void CleanupTags ( NameValueCollection tags , string substring )
{
string [ ] keys = tags . AllKeys ;
for ( int i = 0 ; i < keys . Length ; i + + )
if ( keys [ i ] . ToUpper ( ) . Contains ( substring ) )
tags . Remove ( keys [ i ] ) ;
}
2009-05-01 15:16:26 +00:00
public void FindBestOffset ( uint minConfidence , bool optimizeConfidence , out uint outTracksMatch , out int outBestOffset )
2008-12-07 23:38:00 +00:00
{
uint bestTracksMatch = 0 ;
uint bestConfidence = 0 ;
int bestOffset = 0 ;
for ( int offset = - _arOffsetRange ; offset < = _arOffsetRange ; offset + + )
{
uint tracksMatch = 0 ;
uint sumConfidence = 0 ;
for ( int iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
{
uint confidence = 0 ;
for ( int di = 0 ; di < ( int ) _arVerify . AccDisks . Count ; di + + )
if ( _arVerify . CRC ( iTrack , offset ) = = _arVerify . AccDisks [ di ] . tracks [ iTrack ] . CRC )
confidence + = _arVerify . AccDisks [ di ] . tracks [ iTrack ] . count ;
if ( confidence > = minConfidence )
tracksMatch + + ;
sumConfidence + = confidence ;
}
if ( tracksMatch > bestTracksMatch
| | ( tracksMatch = = bestTracksMatch & & optimizeConfidence & & sumConfidence > bestConfidence )
| | ( tracksMatch = = bestTracksMatch & & optimizeConfidence & & sumConfidence = = bestConfidence & & Math . Abs ( offset ) < Math . Abs ( bestOffset ) )
| | ( tracksMatch = = bestTracksMatch & & ! optimizeConfidence & & Math . Abs ( offset ) < Math . Abs ( bestOffset ) )
)
{
bestTracksMatch = tracksMatch ;
bestConfidence = sumConfidence ;
bestOffset = offset ;
}
}
outBestOffset = bestOffset ;
outTracksMatch = bestTracksMatch ;
}
2009-05-01 15:16:26 +00:00
public string Go ( )
{
2008-12-07 23:38:00 +00:00
int [ ] destLengths ;
2009-05-01 15:16:26 +00:00
bool htoaToFile = ( ( OutputStyle = = CUEStyle . GapsAppended ) & & _config . preserveHTOA & &
2008-12-07 23:38:00 +00:00
( _toc . Pregap ! = 0 ) ) ;
2010-03-20 07:09:07 +00:00
if ( _isCD )
DetectGaps ( ) ;
2008-12-09 07:25:48 +00:00
if ( _usePregapForFirstTrackInSingleFile )
2008-12-07 23:38:00 +00:00
throw new Exception ( "UsePregapForFirstTrackInSingleFile is not supported for writing audio files." ) ;
2009-05-01 15:16:26 +00:00
if ( _action ! = CUEAction . Verify )
2009-05-10 18:34:49 +00:00
for ( int i = 0 ; i < _destPaths . Length ; i + + )
2008-12-09 07:25:48 +00:00
for ( int j = 0 ; j < _sourcePaths . Count ; j + + )
2009-05-10 18:34:49 +00:00
if ( _destPaths [ i ] . ToLower ( ) = = _sourcePaths [ j ] . ToLower ( ) )
2008-12-09 07:25:48 +00:00
throw new Exception ( "Source and destination audio file paths cannot be the same." ) ;
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
destLengths = CalculateAudioFileLengths ( OutputStyle ) ;
2008-12-07 23:38:00 +00:00
2009-03-22 16:59:05 +00:00
// Lookup();
2009-05-01 15:16:26 +00:00
if ( _action ! = CUEAction . Verify )
2008-12-09 07:25:48 +00:00
{
2009-05-10 18:34:49 +00:00
if ( ! Directory . Exists ( OutputDir ) )
Directory . CreateDirectory ( OutputDir ) ;
2009-03-22 16:59:05 +00:00
}
2010-03-20 07:09:07 +00:00
if ( _action = = CUEAction . Encode )
{
string cueContents = CUESheetContents ( OutputStyle ) ;
if ( _config . createEACLOG )
cueContents = CUESheet . Encoding . GetString ( CUESheet . Encoding . GetBytes ( cueContents ) ) ;
if ( OutputStyle = = CUEStyle . SingleFileWithCUE & & _config . createCUEFileWhenEmbedded )
WriteText ( Path . ChangeExtension ( _outputPath , ".cue" ) , cueContents ) ;
else
WriteText ( _outputPath , cueContents ) ;
}
2009-05-01 15:16:26 +00:00
if ( _audioEncoderType ! = AudioEncoderType . NoAudio | | _action = = CUEAction . Verify )
2009-05-10 18:34:49 +00:00
WriteAudioFilesPass ( OutputDir , OutputStyle , destLengths , htoaToFile , _action = = CUEAction . Verify ) ;
2009-08-08 16:14:06 +00:00
2010-02-25 17:04:49 +00:00
if ( _useCUEToolsDB & & _CUEToolsDB . AccResult = = HttpStatusCode . OK )
2010-02-23 15:15:08 +00:00
{
if ( ! _useCUEToolsDBFix )
2010-02-25 17:04:49 +00:00
_CUEToolsDB . DoVerify ( ) ;
2010-02-23 15:15:08 +00:00
}
_processed = true ;
2009-05-10 18:34:49 +00:00
CreateRipperLOG ( ) ;
2009-08-08 16:14:06 +00:00
if ( _action = = CUEAction . Encode )
2009-03-22 16:59:05 +00:00
{
2009-05-01 15:16:26 +00:00
uint tracksMatch = 0 ;
int bestOffset = 0 ;
2008-12-07 23:38:00 +00:00
2009-08-08 16:14:06 +00:00
if ( _useAccurateRip & &
_config . writeArTagsOnEncode & &
2009-05-01 15:16:26 +00:00
_arVerify . AccResult = = HttpStatusCode . OK )
FindBestOffset ( 1 , true , out tracksMatch , out bestOffset ) ;
2008-12-07 23:38:00 +00:00
2010-03-20 07:09:07 +00:00
if ( _config . createEACLOG & & _ripperLog ! = null )
_ripperLog = CUESheet . Encoding . GetString ( CUESheet . Encoding . GetBytes ( _ripperLog ) ) ;
2008-12-09 07:25:48 +00:00
2009-05-01 15:16:26 +00:00
if ( _ripperLog ! = null )
WriteText ( Path . ChangeExtension ( _outputPath , ".log" ) , _ripperLog ) ;
else
if ( _eacLog ! = null & & _config . extractLog )
WriteText ( Path . ChangeExtension ( _outputPath , ".log" ) , _eacLog ) ;
2009-02-19 04:09:59 +00:00
2009-08-08 16:14:06 +00:00
if ( _audioEncoderType ! = AudioEncoderType . NoAudio & & _config . extractAlbumArt )
ExtractAlbumArt ( ) ;
2009-05-01 15:16:26 +00:00
if ( OutputStyle = = CUEStyle . SingleFileWithCUE | | OutputStyle = = CUEStyle . SingleFile )
{
if ( _audioEncoderType ! = AudioEncoderType . NoAudio )
2008-12-09 07:25:48 +00:00
{
2009-05-01 15:16:26 +00:00
NameValueCollection tags = GenerateAlbumTags ( bestOffset , OutputStyle = = CUEStyle . SingleFileWithCUE , _ripperLog ? ? _eacLog ) ;
TagLib . UserDefined . AdditionalFileTypes . Config = _config ;
2009-05-10 18:34:49 +00:00
TagLib . File fileInfo = TagLib . File . Create ( new TagLib . File . LocalFileAbstraction ( _destPaths [ 0 ] ) ) ;
2009-05-01 15:16:26 +00:00
if ( Tagging . UpdateTags ( fileInfo , tags , _config ) )
2008-12-09 07:25:48 +00:00
{
2009-05-01 15:16:26 +00:00
TagLib . File sourceFileInfo = _tracks [ 0 ] . _fileInfo ? ? _fileInfo ;
// first, use cue sheet information
if ( _config . writeBasicTagsFromCUEData )
2008-12-09 07:25:48 +00:00
{
2009-06-24 19:40:23 +00:00
uint temp ;
2009-08-06 13:03:02 +00:00
if ( fileInfo . Tag . Album = = null & & Title ! = "" )
fileInfo . Tag . Album = Title ;
if ( fileInfo . Tag . Performers . Length = = 0 & & Artist ! = "" )
fileInfo . Tag . Performers = new string [ ] { Artist } ;
//if (fileInfo.Tag.AlbumArtists.Length == 0 && Artist != "")
// fileInfo.Tag.AlbumArtists = new string[] { Artist };
if ( fileInfo . Tag . Genres . Length = = 0 & & Genre ! = "" )
fileInfo . Tag . Genres = new string [ ] { Genre } ;
2009-06-24 19:40:23 +00:00
if ( fileInfo . Tag . DiscCount = = 0 & & TotalDiscs ! = "" & & uint . TryParse ( TotalDiscs , out temp ) )
fileInfo . Tag . DiscCount = temp ;
if ( fileInfo . Tag . Disc = = 0 & & DiscNumber ! = "" & & uint . TryParse ( DiscNumber , out temp ) )
fileInfo . Tag . Disc = temp ;
if ( fileInfo . Tag . Year = = 0 & & Year ! = "" & & uint . TryParse ( Year , out temp ) )
fileInfo . Tag . Year = temp ;
2008-12-09 07:25:48 +00:00
}
2009-05-01 15:16:26 +00:00
// fill up missing information from tags
if ( _config . copyBasicTags & & sourceFileInfo ! = null )
{
2009-08-06 13:03:02 +00:00
if ( fileInfo . Tag . DiscCount = = 0 )
fileInfo . Tag . DiscCount = sourceFileInfo . Tag . DiscCount ; // TODO: GetCommonTag?
if ( fileInfo . Tag . Disc = = 0 )
fileInfo . Tag . Disc = sourceFileInfo . Tag . Disc ;
2009-05-01 15:16:26 +00:00
//fileInfo.Tag.Performers = sourceFileInfo.Tag.Performers;
if ( fileInfo . Tag . Album = = null )
fileInfo . Tag . Album = sourceFileInfo . Tag . Album ;
2009-08-06 13:03:02 +00:00
if ( fileInfo . Tag . Performers . Length = = 0 )
fileInfo . Tag . Performers = sourceFileInfo . Tag . Performers ;
2009-05-01 15:16:26 +00:00
if ( fileInfo . Tag . AlbumArtists . Length = = 0 )
fileInfo . Tag . AlbumArtists = sourceFileInfo . Tag . AlbumArtists ;
if ( fileInfo . Tag . Genres . Length = = 0 )
fileInfo . Tag . Genres = sourceFileInfo . Tag . Genres ;
if ( fileInfo . Tag . Year = = 0 )
fileInfo . Tag . Year = sourceFileInfo . Tag . Year ;
}
2009-08-08 16:14:06 +00:00
if ( ( _config . embedAlbumArt | | _config . copyAlbumArt ) & & _albumArt ! = null & & _albumArt . Length > 0 )
fileInfo . Tag . Pictures = _albumArt ;
2009-05-01 15:16:26 +00:00
fileInfo . Save ( ) ;
2008-12-09 07:25:48 +00:00
}
}
2009-05-01 15:16:26 +00:00
}
else
{
if ( _config . createM3U )
WriteText ( Path . ChangeExtension ( _outputPath , ".m3u" ) , M3UContents ( OutputStyle ) ) ;
2009-08-06 13:03:02 +00:00
bool fNeedAlbumArtist = false ;
for ( int iTrack = 1 ; iTrack < TrackCount ; iTrack + + )
if ( _tracks [ iTrack ] . Artist ! = _tracks [ 0 ] . Artist )
fNeedAlbumArtist = true ;
2009-05-01 15:16:26 +00:00
if ( _audioEncoderType ! = AudioEncoderType . NoAudio )
for ( int iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
{
2009-05-10 18:34:49 +00:00
string path = _destPaths [ iTrack + ( htoaToFile ? 1 : 0 ) ] ;
2009-05-01 15:16:26 +00:00
NameValueCollection tags = GenerateTrackTags ( iTrack , bestOffset ) ;
TagLib . UserDefined . AdditionalFileTypes . Config = _config ;
TagLib . File fileInfo = TagLib . File . Create ( new TagLib . File . LocalFileAbstraction ( path ) ) ;
if ( Tagging . UpdateTags ( fileInfo , tags , _config ) )
2008-12-09 07:25:48 +00:00
{
2009-05-01 15:16:26 +00:00
TagLib . File sourceFileInfo = _tracks [ iTrack ] . _fileInfo ? ? _fileInfo ;
if ( _config . writeBasicTagsFromCUEData )
2009-02-19 04:09:59 +00:00
{
2009-06-24 19:40:23 +00:00
uint temp ;
2009-03-04 21:30:56 +00:00
fileInfo . Tag . TrackCount = ( uint ) TrackCount ;
fileInfo . Tag . Track = ( uint ) iTrack + 1 ;
2009-08-06 13:03:02 +00:00
if ( fileInfo . Tag . Title = = null & & _tracks [ iTrack ] . Title ! = "" )
fileInfo . Tag . Title = _tracks [ iTrack ] . Title ;
if ( fileInfo . Tag . Album = = null & & Title ! = "" )
fileInfo . Tag . Album = Title ;
if ( fileInfo . Tag . Performers . Length = = 0 & & _tracks [ iTrack ] . Artist ! = "" )
fileInfo . Tag . Performers = new string [ ] { _tracks [ iTrack ] . Artist } ;
if ( fileInfo . Tag . Performers . Length = = 0 & & Artist ! = "" )
fileInfo . Tag . Performers = new string [ ] { Artist } ;
if ( fNeedAlbumArtist & & fileInfo . Tag . AlbumArtists . Length = = 0 & & Artist ! = "" )
fileInfo . Tag . AlbumArtists = new string [ ] { Artist } ;
if ( fileInfo . Tag . Genres . Length = = 0 & & Genre ! = "" )
fileInfo . Tag . Genres = new string [ ] { Genre } ;
2009-06-24 19:40:23 +00:00
if ( fileInfo . Tag . DiscCount = = 0 & & TotalDiscs ! = "" & & uint . TryParse ( TotalDiscs , out temp ) )
fileInfo . Tag . DiscCount = temp ;
if ( fileInfo . Tag . Disc = = 0 & & DiscNumber ! = "" & & uint . TryParse ( DiscNumber , out temp ) )
fileInfo . Tag . Disc = temp ;
if ( fileInfo . Tag . Year = = 0 & & Year ! = "" & & uint . TryParse ( Year , out temp ) )
fileInfo . Tag . Year = temp ;
2009-02-19 04:09:59 +00:00
}
2009-05-01 15:16:26 +00:00
if ( _config . copyBasicTags & & sourceFileInfo ! = null )
{
2009-08-06 13:03:02 +00:00
if ( fileInfo . Tag . Title = = null & & _tracks [ iTrack ] . _fileInfo ! = null )
fileInfo . Tag . Title = _tracks [ iTrack ] . _fileInfo . Tag . Title ;
if ( fileInfo . Tag . DiscCount = = 0 )
fileInfo . Tag . DiscCount = sourceFileInfo . Tag . DiscCount ;
if ( fileInfo . Tag . Disc = = 0 )
fileInfo . Tag . Disc = sourceFileInfo . Tag . Disc ;
2009-05-01 15:16:26 +00:00
if ( fileInfo . Tag . Performers . Length = = 0 )
fileInfo . Tag . Performers = sourceFileInfo . Tag . Performers ;
if ( fileInfo . Tag . AlbumArtists . Length = = 0 )
fileInfo . Tag . AlbumArtists = sourceFileInfo . Tag . AlbumArtists ;
if ( fileInfo . Tag . Album = = null )
fileInfo . Tag . Album = sourceFileInfo . Tag . Album ;
if ( fileInfo . Tag . Year = = 0 )
fileInfo . Tag . Year = sourceFileInfo . Tag . Year ;
if ( fileInfo . Tag . Genres . Length = = 0 )
fileInfo . Tag . Genres = sourceFileInfo . Tag . Genres ;
}
2009-08-08 16:14:06 +00:00
if ( ( _config . embedAlbumArt | | _config . copyAlbumArt ) & & _albumArt ! = null & & _albumArt . Length > 0 )
fileInfo . Tag . Pictures = _albumArt ;
2009-05-01 15:16:26 +00:00
fileInfo . Save ( ) ;
}
}
}
}
return WriteReport ( ) ;
}
private static Bitmap resizeImage ( Image imgToResize , Size size )
{
int sourceWidth = imgToResize . Width ;
int sourceHeight = imgToResize . Height ;
float nPercent = 0 ;
float nPercentW = 0 ;
float nPercentH = 0 ;
nPercentW = ( ( float ) size . Width / ( float ) sourceWidth ) ;
nPercentH = ( ( float ) size . Height / ( float ) sourceHeight ) ;
if ( nPercentH < nPercentW )
nPercent = nPercentH ;
else
nPercent = nPercentW ;
int destWidth = ( int ) ( sourceWidth * nPercent ) ;
int destHeight = ( int ) ( sourceHeight * nPercent ) ;
Bitmap b = new Bitmap ( destWidth , destHeight ) ;
Graphics g = Graphics . FromImage ( ( Image ) b ) ;
g . InterpolationMode = InterpolationMode . HighQualityBicubic ;
g . DrawImage ( imgToResize , 0 , 0 , destWidth , destHeight ) ;
g . Dispose ( ) ;
return b ;
}
2009-08-06 13:03:02 +00:00
public void ExtractAlbumArt ( )
2009-05-13 16:07:53 +00:00
{
2009-08-06 13:03:02 +00:00
if ( ! _config . extractAlbumArt | | _albumArt = = null | | _albumArt . Length = = 0 )
return ;
string imgPath = Path . Combine ( OutputDir , AlArtFileName ) ;
2009-05-13 16:07:53 +00:00
if ( File . Exists ( imgPath ) )
return ;
2009-08-06 13:03:02 +00:00
foreach ( TagLib . IPicture picture in _albumArt )
using ( FileStream file = new FileStream ( imgPath , FileMode . CreateNew , FileAccess . Write , FileShare . Read ) )
2009-05-13 16:07:53 +00:00
{
2009-08-06 13:03:02 +00:00
file . Write ( picture . Data . Data , 0 , picture . Data . Count ) ;
return ;
}
}
public void LoadAlbumArt ( TagLib . File fileInfo )
{
if ( ( _config . extractAlbumArt | | _config . copyAlbumArt ) & & fileInfo ! = null )
foreach ( TagLib . IPicture picture in fileInfo . Tag . Pictures )
if ( picture . Type = = TagLib . PictureType . FrontCover )
if ( picture . MimeType = = "image/jpeg" )
2009-05-13 16:07:53 +00:00
{
2009-08-06 13:03:02 +00:00
_albumArt = new TagLib . IPicture [ ] { picture } ;
2009-05-13 16:07:53 +00:00
return ;
}
2009-08-06 13:03:02 +00:00
if ( ( _config . extractAlbumArt | | _config . embedAlbumArt ) & & _inputDir ! = null )
{
string imgPath = Path . Combine ( _inputDir , "folder.jpg" ) ;
if ( ! File . Exists ( imgPath ) )
imgPath = Path . Combine ( _inputDir , "cover.jpg" ) ;
if ( ! File . Exists ( imgPath ) )
return ;
_albumArt = new TagLib . IPicture [ ] { new TagLib . Picture ( imgPath ) } ;
}
2009-05-13 16:07:53 +00:00
}
2009-08-06 13:03:02 +00:00
public void ResizeAlbumArt ( )
2009-05-01 15:16:26 +00:00
{
2009-08-06 13:03:02 +00:00
if ( _albumArt = = null )
2009-05-13 16:07:53 +00:00
return ;
2009-08-06 13:03:02 +00:00
foreach ( TagLib . IPicture picture in _albumArt )
using ( MemoryStream imageStream = new MemoryStream ( picture . Data . Data , 0 , picture . Data . Count ) )
using ( Image img = Image . FromStream ( imageStream ) )
if ( img . Width > _config . maxAlbumArtSize | | img . Height > _config . maxAlbumArtSize )
2009-05-01 15:16:26 +00:00
{
2009-08-06 13:03:02 +00:00
using ( Bitmap small = resizeImage ( img , new Size ( _config . maxAlbumArtSize , _config . maxAlbumArtSize ) ) )
2009-05-13 16:07:53 +00:00
using ( MemoryStream encoded = new MemoryStream ( ) )
2009-05-01 15:16:26 +00:00
{
2009-05-13 16:07:53 +00:00
//System.Drawing.Imaging.EncoderParameters encoderParams = new EncoderParameters(1);
//encoderParams.Param[0] = new System.Drawing.Imaging.EncoderParameter(Encoder.Quality, quality);
small . Save ( encoded , System . Drawing . Imaging . ImageFormat . Jpeg ) ;
2009-08-06 13:03:02 +00:00
picture . Data = new TagLib . ByteVector ( encoded . ToArray ( ) ) ;
picture . MimeType = "image/jpeg" ;
2009-05-01 15:16:26 +00:00
}
2008-12-09 07:25:48 +00:00
}
2009-08-06 13:03:02 +00:00
}
public TagLib . IPicture [ ] AlbumArt
{
get
{
return _albumArt ;
}
}
public Image Cover
{
get
{
if ( AlbumArt = = null | | AlbumArt . Length = = 0 )
return null ;
TagLib . IPicture picture = AlbumArt [ 0 ] ;
using ( MemoryStream imageStream = new MemoryStream ( picture . Data . Data , 0 , picture . Data . Count ) )
try { return Image . FromStream ( imageStream ) ; }
catch { }
return null ;
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
}
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
public string WriteReport ( )
{
2009-08-08 16:14:06 +00:00
if ( _useAccurateRip )
2008-12-07 23:38:00 +00:00
{
ShowProgress ( ( string ) "Generating AccurateRip report..." , 0 , 0 , null , null ) ;
2009-05-01 15:16:26 +00:00
if ( _action = = CUEAction . Verify & & _config . writeArTagsOnVerify & & _writeOffset = = 0 & & ! _isArchive & & ! _isCD )
2008-12-07 23:38:00 +00:00
{
uint tracksMatch ;
int bestOffset ;
FindBestOffset ( 1 , true , out tracksMatch , out bestOffset ) ;
if ( _hasEmbeddedCUESheet )
{
2009-02-19 04:09:59 +00:00
if ( _fileInfo is TagLib . Flac . File )
{
NameValueCollection tags = Tagging . Analyze ( _fileInfo ) ;
CleanupTags ( tags , "ACCURATERIP" ) ;
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTags ( tags , bestOffset , - 1 ) ;
2009-02-19 04:09:59 +00:00
if ( Tagging . UpdateTags ( _fileInfo , tags , _config ) )
_fileInfo . Save ( ) ;
}
2008-12-07 23:38:00 +00:00
} else if ( _hasTrackFilenames )
{
for ( int iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
2009-02-19 04:09:59 +00:00
if ( _tracks [ iTrack ] . _fileInfo is TagLib . Flac . File )
2008-12-07 23:38:00 +00:00
{
2009-02-19 04:09:59 +00:00
NameValueCollection tags = Tagging . Analyze ( _tracks [ iTrack ] . _fileInfo ) ;
2008-12-07 23:38:00 +00:00
CleanupTags ( tags , "ACCURATERIP" ) ;
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTags ( tags , bestOffset , iTrack ) ;
2009-02-19 04:09:59 +00:00
if ( Tagging . UpdateTags ( _tracks [ iTrack ] . _fileInfo , tags , _config ) )
_tracks [ iTrack ] . _fileInfo . Save ( ) ;
2008-12-07 23:38:00 +00:00
}
}
}
2009-05-01 15:16:26 +00:00
if ( ( _action ! = CUEAction . Verify & & _config . writeArLogOnConvert ) | |
( _action = = CUEAction . Verify & & _config . writeArLogOnVerify ) )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
if ( ! Directory . Exists ( OutputDir ) )
Directory . CreateDirectory ( OutputDir ) ;
2009-08-06 13:03:02 +00:00
StreamWriter sw = new StreamWriter ( Path . Combine ( OutputDir , ArLogFileName ) ,
2008-12-07 23:38:00 +00:00
false , CUESheet . Encoding ) ;
GenerateAccurateRipLog ( sw ) ;
sw . Close ( ) ;
}
if ( _config . createTOC )
{
2009-05-01 15:16:26 +00:00
if ( ! Directory . Exists ( OutputDir ) )
Directory . CreateDirectory ( OutputDir ) ;
WriteText ( Path . ChangeExtension ( _outputPath , ".toc" ) , TOCContents ( ) ) ;
2008-12-07 23:38:00 +00:00
}
}
2009-03-28 03:57:49 +00:00
return GenerateAccurateRipStatus ( ) ;
2008-12-07 23:38:00 +00:00
}
2009-02-19 04:09:59 +00:00
private NameValueCollection GenerateTrackTags ( int iTrack , int bestOffset )
2008-12-07 23:38:00 +00:00
{
NameValueCollection destTags = new NameValueCollection ( ) ;
2009-05-01 15:16:26 +00:00
if ( _config . copyUnknownTags )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
if ( _hasEmbeddedCUESheet )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
string trackPrefix = String . Format ( "cue_track{0:00}_" , iTrack + 1 ) ;
NameValueCollection albumTags = Tagging . Analyze ( _fileInfo ) ;
foreach ( string key in albumTags . AllKeys )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
if ( key . ToLower ( ) . StartsWith ( trackPrefix )
| | ! key . ToLower ( ) . StartsWith ( "cue_track" ) )
{
string name = key . ToLower ( ) . StartsWith ( trackPrefix ) ?
key . Substring ( trackPrefix . Length ) : key ;
string [ ] values = albumTags . GetValues ( key ) ;
for ( int j = 0 ; j < values . Length ; j + + )
destTags . Add ( name , values [ j ] ) ;
}
2008-12-07 23:38:00 +00:00
}
}
2009-05-01 15:16:26 +00:00
else if ( _hasTrackFilenames )
destTags . Add ( Tagging . Analyze ( _tracks [ iTrack ] . _fileInfo ) ) ;
else if ( _hasSingleFilename )
{
// TODO?
}
2009-02-19 04:09:59 +00:00
2009-05-01 15:16:26 +00:00
// these will be set explicitely
destTags . Remove ( "ARTIST" ) ;
destTags . Remove ( "TITLE" ) ;
destTags . Remove ( "ALBUM" ) ;
destTags . Remove ( "ALBUMARTIST" ) ;
destTags . Remove ( "DATE" ) ;
destTags . Remove ( "GENRE" ) ;
destTags . Remove ( "TRACKNUMBER" ) ;
destTags . Remove ( "TRACKTOTAL" ) ;
destTags . Remove ( "TOTALTRACKS" ) ;
destTags . Remove ( "DISCNUMBER" ) ;
destTags . Remove ( "DISCTOTAL" ) ;
destTags . Remove ( "TOTALDISCS" ) ;
2009-02-19 04:09:59 +00:00
2009-05-01 15:16:26 +00:00
destTags . Remove ( "LOG" ) ;
destTags . Remove ( "LOGFILE" ) ;
destTags . Remove ( "EACLOG" ) ;
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
// these are not valid
destTags . Remove ( "CUESHEET" ) ;
CleanupTags ( destTags , "ACCURATERIP" ) ;
//CleanupTags(destTags, "REPLAYGAIN");
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
2009-08-08 16:14:06 +00:00
if ( _config . writeArTagsOnEncode & & _action = = CUEAction . Encode & & _useAccurateRip & & _arVerify . AccResult = = HttpStatusCode . OK )
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTags ( destTags , bestOffset , iTrack ) ;
2009-02-19 04:09:59 +00:00
return destTags ;
2008-12-07 23:38:00 +00:00
}
2009-03-04 21:30:56 +00:00
private NameValueCollection GenerateAlbumTags ( int bestOffset , bool fWithCUE , string logContents )
2008-12-07 23:38:00 +00:00
{
NameValueCollection destTags = new NameValueCollection ( ) ;
2009-05-01 15:16:26 +00:00
if ( _config . copyUnknownTags )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
if ( _hasEmbeddedCUESheet | | _hasSingleFilename )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
destTags . Add ( Tagging . Analyze ( _fileInfo ) ) ;
if ( ! fWithCUE )
CleanupTags ( destTags , "CUE_TRACK" ) ;
}
else if ( _hasTrackFilenames )
{
for ( int iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
NameValueCollection trackTags = Tagging . Analyze ( _tracks [ iTrack ] . _fileInfo ) ;
foreach ( string key in trackTags . AllKeys )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
string singleValue = GetCommonMiscTag ( key ) ;
if ( singleValue ! = null )
{
if ( destTags . Get ( key ) = = null )
destTags . Add ( key , singleValue ) ;
}
else if ( fWithCUE & & key . ToUpper ( ) ! = "TRACKNUMBER" & & key . ToUpper ( ) ! = "TITLE" & & key . ToUpper ( ) ! = "ARTIST" )
{
string [ ] values = trackTags . GetValues ( key ) ;
for ( int j = 0 ; j < values . Length ; j + + )
destTags . Add ( String . Format ( "cue_track{0:00}_{1}" , iTrack + 1 , key ) , values [ j ] ) ;
}
2008-12-07 23:38:00 +00:00
}
}
}
2009-05-01 15:16:26 +00:00
// these will be set explicitely
destTags . Remove ( "ARTIST" ) ;
destTags . Remove ( "TITLE" ) ;
destTags . Remove ( "ALBUM" ) ;
destTags . Remove ( "ALBUMARTIST" ) ;
destTags . Remove ( "DATE" ) ;
destTags . Remove ( "GENRE" ) ;
destTags . Remove ( "TRACKNUMBER" ) ;
destTags . Remove ( "TRACKTOTAL" ) ;
destTags . Remove ( "TOTALTRACKS" ) ;
destTags . Remove ( "DISCNUMBER" ) ;
destTags . Remove ( "DISCTOTAL" ) ;
destTags . Remove ( "TOTALDISCS" ) ;
destTags . Remove ( "LOG" ) ;
destTags . Remove ( "LOGFILE" ) ;
destTags . Remove ( "EACLOG" ) ;
// these are not valid
CleanupTags ( destTags , "ACCURATERIP" ) ;
//CleanupTags(destTags, "REPLAYGAIN");
2009-02-19 04:09:59 +00:00
2009-05-01 15:16:26 +00:00
destTags . Remove ( "CUESHEET" ) ;
}
2008-12-07 23:38:00 +00:00
2009-02-19 04:09:59 +00:00
if ( fWithCUE )
2008-12-09 07:25:48 +00:00
destTags . Add ( "CUESHEET" , CUESheetContents ( CUEStyle . SingleFileWithCUE ) ) ;
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
if ( _config . embedLog & & logContents ! = null )
destTags . Add ( "LOG" , logContents ) ;
2009-08-08 16:14:06 +00:00
if ( fWithCUE & & _config . writeArTagsOnEncode & & _action = = CUEAction . Encode & & _useAccurateRip & & _arVerify . AccResult = = HttpStatusCode . OK )
2009-05-01 15:16:26 +00:00
GenerateAccurateRipTags ( destTags , bestOffset , - 1 ) ;
2008-12-07 23:38:00 +00:00
2009-02-19 04:09:59 +00:00
return destTags ;
2008-12-07 23:38:00 +00:00
}
2009-05-10 18:34:49 +00:00
public void WriteAudioFilesPass ( string dir , CUEStyle style , int [ ] destLengths , bool htoaToFile , bool noOutput )
2008-12-07 23:38:00 +00:00
{
int iTrack , iIndex ;
2010-02-06 23:17:07 +00:00
AudioBuffer sampleBuffer = new AudioBuffer ( AudioPCMConfig . RedBook , 0x10000 ) ;
2008-12-07 23:38:00 +00:00
TrackInfo track ;
IAudioSource audioSource = null ;
IAudioDest audioDest = null ;
bool discardOutput ;
int iSource = - 1 ;
int iDest = - 1 ;
2010-02-06 23:17:07 +00:00
int samplesRemSource = 0 ;
2009-01-17 04:09:38 +00:00
//CDImageLayout updatedTOC = null;
2008-12-07 23:38:00 +00:00
if ( _writeOffset ! = 0 )
{
2010-02-06 23:17:07 +00:00
int absOffset = Math . Abs ( _writeOffset ) ;
2008-12-07 23:38:00 +00:00
SourceInfo sourceInfo ;
sourceInfo . Path = null ;
sourceInfo . Offset = 0 ;
2010-02-06 23:17:07 +00:00
sourceInfo . Length = ( uint ) absOffset ;
2008-12-07 23:38:00 +00:00
if ( _writeOffset < 0 )
{
_sources . Insert ( 0 , sourceInfo ) ;
int last = _sources . Count - 1 ;
while ( absOffset > = _sources [ last ] . Length )
{
2010-02-06 23:17:07 +00:00
absOffset - = ( int ) _sources [ last ] . Length ;
2008-12-07 23:38:00 +00:00
_sources . RemoveAt ( last - - ) ;
}
sourceInfo = _sources [ last ] ;
2010-02-06 23:17:07 +00:00
sourceInfo . Length - = ( uint ) absOffset ;
2008-12-07 23:38:00 +00:00
_sources [ last ] = sourceInfo ;
}
else
{
_sources . Add ( sourceInfo ) ;
while ( absOffset > = _sources [ 0 ] . Length )
{
2010-02-06 23:17:07 +00:00
absOffset - = ( int ) _sources [ 0 ] . Length ;
2008-12-07 23:38:00 +00:00
_sources . RemoveAt ( 0 ) ;
}
sourceInfo = _sources [ 0 ] ;
2010-02-06 23:17:07 +00:00
sourceInfo . Offset + = ( uint ) absOffset ;
sourceInfo . Length - = ( uint ) absOffset ;
2008-12-07 23:38:00 +00:00
_sources [ 0 ] = sourceInfo ;
}
_appliedWriteOffset = true ;
}
2010-02-08 01:29:31 +00:00
int destBPS = 16 ;
hdcdDecoder = null ;
if ( _config . detectHDCD & & CUEProcessorPlugins . hdcd ! = null )
2008-12-09 07:25:48 +00:00
{
// currently broken verifyThenConvert on HDCD detection!!!! need to check for HDCD results higher
2010-02-08 01:29:31 +00:00
try
{
destBPS = ( ( _outputLossyWAV & & _config . decodeHDCDtoLW16 ) | | ! _config . decodeHDCDto24bit ) ? 20 : 24 ;
hdcdDecoder = Activator . CreateInstance ( CUEProcessorPlugins . hdcd , 2 , 44100 , destBPS , _config . decodeHDCD ) as IAudioDest ;
}
2008-12-09 07:25:48 +00:00
catch { }
2010-02-08 01:29:31 +00:00
if ( hdcdDecoder = = null | | ! _config . decodeHDCD )
destBPS = 16 ;
2008-12-09 07:25:48 +00:00
}
2008-12-07 23:38:00 +00:00
if ( style = = CUEStyle . SingleFile | | style = = CUEStyle . SingleFileWithCUE )
{
iDest + + ;
2010-03-03 23:52:46 +00:00
if ( _isCD & & style = = CUEStyle . SingleFileWithCUE )
_padding + = Encoding . UTF8 . GetByteCount ( CUESheetContents ( style ) ) ;
2010-02-08 01:29:31 +00:00
audioDest = GetAudioDest ( _destPaths [ iDest ] , destLengths [ iDest ] , destBPS , _padding , noOutput ) ;
2008-12-07 23:38:00 +00:00
}
2010-02-06 23:17:07 +00:00
int currentOffset = 0 , previousOffset = 0 ;
int trackLength = ( int ) _toc . Pregap * 588 ;
int diskLength = 588 * ( int ) _toc . AudioLength ;
int diskOffset = 0 ;
2008-12-07 23:38:00 +00:00
2009-08-08 16:14:06 +00:00
if ( _useAccurateRip )
2008-12-07 23:38:00 +00:00
_arVerify . Init ( ) ;
2010-02-23 15:15:08 +00:00
if ( _useCUEToolsDB & & ! _useCUEToolsDBFix )
_CUEToolsDB . Init ( _useCUEToolsDBSibmit ) ;
2008-12-07 23:38:00 +00:00
ShowProgress ( String . Format ( "{2} track {0:00} ({1:00}%)..." , 0 , 0 , noOutput ? "Verifying" : "Writing" ) , 0 , 0.0 , null , null ) ;
2009-01-28 04:53:13 +00:00
#if ! DEBUG
2008-12-09 07:25:48 +00:00
try
2009-01-28 04:53:13 +00:00
#endif
2008-12-09 07:25:48 +00:00
{
for ( iTrack = 0 ; iTrack < TrackCount ; iTrack + + )
{
track = _tracks [ iTrack ] ;
2008-12-07 23:38:00 +00:00
2008-12-09 07:25:48 +00:00
if ( ( style = = CUEStyle . GapsPrepended ) | | ( style = = CUEStyle . GapsLeftOut ) )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
iDest + + ;
2008-12-07 23:38:00 +00:00
if ( hdcdDecoder ! = null )
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = null ;
2008-12-07 23:38:00 +00:00
if ( audioDest ! = null )
audioDest . Close ( ) ;
2010-02-08 01:29:31 +00:00
audioDest = GetAudioDest ( _destPaths [ iDest ] , destLengths [ iDest ] , destBPS , _padding , noOutput ) ;
2008-12-07 23:38:00 +00:00
}
2009-01-28 04:53:13 +00:00
for ( iIndex = 0 ; iIndex < = _toc [ _toc . FirstAudio + iTrack ] . LastIndex ; iIndex + + )
2008-12-09 07:25:48 +00:00
{
2010-02-06 23:17:07 +00:00
int samplesRemIndex = ( int ) _toc . IndexLength ( _toc . FirstAudio + iTrack , iIndex ) * 588 ;
2008-12-09 07:25:48 +00:00
if ( iIndex = = 1 )
{
previousOffset = currentOffset ;
currentOffset = 0 ;
2010-02-06 23:17:07 +00:00
trackLength = ( int ) _toc [ _toc . FirstAudio + iTrack ] . Length * 588 ;
2008-12-09 07:25:48 +00:00
}
if ( ( style = = CUEStyle . GapsAppended ) & & ( iIndex = = 1 ) )
{
if ( hdcdDecoder ! = null )
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = null ;
2008-12-09 07:25:48 +00:00
if ( audioDest ! = null )
audioDest . Close ( ) ;
2008-12-07 23:38:00 +00:00
iDest + + ;
2010-02-08 01:29:31 +00:00
audioDest = GetAudioDest ( _destPaths [ iDest ] , destLengths [ iDest ] , destBPS , _padding , noOutput ) ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
if ( ( style = = CUEStyle . GapsAppended ) & & ( iIndex = = 0 ) & & ( iTrack = = 0 ) )
{
discardOutput = ! htoaToFile ;
if ( htoaToFile )
{
iDest + + ;
2010-02-08 01:29:31 +00:00
audioDest = GetAudioDest ( _destPaths [ iDest ] , destLengths [ iDest ] , destBPS , _padding , noOutput ) ;
2008-12-09 07:25:48 +00:00
}
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
else if ( ( style = = CUEStyle . GapsLeftOut ) & & ( iIndex = = 0 ) )
{
discardOutput = true ;
}
else
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
discardOutput = false ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
while ( samplesRemIndex ! = 0 )
2008-12-07 23:38:00 +00:00
{
2008-12-09 07:25:48 +00:00
if ( samplesRemSource = = 0 )
2008-12-07 23:38:00 +00:00
{
2009-01-17 04:09:38 +00:00
// if (_isCD && audioSource != null && audioSource is CDDriveReader)
// updatedTOC = ((CDDriveReader)audioSource).TOC;
2010-03-20 07:09:07 +00:00
if ( audioSource ! = null ) audioSource . Close ( ) ;
2008-12-09 07:25:48 +00:00
audioSource = GetAudioSource ( + + iSource ) ;
2010-02-06 23:17:07 +00:00
samplesRemSource = ( int ) _sources [ iSource ] . Length ;
2008-12-09 07:25:48 +00:00
}
2010-02-06 23:17:07 +00:00
int copyCount = Math . Min ( samplesRemIndex , samplesRemSource ) ;
2008-12-09 07:25:48 +00:00
if ( trackLength > 0 & & ! _isCD )
{
double trackPercent = ( double ) currentOffset / trackLength ;
2009-12-24 16:17:42 +00:00
ShowProgress ( String . Format ( "{2} track {0:00} ({1:00}%)..." , iIndex > 0 ? iTrack + 1 : iTrack , ( uint ) ( 100 * trackPercent ) ,
2009-08-21 03:26:12 +00:00
noOutput ? "Verifying" : "Writing" ) , trackPercent , ( int ) diskOffset , ( int ) diskLength ,
2008-12-09 07:25:48 +00:00
_isCD ? string . Format ( "{0}: {1:00} - {2}" , audioSource . Path , iTrack + 1 , _tracks [ iTrack ] . Title ) : audioSource . Path , discardOutput ? null : audioDest . Path ) ;
}
2010-02-06 23:17:07 +00:00
copyCount = audioSource . Read ( sampleBuffer , copyCount ) ;
2010-02-23 15:15:08 +00:00
if ( _useCUEToolsDB )
{
if ( _useCUEToolsDBFix )
_CUEToolsDB . SelectedEntry . repair . Write ( sampleBuffer ) ;
else
_CUEToolsDB . Verify . Write ( sampleBuffer ) ;
}
2010-03-20 07:09:07 +00:00
// we use AR after CTDB, so that we can verify what we fixed
if ( _useAccurateRip )
_arVerify . Write ( sampleBuffer ) ;
2008-12-09 07:25:48 +00:00
if ( ! discardOutput )
{
if ( ! _config . detectHDCD | | ! _config . decodeHDCD )
2010-02-06 23:17:07 +00:00
audioDest . Write ( sampleBuffer ) ;
2008-12-09 07:25:48 +00:00
if ( _config . detectHDCD & & hdcdDecoder ! = null )
2008-12-07 23:38:00 +00:00
{
2010-02-08 01:29:31 +00:00
if ( _config . wait750FramesForHDCD & & diskOffset > 750 * 588 & & string . Format ( "{0:s}" , hdcdDecoder ) = = "" )
2008-12-09 07:25:48 +00:00
{
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = null ;
2008-12-09 07:25:48 +00:00
hdcdDecoder = null ;
if ( _config . decodeHDCD )
{
2010-03-20 07:09:07 +00:00
audioSource . Close ( ) ;
2008-12-09 07:25:48 +00:00
audioDest . Delete ( ) ;
throw new Exception ( "HDCD not detected." ) ;
}
}
else
{
if ( _config . decodeHDCD )
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = ( discardOutput | | noOutput ) ? null : audioDest ;
hdcdDecoder . Write ( sampleBuffer ) ;
2008-12-09 07:25:48 +00:00
}
2008-12-07 23:38:00 +00:00
}
}
2008-12-09 07:25:48 +00:00
currentOffset + = copyCount ;
diskOffset + = copyCount ;
samplesRemIndex - = copyCount ;
samplesRemSource - = copyCount ;
2008-12-07 23:38:00 +00:00
2009-02-22 07:47:56 +00:00
CheckStop ( ) ;
2008-12-07 23:38:00 +00:00
}
}
}
}
2009-01-28 04:53:13 +00:00
#if ! DEBUG
2008-12-09 07:25:48 +00:00
catch ( Exception ex )
{
if ( hdcdDecoder ! = null )
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = null ;
2008-12-09 07:25:48 +00:00
hdcdDecoder = null ;
2010-03-20 07:09:07 +00:00
if ( audioSource ! = null )
try { audioSource . Close ( ) ; } catch { }
2008-12-09 07:25:48 +00:00
audioSource = null ;
2010-03-20 07:09:07 +00:00
if ( audioDest ! = null )
try { audioDest . Delete ( ) ; } catch { }
2008-12-09 07:25:48 +00:00
audioDest = null ;
throw ex ;
}
2009-01-28 04:53:13 +00:00
#endif
2008-12-09 07:25:48 +00:00
2008-12-07 23:38:00 +00:00
if ( hdcdDecoder ! = null )
2010-02-08 01:29:31 +00:00
( hdcdDecoder as IAudioFilter ) . AudioDest = null ;
2010-03-20 07:09:07 +00:00
if ( audioSource ! = null )
2008-12-07 23:38:00 +00:00
audioSource . Close ( ) ;
if ( audioDest ! = null )
audioDest . Close ( ) ;
}
2010-03-20 07:09:07 +00:00
private void DetectGaps ( )
{
if ( ! _isCD )
throw new Exception ( "not a CD" ) ;
try { _ripper . DetectGaps ( ) ; }
catch ( Exception ex )
{
if ( ex is StopException )
throw ex ;
}
if ( ! _ripper . GapsDetected )
return ;
_toc = ( CDImageLayout ) _ripper . TOC . Clone ( ) ;
if ( _toc . Catalog ! = null )
Catalog = _toc . Catalog ;
for ( int iTrack = 0 ; iTrack < _toc . AudioTracks ; iTrack + + )
{
if ( _toc [ _toc . FirstAudio + iTrack ] . ISRC ! = null )
General . SetCUELine ( _tracks [ iTrack ] . Attributes , "ISRC" , _toc [ _toc . FirstAudio + iTrack ] . ISRC , false ) ;
if ( _toc [ _toc . FirstAudio + iTrack ] . DCP | | _toc [ _toc . FirstAudio + iTrack ] . PreEmphasis )
_tracks [ iTrack ] . Attributes . Add ( new CUELine ( "FLAGS" + ( _toc [ _toc . FirstAudio + iTrack ] . PreEmphasis ? " PRE" : "" ) + ( _toc [ _toc . FirstAudio + iTrack ] . DCP ? " DCP" : "" ) ) ) ;
}
}
2009-03-28 03:57:49 +00:00
public static string CreateDummyCUESheet ( CUEConfig _config , string pathIn )
{
pathIn = Path . GetFullPath ( pathIn ) ;
List < FileGroupInfo > fileGroups = CUESheet . ScanFolder ( _config , Path . GetDirectoryName ( pathIn ) ) ;
2009-05-01 15:16:26 +00:00
FileGroupInfo fileGroup = FileGroupInfo . WhichContains ( fileGroups , pathIn , FileGroupInfoType . TrackFiles )
? ? FileGroupInfo . WhichContains ( fileGroups , pathIn , FileGroupInfoType . FileWithCUE ) ;
return fileGroup = = null ? null : CreateDummyCUESheet ( _config , fileGroup ) ;
2009-03-28 03:57:49 +00:00
}
2009-05-01 15:16:26 +00:00
public static string CreateDummyCUESheet ( CUEConfig _config , FileGroupInfo fileGroup )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
if ( fileGroup . type = = FileGroupInfoType . FileWithCUE )
{
TagLib . UserDefined . AdditionalFileTypes . Config = _config ;
TagLib . File . IFileAbstraction fileAbsraction = new TagLib . File . LocalFileAbstraction ( fileGroup . main . FullName ) ;
TagLib . File fileInfo = TagLib . File . Create ( fileAbsraction ) ;
return Tagging . Analyze ( fileInfo ) . Get ( "CUESHEET" ) ;
}
2008-12-07 23:38:00 +00:00
StringWriter sw = new StringWriter ( ) ;
sw . WriteLine ( String . Format ( "REM COMMENT \"CUETools generated dummy CUE sheet\"" ) ) ;
2009-03-28 03:57:49 +00:00
int trackNo = 0 ;
foreach ( FileSystemInfo file in fileGroup . files )
2008-12-07 23:38:00 +00:00
{
2009-03-28 03:57:49 +00:00
sw . WriteLine ( String . Format ( "FILE \"{0}\" WAVE" , file . Name ) ) ;
sw . WriteLine ( String . Format ( " TRACK {0:00} AUDIO" , + + trackNo ) ) ;
2008-12-07 23:38:00 +00:00
sw . WriteLine ( String . Format ( " INDEX 01 00:00:00" ) ) ;
}
sw . Close ( ) ;
return sw . ToString ( ) ;
}
2009-05-01 15:16:26 +00:00
public static string CorrectAudioFilenames ( CUEConfig _config , string path , bool always )
2008-12-07 23:38:00 +00:00
{
StreamReader sr = new StreamReader ( path , CUESheet . Encoding ) ;
string cue = sr . ReadToEnd ( ) ;
sr . Close ( ) ;
2009-05-01 15:16:26 +00:00
string extension ;
return CorrectAudioFilenames ( _config , Path . GetDirectoryName ( path ) , cue , always , null , out extension ) ;
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
public static string CorrectAudioFilenames ( CUEConfig _config , string dir , string cue , bool always , List < string > files , out string extension )
2009-01-17 04:09:38 +00:00
{
2008-12-07 23:38:00 +00:00
List < string > lines = new List < string > ( ) ;
List < int > filePos = new List < int > ( ) ;
List < string > origFiles = new List < string > ( ) ;
bool foundAll = true ;
string [ ] audioFiles = null ;
string lineStr ;
CUELine line ;
int i ;
2009-05-01 15:16:26 +00:00
using ( StringReader sr = new StringReader ( cue ) )
{
while ( ( lineStr = sr . ReadLine ( ) ) ! = null )
{
2008-12-07 23:38:00 +00:00
lines . Add ( lineStr ) ;
line = new CUELine ( lineStr ) ;
2009-05-01 15:16:26 +00:00
if ( ( line . Params . Count = = 3 ) & & ( line . Params [ 0 ] . ToUpper ( ) = = "FILE" ) )
{
2008-12-07 23:38:00 +00:00
string fileType = line . Params [ 2 ] . ToUpper ( ) ;
2009-05-01 15:16:26 +00:00
if ( ( fileType ! = "BINARY" ) & & ( fileType ! = "MOTOROLA" ) )
{
2008-12-07 23:38:00 +00:00
filePos . Add ( lines . Count - 1 ) ;
origFiles . Add ( line . Params [ 1 ] ) ;
2009-01-17 04:09:38 +00:00
foundAll & = ( LocateFile ( dir , line . Params [ 1 ] , files ) ! = null ) ;
2008-12-07 23:38:00 +00:00
}
}
}
sr . Close ( ) ;
}
2009-05-01 15:16:26 +00:00
extension = null ;
if ( foundAll & & ! always )
return cue ;
foundAll = false ;
foreach ( KeyValuePair < string , CUEToolsFormat > format in _config . formats )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
List < string > newFiles = new List < string > ( ) ;
for ( int j = 0 ; j < origFiles . Count ; j + + )
2008-12-07 23:38:00 +00:00
{
2009-05-01 15:16:26 +00:00
string newFilename = Path . ChangeExtension ( Path . GetFileName ( origFiles [ j ] ) , "." + format . Key ) ;
string locatedFilename = LocateFile ( dir , newFilename , files ) ;
if ( locatedFilename ! = null )
newFiles . Add ( locatedFilename ) ;
2008-12-07 23:38:00 +00:00
}
2009-05-01 15:16:26 +00:00
if ( newFiles . Count = = origFiles . Count )
{
audioFiles = newFiles . ToArray ( ) ;
extension = format . Key ;
foundAll = true ;
break ;
}
}
if ( ! foundAll )
foreach ( KeyValuePair < string , CUEToolsFormat > format in _config . formats )
2008-12-07 23:38:00 +00:00
{
2009-01-17 04:09:38 +00:00
if ( files = = null )
2009-05-01 15:16:26 +00:00
audioFiles = Directory . GetFiles ( dir = = "" ? "." : dir , "*." + format . Key ) ;
2009-01-17 04:09:38 +00:00
else
{
audioFiles = files . FindAll ( delegate ( string s )
{
2009-05-01 15:16:26 +00:00
return Path . GetDirectoryName ( s ) = = dir & & Path . GetExtension ( s ) . ToLower ( ) = = "." + format . Key ;
2009-01-17 04:09:38 +00:00
} ) . ToArray ( ) ;
}
2008-12-07 23:38:00 +00:00
if ( audioFiles . Length = = filePos . Count )
{
Array . Sort ( audioFiles ) ;
2009-05-01 15:16:26 +00:00
extension = format . Key ;
2008-12-07 23:38:00 +00:00
foundAll = true ;
break ;
}
}
2010-03-03 23:52:46 +00:00
if ( ! foundAll & & files = = null )
{
List < FileGroupInfo > fileGroups = CUESheet . ScanFolder ( _config , dir = = "" ? "." : dir ) ;
foreach ( FileGroupInfo fileGroup in fileGroups )
{
if ( fileGroup . type = = FileGroupInfoType . TrackFiles & & fileGroup . files . Count = = filePos . Count )
{
if ( foundAll )
{
foundAll = false ;
break ;
}
audioFiles = fileGroup . files . ConvertAll < string > ( delegate ( FileSystemInfo info ) { return info . FullName ; } ) . ToArray ( ) ;
Array . Sort ( audioFiles ) ;
extension = fileGroup . main . Extension . ToLower ( ) . TrimStart ( '.' ) ;
foundAll = true ;
}
}
}
2009-05-01 15:16:26 +00:00
if ( ! foundAll )
throw new Exception ( "unable to locate the audio files" ) ;
for ( i = 0 ; i < filePos . Count ; i + + )
lines [ filePos [ i ] ] = "FILE \"" + Path . GetFileName ( audioFiles [ i ] ) + "\" WAVE" ;
2008-12-07 23:38:00 +00:00
2009-05-01 15:16:26 +00:00
using ( StringWriter sw = new StringWriter ( ) )
{
for ( i = 0 ; i < lines . Count ; i + + )
{
2008-12-07 23:38:00 +00:00
sw . WriteLine ( lines [ i ] ) ;
}
2009-05-01 15:16:26 +00:00
return sw . ToString ( ) ;
2008-12-07 23:38:00 +00:00
}
}
2008-12-09 07:25:48 +00:00
private int [ ] CalculateAudioFileLengths ( CUEStyle style )
{
2008-12-07 23:38:00 +00:00
int iTrack , iIndex , iFile ;
TrackInfo track ;
int [ ] fileLengths ;
bool htoaToFile = ( style = = CUEStyle . GapsAppended & & _config . preserveHTOA & & _toc . Pregap ! = 0 ) ;
bool discardOutput ;
if ( style = = CUEStyle . SingleFile | | style = = CUEStyle . SingleFileWithCUE ) {
fileLengths = new int [ 1 ] ;
iFile = 0 ;
}
else {
fileLengths = new int [ TrackCount + ( htoaToFile ? 1 : 0 ) ] ;
iFile = - 1 ;
}
for ( iTrack = 0 ; iTrack < TrackCount ; iTrack + + ) {
track = _tracks [ iTrack ] ;
if ( style = = CUEStyle . GapsPrepended | | style = = CUEStyle . GapsLeftOut )
iFile + + ;
2009-01-28 04:53:13 +00:00
for ( iIndex = 0 ; iIndex < = _toc [ _toc . FirstAudio + iTrack ] . LastIndex ; iIndex + + )
{
2008-12-07 23:38:00 +00:00
if ( style = = CUEStyle . GapsAppended & & ( iIndex = = 1 | | ( iIndex = = 0 & & iTrack = = 0 & & htoaToFile ) ) )
iFile + + ;
if ( style = = CUEStyle . GapsAppended & & iIndex = = 0 & & iTrack = = 0 )
discardOutput = ! htoaToFile ;
else
discardOutput = ( style = = CUEStyle . GapsLeftOut & & iIndex = = 0 ) ;
if ( ! discardOutput )
2009-01-28 04:53:13 +00:00
fileLengths [ iFile ] + = ( int ) _toc . IndexLength ( _toc . FirstAudio + iTrack , iIndex ) * 588 ;
2008-12-07 23:38:00 +00:00
}
}
return fileLengths ;
}
2009-03-22 16:59:05 +00:00
public void CheckStop ( )
2009-02-22 07:47:56 +00:00
{
lock ( this )
{
if ( _stop )
throw new StopException ( ) ;
if ( _pause )
{
ShowProgress ( "Paused..." , 0 , 0 , null , null ) ;
Monitor . Wait ( this ) ;
}
}
}
2008-12-07 23:38:00 +00:00
public void Stop ( ) {
lock ( this ) {
if ( _pause )
{
_pause = false ;
Monitor . Pulse ( this ) ;
}
_stop = true ;
}
}
public void Pause ( )
{
lock ( this )
{
if ( _pause )
{
_pause = false ;
Monitor . Pulse ( this ) ;
} else
{
_pause = true ;
}
}
}
public int TrackCount {
get {
return _tracks . Count ;
}
}
2009-05-01 15:16:26 +00:00
public string OutputPath
{
get
{
return _outputPath ;
}
}
public string OutputDir
{
get
{
string outDir = Path . GetDirectoryName ( _outputPath ) ;
return outDir = = "" ? "." : outDir ;
}
}
2009-02-22 07:47:56 +00:00
public CDImageLayout TOC
{
get
{
return _toc ;
}
2010-02-06 23:17:07 +00:00
set
{
_toc = new CDImageLayout ( value ) ;
if ( Tracks . Count = = 0 )
{
for ( int iTrack = 0 ; iTrack < _toc . AudioTracks ; iTrack + + )
{
//_trackFilenames.Add(string.Format("{0:00}.wav", iTrack + 1));
_tracks . Add ( new TrackInfo ( ) ) ;
}
}
}
2009-02-22 07:47:56 +00:00
}
2009-08-08 16:14:06 +00:00
private IAudioDest GetAudioDest ( string path , int finalSampleCount , int bps , int padding , bool noOutput )
2008-12-07 23:38:00 +00:00
{
if ( noOutput )
2010-02-06 23:17:07 +00:00
return new DummyWriter ( path , new AudioPCMConfig ( bps , 2 , 44100 ) ) ;
2009-08-08 16:14:06 +00:00
return AudioReadWrite . GetAudioDest ( _audioEncoderType , path , finalSampleCount , bps , 44100 , padding , _config ) ;
2008-12-07 23:38:00 +00:00
}
private IAudioSource GetAudioSource ( int sourceIndex ) {
SourceInfo sourceInfo = _sources [ sourceIndex ] ;
IAudioSource audioSource ;
if ( sourceInfo . Path = = null ) {
audioSource = new SilenceGenerator ( sourceInfo . Offset + sourceInfo . Length ) ;
}
else {
2008-12-09 07:25:48 +00:00
if ( _isCD )
{
2009-01-17 04:09:38 +00:00
_ripper . Position = 0 ;
//audioSource = _ripper;
2010-03-20 07:09:07 +00:00
audioSource = new AudioPipe ( _ripper , 0x100000 , false , ThreadPriority . Highest ) ;
2008-12-09 07:25:48 +00:00
} else
2008-12-07 23:38:00 +00:00
if ( _isArchive )
2009-02-19 04:09:59 +00:00
audioSource = AudioReadWrite . GetAudioSource ( sourceInfo . Path , OpenArchive ( sourceInfo . Path , false ) , _config ) ;
2008-12-07 23:38:00 +00:00
else
2009-02-19 04:09:59 +00:00
audioSource = AudioReadWrite . GetAudioSource ( sourceInfo . Path , null , _config ) ;
2008-12-07 23:38:00 +00:00
}
if ( sourceInfo . Offset ! = 0 )
audioSource . Position = sourceInfo . Offset ;
2010-02-23 15:15:08 +00:00
//if (!(audioSource is AudioPipe) && !(audioSource is UserDefinedReader) && _config.separateDecodingThread)
if ( ! ( audioSource is AudioPipe ) & & _config . separateDecodingThread )
2010-03-20 07:09:07 +00:00
audioSource = new AudioPipe ( audioSource , 0x10000 ) ;
2010-02-06 23:17:07 +00:00
2008-12-07 23:38:00 +00:00
return audioSource ;
}
private void WriteLine ( TextWriter sw , int level , CUELine line ) {
WriteLine ( sw , level , line . ToString ( ) ) ;
}
private void WriteLine ( TextWriter sw , int level , string line ) {
sw . Write ( new string ( ' ' , level * 2 ) ) ;
sw . WriteLine ( line ) ;
}
public List < CUELine > Attributes {
get {
return _attributes ;
}
}
public List < TrackInfo > Tracks {
get {
return _tracks ;
}
}
public bool HasHTOAFilename {
get {
return _hasHTOAFilename ;
}
}
public string HTOAFilename {
get {
return _htoaFilename ;
}
set {
_htoaFilename = value ;
}
}
public bool HasTrackFilenames {
get {
return _hasTrackFilenames ;
}
}
public List < string > TrackFilenames {
get {
return _trackFilenames ;
}
}
public bool HasSingleFilename {
get {
return _hasSingleFilename ;
}
}
public string SingleFilename {
get {
return _singleFilename ;
}
set {
_singleFilename = value ;
}
}
2009-08-06 13:03:02 +00:00
public string ArLogFileName
{
get
{
return _arLogFileName ;
}
set
{
_arLogFileName = value ;
}
}
public string AlArtFileName
{
get
{
return _alArtFileName ;
}
set
{
_alArtFileName = value ;
}
}
2009-06-24 19:40:23 +00:00
public NameValueCollection Tags
{
get
{
TagLib . File fileInfo = _tracks [ 0 ] . _fileInfo ? ? _fileInfo ;
return fileInfo ! = null ? Tagging . Analyze ( fileInfo ) : null ;
}
}
2008-12-07 23:38:00 +00:00
public string Artist {
get {
CUELine line = General . FindCUELine ( _attributes , "PERFORMER" ) ;
2009-01-17 04:09:38 +00:00
return ( line = = null | | line . Params . Count < 2 ) ? String . Empty : line . Params [ 1 ] ;
2008-12-07 23:38:00 +00:00
}
set {
General . SetCUELine ( _attributes , "PERFORMER" , value , true ) ;
}
}
2009-01-17 04:09:38 +00:00
public string Year
{
get
{
CUELine line = General . FindCUELine ( _attributes , "REM" , "DATE" ) ;
return ( line = = null | | line . Params . Count < 3 ) ? String . Empty : line . Params [ 2 ] ;
}
set
{
if ( value ! = "" )
General . SetCUELine ( _attributes , "REM" , "DATE" , value , false ) ;
else
General . DelCUELine ( _attributes , "REM" , "DATE" ) ;
}
}
2009-06-24 19:40:23 +00:00
public string DiscNumber
{
get
{
CUELine line = General . FindCUELine ( _attributes , "REM" , "DISCNUMBER" ) ;
return ( line = = null | | line . Params . Count < 3 ) ? String . Empty : line . Params [ 2 ] ;
}
set
{
if ( value ! = "" )
General . SetCUELine ( _attributes , "REM" , "DISCNUMBER" , value , false ) ;
else
General . DelCUELine ( _attributes , "REM" , "DISCNUMBER" ) ;
}
}
public string TotalDiscs
{
get
{
CUELine line = General . FindCUELine ( _attributes , "REM" , "TOTALDISCS" ) ;
return ( line = = null | | line . Params . Count < 3 ) ? String . Empty : line . Params [ 2 ] ;
}
set
{
if ( value ! = "" )
General . SetCUELine ( _attributes , "REM" , "TOTALDISCS" , value , false ) ;
else
General . DelCUELine ( _attributes , "REM" , "TOTALDISCS" ) ;
}
}
2009-01-17 04:09:38 +00:00
public string Genre
{
get
{
CUELine line = General . FindCUELine ( _attributes , "REM" , "GENRE" ) ;
return ( line = = null | | line . Params . Count < 3 ) ? String . Empty : line . Params [ 2 ] ;
}
set
{
if ( value ! = "" )
General . SetCUELine ( _attributes , "REM" , "GENRE" , value , true ) ;
else
General . DelCUELine ( _attributes , "REM" , "GENRE" ) ;
}
}
public string Catalog
{
get
{
CUELine line = General . FindCUELine ( _attributes , "CATALOG" ) ;
return ( line = = null | | line . Params . Count < 2 ) ? String . Empty : line . Params [ 1 ] ;
}
set
{
if ( value ! = "" )
General . SetCUELine ( _attributes , "CATALOG" , value , false ) ;
else
General . DelCUELine ( _attributes , "CATALOG" ) ;
}
}
2008-12-07 23:38:00 +00:00
public string Title {
get {
CUELine line = General . FindCUELine ( _attributes , "TITLE" ) ;
2009-01-17 04:09:38 +00:00
return ( line = = null | | line . Params . Count < 2 ) ? String . Empty : line . Params [ 1 ] ;
2008-12-07 23:38:00 +00:00
}
set {
General . SetCUELine ( _attributes , "TITLE" , value , true ) ;
}
}
public int WriteOffset {
get {
return _writeOffset ;
}
set {
if ( _appliedWriteOffset ) {
throw new Exception ( "Cannot change write offset after audio files have been written." ) ;
}
_writeOffset = value ;
}
}
public bool PaddedToFrame {
get {
return _paddedToFrame ;
}
}
2009-03-22 16:59:05 +00:00
public uint DataTrackLength
2008-12-07 23:38:00 +00:00
{
get
{
2009-03-22 16:59:05 +00:00
if ( ! _toc [ 1 ] . IsAudio )
return _toc [ 1 ] . Length ;
else if ( ! _toc [ _toc . TrackCount ] . IsAudio )
return _toc [ _toc . TrackCount ] . Length ;
else
return 0 U ;
2008-12-07 23:38:00 +00:00
}
set
{
2009-03-22 16:59:05 +00:00
if ( value = = 0 )
return ;
if ( ! _toc [ 1 ] . IsAudio )
2008-12-07 23:38:00 +00:00
{
2009-03-22 16:59:05 +00:00
for ( int i = 2 ; i < = _toc . TrackCount ; i + + )
2009-02-27 14:41:55 +00:00
{
2009-03-22 16:59:05 +00:00
_toc [ i ] . Start + = value - _toc [ 1 ] . Length ;
for ( int j = 0 ; j < = _toc [ i ] . LastIndex ; j + + )
_toc [ i ] [ j ] . Start + = value - _toc [ 1 ] . Length ;
2009-02-27 14:41:55 +00:00
}
2009-03-22 16:59:05 +00:00
_toc [ 1 ] . Length = value ;
2009-02-27 14:41:55 +00:00
}
2009-03-22 16:59:05 +00:00
else if ( ! _toc [ _toc . TrackCount ] . IsAudio )
{
//_toc[_toc.TrackCount].Start = tocFromLog[_toc.TrackCount].Start;
_toc [ _toc . TrackCount ] . Length = value ;
//_toc[_toc.TrackCount][0].Start = tocFromLog[_toc.TrackCount].Start;
//_toc[_toc.TrackCount][1].Start = tocFromLog[_toc.TrackCount].Start;
}
else
_toc . AddTrack ( new CDTrack ( ( uint ) _toc . TrackCount , _toc . Length + 152 U * 75 U , value , false , false ) ) ;
}
}
public string DataTrackLengthMSF
{
get
{
return CDImageLayout . TimeToString ( DataTrackLength ) ;
}
set
{
DataTrackLength = ( uint ) CDImageLayout . TimeFromString ( value ) ;
2009-02-27 14:41:55 +00:00
}
}
public string PreGapLengthMSF
{
get
{
return CDImageLayout . TimeToString ( _toc . Pregap ) ;
}
set
{
PreGapLength = ( uint ) CDImageLayout . TimeFromString ( value ) ;
}
}
public uint PreGapLength
{
get
{
return _toc . Pregap ;
}
set
{
if ( value = = _toc . Pregap | | value = = 0 )
return ;
if ( ! _toc [ 1 ] . IsAudio )
throw new Exception ( "can't set pregap to a data track" ) ;
if ( value < _toc . Pregap )
throw new Exception ( "can't set negative pregap" ) ;
uint offs = value - _toc . Pregap ;
for ( int i = 1 ; i < = _toc . TrackCount ; i + + )
{
_toc [ i ] . Start + = offs ;
for ( int j = 0 ; j < = _toc [ i ] . LastIndex ; j + + )
_toc [ i ] [ j ] . Start + = offs ;
2008-12-07 23:38:00 +00:00
}
2009-02-27 14:41:55 +00:00
_toc [ 1 ] [ 0 ] . Start = 0 ;
SourceInfo sourceInfo ;
sourceInfo . Path = null ;
sourceInfo . Offset = 0 ;
sourceInfo . Length = offs * 588 ;
_sources . Insert ( 0 , sourceInfo ) ;
2008-12-07 23:38:00 +00:00
}
}
public bool UsePregapForFirstTrackInSingleFile {
get {
return _usePregapForFirstTrackInSingleFile ;
}
set {
_usePregapForFirstTrackInSingleFile = value ;
}
}
2008-12-09 07:25:48 +00:00
public CUEConfig Config
{
get
{
2008-12-07 23:38:00 +00:00
return _config ;
}
}
2009-03-22 16:59:05 +00:00
public CUEAction Action
2008-12-09 07:25:48 +00:00
{
get
{
2009-03-22 16:59:05 +00:00
return _action ;
2008-12-07 23:38:00 +00:00
}
2008-12-09 07:25:48 +00:00
set
{
2009-03-22 16:59:05 +00:00
_action = value ;
2008-12-07 23:38:00 +00:00
}
}
2009-05-01 15:16:26 +00:00
public CUEStyle OutputStyle
{
get
{
return _outputStyle ;
}
set
{
_outputStyle = value ;
}
}
2010-02-23 15:15:08 +00:00
public bool Processed
{
get
{
return _processed ;
}
}
2008-12-09 07:25:48 +00:00
public bool IsCD
{
get
{
return _isCD ;
2008-12-07 23:38:00 +00:00
}
}
2009-03-28 03:57:49 +00:00
public static List < FileGroupInfo > ScanFolder ( CUEConfig _config , string path )
{
DirectoryInfo dir = new DirectoryInfo ( path ) ;
return ScanFolder ( _config , dir . GetFileSystemInfos ( ) ) ;
}
public static List < FileGroupInfo > ScanFolder ( CUEConfig _config , IEnumerable < FileSystemInfo > files )
{
List < FileGroupInfo > fileGroups = new List < FileGroupInfo > ( ) ;
foreach ( FileSystemInfo file in files )
{
if ( ( file . Attributes & FileAttributes . Hidden ) ! = 0 )
continue ;
if ( ( file . Attributes & FileAttributes . Directory ) ! = 0 )
{
// foreach (FileSystemInfo subfile in ((DirectoryInfo)e.file).GetFileSystemInfos())
// if (IsVisible(subfile))
// {
// e.isExpandable = true;
// break;
// }
fileGroups . Add ( new FileGroupInfo ( file , FileGroupInfoType . Folder ) ) ;
continue ;
}
string ext = file . Extension . ToLower ( ) ;
if ( ext = = ".cue" )
{
fileGroups . Add ( new FileGroupInfo ( file , FileGroupInfoType . CUESheetFile ) ) ;
continue ;
}
if ( ext = = ".zip" )
{
fileGroups . Add ( new FileGroupInfo ( file , FileGroupInfoType . Archive ) ) ;
//try
//{
// using (ICSharpCode.SharpZipLib.Zip.ZipFile unzip = new ICSharpCode.SharpZipLib.Zip.ZipFile(file.FullName))
// {
// foreach (ICSharpCode.SharpZipLib.Zip.ZipEntry entry in unzip)
// {
// if (entry.IsFile && Path.GetExtension(entry.Name).ToLower() == ".cue")
// {
// e.node.Nodes.Add(fileSystemTreeView1.NewNode(file, false));
// break;
// }
// }
// unzip.Close();
// }
//}
//catch
//{
//}
continue ;
}
if ( ext = = ".rar" )
{
fileGroups . Add ( new FileGroupInfo ( file , FileGroupInfoType . Archive ) ) ;
continue ;
}
2009-05-01 15:16:26 +00:00
CUEToolsFormat fmt ;
if ( ext . StartsWith ( "." ) & & _config . formats . TryGetValue ( ext . Substring ( 1 ) , out fmt ) & & fmt . allowLossless )
2009-03-28 03:57:49 +00:00
{
uint disc = 0 ;
2010-03-03 23:52:46 +00:00
string album = null ;
2009-03-28 03:57:49 +00:00
bool cueFound = false ;
TagLib . UserDefined . AdditionalFileTypes . Config = _config ;
TagLib . File . IFileAbstraction fileAbsraction = new TagLib . File . LocalFileAbstraction ( file . FullName ) ;
try
{
TagLib . File fileInfo = TagLib . File . Create ( fileAbsraction ) ;
disc = fileInfo . Tag . Disc ;
2010-03-03 23:52:46 +00:00
album = fileInfo . Tag . Album ;
2009-05-01 15:16:26 +00:00
cueFound = fmt . allowEmbed & & Tagging . Analyze ( fileInfo ) . Get ( "CUESHEET" ) ! = null ;
2009-03-28 03:57:49 +00:00
}
catch { }
if ( cueFound )
{
fileGroups . Add ( new FileGroupInfo ( file , FileGroupInfoType . FileWithCUE ) ) ;
continue ;
}
disc = Math . Min ( 5 , Math . Max ( 1 , disc ) ) ;
FileGroupInfo groupFound = null ;
foreach ( FileGroupInfo fileGroup in fileGroups )
{
2010-03-03 23:52:46 +00:00
if ( fileGroup . type = = FileGroupInfoType . TrackFiles
& & fileGroup . discNo = = disc
& & fileGroup . album = = album
& & fileGroup . main . Extension . ToLower ( ) = = ext )
2009-03-28 03:57:49 +00:00
{
groupFound = fileGroup ;
break ;
}
}
if ( groupFound ! = null )
{
groupFound . files . Add ( file ) ;
}
else
{
groupFound = new FileGroupInfo ( file , FileGroupInfoType . TrackFiles ) ;
groupFound . discNo = disc ;
2010-03-03 23:52:46 +00:00
groupFound . album = album ;
2009-03-28 03:57:49 +00:00
groupFound . files . Add ( file ) ;
fileGroups . Add ( groupFound ) ;
// TODO: tracks must be sorted according to tracknumer (or filename if missing)
}
}
}
fileGroups . RemoveAll ( new Predicate < FileGroupInfo > ( FileGroupInfo . IsExcessive ) ) ;
return fileGroups ;
}
2009-05-01 15:16:26 +00:00
public string AccurateRipLog
{
get
{
using ( StringWriter logWriter = new StringWriter ( ) )
{
GenerateAccurateRipLog ( logWriter ) ;
return logWriter . ToString ( ) ;
}
}
}
2009-08-06 13:03:02 +00:00
public string ExecuteScript ( CUEToolsScript script )
{
if ( ! script . builtin )
return ExecuteScript ( script . code ) ;
switch ( script . name )
{
case "default" :
return Go ( ) ;
case "only if found" :
return ArVerify . AccResult ! = HttpStatusCode . OK ? WriteReport ( ) : Go ( ) ;
2010-02-23 15:15:08 +00:00
case "submit" :
{
if ( ! _useCUEToolsDB )
return "CUETools DB not enabled" ;
if ( ArVerify . ARStatus ! = null )
return "AccurateRip: " + ArVerify . ARStatus ;
if ( ArVerify . WorstTotal ( ) < 3 )
return "AccurateRip: confidence too low" ;
//if (CTDB.AccResult == HttpStatusCode.OK)
//return "CUEToolsDB: disc already present in database";
2010-02-28 21:04:34 +00:00
if ( CTDB . AccResult ! = HttpStatusCode . NotFound & & CTDB . AccResult ! = HttpStatusCode . OK ) // && CTDB.AccResult != HttpStatusCode.NoContent)
2010-02-23 15:15:08 +00:00
return "CUEToolsDB: " + CTDB . DBStatus ;
_useCUEToolsDBSibmit = true ;
string status = Go ( ) ;
if ( CTDB . AccResult = = HttpStatusCode . OK )
foreach ( DBEntry entry in CTDB . Entries )
2010-03-20 07:09:07 +00:00
if ( entry . toc . TrackOffsets = = _toc . TrackOffsets & & ! entry . hasErrors )
2010-02-23 15:15:08 +00:00
return "CUEToolsDB: " + CTDB . Status ;
if ( ArVerify . WorstConfidence ( ) < 3 )
return status + ": confidence too low" ;
2010-02-25 17:04:49 +00:00
return CTDB . Submit ( ( int ) ArVerify . WorstConfidence ( ) , ( int ) ArVerify . WorstTotal ( ) , Artist , Title ) ;
2010-02-23 15:15:08 +00:00
}
case "repair" :
{
2010-03-25 01:05:26 +00:00
UseCUEToolsDB ( false , "CUETools 2.0.7" ) ;
2010-02-23 15:15:08 +00:00
Action = CUEAction . Verify ;
if ( CTDB . DBStatus ! = null )
return CTDB . DBStatus ;
bool useAR = _useAccurateRip ;
_useAccurateRip = false ;
Go ( ) ;
_useAccurateRip = useAR ;
List < CUEToolsSourceFile > choices = new List < CUEToolsSourceFile > ( ) ;
foreach ( DBEntry entry in CTDB . Entries )
if ( ! entry . hasErrors | | entry . canRecover )
{
CUEToolsSourceFile choice = new CUEToolsSourceFile ( entry . Status , new StringReader ( "" ) ) ;
choice . data = entry ;
choices . Add ( choice ) ;
}
CUEToolsSourceFile selectedEntry = ChooseFile ( choices , null , true ) ;
if ( selectedEntry = = null )
return CTDB . Status ;
CTDB . SelectedEntry = ( DBEntry ) selectedEntry . data ;
if ( ! CTDB . SelectedEntry . hasErrors )
return CTDB . Status ;
_useCUEToolsDBFix = true ;
Action = CUEAction . Encode ;
return Go ( ) ;
}
2009-08-06 13:03:02 +00:00
case "fix offset" :
{
if ( ArVerify . AccResult ! = HttpStatusCode . OK )
return WriteReport ( ) ;
WriteOffset = 0 ;
Action = CUEAction . Verify ;
string status = Go ( ) ;
uint tracksMatch ;
int bestOffset ;
FindBestOffset ( Config . fixOffsetMinimumConfidence , ! Config . fixOffsetToNearest , out tracksMatch , out bestOffset ) ;
if ( tracksMatch * 100 > = Config . fixOffsetMinimumTracksPercent * TrackCount )
{
WriteOffset = bestOffset ;
2009-08-08 16:14:06 +00:00
Action = CUEAction . Encode ;
2009-08-06 13:03:02 +00:00
status = Go ( ) ;
}
return status ;
}
case "encode if verified" :
{
if ( ArVerify . AccResult ! = HttpStatusCode . OK )
return WriteReport ( ) ;
Action = CUEAction . Verify ;
string status = Go ( ) ;
uint tracksMatch ;
int bestOffset ;
FindBestOffset ( Config . encodeWhenConfidence , false , out tracksMatch , out bestOffset ) ;
if ( tracksMatch * 100 > = Config . encodeWhenPercent * TrackCount & & ( ! _config . encodeWhenZeroOffset | | bestOffset = = 0 ) )
{
2009-08-08 16:14:06 +00:00
Action = CUEAction . Encode ;
2009-08-06 13:03:02 +00:00
status = Go ( ) ;
}
return status ;
}
}
return "internal error" ;
}
2009-05-01 15:16:26 +00:00
public string ExecuteScript ( string script )
{
AsmHelper helper = CompileScript ( script ) ;
return ( string ) helper . Invoke ( "*.Execute" , this ) ;
}
public static AsmHelper CompileScript ( string script )
{
//CSScript.GlobalSettings.InMemoryAsssembly = true;
//CSScript.GlobalSettings.HideAutoGeneratedFiles =
//CSScript.CacheEnabled = false;
return new AsmHelper ( CSScript . LoadCode ( "using System; using System.Windows.Forms; using System.Net; using CUETools.Processor; using CUETools.Codecs; using CUETools.AccurateRip; public class Script { "
+ "public static string Execute(CUESheet processor) { \r\n"
+ script
+ "\r\n } "
+ " }" , null , true ) ) ;
}
public static bool TryCompileScript ( string script )
{
AsmHelper helper = CompileScript ( script ) ;
return helper ! = null ;
}
2009-03-28 03:57:49 +00:00
}
public enum FileGroupInfoType
{
Folder ,
Archive ,
CUESheetFile ,
FileWithCUE ,
TrackFiles
}
2009-05-01 15:16:26 +00:00
2009-03-28 03:57:49 +00:00
public class FileGroupInfo
{
public List < FileSystemInfo > files ;
public FileSystemInfo main ;
public FileGroupInfoType type ;
public uint discNo ;
2010-03-03 23:52:46 +00:00
public string album ;
2009-03-28 03:57:49 +00:00
public FileGroupInfo ( FileSystemInfo _main , FileGroupInfoType _type )
{
main = _main ;
type = _type ;
files = new List < FileSystemInfo > ( ) ;
}
public static bool IsExcessive ( FileGroupInfo group )
{
return group . type = = FileGroupInfoType . TrackFiles & & group . files . Count < 2 ;
}
public bool Contains ( string pathIn )
{
if ( type ! = FileGroupInfoType . TrackFiles )
2009-05-01 15:16:26 +00:00
return main . FullName . ToLower ( ) = = pathIn . ToLower ( ) ;
2009-03-28 03:57:49 +00:00
bool found = false ;
foreach ( FileSystemInfo file in files )
if ( file . FullName . ToLower ( ) = = pathIn . ToLower ( ) )
found = true ;
return found ;
}
2009-05-01 15:16:26 +00:00
public static FileGroupInfo WhichContains ( IEnumerable < FileGroupInfo > fileGroups , string pathIn , FileGroupInfoType type )
2009-03-28 03:57:49 +00:00
{
foreach ( FileGroupInfo fileGroup in fileGroups )
{
2009-05-01 15:16:26 +00:00
if ( fileGroup . type = = type & & fileGroup . Contains ( pathIn ) )
2009-03-28 03:57:49 +00:00
return fileGroup ;
}
return null ;
}
2008-12-07 23:38:00 +00:00
}
2009-02-19 04:09:59 +00:00
public class ArchiveFileAbstraction : TagLib . File . IFileAbstraction
{
private string name ;
private CUESheet _cueSheet ;
public ArchiveFileAbstraction ( CUESheet cueSheet , string file )
{
name = file ;
_cueSheet = cueSheet ;
}
public string Name
{
get { return name ; }
}
public System . IO . Stream ReadStream
{
get { return _cueSheet . OpenArchive ( Name , true ) ; }
}
public System . IO . Stream WriteStream
{
get { return null ; }
}
public void CloseStream ( System . IO . Stream stream )
{
stream . Close ( ) ;
}
}
2008-12-07 23:38:00 +00:00
public class CUELine {
private List < String > _params ;
private List < bool > _quoted ;
public CUELine ( ) {
_params = new List < string > ( ) ;
_quoted = new List < bool > ( ) ;
}
public CUELine ( string line ) {
int start , end , lineLen ;
bool isQuoted ;
_params = new List < string > ( ) ;
_quoted = new List < bool > ( ) ;
start = 0 ;
lineLen = line . Length ;
while ( true ) {
while ( ( start < lineLen ) & & ( line [ start ] = = ' ' ) ) {
start + + ;
}
if ( start > = lineLen ) {
break ;
}
isQuoted = ( line [ start ] = = '"' ) ;
if ( isQuoted ) {
start + + ;
}
end = line . IndexOf ( isQuoted ? '"' : ' ' , start ) ;
if ( end = = - 1 ) {
end = lineLen ;
}
_params . Add ( line . Substring ( start , end - start ) ) ;
_quoted . Add ( isQuoted ) ;
start = isQuoted ? end + 1 : end ;
}
}
public List < string > Params {
get {
return _params ;
}
}
public List < bool > IsQuoted {
get {
return _quoted ;
}
}
public override string ToString ( ) {
if ( _params . Count ! = _quoted . Count ) {
throw new Exception ( "Parameter and IsQuoted lists must match." ) ;
}
StringBuilder sb = new StringBuilder ( ) ;
int last = _params . Count - 1 ;
for ( int i = 0 ; i < = last ; i + + ) {
2009-01-28 04:53:13 +00:00
if ( _quoted [ i ] | | _params [ i ] . Contains ( " " ) ) sb . Append ( '"' ) ;
sb . Append ( _params [ i ] . Replace ( '"' , '\'' ) ) ;
if ( _quoted [ i ] | | _params [ i ] . Contains ( " " ) ) sb . Append ( '"' ) ;
2008-12-07 23:38:00 +00:00
if ( i < last ) sb . Append ( ' ' ) ;
}
return sb . ToString ( ) ;
}
}
public class TrackInfo {
private List < CUELine > _attributes ;
2009-02-19 04:09:59 +00:00
public TagLib . File _fileInfo ;
2008-12-07 23:38:00 +00:00
public TrackInfo ( ) {
_attributes = new List < CUELine > ( ) ;
2009-02-19 04:09:59 +00:00
_fileInfo = null ;
2008-12-07 23:38:00 +00:00
}
public List < CUELine > Attributes {
get {
return _attributes ;
}
}
public string Artist {
get {
CUELine line = General . FindCUELine ( _attributes , "PERFORMER" ) ;
2009-01-17 04:09:38 +00:00
return ( line = = null | | line . Params . Count < 2 ) ? String . Empty : line . Params [ 1 ] ;
2008-12-07 23:38:00 +00:00
}
set
{
General . SetCUELine ( _attributes , "PERFORMER" , value , true ) ;
}
}
public string Title {
get {
CUELine line = General . FindCUELine ( _attributes , "TITLE" ) ;
2009-01-17 04:09:38 +00:00
return ( line = = null | | line . Params . Count < 2 ) ? String . Empty : line . Params [ 1 ] ;
2008-12-07 23:38:00 +00:00
}
set
{
General . SetCUELine ( _attributes , "TITLE" , value , true ) ;
}
}
}
struct IndexInfo {
public int Track ;
public int Index ;
public int Time ;
}
struct SourceInfo {
public string Path ;
public uint Offset ;
public uint Length ;
}
public class StopException : Exception {
public StopException ( ) : base ( ) {
}
}
2009-05-01 15:16:26 +00:00
}