summaryrefslogtreecommitdiffstats
path: root/src/filelist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/filelist.cpp')
-rwxr-xr-xsrc/filelist.cpp1445
1 files changed, 1445 insertions, 0 deletions
diff --git a/src/filelist.cpp b/src/filelist.cpp
new file mode 100755
index 0000000..c4e6b5d
--- /dev/null
+++ b/src/filelist.cpp
@@ -0,0 +1,1445 @@
+
+#include "filelist.h"
+#include "cdmanager.h"
+#include "tagengine.h"
+#include "options.h"
+#include "convert.h"
+#include "optionseditor.h"
+#include "outputdirectory.h"
+#include "config.h"
+#include "logger.h"
+#include "convertpluginloader.h" // NOTE DEBUG
+
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kaction.h>
+#include <kactioncollection.h>
+#include <kmimetype.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+#include <kurldrag.h>
+#include <kapplication.h>
+
+#include <qlayout.h>
+#include <qfileinfo.h>
+#include <qsimplerichtext.h>
+#include <qpainter.h>
+#include <qapplication.h>
+#include <qdragobject.h>
+#include <qheader.h>
+#include <qdir.h>
+#include <kprogress.h>
+#include <kuser.h>
+
+// TODO when stopping items by using the context menu, the queue mode restarts that item
+
+// TODO when dropping items, don't let the user select the position
+
+// ### soundkonverter 0.4: draw tooltip like bubble info box
+
+FileListItem::FileListItem( KListView* parent, FileListItem* after )
+ : KListViewItem( parent, after )
+{
+ tags = 0;
+ converting = false;
+ time = 0;
+ ripping = false;
+}
+
+FileListItem::FileListItem( KListView* parent )
+ : KListViewItem( parent )
+{
+ tags = 0;
+ converting = false;
+ time = 0;
+ ripping = false;
+}
+
+FileListItem::~FileListItem()
+{}
+
+void FileListItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment )
+{
+ // NOTE speed up this function
+ // NOTE calculate the red color
+
+ QColorGroup _cg( cg );
+ QColor c;
+
+ if( column == ((FileList*)listView())->columnByName(i18n("Input")) || column == ((FileList*)listView())->columnByName(i18n("Output")) )
+ {
+ int margin = listView()->itemMargin();
+ int w = width - 2*margin;
+ int h = height();
+ QRect textRect = p->boundingRect( margin, 0, w, h, alignment, text(column) );
+
+ if( textRect.width() > w ) {
+ alignment = Qt::AlignRight | Qt::SingleLine;
+ }
+
+ /*if ( textRect.width() <= w ) {
+ p->drawText( margin, 0, w, h, alignment | Qt::SingleLine | Qt::ExpandTabs, text(column), -1 );
+ }
+ else {
+ textRect = p->boundingRect( margin, 0, w, h, Qt::AlignLeft, "... " );
+ p->drawText( margin, 0, textRect.width(), h, Qt::AlignLeft | Qt::SingleLine | Qt::ExpandTabs, "...", -1 );
+ p->drawText( margin+textRect.width(), 0, w-textRect.width(), h, Qt::AlignRight | Qt::SingleLine | Qt::ExpandTabs, text(column), -1 );
+ }*/
+ }
+
+ if( isSelected() && converting ) {
+ _cg.setColor( QColorGroup::Highlight, QColor( 215, 62, 62 ) );
+ QListViewItem::paintCell( p, _cg, column, width, alignment );
+ return;
+ }
+ else if( converting && column != listView()->sortColumn() ) {
+ _cg.setColor( QColorGroup::Base, QColor( 255, 234, 234 ) );
+ QListViewItem::paintCell( p, _cg, column, width, alignment );
+ return;
+ }
+ else if( converting && column == listView()->sortColumn() ) {
+ _cg.setColor( QColorGroup::Base, QColor( 247, 227, 227 ) );
+ QListViewItem::paintCell( p, _cg, column, width, alignment );
+ return;
+ }
+
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+}
+
+/*void FileListItem::updateOutputCell()
+{
+ setText( ((FileList*)listView())->columnByName(i18n("Output")), OutputDirectory::calcPath(this) ); // FIXME no config !!!
+}
+
+void FileListItem::updateOptionsCell()
+{
+ setText( ((FileList*)listView())->columnByName(i18n("Quality")), ((FileList*)listView())->config->getProfileName(options) );
+}*/
+
+FileList::FileList( CDManager* _cdManager, TagEngine* _tagEngine, Config* _config, Options* _options, Logger* _logger, QWidget* parent, const char* name )
+ : KListView( parent, name )
+{
+ cdManager = _cdManager;
+ tagEngine = _tagEngine;
+ config = _config;
+ options = _options;
+ logger = _logger;
+ optionsEditor = 0;
+
+ queue = false;
+ notify = "";
+
+ setAcceptDrops( true );
+ setDragEnabled( true );
+
+ addColumn( i18n("State"), 120 );
+ addColumn( i18n("Input"), 180 );
+ addColumn( i18n("Output"), 180 );
+ addColumn( i18n("Quality") );
+
+ header()->setClickEnabled( false );
+
+ setSelectionMode( QListView::Extended );
+ setAllColumnsShowFocus( true );
+ setResizeMode( LastColumn );
+ setSorting( -1 ); // NOTE if commented out, items aren't moveable anymore
+
+ setMinimumHeight( 200 );
+
+ QGridLayout* grid = new QGridLayout( this, 2, 1, 11, 6 );
+ grid->setRowStretch( 0, 1 );
+ grid->setRowStretch( 2, 1 );
+ grid->setColStretch( 0, 1 );
+ grid->setColStretch( 2, 1 );
+ pScanStatus = new KProgress( this, "pScanStatus" );
+ pScanStatus->setMinimumHeight( pScanStatus->height() );
+ pScanStatus->setFormat( "%v / %m" );
+ pScanStatus->hide();
+ grid->addWidget( pScanStatus, 1, 1 );
+ grid->setColStretch( 1, 2 );
+
+ contextMenu = new KPopupMenu( this );
+ connect( this, SIGNAL(contextMenuRequested( QListViewItem*, const QPoint&, int )),
+ this, SLOT(showContextMenu( QListViewItem*, const QPoint&, int ))
+ );
+
+ // we haven't got access to the action collection of soundKonverter, so let's create a new one
+ actionCollection = new KActionCollection( this );
+
+ edit = new KAction( i18n("Edit options ..."), "view_text", 0, this, SLOT(showOptionsEditorDialog()), actionCollection, "edit_options" );
+ start = new KAction( i18n("Start conversion"), "run", 0, this, SLOT(convertSelectedItems()), actionCollection, "start_conversion" );
+ stop = new KAction( i18n("Stop conversion"), "stop", 0, this, SLOT(stopSelectedItems()), actionCollection, "stop_conversion" );
+ remove = new KAction( i18n("Remove"), "edittrash", Key_Delete, this, SLOT(removeSelectedItems()), actionCollection, "remove" );
+ paste = new KAction( i18n("Paste"), "editpaste", 0, this, 0, actionCollection, "paste" ); // TODO paste
+
+ connect( this, SIGNAL(selectionChanged()),
+ this, SLOT(itemsSelected())
+ );
+
+// connect( this, SIGNAL(clicked(QListViewItem*,const QPoint&,int)),
+// this, SLOT(clickedSomewhere(QListViewItem*,const QPoint&,int))
+// );
+
+ bubble = new QSimpleRichText( i18n( "<div align=center>"
+ "<h3>File List</h3>"
+ "Select your desired output options in the form above and add some files.<br/>"
+ "You can add files by clicking on \"Add files ...\" or dropping them here."
+// "<br/><a href=\"documenation:about_compression\">Learn more about audio compression ...</a>"
+ "</div>" ), QApplication::font() );
+
+ connect( header(), SIGNAL(sizeChange( int, int, int )),
+ SLOT(columnResizeEvent( int, int, int ))
+ );
+ connect( this, SIGNAL( dropped(QDropEvent*, QListViewItem*, QListViewItem*) ),
+ SLOT( slotDropped(QDropEvent*, QListViewItem*, QListViewItem*) )
+ );
+
+// if( QFile::exists(locateLocal("data","soundkonverter/filelist.autosave.xml")) ) load( true );
+
+// debug(); // NOTE DEBUG
+}
+
+FileList::~FileList()
+{
+ delete optionsEditor;
+}
+
+int FileList::columnByName( const QString& name )
+{
+ for( int i = 0; i < columns(); ++i ) {
+ if( columnText( i ) == name ) return i;
+ }
+ return -1;
+}
+
+void FileList::viewportPaintEvent( QPaintEvent* e )
+{
+ KListView::viewportPaintEvent( e );
+
+ // the bubble help
+ if( childCount() == 0 ) {
+ QPainter p( viewport() );
+
+ bubble->setWidth( width() - 50 );
+
+ const uint w = bubble->width() + 20;
+ const uint h = bubble->height() + 20;
+
+ p.setBrush( colorGroup().background() );
+ p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h );
+ bubble->draw( &p, 20, 20, QRect(), colorGroup() );
+ }
+}
+
+void FileList::viewportResizeEvent( QResizeEvent* )
+{
+ // needed for correct redraw of bubble help
+ triggerUpdate();
+}
+
+void FileList::columnResizeEvent( int, int, int )
+{
+ // needed for correct redraw of bubble help
+ triggerUpdate();
+}
+
+// void FileList::clickedSomewhere( QListViewItem*, const QPoint& pos, int )
+// {
+// /* if( childCount() == 0 ) {
+// kdDebug() << "clicked: `" << bubble->anchorAt(mapFromGlobal(pos)-QPoint(24,0)) << " (" << pos.x() << " | " << pos.y() << ")'" << endl;
+// }*/
+// }
+
+bool FileList::acceptDrag( QDropEvent* e ) const
+{
+ return ( e->source() == viewport() || KURLDrag::canDecode(e) ); // TODO verify the files
+}
+
+void FileList::slotDropped( QDropEvent* e, QListViewItem*, QListViewItem* itemAfter )
+{
+ QString file;
+ KURL::List list;
+ QStringList files;
+ if( KURLDrag::decode( e, list ) ) // TODO local?
+ {
+ save( true );
+ for( KURL::List::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ // TODO verify the files (necessary when multiple files are being dropped)
+ // TODO implement cdda:/
+ file = QDir::convertSeparators( (*it).pathOrURL() ); // TODO implement that in the url/file dialog, too?
+ QFileInfo fileInfo( file );
+ if( fileInfo.isDir() )
+ {
+ addDir( file );
+ }
+ else
+ {
+ files.append( (*it).url() );
+ }
+ }
+ addFiles( files, (FileListItem*)itemAfter, true );
+ save( true );
+ }
+}
+
+void FileList::showContextMenu( QListViewItem* item, const QPoint& point, int )
+{
+ // if item is null, we can abort here
+ if( !item ) return;
+
+ // remove all items from the context menu
+ contextMenu->clear();
+
+ // add a tilte to our context manu
+ //contextMenu->insertTitle( static_cast<FileListItem*>(item)->fileName ); // TODO sqeeze or something else
+
+ // TODO implement pasting, etc.
+
+ // is this file (of our item) beeing converted at the moment?
+ if( !static_cast<FileListItem*>(item)->converting ) {
+ edit->plug( contextMenu );
+ contextMenu->insertSeparator();
+ remove->plug( contextMenu );
+ //paste->plug( contextMenu );
+ contextMenu->insertSeparator();
+ start->plug( contextMenu );
+ }
+ else {
+ stop->plug( contextMenu );
+ //contextMenu->insertSeparator();
+ //remove->plug( contextMenu );
+ //paste->plug( contextMenu );
+ }
+
+ // show the popup menu
+ contextMenu->popup( point );
+}
+
+void FileList::removeSelectedItems()
+{
+ FileListItem *item = firstChild(), *nextitem = 0;
+
+ while( item != 0 ) {
+ if( item->isSelected() && !item->converting ) {
+ nextitem = item->nextSibling();
+ emit decreaseTime( item->time );
+ delete item;
+ item = nextitem;
+ }
+ else {
+ item = item->nextSibling();
+ }
+ }
+ emit fileCountChanged( childCount() );
+ itemsSelected();
+}
+
+void FileList::convertSelectedItems()
+{
+ FileListItem* item = firstChild();
+
+ while( item != 0 ) {
+ if( item->isSelected() && !item->converting ) {
+ emit convertItem( item );
+ }
+ item = item->nextSibling();
+ }
+ itemsSelected();
+ emit startedConversion();
+}
+
+void FileList::stopSelectedItems()
+{
+ FileListItem* item = firstChild();
+
+ while( item != 0 ) {
+ if( item->isSelected() && item->converting ) {
+ emit stopItem( item );
+ }
+ item = item->nextSibling();
+ }
+}
+
+int FileList::listDir( const QString& directory, QStringList filter, bool recursive, bool fast, int count )
+{ // NOTE speed up?
+ QDir dir( directory );
+ dir.setFilter( QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::Readable );
+
+ QStringList list = dir.entryList();
+
+ for( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ if( *it == "." || *it == ".." ) continue;
+ QFileInfo fileInfo( directory + "/" + *it );
+ if( fast ) {
+ if( fileInfo.isDir() && recursive ) {
+ count = listDir( fileInfo.filePath(), filter, recursive, fast, count );
+ }
+ else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names
+ // NOTE filter feature
+ for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) {
+ if( (*it).endsWith("."+(*jt),false) ) {
+ count++;
+ pScanStatus->setTotalSteps( count );
+ break;
+ }
+ }
+ if( filter.first() == "" ) {
+ count++;
+ pScanStatus->setTotalSteps( count );
+ }
+ }
+ }
+ else {
+ if( fileInfo.isDir() && recursive ) {
+ count = listDir( fileInfo.filePath(), filter, recursive, fast, count );
+ }
+ else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names
+ // NOTE filter feature
+ for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) {
+ if( (*it).endsWith("."+(*jt),false) ) {
+ addFiles( KURL::encode_string(directory + "/" + *it) );
+ count++;
+ pScanStatus->setProgress( count );
+ break;
+ }
+ }
+ if( filter.first() == "" ) {
+ addFiles( KURL::encode_string(directory + "/" + *it) );
+ count++;
+ pScanStatus->setProgress( count );
+ }
+ }
+ }
+ }
+
+ return count;
+}
+
+// NOTE progressbar when adding files?
+void FileList::addFiles( QStringList fileList, FileListItem* after, bool enabled )
+{
+ // TODO test if everything works with remote files (http://) and local files (media://)
+ FileListItem* lastListItem;
+ if( !after && !enabled ) lastListItem = lastItem();
+ else lastListItem = after;
+ QString filePathName;
+ QString device;
+
+ for( QStringList::Iterator it = fileList.begin(); it != fileList.end(); ++it ) {
+ FileListItem* newItem = new FileListItem( this, lastListItem );
+ lastListItem = newItem;
+ newItem->options = options->getCurrentOptions(); // FIXME speed up
+ newItem->notify = notify;
+ newItem->local = false;
+ newItem->track = -1;
+ newItem->url = *it;
+
+ if( (*it).left( 1 ) == "/" ) {
+ filePathName = *it;
+ newItem->local = true;
+ }
+ else if( (*it).left( 7 ) == "file://" ) {
+ filePathName = *it;
+ filePathName.remove( 0, 7 );
+ newItem->local = true;
+ }
+ else if( (*it).left( 13 ) == "system:/home/" ) {
+ filePathName = *it;
+ filePathName.remove( 0, 13 );
+ filePathName = QDir::homeDirPath() + "/" + filePathName;
+ newItem->local = true;
+ }
+ else if( (*it).left( 14 ) == "system:/users/" || (*it).left( 6 ) == "home:/" ) {
+ int length = ( (*it).left(6) == "home:/" ) ? 6 : 14;
+ QString username = *it;
+ username.remove( 0, length );
+ username = username.left( username.find("/") );
+ filePathName = *it;
+ filePathName.remove( 0, length + username.length() );
+ KUser user( username );
+ filePathName = user.homeDir() + filePathName;
+ newItem->local = true;
+ }
+ else if( (*it).left( 14 ) == "system:/media/" || (*it).left( 7 ) == "media:/" ) {
+ int length = ( (*it).left(7) == "media:/" ) ? 7 : 14;
+ device = *it;
+ device.remove( 0, length );
+ device = "/dev/" + device.left( device.find( "/" ) );
+
+ KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
+
+ for( KMountPoint::List::ConstIterator jt = mountPoints.begin(); jt != mountPoints.end(); ++jt )
+ {
+ const KSharedPtr<KMountPoint> mp = *jt;
+ logger->log( 1000, mp->mountedFrom() + " : " + mp->mountPoint() );
+ if( mp->mountedFrom() == device )
+ {
+ filePathName = ( mp->mountPoint() == "/" ) ? mp->mountPoint() : mp->mountPoint() + "/";
+ filePathName += (*it).right( (*it).length() - device.length() - length + 4 );
+ }
+ }
+
+ newItem->local = true;
+ }
+// else if( (*it).left( 14 ) == "system:/trash/" || (*it).left( 7 ) == "trash:/" ) {
+// }
+
+ if( newItem->local == true ) {
+// logger->log( 1000, i18n("Adding file") + ": " + filePathName );
+ newItem->mimeType = KMimeType::findByFileContent( filePathName )->name();
+ newItem->fileFormat = KMimeType::findByFileContent( filePathName )->patterns().first().lower();
+ newItem->fileFormat.remove( 0, 2 );
+// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" );
+// newItem->mimeType="";
+ if( newItem->mimeType.isEmpty() || newItem->mimeType == "application/octet-stream" || newItem->mimeType == "text/plain" ) {
+ newItem->mimeType = KMimeType::findByURL( filePathName.lower() )->name();
+ newItem->fileFormat = KMimeType::findByURL( filePathName.lower() )->patterns().first().lower();
+ newItem->fileFormat.remove( 0, 2 );
+// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" );
+// newItem->mimeType="";
+ // HACK last choise is to use the extension without KDE's help
+ if( newItem->mimeType.isEmpty() || newItem->mimeType == "application/octet-stream" || newItem->mimeType == "text/plain" ) {
+ newItem->fileFormat = filePathName.right( filePathName.length() - filePathName.findRev(".") - 1 );
+ FormatItem *formatItem = config->getFormatItem( newItem->fileFormat );
+ if( formatItem ) newItem->mimeType = formatItem->mime_types.first();
+// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" );
+ }
+ }
+// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" );
+ // check whether the mime type has a decoder registered
+ if( !config->acceptFile( newItem->mimeType ) || ( newItem->fileFormat == "wav" && newItem->options.encodingOptions.sFormat == "wav" ) ) {
+ delete newItem;
+ continue;
+ }
+ newItem->options.filePathName = filePathName;
+ QFileInfo fileInfo( filePathName );
+ newItem->fileName = fileInfo.fileName();
+ newItem->tags = tagEngine->readTags( KURL::decode_string(filePathName) );
+ if( newItem->tags == 0 ) {
+// logger->log( 1000, " " + i18n("Reading tags failed") );
+ // FIXME check for wav files
+ FormatItem* formatItem = config->getFormatItem( newItem->mimeType );
+ if( formatItem && formatItem->size > 0 ) {
+ newItem->time = fileInfo.size() / formatItem->size;
+ }
+ else {
+ newItem->time = 210;
+ }
+ }
+ else {
+// logger->log( 1000, " " + i18n("Tags successfully read") );
+ newItem->time = newItem->tags->length;
+ }
+ }
+ else {
+// logger->log( 1000, " File is remote (not yet implemented) (" + *it + ")" );
+ filePathName = *it;
+ newItem->fileName = filePathName.right( filePathName.length() - filePathName.findRev("/") - 1 );
+ newItem->fileFormat = newItem->fileName.right( newItem->fileName.length() - newItem->fileName.findRev(".") - 1 ).lower();
+ // NOTE http will not work with KMimeType - this just works
+ if( filePathName.startsWith("http://") ) {
+ newItem->mimeType = KMimeType::findByURL( "file:///" + newItem->fileName.lower() )->name();
+ }
+ else {
+ newItem->mimeType = KMimeType::findByURL( filePathName.lower() )->name();
+ }
+ // check whether the mime type has a decoder registered
+ if( newItem->mimeType == "" ) {
+ newItem->mimeType = newItem->fileFormat;
+ }
+ if( !config->acceptFile( newItem->mimeType ) || ( newItem->fileFormat == "wav" && newItem->options.encodingOptions.sFormat == "wav" ) ) {
+ delete newItem;
+ continue;
+ }
+ newItem->options.filePathName = filePathName;
+ newItem->tags = 0;
+ newItem->time = 210; // NOTE we can't neither get the length nor guess it without accessing the file
+ // TODO get the file size and guess the length
+ }
+
+ updateItem( newItem );
+ emit increaseTime( newItem->time );
+ }
+ emit fileCountChanged( childCount() );
+}
+
+void FileList::addDir( const QString& directory, const QStringList& filter, bool recursive )
+{
+ pScanStatus->setProgress( 0 );
+ pScanStatus->setTotalSteps( 0 );
+ pScanStatus->show(); // show the status while scanning the directories
+ kapp->processEvents();
+
+ int count = listDir( directory, filter, recursive, true );
+ listDir( directory, filter, recursive );
+
+ pScanStatus->hide(); // hide the status bar, when the scan is done
+}
+
+void FileList::addTracks( const QString& device, QValueList<int> trackList )
+{
+ for( QValueList<int>::Iterator it = trackList.begin(); it != trackList.end(); ++it ) {
+// logger->log( 1000, i18n("Adding track") + QString().sprintf(" %02i",*it) );
+ FileListItem* newItem = new FileListItem( this, lastItem() );
+ newItem->options = options->getCurrentOptions(); // FIXME speed up
+// if( newItem->options.outputOptions.mode != OutputDirectory::Specify ) newItem->options.outputOptions.mode = OutputDirectory::MetaData;
+ newItem->notify = notify;
+ newItem->track = (*it);
+ newItem->fileName = i18n("Audio CD (%1)").arg(device) + ": " + i18n("Track") + QString().sprintf(" %02i",newItem->track);
+ newItem->mimeType = "application/x-cda";
+ newItem->fileFormat = "cda";
+ newItem->local = true;
+ newItem->device = device;
+ newItem->tags = cdManager->getTags( device, newItem->track );
+ if( newItem->tags == 0 ) { // NOTE shouldn't happen
+// logger->log( 1000, " " + i18n("Reading tags failed") );
+ newItem->time = 210;
+ newItem->options.filePathName = QDir::homeDirPath() + "/" + i18n("Track") + QString().sprintf(" %02i",newItem->track) + "." + newItem->fileFormat;
+ }
+ else {
+// logger->log( 1000, " " + i18n("Tags successfully read") );
+ newItem->time = newItem->tags->length;
+ newItem->options.filePathName = QDir::homeDirPath() + "/" + QString().sprintf("%02i - ",newItem->track) + newItem->tags->title + "." + newItem->fileFormat;
+ newItem->fileName = i18n("Audio CD (%1)").arg(device) + ": " + QString().sprintf("%02i - ",newItem->track) + newItem->tags->title;
+ }
+ updateItem( newItem );
+ emit increaseTime( newItem->time );
+ }
+ emit fileCountChanged( childCount() );
+}
+
+void FileList::addDisc( const QString& device )
+{
+// logger->log( 1000, i18n("Adding full audio CD (%1)").arg(device) );
+ FileListItem* newItem = new FileListItem( this, lastItem() );
+ newItem->options = options->getCurrentOptions();
+// if( newItem->options.outputOptions.mode != OutputDirectory::Specify ) newItem->options.outputOptions.mode = OutputDirectory::MetaData;
+ newItem->notify = notify;
+ newItem->track = 0;
+ newItem->fileName = i18n("Full audio CD (%1)").arg(device);
+ newItem->mimeType = "application/x-cda";
+ newItem->fileFormat = "cda";
+ newItem->local = true;
+ newItem->device = device;
+ newItem->tags = cdManager->getTags( device, 0 );
+ if( newItem->tags == 0 ) { // NOTE shouldn't happen
+// logger->log( 1000, " " + i18n("Reading tags failed") );
+ newItem->time = 3600;
+ newItem->options.filePathName = QDir::homeDirPath() + "/" + i18n("Audio CD") + "." + newItem->fileFormat;
+ }
+ else {
+// logger->log( 1000, " " + i18n("Tags successfully read") );
+ newItem->time = newItem->tags->length;
+ newItem->options.filePathName = QDir::homeDirPath() + newItem->tags->title + "." + newItem->fileFormat;
+ newItem->fileName = i18n("Full audio CD (%1)").arg(device) + ": " + newItem->tags->title;
+ }
+ updateItem( newItem );
+ emit increaseTime( newItem->time );
+ emit fileCountChanged( childCount() );
+}
+
+void FileList::itemFinished( FileListItem* item, int state )
+{
+ if( state == 0 ) {
+ if( item ) delete item;
+ itemsSelected();
+ }
+ else if( state == 1 ) {
+ item->setText( columnByName(i18n("State")), i18n("Stopped") );
+ }
+ else {
+ item->setText( columnByName(i18n("State")), i18n("Failed") );
+ }
+
+ save( true );
+
+ FileListItem* it = firstChild();
+ int waitingCount = 0, convertingCount = 0;
+
+ while( it != 0 ) {
+ if( it->text(columnByName(i18n("State"))) != i18n("Failed") && it->text(columnByName(i18n("State"))) != i18n("Stopped") && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) {
+ if( it->text(columnByName(i18n("State"))) == i18n("Waiting") /*|| it->text(columnByName(i18n("State"))) == i18n("Stopped")*/ ) {
+ waitingCount++;
+ }
+ else {
+ convertingCount++;
+ }
+ }
+ it = it->nextSibling();
+ }
+
+ if( waitingCount > 0 && queue ) {
+ convertNextItem();
+ }
+ else if( convertingCount == 0 ) {
+ queue = false;
+ float time = 0;
+ it = firstChild();
+ while( it != 0 ) {
+// it->setText( columnByName(i18n("State")), i18n("Waiting") );
+ updateItem( it );
+ time += it->time;
+ it = it->nextSibling();
+ }
+ emit finished( time );
+ emit stoppedConversion();
+ emit fileCountChanged( childCount() );
+ }
+}
+
+void FileList::rippingFinished( const QString& device )
+{
+ if( !queue ) return;
+
+ int count = 0;
+ FileListItem *item = firstChild();
+ while( item != 0 ) {
+ if( item->converting ) {
+ count++;
+ }
+ item = item->nextSibling();
+ }
+
+ // look for "Waiting" files first ...
+ item = firstChild();
+ while( item != 0 && count < config->data.general.numFiles ) {
+ if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Waiting") ) {
+ if( item->track >= 0 && item->device == device ) {
+ convertItem( item );
+ itemsSelected();
+ return;
+ }
+ }
+ item = item->nextSibling();
+ }
+
+ // ... then convert the stopped, too
+/* item = firstChild();
+ while( item != 0 && count < config->data.general.numFiles ) {
+ if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Stopped") ) {
+ if( item->track >= 0 && item->device == device ) {
+ convertItem( item );
+ itemsSelected();
+ return;
+ }
+ }
+ item = item->nextSibling();
+ }*/
+}
+
+void FileList::updateItem( FileListItem* item )
+{
+ if( !item ) return;
+
+ if( !item->converting ) {
+ if( config->data.general.conflictHandling == 1 && QFile::exists(KURL::decode_string(OutputDirectory::calcPath(item,config))) ) { // was: .replace("%2f","%252f")
+ item->setText( columnByName(i18n("State")), i18n("Will be skipped") );
+ }
+ else {
+ item->setText( columnByName(i18n("State")), i18n("Waiting") );
+ }
+ }
+ else {
+ item->setText( columnByName(i18n("State")), i18n("Converting") );
+ }
+
+ if( item->track >= 0 ) item->setText( columnByName(i18n("Input")), KURL::decode_string(item->fileName).replace("%2f","/").replace("%%","%") );
+ else item->setText( columnByName(i18n("Input")), KURL::decode_string(item->options.filePathName).replace("%2f","/").replace("%%","%") );
+
+ item->setText( columnByName(i18n("Output")), KURL::decode_string(OutputDirectory::uniqueFileName(OutputDirectory::calcPath(item,config))).replace("%2f","/").replace("%%","%") );
+
+ item->setText( columnByName(i18n("Quality")), config->getProfileName(item->options) );
+}
+
+void FileList::showOptionsEditorDialog()
+{
+ // FIXME options are set to defaults
+
+ if( optionsEditor == 0 ) {
+ optionsEditor = new OptionsEditor( tagEngine, config, this, 0, "optionsEditor" );
+ if( optionsEditor == 0 ) {
+ // TODO error message
+ return;
+ }
+// }
+ connect( this, SIGNAL(editItems(QValueList<FileListItem*>)),
+ optionsEditor, SLOT(itemsSelected(QValueList<FileListItem*>))
+ );
+ connect( this, SIGNAL(setPreviousItemEnabled(bool)),
+ optionsEditor, SLOT(setPreviousEnabled(bool))
+ );
+ connect( this, SIGNAL(setNextItemEnabled(bool)),
+ optionsEditor, SLOT(setNextEnabled(bool))
+ );
+ connect( optionsEditor, SIGNAL(user2Clicked()),
+ this, SLOT(selectPreviousItem())
+ );
+ connect( optionsEditor, SIGNAL(user1Clicked()),
+ this, SLOT(selectNextItem())
+ );
+ /*connect( this, SIGNAL(moveEditor(int,int)),
+ optionsEditor, SLOT(moveWindow(int,int))
+ );*/
+}
+ itemsSelected();
+ optionsEditor->show();
+}
+
+// FIXME still makes some troubles (wreaks some items) and crashes
+void FileList::selectPreviousItem()
+{
+ if( selectedFiles.first() == 0 ) return;
+ FileListItem* item = selectedFiles.first()->itemAbove();
+ if( item != 0 ) {
+ item->setSelected( true );
+ repaintItem( item );
+ ensureItemVisible( item );
+ }
+
+ for( QValueList<FileListItem*>::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ) {
+ (*it)->setSelected( false );
+ repaintItem( *it );
+ }
+
+ itemsSelected();
+}
+
+void FileList::selectNextItem()
+{
+ if( selectedFiles.last() == 0 ) return;
+ FileListItem* item = selectedFiles.last()->itemBelow();
+ if( item != 0 ) {
+ item->setSelected( true );
+ repaintItem( item );
+ ensureItemVisible( item );
+ }
+
+ for( QValueList<FileListItem*>::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ) {
+ (*it)->setSelected( false );
+ repaintItem( *it );
+ }
+
+ itemsSelected();
+}
+
+void FileList::itemsSelected()
+{
+ selectedFiles.clear();
+ for( FileListItem *item = firstChild(); item != NULL; item = item->nextSibling() ) {
+ if( item->isSelected() ) {
+ selectedFiles.append( item );
+ }
+ }
+
+ if( selectedFiles.count() > 0 ) {
+ if( selectedFiles.first()->itemAbove() != 0 ) emit setPreviousItemEnabled( true );
+ else emit setPreviousItemEnabled( false );
+ if( selectedFiles.last()->itemBelow() != 0 ) emit setNextItemEnabled( true );
+ else emit setNextItemEnabled( false );
+ }
+ else {
+ emit setPreviousItemEnabled( false );
+ emit setNextItemEnabled( false );
+ }
+
+ emit editItems( selectedFiles );
+}
+
+/*void FileList::moveOptionsEditor( int x, int y )
+{
+ emit moveEditor( x, y );
+}*/
+
+void FileList::startConversion()
+{
+ // iterate through all items and set the state to "Waiting"
+ FileListItem* it = firstChild();
+ while( it != 0 ) {
+// it->setText( columnByName(i18n("State")), i18n("Waiting") );
+ if( !it->converting && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) {
+ it->setText( columnByName(i18n("State")), i18n("Waiting") );
+ }
+ it = it->nextSibling();
+ }
+ queue = true;
+ emit startedConversion();
+ convertNextItem();
+}
+
+void FileList::stopConversion()
+{
+ queue = false;
+ emit stopClicked();
+}
+
+void FileList::continueConversion()
+{
+ queue = true;
+ emit continueClicked();
+}
+
+void FileList::killConversion()
+{
+ queue = false;
+
+ FileListItem *item = firstChild();
+
+ while( item != 0 ) {
+ if( item->converting ) {
+ emit stopItem( item );
+ }
+ item = item->nextSibling();
+ }
+}
+
+void FileList::convertNextItem()
+{
+ if( !queue ) return;
+
+ QStringList devices;
+
+ // look for tracks that are being ripped
+ int count = 0;
+ FileListItem *item = firstChild();
+ while( item != 0 ) {
+ if( item->converting ) {
+ count++;
+ if( item->ripping ) {
+ devices += item->device;
+ }
+ }
+ item = item->nextSibling();
+ }
+
+ // look for "Waiting" files first ...
+ item = firstChild();
+ while( item != 0 && count < config->data.general.numFiles ) {
+ if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Waiting") ) {
+ if( item->track >= 0 && devices.findIndex(item->device) == -1 ) {
+ convertItem( item );
+ count++;
+ devices += item->device;
+ }
+ else if( item->track < 0 ) {
+ convertItem( item );
+ count++;
+ }
+ }
+ item = item->nextSibling();
+ }
+
+ // ... then convert the stopped, too
+// item = firstChild();
+// while( item != 0 && count < config->data.general.numFiles ) {
+// if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Stopped") ) {
+// if( item->track >= 0 && devices.findIndex(item->device) == -1 ) {
+// convertItem( item );
+// count++;
+// devices += item->device;
+// }
+// else if( item->track < 0 ) {
+// convertItem( item );
+// count++;
+// }
+// }
+// item = item->nextSibling();
+// }
+
+ itemsSelected();
+
+ FileListItem* it = firstChild();
+ int waitingCount = 0, convertingCount = 0;
+
+ while( it != 0 ) {
+ if( it->text(columnByName(i18n("State"))) != i18n("Failed") && it->text(columnByName(i18n("State"))) != i18n("Stopped") && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) {
+ if( it->text(columnByName(i18n("State"))) == i18n("Waiting") /*|| it->text(columnByName(i18n("State"))) == i18n("Stopped")*/ ) {
+ waitingCount++;
+ }
+ else {
+ convertingCount++;
+ }
+ }
+ it = it->nextSibling();
+ }
+
+ if( waitingCount == 0 && convertingCount == 0 ) itemFinished( 0, 0 );
+}
+
+void FileList::load( bool autosave )
+{
+ // NOTE clear the file list befor adding the saved items?
+
+ int version;
+ QString name;
+ FileListItem* lastListItem = lastItem();
+ QString filename;
+ if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml");
+ else filename = locateLocal("data","soundkonverter/filelist.xml");
+
+ QDomDocument domTree;
+ QFile opmlFile( filename );
+ if( !opmlFile.open( IO_ReadOnly ) ) return;
+ if( !domTree.setContent( &opmlFile ) ) return;
+ opmlFile.close();
+
+ QDomElement root = domTree.documentElement();
+ if( root.attribute("type") != "filelist" ) return;
+ QDomNode node, sub1Node, sub2Node;
+ node = root.firstChild();
+
+ while( !node.isNull() ) {
+ if( node.isElement() && node.nodeName() == "info" ) {
+
+ version = node.toElement().attribute("version").toInt();
+
+ }
+ else if( node.isElement() && node.nodeName() == "file" ) {
+
+ FileListItem* item = new FileListItem( this, lastListItem );
+ lastListItem = item;
+
+ item->fileName = node.toElement().attribute("fileName");
+ item->mimeType = node.toElement().attribute("mimeType");
+ item->fileFormat = node.toElement().attribute("fileFormat");
+ item->local = node.toElement().attribute("local").toInt();
+ item->track = node.toElement().attribute("track").toInt();
+ item->time = node.toElement().attribute("time").toInt();
+
+ item->options.filePathName = node.toElement().attribute("filePathName");
+ item->options.outputFilePathName = node.toElement().attribute("outputFilePathName");
+
+ sub1Node = node.toElement().firstChild();
+ while( !sub1Node.isNull() ) {
+ if( sub1Node.isElement() && sub1Node.nodeName() == "encodingOptions" ) {
+
+ item->options.encodingOptions.sFormat = sub1Node.toElement().attribute("sFormat");
+ item->options.encodingOptions.sQualityMode = sub1Node.toElement().attribute("sQualityMode");
+ item->options.encodingOptions.iQuality = sub1Node.toElement().attribute("iQuality").toInt();
+ item->options.encodingOptions.sBitrateMode = sub1Node.toElement().attribute("sBitrateMode");
+ item->options.encodingOptions.bBitrateRange = sub1Node.toElement().attribute("bBitrateRange").toInt();
+ item->options.encodingOptions.iMinBitrate = sub1Node.toElement().attribute("iMinBitrate").toInt();
+ item->options.encodingOptions.iMaxBitrate = sub1Node.toElement().attribute("iMaxBitrate").toInt();
+ item->options.encodingOptions.sInOutFiles = sub1Node.toElement().attribute("sInOutFiles");
+
+ sub2Node = sub1Node.toElement().firstChild();
+ while( !sub2Node.isNull() ) {
+ if( sub2Node.isElement() && sub2Node.nodeName() == "samplingRate" ) {
+
+ item->options.encodingOptions.samplingRate.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt();
+ item->options.encodingOptions.samplingRate.iSamplingRate = sub2Node.toElement().attribute("iSamplingRate").toInt();
+
+ }
+ else if( sub2Node.isElement() && sub2Node.nodeName() == "channels" ) {
+
+ item->options.encodingOptions.channels.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt();
+ item->options.encodingOptions.channels.sChannels = sub2Node.toElement().attribute("sChannels");
+
+ }
+ else if( sub2Node.isElement() && sub2Node.nodeName() == "replaygain" ) {
+
+ item->options.encodingOptions.replaygain.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt();
+
+ }
+ sub2Node = sub2Node.nextSibling();
+ }
+
+ }
+ else if( sub1Node.isElement() && sub1Node.nodeName() == "outputOptions" ) {
+
+ item->options.outputOptions.mode = (OutputDirectory::Mode)sub1Node.toElement().attribute("mode").toInt();
+ item->options.outputOptions.directory = sub1Node.toElement().attribute("directory");
+
+ }
+ else if( sub1Node.isElement() && sub1Node.nodeName() == "tags" ) {
+
+ item->tags = new TagData();
+
+ item->tags->artist = sub1Node.toElement().attribute("artist");
+ item->tags->composer = sub1Node.toElement().attribute("composer");
+ item->tags->album = sub1Node.toElement().attribute("album");
+ item->tags->title = sub1Node.toElement().attribute("title");
+ item->tags->genre = sub1Node.toElement().attribute("genre");
+ item->tags->comment = sub1Node.toElement().attribute("comment");
+ item->tags->track = sub1Node.toElement().attribute("track").toInt();
+ item->tags->disc = sub1Node.toElement().attribute("disc").toInt();
+ item->tags->year = sub1Node.toElement().attribute("year").toInt();
+ item->tags->track_gain = sub1Node.toElement().attribute("track_gain").toFloat();
+ item->tags->album_gain = sub1Node.toElement().attribute("album_gain").toFloat();
+ item->tags->length = sub1Node.toElement().attribute("length").toInt();
+ item->tags->fileSize = sub1Node.toElement().attribute("fileSize").toInt();
+ item->tags->bitrate = sub1Node.toElement().attribute("bitrate").toInt();
+ item->tags->samplingRate = sub1Node.toElement().attribute("samplingRate").toInt();
+
+ }
+ sub1Node = sub1Node.nextSibling();
+ }
+ updateItem( item );
+ emit increaseTime( item->time );
+ }
+ node = node.nextSibling();
+ }
+ emit fileCountChanged( childCount() );
+}
+
+void FileList::save( bool autosave )
+{
+ // NOTE filenames should be encoded before saving - but it works fine without it (hm...)
+
+ QTime time;
+ time.start();
+
+ QDomDocument domTree;
+ QDomElement root = domTree.createElement( "soundkonverter" );
+ root.setAttribute( "type", "filelist" );
+ domTree.appendChild( root );
+
+ QDomElement info = domTree.createElement( "info" );
+ info.setAttribute( "version", "300" );
+ root.appendChild( info );
+
+ for( FileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) {
+ QDomElement file = domTree.createElement( "file" );
+ file.setAttribute( "fileName", item->fileName );
+ file.setAttribute( "mimeType", item->mimeType );
+ file.setAttribute( "fileFormat", item->fileFormat );
+ file.setAttribute( "local", item->local );
+ file.setAttribute( "track", item->track );
+ file.setAttribute( "device", item->device );
+ file.setAttribute( "time", item->time );
+
+ file.setAttribute( "filePathName", item->options.filePathName );
+ file.setAttribute( "outputFilePathName", item->options.outputFilePathName );
+
+ QDomElement encodingOptions = domTree.createElement( "encodingOptions" );
+
+ encodingOptions.setAttribute( "sFormat", item->options.encodingOptions.sFormat );
+ encodingOptions.setAttribute( "sQualityMode", item->options.encodingOptions.sQualityMode );
+ encodingOptions.setAttribute( "iQuality", item->options.encodingOptions.iQuality );
+ encodingOptions.setAttribute( "sBitrateMode", item->options.encodingOptions.sBitrateMode );
+ encodingOptions.setAttribute( "bBitrateRange", item->options.encodingOptions.bBitrateRange );
+ encodingOptions.setAttribute( "iMinBitrate", item->options.encodingOptions.iMinBitrate );
+ encodingOptions.setAttribute( "iMaxBitrate", item->options.encodingOptions.iMaxBitrate );
+
+ QDomElement samplingRate = domTree.createElement( "samplingRate" );
+
+ samplingRate.setAttribute( "bEnabled", item->options.encodingOptions.samplingRate.bEnabled );
+ samplingRate.setAttribute( "iSamplingRate", item->options.encodingOptions.samplingRate.iSamplingRate );
+
+ encodingOptions.appendChild( samplingRate );
+
+ QDomElement channels = domTree.createElement( "channels" );
+
+ channels.setAttribute( "bEnabled", item->options.encodingOptions.channels.bEnabled );
+ channels.setAttribute( "sChannels", item->options.encodingOptions.channels.sChannels );
+
+ encodingOptions.appendChild( channels );
+
+ QDomElement replaygain = domTree.createElement( "replaygain" );
+
+ replaygain.setAttribute( "bEnabled", item->options.encodingOptions.replaygain.bEnabled );
+
+ encodingOptions.appendChild( replaygain );
+
+ encodingOptions.setAttribute( "sInOutFiles", item->options.encodingOptions.sInOutFiles );
+
+ file.appendChild( encodingOptions );
+
+ QDomElement outputOptions = domTree.createElement( "outputOptions" );
+
+ outputOptions.setAttribute( "mode", int(item->options.outputOptions.mode) );
+ outputOptions.setAttribute( "directory", item->options.outputOptions.directory );
+
+ file.appendChild( outputOptions );
+
+ if( item->tags )
+ {
+ QDomElement tags = domTree.createElement( "tags" );
+
+ tags.setAttribute( "artist", item->tags->artist );
+ tags.setAttribute( "composer", item->tags->composer );
+ tags.setAttribute( "album", item->tags->album );
+ tags.setAttribute( "title", item->tags->title );
+ tags.setAttribute( "genre", item->tags->genre );
+ tags.setAttribute( "comment", item->tags->comment );
+ tags.setAttribute( "track", item->tags->track );
+ tags.setAttribute( "disc", item->tags->disc );
+ tags.setAttribute( "year", item->tags->year );
+ tags.setAttribute( "track_gain", item->tags->track_gain );
+ tags.setAttribute( "album_gain", item->tags->album_gain );
+ tags.setAttribute( "length", item->tags->length );
+ tags.setAttribute( "fileSize", item->tags->fileSize );
+ tags.setAttribute( "bitrate", item->tags->bitrate );
+ tags.setAttribute( "samplingRate", item->tags->samplingRate );
+
+ file.appendChild( tags );
+ }
+
+ root.appendChild( file );
+ }
+
+ QString filename;
+ if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml");
+ else filename = locateLocal("data","soundkonverter/filelist.xml");
+
+ QFile opmlFile( filename );
+ if( !opmlFile.open( IO_WriteOnly ) ) return;
+
+ QTextStream ts( &opmlFile );
+ ts << domTree.toString();
+
+ opmlFile.close();
+
+ logger->log( 1000, "save file list: " + QString::number(time.elapsed()) );
+}
+
+void FileList::debug() // NOTE DEBUG
+{
+ logger->log( 1000, "DEBUG begin" );
+
+ ConversionOptions conversionOptions;
+
+ QStringList formats = config->allEncodableFormats();
+
+ for( QStringList::Iterator a = formats.begin(); a != formats.end(); ++a )
+ {
+ logger->log( 1000, "format: " + (*a) );
+ FormatItem* formatItem = config->getFormatItem( *a );
+ if( formatItem == 0 ) continue;
+
+ for( QValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
+ logger->log( 1000, " encoder: " + (*b)->enc.bin );
+ formatItem->encoder = (*b);
+ if( (*b)->enc.strength.enabled ) {
+ formatItem->compressionLevel = (*b)->enc.strength.default_value;
+ }
+ if( (*b)->enc.replaygain.enabled ) {
+ formatItem->internalReplayGain = true;
+ }
+
+ if( (*b)->enc.lossless.enabled ) {
+ options->setProfile( "Lossless" );
+ options->setFormat( *a );
+ options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" );
+ conversionOptions = options->getCurrentOptions();
+ conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem );
+ options->setCurrentOptions( conversionOptions );
+ addFiles( "/home/daniel/soundKonverter/test.mp3" );
+ }
+ if( (*b)->enc.lossy.enabled ) {
+ options->setProfile( "Medium" );
+ if( (*b)->enc.lossy.bitrate.cbr.enabled ) {
+ options->setFormat( *a );
+ conversionOptions = options->getCurrentOptions();
+ conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate");
+ conversionOptions.encodingOptions.sBitrateMode = "cbr";
+ conversionOptions.encodingOptions.iQuality = 128;
+ conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem );
+ options->setCurrentOptions( conversionOptions );
+ options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" );
+ addFiles( "/home/daniel/soundKonverter/test.mp3" );
+ }
+ if( (*b)->enc.lossy.bitrate.abr.enabled ) {
+ options->setFormat( *a );
+ conversionOptions = options->getCurrentOptions();
+ conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate");
+ conversionOptions.encodingOptions.sBitrateMode = "abr";
+ conversionOptions.encodingOptions.iQuality = 128;
+ conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem );
+ options->setCurrentOptions( conversionOptions );
+ options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" );
+ addFiles( "/home/daniel/soundKonverter/test.mp3" );
+ if( (*b)->enc.lossy.bitrate.abr.bitrate_range.enabled ) {
+ options->setFormat( *a );
+ conversionOptions = options->getCurrentOptions();
+ conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate");
+ conversionOptions.encodingOptions.sBitrateMode = "abr";
+ conversionOptions.encodingOptions.iQuality = 128;
+ conversionOptions.encodingOptions.bBitrateRange = true;
+ conversionOptions.encodingOptions.iMinBitrate = 64;
+ conversionOptions.encodingOptions.iMaxBitrate = 192;
+ conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem );
+ options->setCurrentOptions( conversionOptions );
+ options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" );
+ addFiles( "/home/daniel/soundKonverter/test.mp3" );
+ }
+ }
+ if( (*b)->enc.lossy.quality.enabled ) {
+ options->setFormat( *a );
+ conversionOptions = options->getCurrentOptions();
+ conversionOptions.encodingOptions.sQualityMode = i18n("Quality");
+ conversionOptions.encodingOptions.iQuality = 40;
+ conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem );
+ options->setCurrentOptions( conversionOptions );
+ options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" );
+ addFiles( "/home/daniel/soundKonverter/test.mp3" );
+ }
+ }
+ }
+
+ for( QValueList<ConvertPlugin*>::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) {
+ formatItem->decoder = (*b);
+ }
+
+ for( QValueList<ReplayGainPlugin*>::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) {
+ formatItem->replaygain = (*b);
+ }
+ }
+
+ logger->log( 1000, "DEBUG end" );
+}
+
+QString FileList::debug_params( ConversionOptions conversionOptions, FormatItem* formatItem ) // NOTE DEBUG
+{
+ ConvertPlugin* plugin = formatItem->encoder;
+
+ QString sStrength;
+ QString sBitrate;
+ QString sQuality;
+ QString sMinBitrate;
+ QString sMaxBitrate;
+ QString sSamplingRate;
+
+ int t_int;
+ float t_float;
+
+ QString 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 = QString::number( compressionLevel );
+ else
+ sStrength = QString::number( plugin->enc.strength.range_min - compressionLevel );
+ }
+ else {
+ if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min )
+ sStrength = QString::number( int(compressionLevel) );
+ else
+ sStrength = QString::number( int(plugin->enc.strength.range_min - compressionLevel) );
+ }
+ if( plugin->enc.strength.separator != '.' ) sStrength.replace( QChar('.'), plugin->enc.strength.separator );
+ }
+ else {
+ QStringList::Iterator it = plugin->enc.strength.profiles.at( compressionLevel );
+ sStrength = *it;
+ }
+ }
+
+ if( conversionOptions.encodingOptions.sQualityMode == i18n("Bitrate") ) {
+ if( conversionOptions.encodingOptions.sBitrateMode == "cbr" && plugin->enc.lossy.bitrate.cbr.enabled ) {
+ param.append( " " + plugin->enc.lossy.bitrate.cbr.param );
+ sBitrate = QString::number( conversionOptions.encodingOptions.iQuality );
+ }
+ else if( conversionOptions.encodingOptions.sBitrateMode == "abr" && plugin->enc.lossy.bitrate.abr.enabled ) {
+ param.append( " " + plugin->enc.lossy.bitrate.abr.param );
+ sBitrate = QString::number( conversionOptions.encodingOptions.iQuality );
+ if( conversionOptions.encodingOptions.bBitrateRange && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) {
+ param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_min );
+ sMinBitrate = QString::number( conversionOptions.encodingOptions.iMinBitrate );
+ param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max );
+ sMaxBitrate = QString::number( conversionOptions.encodingOptions.iMaxBitrate );
+ }
+ }
+ }
+ else if( conversionOptions.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)conversionOptions.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)conversionOptions.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 = QString().sprintf( "%.2f", t_float );
+ sQuality = QString::number( t_float );
+ }
+ else {
+ if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min)
+ t_int = ( conversionOptions.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 - conversionOptions.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 = QString::number( t_int );
+ }
+ if( plugin->enc.bin == "oggenc" ) sQuality.replace(QChar('.'),KGlobal::locale()->decimalSymbol());
+ else if( plugin->enc.lossy.quality.separator != '.' ) sQuality.replace(QChar('.'),plugin->enc.lossy.quality.separator);
+ }
+ else {
+ QStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( int(conversionOptions.encodingOptions.iQuality*plugin->enc.lossy.quality.range_max/100) );
+ sQuality = *it;
+ }
+ }
+ else if( conversionOptions.encodingOptions.sQualityMode == i18n("Lossless") && plugin->enc.lossless.enabled ) {
+ param.append( " " + plugin->enc.lossless.param );
+ }
+ else if( conversionOptions.encodingOptions.sQualityMode == i18n("Hybrid") && plugin->enc.hybrid.enabled ) {
+ param.append( " " + plugin->enc.hybrid.param );
+ sBitrate = QString::number( conversionOptions.encodingOptions.iQuality );
+ }
+
+ if( conversionOptions.encodingOptions.samplingRate.bEnabled && plugin->enc.lossy.samplingrate.enabled ) {
+ param.append( " " + plugin->enc.lossy.samplingrate.param );
+ if( plugin->enc.lossy.samplingrate.unit == PluginLoaderBase::Hz ) {
+ sSamplingRate = QString::number( conversionOptions.encodingOptions.samplingRate.iSamplingRate );
+ }
+ else {
+ sSamplingRate = QString::number( (float)conversionOptions.encodingOptions.samplingRate.iSamplingRate/1000 );
+ }
+ }
+
+ if( conversionOptions.encodingOptions.channels.bEnabled ) {
+ if( conversionOptions.encodingOptions.channels.sChannels == i18n("Mono") && plugin->enc.lossy.channels.mono_enabled ) {
+ param.append( " " + plugin->enc.lossy.channels.mono_param );
+ }
+ else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Stereo") && plugin->enc.lossy.channels.stereo_enabled ) {
+ param.append( " " + plugin->enc.lossy.channels.stereo_param );
+ }
+ else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Joint-Stereo") && plugin->enc.lossy.channels.joint_stereo_enabled ) {
+ param.append( " " + plugin->enc.lossy.channels.joint_stereo_param );
+ }
+ else if( conversionOptions.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( conversionOptions.encodingOptions.channels.sChannels == i18n("Dual Channels") && plugin->enc.lossy.channels.dual_channels_enabled ) {
+ param.append( " " + plugin->enc.lossy.channels.dual_channels_param );
+ }
+ }
+
+ if( conversionOptions.encodingOptions.replaygain.bEnabled && plugin->enc.replaygain.enabled && plugin->enc.replaygain.use && formatItem->internalReplayGain ) {
+ param.append( " " + plugin->enc.replaygain.use );
+ }
+ else if( plugin->enc.replaygain.enabled && plugin->enc.replaygain.avoid ) {
+ param.append( " " + plugin->enc.replaygain.avoid );
+ }
+
+// if( !tagEngine->canWrite(conversionOptions.encodingOptions.sFormat) && item->fileListItem->tags && plugin->enc.tag.enabled ) {
+ if( plugin->enc.tag.enabled && conversionOptions.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() ) param.append( " " + plugin->enc.tag.artist );
+ if( !plugin->enc.tag.album.isEmpty() ) param.append( " " + plugin->enc.tag.album );
+ if( !plugin->enc.tag.comment.isEmpty() ) param.append( " " + plugin->enc.tag.comment );
+ if( !plugin->enc.tag.disc.isEmpty() ) param.append( " " + plugin->enc.tag.disc );
+ if( !plugin->enc.tag.genre.isEmpty() ) param.append( " " + plugin->enc.tag.genre );
+ if( !plugin->enc.tag.track.isEmpty() ) param.append( " " + plugin->enc.tag.track );
+ if( !plugin->enc.tag.composer.isEmpty() ) param.append( " " + plugin->enc.tag.composer );
+ if( !plugin->enc.tag.title.isEmpty() ) param.append( " " + plugin->enc.tag.title );
+ if( !plugin->enc.tag.year.isEmpty() ) param.append( " " + plugin->enc.tag.year );
+ }
+
+ param.replace( "%c", sStrength );
+ param.replace( "%b", sBitrate );
+ param.replace( "%q", sQuality );
+ param.replace( "%m", sMinBitrate );
+ param.replace( "%M", sMaxBitrate );
+ param.replace( "%s", sSamplingRate );
+
+ return conversionOptions.encodingOptions.sInOutFiles.replace( "%p", param );
+}