@@ -1,18 +1,21 @@
using AAXClean ;
using Dinah.Core ;
using Dinah.Core.IO ;
using Dinah.Core.Net.Http ;
using Dinah.Core.StepRunner ;
using System ;
using System.IO ;
using System.Linq ;
namespace AaxDecrypter
{
public class AaxcDownloadConverter : AudiobookDownloadBase
{
const int MAX_FILENAME_LENGTH = 255 ;
private static readonly TimeSpan minChapterLength = TimeSpan . FromSeconds ( 3 ) ;
protected override StepSequence steps { get ; }
private AaxFile aaxFile ;
private OutputFormat OutputFormat { get ; }
public AaxcDownloadConverter ( string outFileName , string cacheDirectory , DownloadLicense dlLic , OutputFormat outputFormat , bool splitFileByChapters )
@@ -81,16 +84,38 @@ namespace AaxDecrypter
{
var zeroProgress = Step2_Start ( ) ;
var chapters = downloadLicense . ChapterInfo . Chapters . ToList ( ) ;
//Ensure split files are at least minChapterLength in duration.
var splitChapters = new ChapterInfo ( ) ;
var runningTotal = TimeSpan . Zero ;
string title = "" ;
for ( int i = 0 ; i < chapters . Count ; i + + )
{
if ( runningTotal = = TimeSpan . Zero )
title = chapters [ i ] . Title ;
runningTotal + = chapters [ i ] . Duration ;
if ( runningTotal > = minChapterLength )
{
splitChapters . AddChapter ( title , runningTotal ) ;
runningTotal = TimeSpan . Zero ;
}
}
aaxFile . ConversionProgressUpdate + = AaxFile_ConversionProgressUpdate ;
if ( OutputFormat = = OutputFormat . M4b )
ConvertToMultiMp4b ( ) ;
ConvertToMultiMp4b ( splitChapters ) ;
else
ConvertToMultiMp3 ( ) ;
ConvertToMultiMp3 ( splitChapters ) ;
aaxFile . ConversionProgressUpdate - = AaxFile_ConversionProgressUpdate ;
Step2_End ( zeroProgress ) ;
return true ;
return ! isCanceled ;
}
private DownloadProgress Step2_Start ( )
@@ -117,26 +142,24 @@ namespace AaxDecrypter
OnDecryptProgressUpdate ( zeroProgress ) ;
}
private void ConvertToMultiMp4b ( )
private void ConvertToMultiMp4b ( ChapterInfo splitChapters )
{
var chapterCount = 0 ;
aaxFile . ConvertToMultiMp4a ( downloadLicense . ChapterInfo , newSplitCallback = >
aaxFile . ConvertToMultiMp4a ( split Chapters , newSplitCallback = >
{
chapterCount + + ;
var fileName = Path . ChangeExtension ( outputFileName , $"{chapterCount}.m4b" ) ;
var fileName = GetMultipartFileName ( outputFileName , + + chapterCount , newSplitCallback . Chapter . Title ) ;
if ( File . Exists ( fileName ) )
FileExt . SafeDelete ( fileName ) ;
newSplitCallback . OutputFile = File . Open ( fileName , FileMode . OpenOrCreate ) ;
} ) ;
}
private void ConvertToMultiMp3 ( )
private void ConvertToMultiMp3 ( ChapterInfo splitChapters )
{
var chapterCount = 0 ;
aaxFile . ConvertToMultiMp3 ( downloadLicense . ChapterInfo , newSplitCallback = >
aaxFile . ConvertToMultiMp3 ( split Chapters , newSplitCallback = >
{
chapterCount + + ;
var fileName = Path . ChangeExtension ( outputFileName , $"{chapterCount}.mp3" ) ;
var fileName = GetMultipartFileName ( outputFileName , + + chapterCount , newSplitCallback . Chapter . Title ) ;
if ( File . Exists ( fileName ) )
FileExt . SafeDelete ( fileName ) ;
newSplitCallback . OutputFile = File . Open ( fileName , FileMode . OpenOrCreate ) ;
@@ -144,6 +167,30 @@ namespace AaxDecrypter
} ) ;
}
private static string GetMultipartFileName ( string baseFileName , int chapterCount , string chapterTitle )
{
string extension = Path . GetExtension ( baseFileName ) ;
var fileNameChars = $"{Path.GetFileNameWithoutExtension(baseFileName)} - {chapterCount:D2} - {chapterTitle}" . ToCharArray ( ) ;
//Replace illegal path characters with spaces.
for ( int i = 0 ; i < fileNameChars . Length ; i + + )
{
foreach ( var illegal in Path . GetInvalidFileNameChars ( ) )
{
if ( fileNameChars [ i ] = = illegal )
{
fileNameChars [ i ] = ' ' ;
break ;
}
}
}
var fileName = new string ( fileNameChars ) . Truncate ( MAX_FILENAME_LENGTH - extension . Length ) ;
return Path . Combine ( Path . GetDirectoryName ( baseFileName ) , fileName + extension ) ;
}
private void AaxFile_ConversionProgressUpdate ( object sender , ConversionProgressEventArgs e )
{
var duration = aaxFile . Duration ;
@@ -156,7 +203,7 @@ namespace AaxDecrypter
double progressPercent = e . ProcessPosition . TotalSeconds / duration . TotalSeconds ;
OnDecryptProgressUpdate (
new DownloadProgress
new DownloadProgress
{
ProgressPercentage = 100 * progressPercent ,
BytesReceived = ( long ) ( InputFileStream . Length * progressPercent ) ,