#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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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( TQPainter *p, const TQColorGroup &cg, int column, int width, int alignment ) { // NOTE speed up this function // NOTE calculate the red color TQColorGroup _cg( cg ); TQColor 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(); TQRect textRect = p->boundingRect( margin, 0, w, h, alignment, text(column) ); if( textRect.width() > w ) { alignment = TQt::AlignRight | TQt::SingleLine; } /*if ( textRect.width() <= w ) { p->drawText( margin, 0, w, h, alignment | TQt::SingleLine | TQt::ExpandTabs, text(column), -1 ); } else { textRect = p->boundingRect( margin, 0, w, h, TQt::AlignLeft, "... " ); p->drawText( margin, 0, textRect.width(), h, TQt::AlignLeft | TQt::SingleLine | TQt::ExpandTabs, "...", -1 ); p->drawText( margin+textRect.width(), 0, w-textRect.width(), h, TQt::AlignRight | TQt::SingleLine | TQt::ExpandTabs, text(column), -1 ); }*/ } if( isSelected() && converting ) { _cg.setColor( TQColorGroup::Highlight, TQColor( 215, 62, 62 ) ); TQListViewItem::paintCell( p, _cg, column, width, alignment ); return; } else if( converting && column != listView()->sortColumn() ) { _cg.setColor( TQColorGroup::Base, TQColor( 255, 234, 234 ) ); TQListViewItem::paintCell( p, _cg, column, width, alignment ); return; } else if( converting && column == listView()->sortColumn() ) { _cg.setColor( TQColorGroup::Base, TQColor( 247, 227, 227 ) ); TQListViewItem::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, TQWidget* 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( TQListView::Extended ); setAllColumnsShowFocus( true ); setResizeMode( LastColumn ); setSorting( -1 ); // NOTE if commented out, items aren't moveable anymore setMinimumHeight( 200 ); TQGridLayout* grid = new TQGridLayout( 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( TQT_TQOBJECT(this), TQT_SIGNAL(contextMenuRequested( TQListViewItem*, const TQPoint&, int )), TQT_TQOBJECT(this), TQT_SLOT(showContextMenu( TQListViewItem*, const TQPoint&, 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, TQT_TQOBJECT(this), TQT_SLOT(showOptionsEditorDialog()), actionCollection, "edit_options" ); start = new KAction( i18n("Start conversion"), "run", 0, TQT_TQOBJECT(this), TQT_SLOT(convertSelectedItems()), actionCollection, "start_conversion" ); stop = new KAction( i18n("Stop conversion"), "stop", 0, TQT_TQOBJECT(this), TQT_SLOT(stopSelectedItems()), actionCollection, "stop_conversion" ); remove = new KAction( i18n("Remove"), "edittrash", Key_Delete, TQT_TQOBJECT(this), TQT_SLOT(removeSelectedItems()), actionCollection, "remove" ); paste = new KAction( i18n("Paste"), "editpaste", 0, TQT_TQOBJECT(this), 0, actionCollection, "paste" ); // TODO paste connect( TQT_TQOBJECT(this), TQT_SIGNAL(selectionChanged()), TQT_TQOBJECT(this), TQT_SLOT(itemsSelected()) ); // connect( TQT_TQOBJECT(this), TQT_SIGNAL(clicked(TQListViewItem*,const TQPoint&,int)), // TQT_TQOBJECT(this), TQT_SLOT(clickedSomewhere(TQListViewItem*,const TQPoint&,int)) // ); bubble = new TQSimpleRichText( i18n( "
" "

File List

