2011-05-12 22:57:08 +02:00
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2011 LoRd_MuldeR <MuldeR2@GMX.de>
//
// 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.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
# include "Dialog_CueImport.h"
# include "Global.h"
# include "Model_CueSheet.h"
2011-05-14 18:34:34 +02:00
# include "Model_AudioFile.h"
2011-05-15 01:45:27 +02:00
# include "Model_FileList.h"
2011-05-13 13:17:21 +02:00
# include "Dialog_WorkingBanner.h"
2011-05-14 18:34:34 +02:00
# include "Thread_FileAnalyzer.h"
2011-05-15 01:45:27 +02:00
# include "Thread_CueSplitter.h"
# include "LockedFile.h"
2011-05-12 22:57:08 +02:00
# include <QFileInfo>
# include <QMessageBox>
# include <QTimer>
# include <QFileDialog>
2011-05-13 13:17:21 +02:00
# include <QProgressDialog>
2011-05-12 22:57:08 +02:00
# include <QMenu>
# define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
////////////////////////////////////////////////////////////
// Constructor & Destructor
////////////////////////////////////////////////////////////
2011-05-15 01:45:27 +02:00
CueImportDialog : : CueImportDialog ( QWidget * parent , FileListModel * fileList , const QString & cueFile )
2011-05-12 22:57:08 +02:00
:
2011-05-15 01:45:27 +02:00
QDialog ( parent ) ,
m_cueFileName ( cueFile ) ,
m_fileList ( fileList )
2011-05-12 22:57:08 +02:00
{
//Init the dialog, from the .ui file
setupUi ( this ) ;
//Fix size
setMinimumSize ( this - > size ( ) ) ;
setMaximumHeight ( this - > height ( ) ) ;
//Create model
m_model = new CueSheetModel ( ) ;
2011-05-13 02:44:20 +02:00
connect ( m_model , SIGNAL ( modelReset ( ) ) , this , SLOT ( modelChanged ( ) ) ) ;
2011-05-12 22:57:08 +02:00
//Setup table view
treeView - > setModel ( m_model ) ;
treeView - > header ( ) - > setStretchLastSection ( false ) ;
treeView - > header ( ) - > setResizeMode ( QHeaderView : : ResizeToContents ) ;
treeView - > header ( ) - > setResizeMode ( 1 , QHeaderView : : Stretch ) ;
treeView - > header ( ) - > setMovable ( false ) ;
treeView - > setItemsExpandable ( false ) ;
//Enable up/down button
connect ( imprtButton , SIGNAL ( clicked ( ) ) , this , SLOT ( importButtonClicked ( ) ) ) ;
2011-05-14 15:54:04 +02:00
connect ( browseButton , SIGNAL ( clicked ( ) ) , this , SLOT ( browseButtonClicked ( ) ) ) ;
2011-05-12 22:57:08 +02:00
//Translate
labelHeaderText - > setText ( QString ( " <b>%1</b><br>%2 " ) . arg ( tr ( " Import Cue Sheet " ) , tr ( " The following Cue Sheet will be split and imported into LameXP. " ) ) ) ;
}
CueImportDialog : : ~ CueImportDialog ( void )
{
LAMEXP_DELETE ( m_model ) ;
}
2011-05-13 02:44:20 +02:00
////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////
void CueImportDialog : : showEvent ( QShowEvent * event )
{
QDialog : : showEvent ( event ) ;
modelChanged ( ) ;
}
2011-05-12 22:57:08 +02:00
////////////////////////////////////////////////////////////
// Slots
////////////////////////////////////////////////////////////
2011-05-15 01:45:27 +02:00
int CueImportDialog : : exec ( void )
2011-05-12 22:57:08 +02:00
{
2011-05-13 13:17:21 +02:00
WorkingBanner * progress = new WorkingBanner ( dynamic_cast < QWidget * > ( parent ( ) ) ) ;
progress - > show ( tr ( " Loading Cue Sheet file, please be patient... " ) ) ;
2011-05-15 01:45:27 +02:00
QFileInfo cueFileInfo ( m_cueFileName ) ;
2011-05-15 15:14:33 +02:00
if ( ! cueFileInfo . exists ( ) | | ! cueFileInfo . isFile ( ) )
2011-05-14 15:54:04 +02:00
{
2011-05-15 01:45:27 +02:00
QString text = QString ( " <nobr>%1</nobr><br><nobr>%2</nobr><br><br><nobr>%3</nobr> " ) . arg ( tr ( " Failed to load the Cue Sheet file: " ) , QDir : : toNativeSeparators ( m_cueFileName ) , tr ( " The specified file could not be found! " ) ) . replace ( " - " , " − " ) ;
2011-05-14 15:54:04 +02:00
QMessageBox : : warning ( progress , tr ( " Cue Sheet Error " ) , text ) ;
progress - > close ( ) ;
LAMEXP_DELETE ( progress ) ;
return CueSheetModel : : ErrorIOFailure ;
}
2011-05-15 15:14:33 +02:00
m_outputDir = QString ( " %1/%2 " ) . arg ( cueFileInfo . canonicalPath ( ) , cueFileInfo . completeBaseName ( ) ) ;
2011-05-16 18:05:50 +02:00
for ( int n = 2 ; QDir ( m_outputDir ) . exists ( ) ; n + + )
{
m_outputDir = QString ( " %1/%2 (%3) " ) . arg ( cueFileInfo . canonicalPath ( ) , cueFileInfo . completeBaseName ( ) , QString : : number ( n ) ) ;
}
2011-05-15 15:14:33 +02:00
setWindowTitle ( QString ( " %1: %2 " ) . arg ( windowTitle ( ) . split ( " : " , QString : : SkipEmptyParts ) . first ( ) . trimmed ( ) , cueFileInfo . fileName ( ) ) ) ;
2011-05-15 01:45:27 +02:00
int iResult = m_model - > loadCueSheet ( m_cueFileName , QApplication : : instance ( ) ) ;
2011-05-14 15:54:04 +02:00
if ( iResult ! = CueSheetModel : : ErrorSuccess )
2011-05-12 22:57:08 +02:00
{
2011-05-13 02:44:20 +02:00
QString errorMsg = tr ( " An unknown error has occured! " ) ;
switch ( iResult )
2011-05-12 22:57:08 +02:00
{
2011-05-14 15:54:04 +02:00
case CueSheetModel : : ErrorIOFailure :
errorMsg = tr ( " The file could not be opened for reading. Make sure you have the required rights! " ) ;
break ;
case CueSheetModel : : ErrorBadFile :
errorMsg = tr ( " The provided file does not look like a valid Cue Sheet disc image file! " ) ;
2011-05-13 02:44:20 +02:00
break ;
2011-05-14 15:54:04 +02:00
case CueSheetModel : : ErrorUnsupported :
errorMsg = QString ( " %1<br>%2 " ) . arg ( tr ( " Could not find any supported audio track in the Cue Sheet image! " ) , tr ( " Note that LameXP can not handle \" binary \" Cue Sheet images. " ) ) ;
2011-05-13 02:44:20 +02:00
break ;
2011-05-14 15:54:04 +02:00
case CueSheetModel : : ErrorInconsistent :
errorMsg = tr ( " The selected Cue Sheet file contains inconsistent information. Take care! " ) ;
2011-05-13 02:44:20 +02:00
break ;
2011-05-12 22:57:08 +02:00
}
2011-05-13 02:44:20 +02:00
2011-05-15 01:45:27 +02:00
QString text = QString ( " <nobr>%1</nobr><br><nobr>%2</nobr><br><br><nobr>%3</nobr> " ) . arg ( tr ( " Failed to load the Cue Sheet file: " ) , QDir : : toNativeSeparators ( m_cueFileName ) , errorMsg ) . replace ( " - " , " − " ) ;
2011-05-14 15:54:04 +02:00
QMessageBox : : warning ( progress , tr ( " Cue Sheet Error " ) , text ) ;
progress - > close ( ) ;
LAMEXP_DELETE ( progress ) ;
2011-05-13 02:44:20 +02:00
return iResult ;
2011-05-12 22:57:08 +02:00
}
2011-05-14 15:54:04 +02:00
progress - > close ( ) ;
LAMEXP_DELETE ( progress ) ;
2011-05-12 22:57:08 +02:00
return QDialog : : exec ( ) ;
}
2011-05-13 02:44:20 +02:00
void CueImportDialog : : modelChanged ( void )
{
treeView - > expandAll ( ) ;
2011-05-14 15:54:04 +02:00
editOutputDir - > setText ( QDir : : toNativeSeparators ( m_outputDir ) ) ;
}
void CueImportDialog : : browseButtonClicked ( void )
{
QString newOutDir = QFileDialog : : getExistingDirectory ( this , tr ( " Choose Output Directory " ) ) ;
if ( ! newOutDir . isEmpty ( ) )
{
m_outputDir = newOutDir ;
modelChanged ( ) ;
}
2011-05-13 02:44:20 +02:00
}
2011-05-12 22:57:08 +02:00
void CueImportDialog : : importButtonClicked ( void )
{
2011-05-14 18:34:34 +02:00
static const __int64 oneGigabyte = 1073741824 i64 ;
static const __int64 minimumFreeDiskspaceMultiplier = 2 i64 ;
static const char * writeTestBuffer = " LAMEXP_WRITE_TEST " ;
2011-05-15 15:14:33 +02:00
QDir outputDir ( m_outputDir ) ;
outputDir . mkpath ( " . " ) ;
if ( ! ( outputDir . exists ( ) & & outputDir . isReadable ( ) ) )
{
QMessageBox : : warning ( this , tr ( " LameXP " ) , QString ( " <nobr>%2</nobr> " ) . arg ( tr ( " Error: The selected output directory could not be created! " ) ) ) ;
return ;
}
2011-05-14 18:34:34 +02:00
QFile writeTest ( QString ( " %1/~%2.txt " ) . arg ( m_outputDir , lamexp_rand_str ( ) ) ) ;
if ( ! ( writeTest . open ( QIODevice : : ReadWrite ) & & ( writeTest . write ( writeTestBuffer ) = = strlen ( writeTestBuffer ) ) ) )
{
QMessageBox : : warning ( this , tr ( " LameXP " ) , QString ( " <nobr>%2</nobr> " ) . arg ( tr ( " Error: The selected output directory is not writable! " ) ) ) ;
return ;
}
else
{
writeTest . close ( ) ;
writeTest . remove ( ) ;
}
qint64 currentFreeDiskspace = lamexp_free_diskspace ( m_outputDir ) ;
if ( currentFreeDiskspace < ( oneGigabyte * minimumFreeDiskspaceMultiplier ) )
{
QMessageBox : : warning ( this , tr ( " Low Diskspace Warning " ) , QString ( " <nobr>%1</nobr><br><nobr>%2</nobr> " ) . arg ( tr ( " There are less than %1 GB of free diskspace available in the selected output directory. " ) . arg ( QString : : number ( minimumFreeDiskspaceMultiplier ) ) , tr ( " It is highly recommend to free up more diskspace before proceeding with the import! " ) ) ) ;
return ;
}
importCueSheet ( ) ;
2011-05-15 01:45:27 +02:00
accept ( ) ;
2011-05-14 18:34:34 +02:00
}
void CueImportDialog : : analyzedFile ( const AudioFileModel & file )
{
2011-05-15 01:45:27 +02:00
qDebug ( " Received result: <%s> <%s/%s> " , file . filePath ( ) . toLatin1 ( ) . constData ( ) , file . formatContainerType ( ) . toLatin1 ( ) . constData ( ) , file . formatAudioType ( ) . toLatin1 ( ) . constData ( ) ) ;
m_fileInfo < < file ;
2011-05-14 18:34:34 +02:00
}
////////////////////////////////////////////////////////////
2011-05-15 01:45:27 +02:00
// Private Functions
2011-05-14 18:34:34 +02:00
////////////////////////////////////////////////////////////
void CueImportDialog : : importCueSheet ( void )
{
QStringList files ;
2011-05-15 01:45:27 +02:00
//Fetch all files that are referenced in the Cue Sheet and lock them
int nFiles = m_model - > getFileCount ( ) ;
2011-05-14 18:34:34 +02:00
for ( int i = 0 ; i < nFiles ; i + + )
{
2011-05-15 01:45:27 +02:00
QString temp = m_model - > getFileName ( i ) ;
try
{
m_locks < < new LockedFile ( temp ) ;
}
catch ( char * err )
{
qWarning ( " Failed to lock file: %s " , err ) ;
continue ;
}
files < < temp ;
2011-05-14 18:34:34 +02:00
}
2011-05-15 18:53:44 +02:00
//Analyze all source files first
if ( analyzeFiles ( files ) )
{
//Now split files according to Cue Sheet
splitFiles ( ) ;
}
2011-05-15 01:45:27 +02:00
//Release locks
while ( ! m_locks . isEmpty ( ) )
{
delete m_locks . takeFirst ( ) ;
}
2011-05-14 18:34:34 +02:00
}
2011-05-15 18:53:44 +02:00
bool CueImportDialog : : analyzeFiles ( QStringList & files )
2011-05-14 18:34:34 +02:00
{
m_fileInfo . clear ( ) ;
2011-05-15 18:53:44 +02:00
bool bSuccess = true ;
2011-05-14 18:34:34 +02:00
2011-05-15 15:14:33 +02:00
WorkingBanner * progress = new WorkingBanner ( this ) ;
2011-05-14 18:34:34 +02:00
FileAnalyzer * analyzer = new FileAnalyzer ( files ) ;
2011-05-15 01:45:27 +02:00
2011-05-14 18:34:34 +02:00
connect ( analyzer , SIGNAL ( fileSelected ( QString ) ) , progress , SLOT ( setText ( QString ) ) , Qt : : QueuedConnection ) ;
connect ( analyzer , SIGNAL ( fileAnalyzed ( AudioFileModel ) ) , this , SLOT ( analyzedFile ( AudioFileModel ) ) , Qt : : QueuedConnection ) ;
2011-05-15 01:45:27 +02:00
progress - > show ( tr ( " Analyzing file(s), please wait... " ) , analyzer ) ;
2011-05-14 18:34:34 +02:00
progress - > close ( ) ;
2011-05-15 18:53:44 +02:00
2011-05-16 18:05:50 +02:00
if ( analyzer - > filesAccepted ( ) < static_cast < unsigned int > ( files . count ( ) ) )
2011-05-15 18:53:44 +02:00
{
if ( QMessageBox : : warning ( this , tr ( " Analysis Failed " ) , tr ( " Warning: The format of some of the input files could not be determined! " ) , tr ( " Continue Anyway " ) , tr ( " Abort " ) ) = = 1 )
{
bSuccess = false ;
}
}
2011-05-14 18:34:34 +02:00
LAMEXP_DELETE ( progress ) ;
2011-05-15 18:53:44 +02:00
LAMEXP_DELETE ( analyzer ) ;
return bSuccess ;
2011-05-12 22:57:08 +02:00
}
2011-05-15 01:45:27 +02:00
void CueImportDialog : : splitFiles ( void )
{
2011-05-16 18:05:50 +02:00
QString baseName = QFileInfo ( m_cueFileName ) . completeBaseName ( ) . replace ( " . " , " " ) . left ( 42 ) . trimmed ( ) ;
2011-05-15 15:14:33 +02:00
2011-05-15 01:45:27 +02:00
WorkingBanner * progress = new WorkingBanner ( this ) ;
2011-05-16 18:05:50 +02:00
CueSplitter * splitter = new CueSplitter ( m_outputDir , baseName , m_model , m_fileInfo ) ;
2011-05-15 15:14:33 +02:00
2011-05-15 01:45:27 +02:00
connect ( splitter , SIGNAL ( fileSelected ( QString ) ) , progress , SLOT ( setText ( QString ) ) , Qt : : QueuedConnection ) ;
2011-05-16 18:05:50 +02:00
connect ( progress , SIGNAL ( userAbort ( ) ) , splitter , SLOT ( abortProcess ( ) ) , Qt : : DirectConnection ) ;
2011-05-15 01:45:27 +02:00
connect ( splitter , SIGNAL ( fileSplit ( AudioFileModel ) ) , m_fileList , SLOT ( addFile ( AudioFileModel ) ) , Qt : : QueuedConnection ) ;
2011-05-15 15:14:33 +02:00
2011-05-15 01:45:27 +02:00
progress - > show ( tr ( " Splitting file(s), please wait... " ) , splitter ) ;
progress - > close ( ) ;
2011-05-16 18:05:50 +02:00
if ( splitter - > getAborted ( ) )
{
QMessageBox : : warning ( this , tr ( " Cue Sheet Error " ) , tr ( " Process was aborted by the user after %1 track(s)! " ) . arg ( QString : : number ( splitter - > getTracksSuccess ( ) ) ) ) ;
}
else if ( ! splitter - > getSuccess ( ) )
2011-05-15 15:14:33 +02:00
{
QMessageBox : : warning ( this , tr ( " Cue Sheet Error " ) , tr ( " An unexpected error has occured while splitting the Cue Sheet! " ) ) ;
}
else
{
2011-05-16 18:05:50 +02:00
QString text = QString ( " <nobr>%1</nobr> " ) . arg ( tr ( " Imported %1 track(s) from the Cue Sheet and skipped %2 track(s). " ) . arg ( QString : : number ( splitter - > getTracksSuccess ( ) ) , QString : : number ( splitter - > getTracksSkipped ( ) /*+ nTracksSkipped*/ ) ) ) ;
2011-05-15 15:14:33 +02:00
QMessageBox : : information ( this , tr ( " Cue Sheet Completed " ) , text ) ;
}
2011-05-15 01:45:27 +02:00
LAMEXP_DELETE ( splitter ) ;
LAMEXP_DELETE ( progress ) ;
}