|
|
|
|
|
|
|
#include "convert.h"
|
|
|
|
//#include "conversionoptions.h"
|
|
|
|
#include "convertpluginloader.h"
|
|
|
|
#include "replaygainpluginloader.h"
|
|
|
|
#include "replaygain.h"
|
|
|
|
#include "ripperpluginloader.h"
|
|
|
|
#include "configuration.h"
|
|
|
|
#include "tagengine.h"
|
|
|
|
#include "cdmanager.h"
|
|
|
|
#include "logger.h"
|
|
|
|
#include "filelist.h"
|
|
|
|
#include "replaygainscanner.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
//#include <kdebug.h>
|
|
|
|
#include <tdetempfile.h>
|
|
|
|
#include <tdeio/job.h>
|
|
|
|
//#include <kprocess.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
ConvertItem::ConvertItem()
|
|
|
|
{
|
|
|
|
// create a new item with the file list item pointer set to zero
|
|
|
|
ConvertItem( (FileListItem*)0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
ConvertItem::ConvertItem( FileListItem* item )
|
|
|
|
{
|
|
|
|
fileListItem = item;
|
|
|
|
getTime = getCorrectionTime = ripTime = decodeTime = encodeTime = replaygainTime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ConvertItem::~ConvertItem()
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
Convert::Convert( Config* _config, TagEngine* _tagEngine, CDManager* _cdManager, FileList* _fileList, Logger* _logger )
|
|
|
|
{
|
|
|
|
config = _config;
|
|
|
|
tagEngine = _tagEngine;
|
|
|
|
cdManager = _cdManager;
|
|
|
|
fileList = _fileList;
|
|
|
|
connect( fileList, TQ_SIGNAL(convertItem(FileListItem*)),
|
|
|
|
this, TQ_SLOT(add(FileListItem*))
|
|
|
|
);
|
|
|
|
connect( fileList, TQ_SIGNAL(stopItem(FileListItem*)),
|
|
|
|
this, TQ_SLOT(stop(FileListItem*))
|
|
|
|
);
|
|
|
|
connect( this, TQ_SIGNAL(finished(FileListItem*,int)),
|
|
|
|
fileList, TQ_SLOT(itemFinished(FileListItem*,int))
|
|
|
|
);
|
|
|
|
connect( this, TQ_SIGNAL(rippingFinished(const TQString&)),
|
|
|
|
fileList, TQ_SLOT(rippingFinished(const TQString&))
|
|
|
|
);
|
|
|
|
logger = _logger;
|
|
|
|
connect( this, TQ_SIGNAL(finishedProcess(int,int)),
|
|
|
|
logger, TQ_SLOT(processCompleted(int,int))
|
|
|
|
);
|
|
|
|
|
|
|
|
tUpdateProgressIndicator = new TQTimer( this, "tUpdateProgressIndicator" );
|
|
|
|
connect( tUpdateProgressIndicator, TQ_SIGNAL(timeout()),
|
|
|
|
this, TQ_SLOT(updateProgressIndicator())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Convert::~Convert()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void Convert::cleanUp()
|
|
|
|
{
|
|
|
|
// TODO clean up
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::get( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Getting file") );
|
|
|
|
item->state = ConvertItem::get;
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting file")+"... 00 %" );
|
|
|
|
|
|
|
|
KURL source( item->fileListItem->options.filePathName.replace("?","%3f") );
|
|
|
|
KURL destination( item->tempInFile->name() );
|
|
|
|
|
|
|
|
if( source.isLocalFile() && destination.isLocalFile() ) {
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
*(item->convertProcess) << "cp";
|
|
|
|
*(item->convertProcess) << source.path();
|
|
|
|
*(item->convertProcess) << destination.path();
|
|
|
|
|
|
|
|
logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item->moveJob = new TDEIO::FileCopyJob( source, destination, -1, false, true, false, false );
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(percent(TDEIO::Job*,unsigned long)),
|
|
|
|
this, TQ_SLOT(moveProgress(TDEIO::Job*,unsigned long))
|
|
|
|
);
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(result(TDEIO::Job*)),
|
|
|
|
this, TQ_SLOT(moveFinished(TDEIO::Job*))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::getCorrection( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Getting correction file") );
|
|
|
|
item->state = ConvertItem::get_correction;
|
|
|
|
|
|
|
|
// calculate the name of the correction input file
|
|
|
|
TQFile file( OutputDirectory::changeExtension(item->fileListItem->options.filePathName,item->correctionInputExtension) );
|
|
|
|
if( !file.exists() ) {
|
|
|
|
logger->log( item->logID, " " + i18n("Aborting, file does not exist") + " (" + file.name() + ")" );
|
|
|
|
executeNextStep( item );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KURL source( file.name() );
|
|
|
|
KURL destination( item->correctionInFile );
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting correction file")+"... 00 %" );
|
|
|
|
|
|
|
|
if( source.isLocalFile() && destination.isLocalFile() ) {
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
*(item->convertProcess) << "cp";
|
|
|
|
*(item->convertProcess) << source.path();
|
|
|
|
*(item->convertProcess) << destination.path();
|
|
|
|
|
|
|
|
logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item->moveJob = new TDEIO::FileCopyJob( source, destination, -1, false, true, false, false );
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(percent(TDEIO::Job*,unsigned long)),
|
|
|
|
this, TQ_SLOT(moveProgress(TDEIO::Job*,unsigned long))
|
|
|
|
);
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(result(TDEIO::Job*)),
|
|
|
|
this, TQ_SLOT(moveFinished(TDEIO::Job*))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::rip( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Ripping") );
|
|
|
|
item->state = ConvertItem::rip;
|
|
|
|
|
|
|
|
/** kaudiocreator
|
|
|
|
TQString wavFile;
|
|
|
|
TQString args = job->device;
|
|
|
|
if(!args.isEmpty())
|
|
|
|
args = TQString("?device=%1").arg(args);
|
|
|
|
args = args+"&fileNameTemplate=Track %{number}";
|
|
|
|
if(job->track < 10)
|
|
|
|
wavFile = TQString("audiocd:/Wav/Track 0%1.wav%2").arg(job->track).arg(args);
|
|
|
|
else
|
|
|
|
wavFile = TQString("audiocd:/Wav/Track %1.wav%2").arg(job->track).arg(args);
|
|
|
|
*/
|
|
|
|
|
|
|
|
RipperPlugin* plugin = config->getCurrentRipper();
|
|
|
|
|
|
|
|
if( plugin == 0 ) {
|
|
|
|
// NOTE process devices like '/dev/cdrom' - seems to be done
|
|
|
|
// TODO implement process priority (nice level)
|
|
|
|
TQString src;
|
|
|
|
if( item->fileListItem->track != 0 ) {
|
|
|
|
// TODO does it work with cds with less than 10 tracks?
|
|
|
|
src = TQString("audiocd:/Wav/Track %1.wav?device=%2&fileNameTemplate=Track %%{number}").
|
|
|
|
arg(TQString::number(item->fileListItem->track).rightJustify(2, '0')).
|
|
|
|
arg(item->fileListItem->device);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// FIXME implement ripping of full cds
|
|
|
|
src = TQString("audiocd:/Full CD/Full CD.wav?device=%1&albumTemplate=Full CD").arg(item->fileListItem->device);
|
|
|
|
item->tracks = 1;
|
|
|
|
}
|
|
|
|
KURL source( src );
|
|
|
|
KURL dest( item->tempWavFile->name() );
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... 00 %" );
|
|
|
|
item->fileListItem->ripping = true;
|
|
|
|
|
|
|
|
item->moveJob = new TDEIO::FileCopyJob( source, dest, -1, false, true, false, false );
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(percent(TDEIO::Job*,unsigned long)),
|
|
|
|
this, TQ_SLOT(moveProgress(TDEIO::Job*,unsigned long))
|
|
|
|
);
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(result(TDEIO::Job*)),
|
|
|
|
this, TQ_SLOT(moveFinished(TDEIO::Job*))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQStringList params;
|
|
|
|
TQString param, paramSplinter;
|
|
|
|
|
|
|
|
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
param = TQString();
|
|
|
|
if( !plugin->rip.param.isEmpty() ) param.append( " " + plugin->rip.param );
|
|
|
|
if( !plugin->rip.device.isEmpty() ) param.append( " " + plugin->rip.device );
|
|
|
|
if( !plugin->rip.overwrite.isEmpty() ) param.append( " " + plugin->rip.overwrite );
|
|
|
|
|
|
|
|
if( item->fileListItem->track != 0 ) {
|
|
|
|
if( !plugin->rip.track.isEmpty() ) param.append( " " + plugin->rip.track );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( !plugin->rip.full_disc.param.isEmpty() ) param.append( " " + plugin->rip.full_disc.param );
|
|
|
|
item->tracks = cdManager->getTrackCount( item->fileListItem->device );
|
|
|
|
item->track = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if( plugin->rip.out_file.find("%p") != -1 ) {
|
|
|
|
// TQString t_str = plugin->rip.out_file;
|
|
|
|
// t_str.replace( "%p", param );
|
|
|
|
// param = plugin->rip.bin + " " + t_str;
|
|
|
|
// }
|
|
|
|
// else {
|
|
|
|
// param = plugin->rip.bin + param + " " + plugin->rip.out_file;
|
|
|
|
// }
|
|
|
|
|
|
|
|
TQString t_str = plugin->rip.out_file;
|
|
|
|
t_str.replace( "%p", param );
|
|
|
|
param = config->binaries[plugin->rip.bin] + " " + t_str;
|
|
|
|
|
|
|
|
param.simplifyWhiteSpace();
|
|
|
|
|
|
|
|
params = TQStringList::split( ' ', param );
|
|
|
|
|
|
|
|
for( TQStringList::Iterator it = params.begin(); it != params.end(); ++it )
|
|
|
|
{
|
|
|
|
paramSplinter = *it;
|
|
|
|
paramSplinter.replace( "%d", item->fileListItem->device );
|
|
|
|
paramSplinter.replace( "%t", TQString().sprintf("%i",item->fileListItem->track) );
|
|
|
|
paramSplinter.replace( "%n", TQString().sprintf("%i",cdManager->getTrackCount(item->fileListItem->device)) );
|
|
|
|
paramSplinter.replace( "%o", item->tempWavFile->name() );
|
|
|
|
*(item->convertProcess) << paramSplinter;
|
|
|
|
}
|
|
|
|
|
|
|
|
param.replace( "%d", item->fileListItem->device );
|
|
|
|
param.replace( "%t", TQString().sprintf("%i",item->fileListItem->track) );
|
|
|
|
param.replace( "%n", TQString().sprintf("%i",cdManager->getTrackCount(item->fileListItem->device)) );
|
|
|
|
param.replace( "%o", "\""+item->tempWavFile->name()+"\"" );
|
|
|
|
logger->log( item->logID, param );
|
|
|
|
|
|
|
|
//kdDebug() << " Executing: `" << param << "'" << endl;
|
|
|
|
|
|
|
|
//item->readOutputTimer.start();
|
|
|
|
item->lastOutputTimer.start();
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... 00 %" );
|
|
|
|
item->fileListItem->ripping = true;
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::decode( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Decoding") );
|
|
|
|
item->state = ConvertItem::decode;
|
|
|
|
|
|
|
|
TQStringList params;
|
|
|
|
TQString param, paramSplinter;
|
|
|
|
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
ConvertPlugin* plugin = config->decoderForFormat( item->fileListItem->mimeType );
|
|
|
|
if( plugin == 0 ) {
|
|
|
|
logger->log( item->logID, " NULL POINTER: Convert::decode( ... ) / plugin" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
param = "";
|
|
|
|
if( !plugin->dec.param.isEmpty() ) param.append( " " + plugin->dec.param );
|
|
|
|
if( !plugin->dec.overwrite.isEmpty() ) param.append( " " + plugin->dec.overwrite );
|
|
|
|
|
|
|
|
TQString t_str = plugin->dec.in_out_files;
|
|
|
|
t_str.replace( "%p", param );
|
|
|
|
param = config->binaries[plugin->dec.bin] + " " + t_str;
|
|
|
|
|
|
|
|
param = param.simplifyWhiteSpace();
|
|
|
|
|
|
|
|
params = TQStringList::split( ' ', param );
|
|
|
|
|
|
|
|
for( TQStringList::Iterator it = params.begin(); it != params.end(); ++it )
|
|
|
|
{
|
|
|
|
paramSplinter = *it;
|
|
|
|
paramSplinter.replace( "%i", item->tempInFile->name() );
|
|
|
|
paramSplinter.replace( "%o", item->tempWavFile->name() );
|
|
|
|
*(item->convertProcess) << paramSplinter;
|
|
|
|
}
|
|
|
|
|
|
|
|
param.replace( "%i", "\""+item->tempInFile->name()+"\"" );
|
|
|
|
param.replace( "%o", "\""+item->tempWavFile->name()+"\"" );
|
|
|
|
//item->log = param;
|
|
|
|
logger->log( item->logID, param );
|
|
|
|
|
|
|
|
//kdDebug() << " Executing: `" << param << "'" << endl;
|
|
|
|
|
|
|
|
//item->readOutputTimer.start();
|
|
|
|
item->lastOutputTimer.start();
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... 00 %" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::encode( ConvertItem* item )
|
|
|
|
{
|
|
|
|
// TODO test quality profiles (never done)
|
|
|
|
|
|
|
|
TQString sStrength;
|
|
|
|
TQString sBitrate;
|
|
|
|
TQString sQuality;
|
|
|
|
TQString sMinBitrate;
|
|
|
|
TQString sMaxBitrate;
|
|
|
|
TQString sSamplingRate;
|
|
|
|
|
|
|
|
int t_int;
|
|
|
|
float t_float;
|
|
|
|
|
|
|
|
logger->log( item->logID, i18n("Encoding") );
|
|
|
|
item->state = ConvertItem::encode;
|
|
|
|
|
|
|
|
TQStringList params;
|
|
|
|
TQString param, paramSplinter;
|
|
|
|
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
// NOTE use mimetype
|
|
|
|
FormatItem* formatItem = config->getFormatItem( item->fileListItem->options.encodingOptions.sFormat );
|
|
|
|
if( formatItem == 0 ) {
|
|
|
|
//kdDebug() << "NULL POINTER: `" << "Convert::encode( ... ) / formatItem" << "'" << endl;
|
|
|
|
logger->log( 1000, "NULL POINTER: `Convert::encode( ... ) / formatItem'" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ConvertPlugin* plugin = formatItem->encoder;
|
|
|
|
if( plugin == 0 ) {
|
|
|
|
//kdDebug() << "NULL POINTER: `" << "Convert::encode( ... ) / plugin" << "'" << endl;
|
|
|
|
logger->log( 1000, "NULL POINTER: `Convert::encode( ... ) / plugin'" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// item->binary = plugin->enc.bin;
|
|
|
|
|
|
|
|
param = "";
|
|
|
|
if( !plugin->enc.param.isEmpty() ) param.append( " " + plugin->enc.param );
|
|
|
|
if( !plugin->enc.overwrite.isEmpty() ) param.append( " " + plugin->enc.overwrite );
|
|
|
|
|
|
|
|
if( plugin->enc.strength.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.strength.param );
|
|
|
|
int compressionLevel = formatItem->compressionLevel;
|
|
|
|
|
|
|
|
if( plugin->enc.strength.profiles.empty() ) {
|
|
|
|
if( plugin->enc.strength.step < 1 ) {
|
|
|
|
if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min )
|
|
|
|
sStrength = TQString::number( compressionLevel * plugin->enc.strength.step );
|
|
|
|
else
|
|
|
|
sStrength = TQString::number( plugin->enc.strength.range_min - compressionLevel * plugin->enc.strength.step );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min )
|
|
|
|
sStrength = TQString::number( int(compressionLevel * plugin->enc.strength.step) );
|
|
|
|
else
|
|
|
|
sStrength = TQString::number( int(plugin->enc.strength.range_min - compressionLevel * plugin->enc.strength.step) );
|
|
|
|
}
|
|
|
|
if( plugin->enc.strength.separator != '.' ) sStrength.replace( TQChar('.'), plugin->enc.strength.separator );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQStringList::Iterator it = plugin->enc.strength.profiles.at( compressionLevel );
|
|
|
|
sStrength = *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") ) {
|
|
|
|
if( item->fileListItem->options.encodingOptions.sBitrateMode == "cbr" && plugin->enc.lossy.bitrate.cbr.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.bitrate.cbr.param );
|
|
|
|
sBitrate = TQString::number( item->fileListItem->options.encodingOptions.iQuality );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.sBitrateMode == "abr" && plugin->enc.lossy.bitrate.abr.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.bitrate.abr.param );
|
|
|
|
sBitrate = TQString::number( item->fileListItem->options.encodingOptions.iQuality );
|
|
|
|
if( item->fileListItem->options.encodingOptions.bBitrateRange && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_min );
|
|
|
|
sMinBitrate = TQString::number( item->fileListItem->options.encodingOptions.iMinBitrate );
|
|
|
|
param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max );
|
|
|
|
sMaxBitrate = TQString::number( item->fileListItem->options.encodingOptions.iMaxBitrate );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") && plugin->enc.lossy.quality.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.quality.param );
|
|
|
|
if( plugin->enc.lossy.quality.profiles.empty() ) {
|
|
|
|
if( plugin->enc.lossy.quality.step < 1 ) {
|
|
|
|
if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min)
|
|
|
|
t_float = ( (float)item->fileListItem->options.encodingOptions.iQuality * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min;
|
|
|
|
else
|
|
|
|
t_float = ( (100.0f - (float)item->fileListItem->options.encodingOptions.iQuality) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max;
|
|
|
|
//t_float -= t_float%plugin->enc.quality.step;
|
|
|
|
//sQuality = TQString().sprintf( "%.2f", t_float );
|
|
|
|
sQuality = TQString::number( t_float );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min)
|
|
|
|
t_int = ( item->fileListItem->options.encodingOptions.iQuality * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min;
|
|
|
|
else
|
|
|
|
t_int = ( (100 - item->fileListItem->options.encodingOptions.iQuality) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max;
|
|
|
|
//t_int -= t_int%plugin->enc.quality.step;
|
|
|
|
sQuality = TQString::number( t_int );
|
|
|
|
}
|
|
|
|
if( plugin->enc.bin == "oggenc" ) sQuality.replace(TQChar('.'),TDEGlobal::locale()->decimalSymbol()); // HACK make oggenc usable with all langauges
|
|
|
|
else if( plugin->enc.lossy.quality.separator != '.' ) sQuality.replace(TQChar('.'),plugin->enc.lossy.quality.separator);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( rint(item->fileListItem->options.encodingOptions.iQuality*plugin->enc.lossy.quality.range_max/100) );
|
|
|
|
sQuality = *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Lossless") && plugin->enc.lossless.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossless.param );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Hybrid") && plugin->enc.hybrid.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.hybrid.param );
|
|
|
|
sBitrate = TQString::number( item->fileListItem->options.encodingOptions.iQuality );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item->fileListItem->options.encodingOptions.samplingRate.bEnabled && plugin->enc.lossy.samplingrate.enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.samplingrate.param );
|
|
|
|
if( plugin->enc.lossy.samplingrate.unit == PluginLoaderBase::Hz ) {
|
|
|
|
sSamplingRate = TQString::number( item->fileListItem->options.encodingOptions.samplingRate.iSamplingRate );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sSamplingRate = TQString::number( (float)item->fileListItem->options.encodingOptions.samplingRate.iSamplingRate/1000 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item->fileListItem->options.encodingOptions.channels.bEnabled ) {
|
|
|
|
if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Mono") && plugin->enc.lossy.channels.mono_enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.channels.mono_param );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Stereo") && plugin->enc.lossy.channels.stereo_enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.channels.stereo_param );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Joint-Stereo") && plugin->enc.lossy.channels.joint_stereo_enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.channels.joint_stereo_param );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Forced Joint-Stereo") && plugin->enc.lossy.channels.forced_joint_stereo_enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.channels.forced_joint_stereo_param );
|
|
|
|
}
|
|
|
|
else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Dual Channels") && plugin->enc.lossy.channels.dual_channels_enabled ) {
|
|
|
|
param.append( " " + plugin->enc.lossy.channels.dual_channels_param );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item->fileListItem->options.encodingOptions.replaygain.bEnabled && plugin->enc.replaygain.enabled && !plugin->enc.replaygain.use.isEmpty() && formatItem->internalReplayGain ) {
|
|
|
|
param.append( " " + plugin->enc.replaygain.use );
|
|
|
|
}
|
|
|
|
else if( plugin->enc.replaygain.enabled && !plugin->enc.replaygain.avoid.isEmpty() ) {
|
|
|
|
param.append( " " + plugin->enc.replaygain.avoid );
|
|
|
|
}
|
|
|
|
|
|
|
|
// if( !tagEngine->canWrite(item->fileListItem->options.encodingOptions.sFormat) && item->fileListItem->tags && plugin->enc.tag.enabled ) {
|
|
|
|
if( item->fileListItem->tags && plugin->enc.tag.enabled && item->fileListItem->options.encodingOptions.sFormat != "aac" ) { // HACK don't write metadata to aac
|
|
|
|
if( !plugin->enc.tag.param.isEmpty() ) param.append( " " + plugin->enc.tag.param );
|
|
|
|
if( !plugin->enc.tag.artist.isEmpty() && !item->fileListItem->tags->artist.isEmpty() ) param.append( " " + plugin->enc.tag.artist );
|
|
|
|
if( !plugin->enc.tag.album.isEmpty() && !item->fileListItem->tags->album.isEmpty() ) param.append( " " + plugin->enc.tag.album );
|
|
|
|
if( !plugin->enc.tag.comment.isEmpty() && !item->fileListItem->tags->comment.isEmpty() ) param.append( " " + plugin->enc.tag.comment );
|
|
|
|
if( !plugin->enc.tag.disc.isEmpty() && item->fileListItem->tags->disc != 0 ) param.append( " " + plugin->enc.tag.disc );
|
|
|
|
if( !plugin->enc.tag.genre.isEmpty() && !item->fileListItem->tags->genre.isEmpty() ) param.append( " " + plugin->enc.tag.genre );
|
|
|
|
if( !plugin->enc.tag.track.isEmpty() && item->fileListItem->tags->track != 0 ) param.append( " " + plugin->enc.tag.track );
|
|
|
|
if( !plugin->enc.tag.composer.isEmpty() && !item->fileListItem->tags->composer.isEmpty() ) param.append( " " + plugin->enc.tag.composer );
|
|
|
|
if( !plugin->enc.tag.title.isEmpty() && !item->fileListItem->tags->title.isEmpty() ) param.append( " " + plugin->enc.tag.title );
|
|
|
|
if( !plugin->enc.tag.year.isEmpty() && item->fileListItem->tags->year != 0 ) param.append( " " + plugin->enc.tag.year );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString sInOutFiles = item->fileListItem->options.encodingOptions.sInOutFiles;
|
|
|
|
param = sInOutFiles.replace( "%p", param );
|
|
|
|
|
|
|
|
// cosmetic surgery
|
|
|
|
param = param.simplifyWhiteSpace();
|
|
|
|
|
|
|
|
params = TQStringList::split( ' ', param );
|
|
|
|
|
|
|
|
TQString inputFile;
|
|
|
|
if( item->mode & ConvertItem::decode || item->mode & ConvertItem::rip ) inputFile = item->tempWavFile->name();
|
|
|
|
else inputFile = item->tempInFile->name();
|
|
|
|
|
|
|
|
for( TQStringList::Iterator it = params.begin(); it != params.end(); ++it )
|
|
|
|
{
|
|
|
|
paramSplinter = *it;
|
|
|
|
paramSplinter.replace( "%i", inputFile );
|
|
|
|
paramSplinter.replace( "%o", item->tempOutFile->name() );
|
|
|
|
paramSplinter.replace( "%c", sStrength );
|
|
|
|
paramSplinter.replace( "%b", sBitrate );
|
|
|
|
paramSplinter.replace( "%q", sQuality );
|
|
|
|
paramSplinter.replace( "%m", sMinBitrate );
|
|
|
|
paramSplinter.replace( "%M", sMaxBitrate );
|
|
|
|
paramSplinter.replace( "%s", sSamplingRate );
|
|
|
|
|
|
|
|
if( item->fileListItem->tags ) {
|
|
|
|
paramSplinter.replace( "%ta", ( item->fileListItem->tags->artist != "" ) ? item->fileListItem->tags->artist : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%tb", ( item->fileListItem->tags->album != "" ) ? item->fileListItem->tags->album : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%tc", ( item->fileListItem->tags->comment != "" ) ? item->fileListItem->tags->comment : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%td", ( TQString::number(item->fileListItem->tags->disc) != "" ) ? TQString::number(item->fileListItem->tags->disc) : "0" );
|
|
|
|
paramSplinter.replace( "%tg", ( item->fileListItem->tags->genre != "" ) ? item->fileListItem->tags->genre : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%tn", ( TQString::number(item->fileListItem->tags->track) != "" ) ? TQString::number(item->fileListItem->tags->track) : "0" );
|
|
|
|
paramSplinter.replace( "%tp", ( item->fileListItem->tags->composer != "" ) ? item->fileListItem->tags->composer : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%tt", ( item->fileListItem->tags->title != "" ) ? item->fileListItem->tags->title : i18n("Unknown") );
|
|
|
|
paramSplinter.replace( "%ty", ( TQString::number(item->fileListItem->tags->year) != "" ) ? TQString::number(item->fileListItem->tags->year) : "0" );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( paramSplinter != "" && paramSplinter != " " ) *(item->convertProcess) << paramSplinter; // NOTE fixes wavpack encoding
|
|
|
|
}
|
|
|
|
|
|
|
|
param.replace( "%i", "\""+inputFile+"\"" );
|
|
|
|
param.replace( "%o", "\""+item->tempOutFile->name()+"\"" );
|
|
|
|
param.replace( "%c", sStrength );
|
|
|
|
param.replace( "%b", sBitrate );
|
|
|
|
param.replace( "%q", sQuality );
|
|
|
|
param.replace( "%m", sMinBitrate );
|
|
|
|
param.replace( "%M", sMaxBitrate );
|
|
|
|
param.replace( "%s", sSamplingRate );
|
|
|
|
|
|
|
|
if( item->fileListItem->tags ) {
|
|
|
|
param.replace( "%ta", "\""+item->fileListItem->tags->artist+"\"" );
|
|
|
|
param.replace( "%tb", "\""+item->fileListItem->tags->album+"\"" );
|
|
|
|
param.replace( "%tc", "\""+item->fileListItem->tags->comment+"\"" );
|
|
|
|
param.replace( "%td", TQString::number(item->fileListItem->tags->disc) );
|
|
|
|
param.replace( "%tg", "\""+item->fileListItem->tags->genre+"\"" );
|
|
|
|
param.replace( "%tn", TQString::number(item->fileListItem->tags->track) );
|
|
|
|
param.replace( "%tp", "\""+item->fileListItem->tags->composer+"\"" );
|
|
|
|
param.replace( "%tt", "\""+item->fileListItem->tags->title+"\"" );
|
|
|
|
param.replace( "%ty", TQString::number(item->fileListItem->tags->year) );
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->log( item->logID, param );
|
|
|
|
|
|
|
|
//kdDebug() << " Executing: `" << param << "'" << endl;
|
|
|
|
|
|
|
|
//item->readOutputTimer.start();
|
|
|
|
item->lastOutputTimer.start();
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... 00 %" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::replaygain( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Applying Replay Gain") );
|
|
|
|
item->state = ConvertItem::replaygain;
|
|
|
|
|
|
|
|
FormatItem* formatItem = config->getFormatItem( item->fileListItem->options.encodingOptions.sFormat );
|
|
|
|
if( formatItem == 0 ) {
|
|
|
|
logger->log( item->logID, " NULL POINTER: Convert::replaygain( ... ) / formatItem" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ConvertPlugin* plugin = formatItem->encoder;
|
|
|
|
if( plugin == 0 ) {
|
|
|
|
logger->log( item->logID, " NULL POINTER: Convert::replaygain( ... ) / plugin" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( plugin->enc.replaygain.enabled && formatItem->internalReplayGain ) {
|
|
|
|
executeNextStep( item );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->replayGain = new ReplayGain( config, logger );
|
|
|
|
bool ret = item->replayGain->apply( item->tempOutFile->name(), item->fileListItem->options.encodingOptions.sFormat, item->convertProcess, item->logID );
|
|
|
|
|
|
|
|
if( !ret ) {
|
|
|
|
executeNextStep( item );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//item->readOutputTimer.start();
|
|
|
|
item->lastOutputTimer.start();
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Replay Gain")+"... 00 %" );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::writeTags( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Writing tags") );
|
|
|
|
item->state = ConvertItem::write_tags;
|
|
|
|
|
|
|
|
if( item->mode & ConvertItem::encode ) {
|
|
|
|
tagEngine->writeTags( item->tempOutFile->name(), item->fileListItem->tags );
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Writing tags")+"... 00 %" );
|
|
|
|
}
|
|
|
|
|
|
|
|
executeNextStep( item );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::put( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Moving file") );
|
|
|
|
item->state = ConvertItem::put;
|
|
|
|
|
|
|
|
TQString src;
|
|
|
|
if( item->mode & ConvertItem::encode ) src = item->tempOutFile->name();
|
|
|
|
else src = item->tempWavFile->name();
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving file")+"... 00 %" );
|
|
|
|
|
|
|
|
item->outputFilePathName = OutputDirectory::makePath( OutputDirectory::uniqueFileName(OutputDirectory::calcPath(item->fileListItem,config)) ).replace("%2f","%252f");
|
|
|
|
|
|
|
|
KURL source( src );
|
|
|
|
KURL destination( item->outputFilePathName );
|
|
|
|
|
|
|
|
if( source.isLocalFile() && destination.isLocalFile() ) {
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
*(item->convertProcess) << "cp";
|
|
|
|
*(item->convertProcess) << source.path();
|
|
|
|
*(item->convertProcess) << destination.path();
|
|
|
|
|
|
|
|
logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item->moveJob = new TDEIO::FileCopyJob( source, destination, -1, false, false, false, false );
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(percent(TDEIO::Job*,unsigned long)),
|
|
|
|
this, TQ_SLOT(moveProgress(TDEIO::Job*,unsigned long))
|
|
|
|
);
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(result(TDEIO::Job*)),
|
|
|
|
this, TQ_SLOT(moveFinished(TDEIO::Job*))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::putCorrection( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Moving correction file") );
|
|
|
|
item->state = ConvertItem::put_correction;
|
|
|
|
|
|
|
|
TQString src = item->correctionOutFile;
|
|
|
|
|
|
|
|
TQString dest = OutputDirectory::makePath( OutputDirectory::calcPath(item->fileListItem,config,item->correctionOutputExtension) ).replace("%2f","%252f");
|
|
|
|
|
|
|
|
KURL source( src );
|
|
|
|
// KURL destination( dest );
|
|
|
|
KURL destination;
|
|
|
|
destination.setPath( dest );
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving correction file")+"... 00 %" );
|
|
|
|
|
|
|
|
if( source.isLocalFile() && destination.isLocalFile() ) {
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
*(item->convertProcess) << "cp";
|
|
|
|
*(item->convertProcess) << source.path();
|
|
|
|
*(item->convertProcess) << destination.path();
|
|
|
|
|
|
|
|
logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item->moveJob = new TDEIO::FileCopyJob( source, destination, -1, false, false, false, false );
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(percent(TDEIO::Job*,unsigned long)),
|
|
|
|
this, TQ_SLOT(moveProgress(TDEIO::Job*,unsigned long))
|
|
|
|
);
|
|
|
|
connect( item->moveJob, TQ_SIGNAL(result(TDEIO::Job*)),
|
|
|
|
this, TQ_SLOT(moveFinished(TDEIO::Job*))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::executeUserScript( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Running user script") );
|
|
|
|
item->state = ConvertItem::execute_userscript;
|
|
|
|
|
|
|
|
KURL source( item->fileListItem->options.filePathName );
|
|
|
|
KURL destination( item->outputFilePathName );
|
|
|
|
|
|
|
|
item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Running user script")+"... 00 %" );
|
|
|
|
|
|
|
|
item->convertProcess->clearArguments();
|
|
|
|
|
|
|
|
TQString userscript = locate( "data", "soundkonverter/userscript.sh" );
|
|
|
|
if( userscript == "" ) executeNextStep( item );
|
|
|
|
|
|
|
|
*(item->convertProcess) << userscript;
|
|
|
|
*(item->convertProcess) << source.path();
|
|
|
|
*(item->convertProcess) << destination.path();
|
|
|
|
|
|
|
|
logger->log( item->logID, userscript + " \"" + source.path() + "\" \"" + destination.path() + "\"" );
|
|
|
|
|
|
|
|
item->convertProcess->setPriority( config->data.general.priority );
|
|
|
|
item->convertProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::executeNextStep( ConvertItem* item )
|
|
|
|
{
|
|
|
|
logger->log( item->logID, i18n("Executing next step") );
|
|
|
|
|
|
|
|
item->percent = 0;
|
|
|
|
item->lastPercent = 0; // used for ripping a whole cd to one file
|
|
|
|
|
|
|
|
switch( item->state )
|
|
|
|
{
|
|
|
|
case ConvertItem::get:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::get_correction ) getCorrection( item );
|
|
|
|
else if( item->mode & ConvertItem::rip ) rip( item );
|
|
|
|
else if( item->mode & ConvertItem::decode ) decode( item );
|
|
|
|
else if( item->mode & ConvertItem::encode ) encode( item );
|
|
|
|
else if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::get_correction:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::rip ) rip( item );
|
|
|
|
else if( item->mode & ConvertItem::decode ) decode( item );
|
|
|
|
else if( item->mode & ConvertItem::encode ) encode( item );
|
|
|
|
else if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::rip:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::decode ) decode( item );
|
|
|
|
else if( item->mode & ConvertItem::encode ) encode( item );
|
|
|
|
else if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::decode:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::encode ) encode( item );
|
|
|
|
else if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::encode:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::replaygain:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::write_tags:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::put:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::put_correction:
|
|
|
|
{
|
|
|
|
if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ConvertItem::execute_userscript:
|
|
|
|
{
|
|
|
|
remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: // case (ConvertItem::Mode)0x0000:
|
|
|
|
{
|
|
|
|
if( item->mode & ConvertItem::get ) get( item );
|
|
|
|
else if( item->mode & ConvertItem::get_correction ) getCorrection( item );
|
|
|
|
else if( item->mode & ConvertItem::rip ) rip( item );
|
|
|
|
else if( item->mode & ConvertItem::decode ) decode( item );
|
|
|
|
else if( item->mode & ConvertItem::encode ) encode( item );
|
|
|
|
else if( item->mode & ConvertItem::replaygain ) replaygain( item );
|
|
|
|
else if( item->mode & ConvertItem::write_tags ) writeTags( item );
|
|
|
|
else if( item->mode & ConvertItem::put ) put( item );
|
|
|
|
else if( item->mode & ConvertItem::put_correction ) putCorrection( item );
|
|
|
|
else if( config->data.general.executeUserScript ) executeUserScript( item );
|
|
|
|
else remove( item );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::moveProgress( TDEIO::Job* job, unsigned long percent )
|
|
|
|
{
|
|
|
|
// search the item list for our item
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator item = items.begin(); item != items.end(); item++ ) {
|
|
|
|
if( (*item)->moveJob == job ) {
|
|
|
|
(*item)->percent = percent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::moveFinished( TDEIO::Job* job )
|
|
|
|
{
|
|
|
|
// search the item list for our item
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator item = items.begin(); item != items.end(); item++ ) {
|
|
|
|
if( (*item)->moveJob == job ) {
|
|
|
|
|
|
|
|
(*item)->percent = 0;
|
|
|
|
if( (*item)->state == ConvertItem::get ) {
|
|
|
|
if( job->error() != 0 ) {
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->log( (*item)->logID, " " + i18n("Got file") );
|
|
|
|
|
|
|
|
// if file is remote or the tag reding failed previously, read the tags now
|
|
|
|
if( (*item)->fileListItem->tags == 0 ) {
|
|
|
|
(*item)->fileListItem->tags = tagEngine->readTags( (*item)->tempInFile->name() );
|
|
|
|
}
|
|
|
|
|
|
|
|
emit countTime( (*item)->getTime );
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::get_correction ) {
|
|
|
|
if( job->error() != 0 ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->log( (*item)->logID, " " + i18n("Got file") );
|
|
|
|
emit countTime( (*item)->getCorrectionTime );
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::rip ) {
|
|
|
|
if( job->error() != 0 ) {
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//logger->log( (*item)->logID, " " + i18n("Ripped track") );
|
|
|
|
(*item)->fileListItem->ripping = false;
|
|
|
|
emit countTime( (*item)->ripTime );
|
|
|
|
emit rippingFinished( (*item)->fileListItem->device );
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::put ) {
|
|
|
|
if( job->error() != 0 ) {
|
|
|
|
logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) );
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->log( (*item)->logID, " " + i18n("File moved") );
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::put_correction ) {
|
|
|
|
if( job->error() != 0 ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger->log( (*item)->logID, " " + i18n("File moved") );
|
|
|
|
}
|
|
|
|
|
|
|
|
executeNextStep( *item );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::processOutput( TDEProcess* proc, char* data, int )
|
|
|
|
{
|
|
|
|
int iPercent = 0, iTime = 0, iPos = 0, iNum = 0;
|
|
|
|
|
|
|
|
// search the item list for our item
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator item = items.begin(); item != items.end(); item++ )
|
|
|
|
{
|
|
|
|
if( (*item)->convertProcess == proc )
|
|
|
|
{
|
|
|
|
TQString log_data = data;
|
|
|
|
/* log_data.replace("\n","\\n");
|
|
|
|
log_data.replace("\t","\\t");
|
|
|
|
log_data.replace("\r","\\r");
|
|
|
|
log_data.replace("\b","\\b");*/
|
|
|
|
logger->log( (*item)->logID, " " + i18n("Output") + ": " + log_data );
|
|
|
|
|
|
|
|
//if( (*item)->readOutputTimer.elapsed() < /*config->pauseTime*/ 100 ) return; // TODO use config value
|
|
|
|
//(*item)->readOutputTimer.start();
|
|
|
|
|
|
|
|
if( (*item)->state == ConvertItem::decode )
|
|
|
|
{
|
|
|
|
if( (*item)->fileListItem == 0 ) return;
|
|
|
|
|
|
|
|
ConvertPlugin* plugin = config->decoderForFormat( (*item)->fileListItem->mimeType );
|
|
|
|
// TODO null pointer check
|
|
|
|
|
|
|
|
TQString outputPattern = plugin->dec.output;
|
|
|
|
//outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins
|
|
|
|
|
|
|
|
if( outputPattern.find("%p") != -1 ) {
|
|
|
|
outputPattern.replace( "%p", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPercent );
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%t") != -1 ) {
|
|
|
|
outputPattern.replace( "%t", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iTime );
|
|
|
|
iPercent = iTime * 100 / (*item)->fileListItem->time;
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) {
|
|
|
|
if( outputPattern.find("%0") < outputPattern.find("%1") ) {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPos, &iNum );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iNum, &iPos );
|
|
|
|
}
|
|
|
|
if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iPercent > 0 && iPercent <= 100 )
|
|
|
|
{
|
|
|
|
// TODO guess progress, when no signal is received
|
|
|
|
(*item)->lastOutputTimer.start();
|
|
|
|
(*item)->percent = iPercent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::encode )
|
|
|
|
{
|
|
|
|
if( (*item)->fileListItem == 0 ) return;
|
|
|
|
|
|
|
|
// NOTE use mimetype
|
|
|
|
ConvertPlugin* plugin = config->encoderForFormat( (*item)->fileListItem->options.encodingOptions.sFormat );
|
|
|
|
// TODO null pointer check
|
|
|
|
|
|
|
|
TQString outputPattern;
|
|
|
|
if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") ) outputPattern = plugin->enc.lossy.quality.output;
|
|
|
|
else if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*item)->fileListItem->options.encodingOptions.sBitrateMode == "cbr" ) outputPattern = plugin->enc.lossy.bitrate.cbr.output;
|
|
|
|
else if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*item)->fileListItem->options.encodingOptions.sBitrateMode == "abr" ) outputPattern = plugin->enc.lossy.bitrate.abr.output;
|
|
|
|
|
|
|
|
//outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins
|
|
|
|
|
|
|
|
if( outputPattern.find("%p") != -1 ) {
|
|
|
|
outputPattern.replace( "%p", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPercent );
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%t") != -1 ) {
|
|
|
|
outputPattern.replace( "%t", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iTime );
|
|
|
|
iPercent = iTime * 100 / (*item)->fileListItem->time;
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) {
|
|
|
|
if( outputPattern.find("%0") < outputPattern.find("%1") ) {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPos, &iNum );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iNum, &iPos );
|
|
|
|
}
|
|
|
|
if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iPercent > 0 && iPercent <= 100 )
|
|
|
|
{
|
|
|
|
// TODO guess progress, when no signal is received
|
|
|
|
(*item)->lastOutputTimer.start();
|
|
|
|
(*item)->percent = iPercent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*item)->state == ConvertItem::rip ) // ### soundkonverter 0.4 make the progress dependent on the track length
|
|
|
|
{
|
|
|
|
if( (*item)->fileListItem == 0 ) return;
|
|
|
|
|
|
|
|
RipperPlugin* plugin = config->getCurrentRipper();
|
|
|
|
// TODO null pointer check
|
|
|
|
|
|
|
|
TQString outputPattern;
|
|
|
|
if( (*item)->fileListItem->track != 0 ) outputPattern = plugin->rip.output;
|
|
|
|
else outputPattern = plugin->rip.full_disc.output;
|
|
|
|
//outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins
|
|
|
|
|
|
|
|
if( outputPattern.find("%p") != -1 || outputPattern.find("%a") != -1 ) {
|
|
|
|
outputPattern.replace( "%p", "%i" );
|
|
|
|
outputPattern.replace( "%a", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPercent );
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%t") != -1 ) {
|
|
|
|
outputPattern.replace( "%t", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iTime );
|
|
|
|
iPercent = iTime * 100 / (*item)->fileListItem->time;
|
|
|
|
}
|
|
|
|
else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) {
|
|
|
|
if( outputPattern.find("%0") < outputPattern.find("%1") ) {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iPos, &iNum );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
outputPattern.replace( "%0", "%i" );
|
|
|
|
outputPattern.replace( "%1", "%i" );
|
|
|
|
sscanf( data, outputPattern.local8Bit().data(), &iNum, &iPos );
|
|
|
|
}
|
|
|
|
if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iPercent > 0 && iPercent <= 100 )
|
|
|
|
{
|
|
|
|
// TODO guess progress, when no signal is received
|
|
|
|
(*item)->lastOutputTimer.start();
|
|
|
|
if( (*item)->fileListItem->track == 0 && plugin->rip.full_disc.output.find("%a") != -1 ) {
|
|
|
|
if( iPercent < (*item)->lastPercent ) (*item)->track++;
|
|
|
|
(*item)->lastPercent = iPercent;
|
|
|
|
(*item)->percent = (*item)->track * 100 / (*item)->tracks + iPercent / (*item)->tracks;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(*item)->percent = iPercent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::processExit( TDEProcess* proc )
|
|
|
|
{
|
|
|
|
// search the item list for our item
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator item = items.begin(); item != items.end(); item++ ) {
|
|
|
|
// if( (*item)->convertProcess == proc && (*item)->fileListItem != 0 ) {
|
|
|
|
if( (*item)->convertProcess == proc ) {
|
|
|
|
|
|
|
|
(*item)->percent = 0;
|
|
|
|
if( (*item)->state == ConvertItem::rip ) {
|
|
|
|
if( proc->signalled() ) { // FIXME does only check, whether the process has been killed
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(*item)->fileListItem->ripping = false;
|
|
|
|
emit countTime( (*item)->ripTime );
|
|
|
|
emit rippingFinished( (*item)->fileListItem->device );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::get ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->log( (*item)->logID, " " + i18n("Got file") );
|
|
|
|
|
|
|
|
// if file is remote or the tag reding failed previously, read the tags now
|
|
|
|
if( (*item)->fileListItem->tags == 0 ) {
|
|
|
|
(*item)->fileListItem->tags = tagEngine->readTags( (*item)->tempInFile->name() );
|
|
|
|
}
|
|
|
|
|
|
|
|
emit countTime( (*item)->getTime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::get_correction ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->log( (*item)->logID, " " + i18n("Got file") );
|
|
|
|
emit countTime( (*item)->getCorrectionTime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::decode ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
emit countTime( (*item)->decodeTime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::encode ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* if( (*item)->binary == "faac" ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}*/
|
|
|
|
emit countTime( (*item)->encodeTime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::put ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) );
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( !proc->normalExit() ) {
|
|
|
|
logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) );
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->log( (*item)->logID, " " + i18n("File moved") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::put_correction ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( !proc->normalExit() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
emit uncountTime( (*item)->replaygainTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->log( (*item)->logID, " " + i18n("File moved") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*item)->state == ConvertItem::replaygain ) {
|
|
|
|
if( proc->signalled() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
remove( *item, 1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( !proc->normalExit() ) {
|
|
|
|
emit uncountTime( (*item)->getTime );
|
|
|
|
emit uncountTime( (*item)->getCorrectionTime );
|
|
|
|
emit uncountTime( (*item)->ripTime );
|
|
|
|
emit uncountTime( (*item)->decodeTime );
|
|
|
|
emit uncountTime( (*item)->encodeTime );
|
|
|
|
remove( *item, -1 );
|
|
|
|
updateProgressIndicator();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
emit countTime( (*item)->replaygainTime );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO did we get errors? (complete)
|
|
|
|
executeNextStep( *item );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::add( FileListItem* item )
|
|
|
|
{
|
|
|
|
logger->log( 1000, i18n("Adding new item to conversion list: `%1'").arg(item->options.filePathName) );
|
|
|
|
|
|
|
|
// append the item to the item list and store the iterator
|
|
|
|
TQValueList<ConvertItem*>::Iterator newItem = items.append( new ConvertItem( item ) );
|
|
|
|
|
|
|
|
// register at the logger
|
|
|
|
(*newItem)->logID = logger->registerProcess( item->options.filePathName );
|
|
|
|
logger->log( 1000, " " + i18n("Got log ID: %1").arg((*newItem)->logID) );
|
|
|
|
|
|
|
|
logger->log( (*newItem)->logID, "Mime Type: " + (*newItem)->fileListItem->mimeType );
|
|
|
|
if( (*newItem)->fileListItem->tags ) logger->log( (*newItem)->logID, i18n("Tags successfully read") );
|
|
|
|
else logger->log( (*newItem)->logID, i18n("Reading tags failed") );
|
|
|
|
|
|
|
|
// set some variables to default values
|
|
|
|
(*newItem)->mode = (ConvertItem::Mode)0x0000;
|
|
|
|
(*newItem)->state = (ConvertItem::Mode)0x0000;
|
|
|
|
(*newItem)->convertProcess = 0;
|
|
|
|
(*newItem)->moveJob = 0;
|
|
|
|
(*newItem)->replayGain = 0;
|
|
|
|
|
|
|
|
/* seems to be unnecessary
|
|
|
|
(*newItem)->correctionInFile = TQString()();
|
|
|
|
(*newItem)->correctionOutFile = TQString()();
|
|
|
|
(*newItem)->correctionInputExtension = TQString()();
|
|
|
|
(*newItem)->correctionOutputExtension = TQString()();*/
|
|
|
|
|
|
|
|
// connect convertProcess of our new item with the slots of Convert
|
|
|
|
(*newItem)->convertProcess = new TDEProcess();
|
|
|
|
connect( (*newItem)->convertProcess, TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
|
|
|
|
this, TQ_SLOT(processOutput(TDEProcess*,char*,int))
|
|
|
|
);
|
|
|
|
connect( (*newItem)->convertProcess, TQ_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
|
|
|
|
this, TQ_SLOT(processOutput(TDEProcess*,char*,int))
|
|
|
|
);
|
|
|
|
connect( (*newItem)->convertProcess, TQ_SIGNAL(processExited(TDEProcess*)),
|
|
|
|
this, TQ_SLOT(processExit(TDEProcess*))
|
|
|
|
);
|
|
|
|
|
|
|
|
// NOTE the tempInFile is also created if the file is a audio cd track
|
|
|
|
|
|
|
|
// set up the names of our temp files
|
|
|
|
(*newItem)->tempInFile = new KTempFile( TQString(), "." + item->fileFormat );
|
|
|
|
(*newItem)->tempInFile->setAutoDelete( true );
|
|
|
|
(*newItem)->tempInFile->close();
|
|
|
|
|
|
|
|
(*newItem)->tempWavFile = new KTempFile( TQString(), ".wav" );
|
|
|
|
(*newItem)->tempWavFile->setAutoDelete( true );
|
|
|
|
(*newItem)->tempWavFile->close();
|
|
|
|
|
|
|
|
(*newItem)->tempOutFile = new KTempFile( TQString(), "." + item->options.encodingOptions.sFormat );
|
|
|
|
(*newItem)->tempOutFile->setAutoDelete( true );
|
|
|
|
(*newItem)->tempOutFile->close();
|
|
|
|
|
|
|
|
if( item->track >= 0 ) // it's an audio cd track
|
|
|
|
{
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( ConvertItem::rip );
|
|
|
|
}
|
|
|
|
else // it's a file
|
|
|
|
{
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( ConvertItem::get );
|
|
|
|
if( item->fileFormat != "wav" )
|
|
|
|
{
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::decode );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( item->options.encodingOptions.sFormat != "wav" )
|
|
|
|
{
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::encode );
|
|
|
|
}
|
|
|
|
if( item->options.encodingOptions.replaygain.bEnabled )
|
|
|
|
{
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::replaygain );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString extension;
|
|
|
|
|
|
|
|
extension = config->getCorrectionExtension( item->mimeType );
|
|
|
|
if( !extension.isEmpty() ) {
|
|
|
|
(*newItem)->correctionInputExtension = extension;
|
|
|
|
(*newItem)->correctionInFile = OutputDirectory::changeExtension( (*newItem)->tempInFile->name(), extension );
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::get_correction );
|
|
|
|
logger->log( (*newItem)->logID, " correctionInFile: `" + (*newItem)->correctionInFile + "'" );
|
|
|
|
}
|
|
|
|
|
|
|
|
extension = config->getCorrectionExtension( item->options.encodingOptions.sFormat );
|
|
|
|
if( !extension.isEmpty() && item->options.encodingOptions.sQualityMode == i18n("Hybrid") ) {
|
|
|
|
(*newItem)->correctionOutputExtension = extension;
|
|
|
|
(*newItem)->correctionOutFile = OutputDirectory::changeExtension( (*newItem)->tempOutFile->name(), extension );
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::put_correction );
|
|
|
|
logger->log( (*newItem)->logID, " correctionOutFile: `" + (*newItem)->correctionOutFile + "'" );
|
|
|
|
}
|
|
|
|
|
|
|
|
(*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::write_tags | ConvertItem::put );
|
|
|
|
|
|
|
|
// TODO use the values from the format info files !!!
|
|
|
|
|
|
|
|
if( (*newItem)->mode & ConvertItem::get ) {
|
|
|
|
if( !item->local ) {
|
|
|
|
(*newItem)->getTime = 0.8; // TODO use the file size from the format info files
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*newItem)->mode & ConvertItem::get_correction ) {
|
|
|
|
if( !item->local ) {
|
|
|
|
(*newItem)->getCorrectionTime = 2.0; // TODO use the file size from the format info files
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( (*newItem)->mode & ConvertItem::rip ) {
|
|
|
|
(*newItem)->ripTime = 1.0;
|
|
|
|
}
|
|
|
|
if( (*newItem)->mode & ConvertItem::decode ) {
|
|
|
|
(*newItem)->decodeTime = 0.4;
|
|
|
|
}
|
|
|
|
if( (*newItem)->mode & ConvertItem::encode ) {
|
|
|
|
(*newItem)->encodeTime = 1.0;
|
|
|
|
}
|
|
|
|
if( (*newItem)->mode & ConvertItem::replaygain ) {
|
|
|
|
(*newItem)->replaygainTime = 0.2;
|
|
|
|
}
|
|
|
|
|
|
|
|
float sum = ( (*newItem)->getTime + (*newItem)->getCorrectionTime + (*newItem)->ripTime + (*newItem)->decodeTime + (*newItem)->encodeTime + (*newItem)->replaygainTime ) / item->time;
|
|
|
|
|
|
|
|
(*newItem)->getTime /= sum;
|
|
|
|
(*newItem)->getCorrectionTime /= sum;
|
|
|
|
(*newItem)->ripTime /= sum;
|
|
|
|
(*newItem)->decodeTime /= sum;
|
|
|
|
(*newItem)->encodeTime /= sum;
|
|
|
|
(*newItem)->replaygainTime /= sum;
|
|
|
|
|
|
|
|
// visual feedback
|
|
|
|
item->converting = true;
|
|
|
|
|
|
|
|
if( !tUpdateProgressIndicator->isActive() ) {
|
|
|
|
tUpdateProgressIndicator->start( config->data.general.updateDelay );
|
|
|
|
}
|
|
|
|
|
|
|
|
// and start
|
|
|
|
executeNextStep( *newItem );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::stop( FileListItem* item )
|
|
|
|
{
|
|
|
|
// search the item list for our item to stop
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator stopItem = items.begin(); stopItem != items.end(); stopItem++ ) {
|
|
|
|
// is fileListItem pointing at the same address, as item
|
|
|
|
if( (*stopItem)->fileListItem == item ) {
|
|
|
|
|
|
|
|
if( (*stopItem)->convertProcess->isRunning() ) {
|
|
|
|
bool ret = (*stopItem)->convertProcess->kill( SIGKILL );
|
|
|
|
//kdDebug() << "Killing process... (" << ret << ")" << endl;
|
|
|
|
if( ret ) {
|
|
|
|
logger->log( (*stopItem)->logID, i18n("Killing process ...") );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->log( (*stopItem)->logID, i18n("Killing process failed. Stopping after files are completed ...") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*stopItem)->moveJob != 0 ) {
|
|
|
|
//kdDebug() << "Killing file copy..." << endl;
|
|
|
|
// FIXME crashes sometimes - should be fixed by SIGKILL
|
|
|
|
// FIXME crash if file_copy was stealthed
|
|
|
|
logger->log( (*stopItem)->logID, i18n("Killing process ...") );
|
|
|
|
(*stopItem)->moveJob->kill( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::remove( ConvertItem* item, int state )
|
|
|
|
{
|
|
|
|
// TODO "remove" (re-add) the times to the progress indicator
|
|
|
|
//emit uncountTime( item->getTime + item->getCorrectionTime + item->ripTime +
|
|
|
|
// item->decodeTime + item->encodeTime + item->replaygainTime );
|
|
|
|
|
|
|
|
logger->log( item->logID, i18n("Removing file from conversion list. Exit code %1").arg(state) );
|
|
|
|
|
|
|
|
if( item->fileListItem->notify != "" ) {
|
|
|
|
TQString command = item->fileListItem->notify;
|
|
|
|
command.replace( "%u", item->fileListItem->url );
|
|
|
|
command.replace( "%i", item->fileListItem->options.filePathName.replace(" ","%20") );
|
|
|
|
command.replace( "%o", item->outputFilePathName.replace(" ","%20") );
|
|
|
|
logger->log( item->logID, " "+i18n("Executing command: \"%1\"").arg(command) );
|
|
|
|
notify.clearArguments();
|
|
|
|
TQString paramSplinter;
|
|
|
|
// FIXME split correct (strings with spaces are splited by mistake)
|
|
|
|
// FIXME only one command can be executed at once!?
|
|
|
|
TQStringList params = TQStringList::split( ' ', item->fileListItem->notify );
|
|
|
|
for( TQStringList::Iterator it = params.begin(); it != params.end(); ++it )
|
|
|
|
{
|
|
|
|
paramSplinter = *it;
|
|
|
|
paramSplinter.replace( "%u", item->fileListItem->url );
|
|
|
|
paramSplinter.replace( "%i", item->fileListItem->options.filePathName );
|
|
|
|
paramSplinter.replace( "%o", item->outputFilePathName );
|
|
|
|
notify << paramSplinter;
|
|
|
|
}
|
|
|
|
notify.start( TDEProcess::DontCare );
|
|
|
|
}
|
|
|
|
|
|
|
|
item->fileListItem->converting = false;
|
|
|
|
emit finished( item->fileListItem, state ); // send signal to FileList
|
|
|
|
emit finishedProcess( item->logID, state ); // send signal to Logger
|
|
|
|
|
|
|
|
item->fileListItem = 0;
|
|
|
|
if( item->convertProcess != 0 ) delete item->convertProcess;
|
|
|
|
item->convertProcess = 0;
|
|
|
|
//if( item->moveJob != 0 ) delete item->moveJob; // NOTE makes soundkonverter crash
|
|
|
|
//item->moveJob = 0;
|
|
|
|
if( item->replayGain != 0 ) delete item->replayGain;
|
|
|
|
item->replayGain = 0;
|
|
|
|
|
|
|
|
if( item->tempInFile != 0 ) delete item->tempInFile;
|
|
|
|
item->tempInFile = 0;
|
|
|
|
if( item->tempWavFile != 0 ) delete item->tempWavFile;
|
|
|
|
item->tempWavFile = 0;
|
|
|
|
if( item->tempOutFile != 0 ) delete item->tempOutFile;
|
|
|
|
item->tempOutFile = 0;
|
|
|
|
TQFile file;
|
|
|
|
file.setName( item->correctionInFile );
|
|
|
|
if( file.exists() ) file.remove();
|
|
|
|
file.setName( item->correctionOutFile );
|
|
|
|
if( file.exists() ) file.remove();
|
|
|
|
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator it = items.begin(); it != items.end(); it++ ) {
|
|
|
|
if( (*it) == item ) {
|
|
|
|
items.remove( it );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete item;
|
|
|
|
item = 0;
|
|
|
|
|
|
|
|
if( items.count() == 0 ) {
|
|
|
|
tUpdateProgressIndicator->stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Convert::updateProgressIndicator()
|
|
|
|
{
|
|
|
|
float time = 0;
|
|
|
|
|
|
|
|
for( TQValueList<ConvertItem*>::Iterator it = items.begin(); it != items.end(); it++ ) {
|
|
|
|
if( (*it)->state == ConvertItem::get ) {
|
|
|
|
time += (*it)->getTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting file")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::get_correction ) {
|
|
|
|
time += (*it)->getCorrectionTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting correction file")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::rip ) {
|
|
|
|
RipperPlugin* plugin = config->getCurrentRipper();
|
|
|
|
if( plugin != 0 && plugin->rip.output.isEmpty() ) {
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... "+i18n("State")+": "+i18n("Unknown") );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
time += (*it)->ripTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::decode ) {
|
|
|
|
ConvertPlugin* plugin = config->decoderForFormat( (*it)->fileListItem->mimeType );
|
|
|
|
if( plugin == 0 || plugin->dec.output.isEmpty() ) {
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... "+i18n("State")+": "+i18n("Unknown") );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
time += (*it)->decodeTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::encode ) {
|
|
|
|
ConvertPlugin* plugin = config->encoderForFormat( (*it)->fileListItem->options.encodingOptions.sFormat );
|
|
|
|
TQString outputPattern;
|
|
|
|
if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") ) outputPattern = plugin->enc.lossy.quality.output;
|
|
|
|
else if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*it)->fileListItem->options.encodingOptions.sBitrateMode == "cbr" ) outputPattern = plugin->enc.lossy.bitrate.cbr.output;
|
|
|
|
else if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*it)->fileListItem->options.encodingOptions.sBitrateMode == "abr" ) outputPattern = plugin->enc.lossy.bitrate.abr.output;
|
|
|
|
if( outputPattern.isEmpty() ) {
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... "+i18n("State")+": "+i18n("Unknown") );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
time += (*it)->encodeTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::replaygain ) {
|
|
|
|
time += (*it)->replaygainTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Replay Gain")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::put ) {
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving file")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
else if( (*it)->state == ConvertItem::put_correction ) {
|
|
|
|
time += (*it)->getCorrectionTime * (*it)->percent / 100;
|
|
|
|
(*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving correction file")+"... "+TQString().sprintf("%02i %%",(*it)->percent) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
emit update( time );
|
|
|
|
}
|
|
|
|
|
|
|
|
// void Convert::priorityChanged( int priority )
|
|
|
|
// { // FIXME setting a higher priority does not work
|
|
|
|
// TDEProcess pChangePriority;
|
|
|
|
//
|
|
|
|
// for( TQValueList<ConvertItem*>::Iterator it = items.begin(); it != items.end(); it++ ) {
|
|
|
|
// if( (*it)->convertProcess->isRunning() ) {
|
|
|
|
// //(*it)->convertProcess->setPriority( priority );
|
|
|
|
// pChangePriority.clearArguments();
|
|
|
|
// pChangePriority << "renice";
|
|
|
|
// TQString prio;
|
|
|
|
// prio.sprintf( "%i", priority );
|
|
|
|
// pChangePriority << prio;
|
|
|
|
// TQString pid;
|
|
|
|
// pid.sprintf( "%i", (*it)->convertProcess->pid() );
|
|
|
|
// pChangePriority << pid;
|
|
|
|
// //TQString cmd;
|
|
|
|
// //cmd.sprintf( "renice %i %i", );
|
|
|
|
// pChangePriority.start( TDEProcess::Block );
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
#include "convert.moc"
|