" "Select your desired output options in the form above and add some files.
" "You can add files by clicking on \"Add files ...\" or dropping them here." // "
Learn more about audio compression ..." "
" ), TQApplication::font() ); connect( header(), TQT_SIGNAL(sizeChange( int, int, int )), TQT_SLOT(columnResizeEvent( int, int, int )) ); connect( TQT_TQOBJECT(this), TQT_SIGNAL( dropped(TQDropEvent*, TQListViewItem*, TQListViewItem*) ), TQT_SLOT( slotDropped(TQDropEvent*, TQListViewItem*, TQListViewItem*) ) ); // if( TQFile::exists(locateLocal("data","soundkonverter/filelist.autosave.xml")) ) load( true ); // debug(); // NOTE DEBUG } FileList::~FileList() { delete optionsEditor; } int FileList::columnByName( const TQString& name ) { for( int i = 0; i < columns(); ++i ) { if( columnText( i ) == name ) return i; } return -1; } void FileList::viewportPaintEvent( TQPaintEvent* e ) { KListView::viewportPaintEvent( e ); // the bubble help if( childCount() == 0 ) { TQPainter 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, TQRect(), colorGroup() ); } } void FileList::viewportResizeEvent( TQResizeEvent* ) { // 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( TQListViewItem*, const TQPoint& pos, int ) // { // /* if( childCount() == 0 ) { // kdDebug() << "clicked: `" << bubble->anchorAt(mapFromGlobal(pos)-TQPoint(24,0)) << " (" << pos.x() << " | " << pos.y() << ")'" << endl; // }*/ // } bool FileList::acceptDrag( TQDropEvent* e ) const { return ( e->source() == viewport() || KURLDrag::canDecode(e) ); // TODO verify the files } void FileList::slotDropped( TQDropEvent* e, TQListViewItem*, TQListViewItem* itemAfter ) { TQString file; KURL::List list; TQStringList 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 = TQDir::convertSeparators( (*it).pathOrURL() ); // TODO implement that in the url/file dialog, too? TQFileInfo fileInfo( file ); if( fileInfo.isDir() ) { addDir( file ); } else { files.append( (*it).url() ); } } addFiles( files, (FileListItem*)itemAfter, true ); save( true ); } } void FileList::showContextMenu( TQListViewItem* item, const TQPoint& 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(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(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 TQString& directory, TQStringList filter, bool recursive, bool fast, int count ) { // NOTE speed up? TQDir dir( directory ); dir.setFilter( TQDir::Files | TQDir::Dirs | TQDir::NoSymLinks | TQDir::Readable ); TQStringList list = dir.entryList(); for( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) { if( *it == "." || *it == ".." ) continue; TQFileInfo 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( TQStringList::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( TQStringList::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( TQStringList 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; TQString filePathName; TQString device; for( TQStringList::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 = TQDir::homeDirPath() + "/" + filePathName; newItem->local = true; } else if( (*it).left( 14 ) == "system:/users/" || (*it).left( 6 ) == "home:/" ) { int length = ( (*it).left(6) == "home:/" ) ? 6 : 14; TQString 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 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; TQFileInfo 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 TQString& directory, const TQStringList& 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 TQString& device, TQValueList trackList ) { for( TQValueList::Iterator it = trackList.begin(); it != trackList.end(); ++it ) { // logger->log( 1000, i18n("Adding track") + TQString().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") + TQString().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 = TQDir::homeDirPath() + "/" + i18n("Track") + TQString().sprintf(" %02i",newItem->track) + "." + newItem->fileFormat; } else { // logger->log( 1000, " " + i18n("Tags successfully read") ); newItem->time = newItem->tags->length; newItem->options.filePathName = TQDir::homeDirPath() + "/" + TQString().sprintf("%02i - ",newItem->track) + newItem->tags->title + "." + newItem->fileFormat; newItem->fileName = i18n("Audio CD (%1)").arg(device) + ": " + TQString().sprintf("%02i - ",newItem->track) + newItem->tags->title; } updateItem( newItem ); emit increaseTime( newItem->time ); } emit fileCountChanged( childCount() ); } void FileList::addDisc( const TQString& 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 = TQDir::homeDirPath() + "/" + i18n("Audio CD") + "." + newItem->fileFormat; } else { // logger->log( 1000, " " + i18n("Tags successfully read") ); newItem->time = newItem->tags->length; newItem->options.filePathName = TQDir::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 TQString& 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 && TQFile::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( TQT_TQOBJECT(this), TQT_SIGNAL(editItems(TQValueList)), optionsEditor, TQT_SLOT(itemsSelected(TQValueList)) ); connect( TQT_TQOBJECT(this), TQT_SIGNAL(setPreviousItemEnabled(bool)), optionsEditor, TQT_SLOT(setPreviousEnabled(bool)) ); connect( TQT_TQOBJECT(this), TQT_SIGNAL(setNextItemEnabled(bool)), optionsEditor, TQT_SLOT(setNextEnabled(bool)) ); connect( optionsEditor, TQT_SIGNAL(user2Clicked()), TQT_TQOBJECT(this), TQT_SLOT(selectPreviousItem()) ); connect( optionsEditor, TQT_SIGNAL(user1Clicked()), TQT_TQOBJECT(this), TQT_SLOT(selectNextItem()) ); /*connect( TQT_TQOBJECT(this), TQT_SIGNAL(moveEditor(int,int)), optionsEditor, TQT_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( TQValueList::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( TQValueList::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; TQStringList 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; TQString name; FileListItem* lastListItem = lastItem(); TQString filename; if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml"); else filename = locateLocal("data","soundkonverter/filelist.xml"); TQDomDocument domTree; TQFile opmlFile( filename ); if( !opmlFile.open( IO_ReadOnly ) ) return; if( !domTree.setContent( &opmlFile ) ) return; opmlFile.close(); TQDomElement root = domTree.documentElement(); if( root.attribute("type") != "filelist" ) return; TQDomNode 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...) TQTime time; time.start(); TQDomDocument domTree; TQDomElement root = domTree.createElement( "soundkonverter" ); root.setAttribute( "type", "filelist" ); domTree.appendChild( root ); TQDomElement info = domTree.createElement( "info" ); info.setAttribute( "version", "300" ); root.appendChild( info ); for( FileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { TQDomElement 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 ); TQDomElement 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 ); TQDomElement samplingRate = domTree.createElement( "samplingRate" ); samplingRate.setAttribute( "bEnabled", item->options.encodingOptions.samplingRate.bEnabled ); samplingRate.setAttribute( "iSamplingRate", item->options.encodingOptions.samplingRate.iSamplingRate ); encodingOptions.appendChild( samplingRate ); TQDomElement channels = domTree.createElement( "channels" ); channels.setAttribute( "bEnabled", item->options.encodingOptions.channels.bEnabled ); channels.setAttribute( "sChannels", item->options.encodingOptions.channels.sChannels ); encodingOptions.appendChild( channels ); TQDomElement 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 ); TQDomElement 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 ) { TQDomElement 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 ); } TQString filename; if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml"); else filename = locateLocal("data","soundkonverter/filelist.xml"); TQFile opmlFile( filename ); if( !opmlFile.open( IO_WriteOnly ) ) return; TQTextStream ts( &opmlFile ); ts << domTree.toString(); opmlFile.close(); logger->log( 1000, "save file list: " + TQString::number(time.elapsed()) ); } void FileList::debug() // NOTE DEBUG { logger->log( 1000, "DEBUG begin" ); ConversionOptions conversionOptions; TQStringList formats = config->allEncodableFormats(); for( TQStringList::Iterator a = formats.begin(); a != formats.end(); ++a ) { logger->log( 1000, "format: " + (*a) ); FormatItem* formatItem = config->getFormatItem( *a ); if( formatItem == 0 ) continue; for( TQValueList::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( TQValueList::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) { formatItem->decoder = (*b); } for( TQValueList::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) { formatItem->replaygain = (*b); } } logger->log( 1000, "DEBUG end" ); } TQString FileList::debug_params( ConversionOptions conversionOptions, FormatItem* formatItem ) // NOTE DEBUG { ConvertPlugin* plugin = formatItem->encoder; TQString sStrength; TQString sBitrate; TQString sQuality; TQString sMinBitrate; TQString sMaxBitrate; TQString sSamplingRate; int t_int; float t_float; TQString 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 ); else sStrength = TQString::number( plugin->enc.strength.range_min - compressionLevel ); } else { if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min ) sStrength = TQString::number( int(compressionLevel) ); else sStrength = TQString::number( int(plugin->enc.strength.range_min - compressionLevel) ); } 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( 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 = TQString::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 = TQString::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 = TQString::number( conversionOptions.encodingOptions.iMinBitrate ); param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max ); sMaxBitrate = TQString::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 = 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 = ( 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 = TQString::number( t_int ); } if( plugin->enc.bin == "oggenc" ) sQuality.replace(TQChar('.'),KGlobal::locale()->decimalSymbol()); 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( 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 = TQString::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 = TQString::number( conversionOptions.encodingOptions.samplingRate.iSamplingRate ); } else { sSamplingRate = TQString::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 ); }