File indexing completed on 2024-05-12 04:51:52

0001 /*
0002     SPDX-FileCopyrightText: 2006-2009 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "k3bvideodvdrippingdialog.h"
0009 #include "k3bapplication.h"
0010 #include "k3bfilesysteminfo.h"
0011 #include "k3bglobals.h"
0012 #include "k3bjobprogressdialog.h"
0013 #include "k3bmedium.h"
0014 #include "k3bmediacache.h"
0015 #include "k3bvideodvd.h"
0016 #include "k3bvideodvdaudiomodel.h"
0017 #include "k3bvideodvdrippingjob.h"
0018 #include "k3bvideodvdrippingwidget.h"
0019 #include "k3bvideodvdtitletranscodingjob.h"
0020 
0021 #include <KComboBox>
0022 #include <KLineEdit>
0023 #include <KConfig>
0024 #include <KLocalizedString>
0025 #include <KUrlRequester>
0026 #include <KIO/Global>
0027 #include <KMessageBox>
0028 
0029 #include <QList>
0030 #include <QLocale>
0031 #include <QMap>
0032 #include <QVector>
0033 #include <QFontMetrics>
0034 #include <QCheckBox>
0035 #include <QHBoxLayout>
0036 #include <QHeaderView>
0037 #include <QLayout>
0038 #include <QSpinBox>
0039 #include <QStyle>
0040 
0041 
0042 namespace {
0043 
0044 QString videoCodecId( K3b::VideoDVDTitleTranscodingJob::VideoCodec codec )
0045 {
0046     switch( codec ) {
0047     case K3b::VideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4:
0048         return "ffmpeg_mpeg4";
0049     case K3b::VideoDVDTitleTranscodingJob::VIDEO_CODEC_XVID:
0050         return "xvid";
0051     default:
0052         return "none";
0053     }
0054 }
0055 
0056 
0057 QString audioCodecId( K3b::VideoDVDTitleTranscodingJob::AudioCodec codec )
0058 {
0059     switch( codec ) {
0060     case K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3:
0061         return "mp3";
0062     case K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_STEREO:
0063         return "ac3_stereo";
0064     case K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH:
0065         return "ac3_passthrough";
0066     default:
0067         return "none";
0068     }
0069 }
0070 
0071 
0072 K3b::VideoDVDTitleTranscodingJob::VideoCodec videoCodecFromId( const QString& codec )
0073 {
0074     if( codec == "xvid" )
0075         return K3b::VideoDVDTitleTranscodingJob::VIDEO_CODEC_XVID;
0076     else //  if( codec == "ffmpeg_mpeg4" )
0077         return K3b::VideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4;
0078 }
0079 
0080 
0081 K3b::VideoDVDTitleTranscodingJob::AudioCodec audioCodecFromId( const QString& codec )
0082 {
0083     if( codec == "ac3_stereo" )
0084         return K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_STEREO;
0085     else if( codec == "ac3_passthrough" )
0086         return K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH;
0087     else // if( codec == "mp3" )
0088         return K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3;
0089 }
0090 
0091 
0092 // resize according to aspect ratio
0093 QSize resizeTitle( const K3b::VideoDVD::VideoStream& title, const QSize& size )
0094 {
0095     int w = size.width();
0096     int h = size.height();
0097     int rw = title.realPictureWidth();
0098     int rh = title.realPictureHeight();
0099 
0100     if( w == 0 && h == 0 ) {
0101         w = rw;
0102         h = rh;
0103     }
0104     else if( w == 0 ) {
0105         w = h * rw / rh;
0106     }
0107     else if( h == 0 ) {
0108         h = w * rh / rw;
0109     }
0110 
0111     return QSize(w,h);
0112 }
0113 
0114 typedef QMap< const K3b::VideoDVD::Title*, K3b::VideoDVDRippingJob::TitleRipInfo > TitleRipInfos;
0115 
0116 } // namespace
0117 
0118 
0119 class K3b::VideoDVDRippingDialog::Private
0120 {
0121 public:
0122     Private( const K3b::VideoDVD::VideoDVD& d )
0123         : dvd( d ), w( 0 ), audioModel( 0 ) {}
0124 
0125     VideoDVD::VideoDVD dvd;
0126     VideoDVDRippingWidget* w;
0127     VideoDVDAudioModel* audioModel;
0128     TitleRipInfos titleRipInfos;
0129     K3b::FileSystemInfo fsInfo;
0130 
0131     QString createFilename( const VideoDVDRippingJob::TitleRipInfo& info, const QString& pattern ) const;
0132 };
0133 
0134 
0135 QString K3b::VideoDVDRippingDialog::Private::createFilename( const K3b::VideoDVDRippingJob::TitleRipInfo& info, const QString& pattern ) const
0136 {
0137     QString f;
0138 
0139     const K3b::VideoDVD::Title& title = dvd[info.title-1];
0140 
0141     for( int i = 0; i < pattern.length(); ++i ) {
0142         //
0143         // every pattern starts with a % sign
0144         //
0145         if( pattern[i] == '%' && i+1 < pattern.length() ) {
0146             ++i; // skip the %
0147             char c = pattern[i].toLatin1();
0148 
0149             //
0150             // first check if we have a long keyword instead of a one-char
0151             //
0152             if( pattern[i] == '{' ) {
0153                 int j = pattern.indexOf( '}', i );
0154                 if( j < 0 ) // no closing bracket -> no valid pattern
0155                     c = '*';
0156                 else {
0157                     QString keyword = pattern.mid( i+1, j-i-1 );
0158                     if( keyword == "titlenumber"  ||
0159                         keyword == "title_number" ||
0160                         keyword == "title" ) {
0161                         c = PATTERN_TITLE_NUMBER;
0162                     }
0163                     else if( keyword == "volumeid"  ||
0164                              keyword == "volume_id" ||
0165                              keyword == "volid"     ||
0166                              keyword == "vol_id" ) {
0167                         c = PATTERN_VOLUME_ID;
0168                     }
0169                     else if( keyword == "beautifiedvolumeid"   ||
0170                              keyword == "beautified_volumeid"  ||
0171                              keyword == "beautified_volume_id" ||
0172                              keyword == "beautifiedvolid"      ||
0173                              keyword == "beautified_volid"     ||
0174                              keyword == "beautified_vol_id"    ||
0175                              keyword == "nicevolid"            ||
0176                              keyword == "nice_volid"           ||
0177                              keyword == "nice_vol_id" ) {
0178                         c = PATTERN_BEAUTIFIED_VOLUME_ID;
0179                     }
0180                     else if( keyword == "languagecode"  ||
0181                              keyword == "language_code" ||
0182                              keyword == "langcode"      ||
0183                              keyword == "lang_code" ) {
0184                         c = PATTERN_LANGUAGE_CODE;
0185 
0186                     }
0187                     else if( keyword == "lang" ||
0188                              keyword == "language" ||
0189                              keyword == "langname" ||
0190                              keyword == "languagename" ||
0191                              keyword == "lang_name" ||
0192                              keyword == "language_name" ) {
0193                         c = PATTERN_LANGUAGE_NAME;
0194                     }
0195                     else if( keyword == "audioformat"  ||
0196                              keyword == "audio_format" ||
0197                              keyword == "audio" ) {
0198                         c = PATTERN_AUDIO_FORMAT;
0199                     }
0200                     else if( keyword == "channels" ||
0201                              keyword == "audiochannels" ||
0202                              keyword == "audio_channels" ||
0203                              keyword == "ch" ) {
0204                         c = PATTERN_AUDIO_CHANNELS;
0205                     }
0206                     else if( keyword == "videosize"  ||
0207                              keyword == "video_size" ||
0208                              keyword == "vsize" ) {
0209                         c = PATTERN_VIDEO_SIZE;
0210                     }
0211                     else if( keyword == "originalvideosize"  ||
0212                              keyword == "original_video_size" ||
0213                              keyword == "origvideosize"  ||
0214                              keyword == "orig_video_size" ||
0215                              keyword == "origvsize" ) {
0216                         c = PATTERN_ORIG_VIDEO_SIZE;
0217                     }
0218                     else if( keyword == "aspect_ratio" ||
0219                              keyword == "aspectratio" ||
0220                              keyword == "ratio" ) {
0221                         c = PATTERN_ASPECT_RATIO;
0222                     }
0223                     else if( keyword == "current_date" ||
0224                              keyword == "currentdate" ||
0225                              keyword == "date" ) {
0226                         c = PATTERN_CURRENT_DATE;
0227                     }
0228                     else {
0229                         // unusable pattern
0230                         c = '*';
0231                     }
0232 
0233                     //
0234                     // skip the keyword and the closing bracket
0235                     //
0236                     if( c != '*' ) {
0237                         i += keyword.length() + 1;
0238                     }
0239                 }
0240             }
0241 
0242             switch( c ) {
0243             case PATTERN_TITLE_NUMBER:
0244                 f.append( QString::number(info.title).rightJustified( 2, '0' ) );
0245                 break;
0246             case PATTERN_VOLUME_ID:
0247                 f.append( dvd.volumeIdentifier() );
0248                 break;
0249             case PATTERN_BEAUTIFIED_VOLUME_ID:
0250                 f.append( k3bappcore->mediaCache()->medium( dvd.device() ).beautifiedVolumeId() );
0251                 break;
0252             case PATTERN_LANGUAGE_CODE:
0253                 if( title.numAudioStreams() > 0 )
0254                     f.append( title.audioStream( info.audioStream ).langCode() );
0255                 break;
0256             case PATTERN_LANGUAGE_NAME:
0257                 if( title.numAudioStreams() > 0 )
0258                     f.append( QLocale( title.audioStream( info.audioStream ).langCode() ).nativeLanguageName() );
0259                 break;
0260             case PATTERN_AUDIO_FORMAT:
0261                 // FIXME: what about MPEG audio streams?
0262                 if( title.numAudioStreams() > 0 ) {
0263                     if( w->selectedAudioCodec() == K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 )
0264                         f.append( K3b::VideoDVDTitleTranscodingJob::audioCodecString( w->selectedAudioCodec() ) );
0265                     else
0266                         f.append( K3b::VideoDVD::audioFormatString( title.audioStream( info.audioStream ).format() ) );
0267                 }
0268                 break;
0269             case PATTERN_AUDIO_CHANNELS:
0270                 if( title.numAudioStreams() > 0 )
0271                     // xgettext: no-c-format
0272                     f.append( i18ncp("Ch is short for Channels", "%1Ch", "%1Ch",
0273                                      w->selectedAudioCodec() == K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH
0274                                      ? title.audioStream( info.audioStream ).channels()
0275                                      : 2 ) );
0276                 break;
0277             case PATTERN_ORIG_VIDEO_SIZE:
0278                 f.append( QString("%1x%2")
0279                           .arg(title.videoStream().pictureWidth())
0280                           .arg(title.videoStream().pictureHeight()) );
0281                 break;
0282             case PATTERN_VIDEO_SIZE: {
0283                 QSize s( resizeTitle( dvd[info.title-1].videoStream(), w->selectedPictureSize() ) );
0284                 f.append( QString("%1x%2").arg(s.width()).arg(s.height()) );
0285                 break;
0286             }
0287             case PATTERN_ASPECT_RATIO:
0288                 if( title.videoStream().displayAspectRatio() == K3b::VideoDVD::VIDEO_ASPECT_RATIO_4_3 )
0289                     f.append( "4:3" );
0290                 else
0291                     f.append( "16:9" );
0292                 break;
0293             case PATTERN_CURRENT_DATE:
0294                 f.append( QLocale().toString( QDate::currentDate() ) );
0295                 break;
0296             default:
0297                 f.append( pattern[i-1] );
0298                 f.append( pattern[i] );
0299             }
0300         }
0301 
0302         //
0303         // normal character -> just append to filename
0304         //
0305         else {
0306             f.append( pattern[i] );
0307         }
0308     }
0309 
0310     //
0311     // and the extension (for now only avi)
0312     //
0313     f.append( ".avi" );
0314 
0315     return f;
0316 }
0317 
0318 
0319 K3b::VideoDVDRippingDialog::VideoDVDRippingDialog( const K3b::VideoDVD::VideoDVD& dvd,
0320                                                     const QList<int>& titles,
0321                                                     QWidget* parent )
0322     : K3b::InteractionDialog( parent,
0323                             i18n("Video DVD Ripping"),
0324                             QString(),
0325                             START_BUTTON|CANCEL_BUTTON,
0326                             START_BUTTON,
0327                             "VideoDVD Ripping" ), // config group
0328       d( new Private( dvd ) )
0329 {
0330     d->audioModel = new VideoDVDAudioModel( dvd, titles, this );
0331 
0332     QWidget* frame = mainWidget();
0333     d->w = new K3b::VideoDVDRippingWidget( frame );
0334     d->w->m_titleView->setModel( d->audioModel );
0335     d->w->m_titleView->expandAll();
0336     d->w->m_titleView->header()->setSectionResizeMode( VideoDVDAudioModel::TitleColumn, QHeaderView::ResizeToContents );
0337     d->w->m_titleView->header()->setSectionResizeMode( VideoDVDAudioModel::VideoSizeColumn, QHeaderView::ResizeToContents );
0338     d->w->m_titleView->header()->setSectionResizeMode( VideoDVDAudioModel::FileSizeColumn, QHeaderView::ResizeToContents );
0339 
0340     QHBoxLayout* frameLayout = new QHBoxLayout( frame );
0341     frameLayout->setContentsMargins( 0, 0, 0, 0 );
0342     frameLayout->addWidget( d->w );
0343 
0344     connect( d->w, SIGNAL(changed()),
0345              this, SLOT(slotUpdateFilesizes()) );
0346     connect( d->w, SIGNAL(changed()),
0347              this, SLOT(slotUpdateFilenames()) );
0348     connect( d->w, SIGNAL(changed()),
0349              this, SLOT(slotUpdateVideoSizes()) );
0350     connect( d->audioModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0351              this, SLOT(slotAudioModelChanged(QModelIndex,QModelIndex)) );
0352 
0353     setTitle( i18n("Video DVD Ripping"),
0354               i18np("1 title from %2", "%1 titles from %2", titles.count(),
0355                     k3bappcore->mediaCache()->medium(d->dvd.device()).beautifiedVolumeId() ) );
0356 
0357     // populate rip infos
0358     d->titleRipInfos.clear();
0359     for( QList<int>::const_iterator it = titles.begin(); it != titles.end(); ++it ) {
0360         if( *it > 0 && *it <= static_cast<int>( d->dvd.numTitles() ) ) {
0361             const VideoDVD::Title& title = d->dvd[ *it-1 ];
0362             K3b::VideoDVDRippingJob::TitleRipInfo ri( *it );
0363             ri.audioStream = d->audioModel->chosenAudio( title );
0364             d->titleRipInfos.insert( &title, ri );
0365         }
0366     }
0367 }
0368 
0369 
0370 K3b::VideoDVDRippingDialog::~VideoDVDRippingDialog()
0371 {
0372     delete d;
0373 }
0374 
0375 
0376 void K3b::VideoDVDRippingDialog::slotUpdateFilenames()
0377 {
0378     QString baseDir = K3b::prepareDir( d->w->m_editBaseDir->url().toLocalFile() );
0379     d->fsInfo.setPath( baseDir );
0380 
0381     for( TitleRipInfos::iterator it = d->titleRipInfos.begin(); it != d->titleRipInfos.end(); ++it ) {
0382         QString f = d->fsInfo.fixupPath( d->createFilename( it.value(), d->w->m_comboFilenamePattern->currentText() ) );
0383         if( d->w->m_checkBlankReplace->isChecked() ) {
0384             static const QRegularExpression rx( "\\s" );
0385             f.replace( rx, d->w->m_editBlankReplace->text() );
0386         }
0387         it.value().filename = baseDir + f;
0388 
0389         d->audioModel->setFileName( *it.key(), f );
0390     }
0391 }
0392 
0393 
0394 void K3b::VideoDVDRippingDialog::slotUpdateFilesizes()
0395 {
0396     double bitrate = (double)d->w->m_spinVideoBitrate->value();
0397     KIO::filesize_t overallSize = 0ULL;
0398 
0399     // update file sizes
0400     for( TitleRipInfos::iterator it = d->titleRipInfos.begin(); it != d->titleRipInfos.end(); ++it ) {
0401 
0402         double sec = d->dvd[it.value().title-1].playbackTime().totalSeconds();
0403 
0404         // estimate the filesize
0405         KIO::filesize_t size = (KIO::filesize_t)( sec * bitrate * 1000.0 / 8.0 );
0406 
0407         // add audio stream size
0408         // FIXME: consider AC3 passthrough
0409         size += (KIO::filesize_t)( sec * d->w->selectedAudioBitrate() / 8.0 * 1024.0 );
0410 
0411         d->audioModel->setFileSize( *it.key(), size );
0412 
0413         overallSize += size;
0414     }
0415 
0416     d->w->setNeededSize( overallSize );
0417 }
0418 
0419 
0420 void K3b::VideoDVDRippingDialog::slotUpdateVideoSizes()
0421 {
0422     QSize size = d->w->selectedPictureSize();
0423     for( TitleRipInfos::iterator it = d->titleRipInfos.begin(); it != d->titleRipInfos.end(); ++it ) {
0424         QSize s( resizeTitle( d->dvd[it.value().title-1].videoStream(), size ) );
0425         d->audioModel->setVideoSize( *it.key(), s );
0426     }
0427 }
0428 
0429 
0430 void K3b::VideoDVDRippingDialog::slotAudioModelChanged( const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/ )
0431 {
0432     QModelIndex parent = topLeft.parent();
0433     if( parent.isValid() ) {
0434         if( const VideoDVD::Title* title = d->audioModel->titleForIndex( parent ) ) {
0435             d->titleRipInfos[ title ].audioStream = d->audioModel->chosenAudio( *title );
0436             slotUpdateFilenames();
0437         }
0438     }
0439 }
0440 
0441 
0442 void K3b::VideoDVDRippingDialog::setBaseDir( const QString& path )
0443 {
0444     d->w->m_editBaseDir->setUrl(QUrl::fromLocalFile(path));
0445 }
0446 
0447 
0448 void K3b::VideoDVDRippingDialog::loadSettings( const KConfigGroup& c )
0449 {
0450     d->w->m_spinVideoBitrate->setValue( c.readEntry( "video bitrate", 1200 ) );
0451     d->w->m_checkTwoPassEncoding->setChecked( c.readEntry( "two pass encoding", true ) );
0452     d->w->m_checkAudioResampling->setChecked( c.readEntry( "audio resampling", false ) );
0453     d->w->m_checkAutoClipping->setChecked( c.readEntry( "auto clipping", false ) );
0454     d->w->m_checkLowPriority->setChecked( c.readEntry( "low priority", true ) );
0455     d->w->m_checkAudioVBR->setChecked( c.readEntry( "vbr audio", true ) );
0456     d->w->setSelectedAudioBitrate( c.readEntry( "audio bitrate", 128 ) );
0457     d->w->setSelectedVideoCodec( videoCodecFromId( c.readEntry( "video codec", videoCodecId( K3b::VideoDVDTitleTranscodingJob::VIDEO_CODEC_FFMPEG_MPEG4 ) ) ) );
0458     d->w->setSelectedAudioCodec( audioCodecFromId( c.readEntry( "audio codec", audioCodecId( K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_MP3 ) ) ) );
0459     d->w->m_checkBlankReplace->setChecked( c.readEntry( "replace blanks", false ) );
0460     d->w->m_editBlankReplace->setText( c.readEntry( "blank replace string", "_" ) );
0461     d->w->m_comboFilenamePattern->setEditText( c.readEntry( "filename pattern", d->w->m_comboFilenamePattern->itemText(0) ) );
0462     d->w->m_editBaseDir->setUrl(QUrl::fromLocalFile(c.readPathEntry("base dir", K3b::defaultTempPath())));
0463 }
0464 
0465 
0466 void K3b::VideoDVDRippingDialog::saveSettings( KConfigGroup c )
0467 {
0468     c.writeEntry( "video bitrate", d->w->m_spinVideoBitrate->value() );
0469     c.writeEntry( "two pass encoding", d->w->m_checkTwoPassEncoding->isChecked() );
0470     c.writeEntry( "audio resampling", d->w->m_checkAudioResampling->isChecked() );
0471     c.writeEntry( "auto clipping", d->w->m_checkAutoClipping->isChecked() );
0472     c.writeEntry( "low priority", d->w->m_checkLowPriority->isChecked() );
0473     c.writeEntry( "vbr audio", d->w->m_checkAudioVBR->isChecked() );
0474     c.writeEntry( "audio bitrate", d->w->selectedAudioBitrate() );
0475     c.writeEntry( "video codec", videoCodecId( d->w->selectedVideoCodec() ) );
0476     c.writeEntry( "audio codec", audioCodecId( d->w->selectedAudioCodec() ) );
0477     c.writeEntry( "replace blanks", d->w->m_checkBlankReplace->isChecked() );
0478     c.writeEntry( "blank replace string", d->w->m_editBlankReplace->text() );
0479     c.writeEntry( "filename pattern", d->w->m_comboFilenamePattern->currentText() );
0480     c.writePathEntry( "base dir", d->w->m_editBaseDir->url().toLocalFile() );
0481 }
0482 
0483 
0484 void K3b::VideoDVDRippingDialog::slotStartClicked()
0485 {
0486     //
0487     // check if the selected audio codec is usable for all selected audio streams
0488     // We can only use the AC3 pass-through mode for AC3 streams
0489     //
0490     if( d->w->selectedAudioCodec() == K3b::VideoDVDTitleTranscodingJob::AUDIO_CODEC_AC3_PASSTHROUGH ) {
0491         for( TitleRipInfos::iterator it = d->titleRipInfos.begin(); it != d->titleRipInfos.end(); ++it ) {
0492             if( d->dvd[it.value().title-1].numAudioStreams() > 0 &&
0493                 d->dvd[it.value().title-1].audioStream(it.value().audioStream).format() != K3b::VideoDVD::AUDIO_FORMAT_AC3 ) {
0494                 KMessageBox::error( this, i18n("<p>When using the <em>AC3 pass-through</em> audio codec all selected audio "
0495                                                "streams need to be in AC3 format. Please select another audio codec or "
0496                                                "choose AC3 audio streams for all ripped titles."),
0497                                     i18n("AC3 Pass-through") );
0498                 return;
0499             }
0500         }
0501     }
0502 
0503     // check if we need to overwrite some files...
0504     QStringList filesToOverwrite;
0505     for( TitleRipInfos::iterator it = d->titleRipInfos.begin(); it != d->titleRipInfos.end(); ++it ) {
0506         if( QFile::exists( it.value().filename ) )
0507             filesToOverwrite.append( it.value().filename );
0508     }
0509 
0510     if( !filesToOverwrite.isEmpty() )
0511         if( KMessageBox::questionTwoActionsList( this,
0512                                                  i18n("Do you want to overwrite these files?"),
0513                                                  filesToOverwrite,
0514                                                  i18n("Files Exist"),
0515                                                  KStandardGuiItem::overwrite(),
0516                                                  KStandardGuiItem::cancel() ) == KMessageBox::SecondaryAction )
0517             return;
0518 
0519 
0520     QSize videoSize = d->w->selectedPictureSize();
0521     int i = 0;
0522     QVector<K3b::VideoDVDRippingJob::TitleRipInfo> titles( d->titleRipInfos.count() );
0523     for( TitleRipInfos::const_iterator it = d->titleRipInfos.constBegin(); it != d->titleRipInfos.constEnd(); ++it ) {
0524         titles[i] = it.value();
0525         titles[i].videoBitrate = 0; // use the global bitrate set below
0526         titles[i].width = videoSize.width();
0527         titles[i].height = videoSize.height();
0528         ++i;
0529     }
0530 
0531     // sort the titles which come from a map and are thus not sorted properly
0532     // simple bubble sort for these small arrays is sufficient
0533     for( int i = 0; i < titles.count(); ++i ) {
0534         for( int j = i+1; j < titles.count(); ++j ) {
0535             if( titles[i].title > titles[j].title ) {
0536                 K3b::VideoDVDRippingJob::TitleRipInfo tmp = titles[i];
0537                 titles[i] = titles[j];
0538                 titles[j] = tmp;
0539             }
0540         }
0541     }
0542 
0543     // start the job
0544     K3b::JobProgressDialog dlg( parentWidget() );
0545     K3b::VideoDVDRippingJob* job = new K3b::VideoDVDRippingJob( &dlg, &dlg );
0546     job->setVideoDVD( d->dvd );
0547     job->setTitles( titles );
0548 
0549     job->setVideoBitrate( d->w->m_spinVideoBitrate->value() );
0550     job->setTwoPassEncoding( d->w->m_checkTwoPassEncoding->isChecked() );
0551     job->setResampleAudioTo44100( d->w->m_checkAudioResampling->isChecked() );
0552     job->setAutoClipping( d->w->m_checkAutoClipping->isChecked() );
0553     job->setVideoCodec( d->w->selectedVideoCodec() );
0554     job->setAudioCodec( d->w->selectedAudioCodec() );
0555     job->setLowPriority( d->w->m_checkLowPriority->isChecked() );
0556     job->setAudioBitrate( d->w->selectedAudioBitrate() );
0557     job->setAudioVBR( d->w->m_checkAudioVBR->isChecked() );
0558 
0559     hide();
0560     dlg.startJob( job );
0561     close();
0562 }
0563 
0564 #include "moc_k3bvideodvdrippingdialog.cpp"