File indexing completed on 2024-05-12 04:51:09
0001 /* 0002 SPDX-FileCopyrightText: 2003-2005 Christian Kvasny <chris@k3b.org> 0003 SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl> 0004 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "k3bvcddoc.h" 0010 #include "k3bvcdtrack.h" 0011 #include "k3bvcdjob.h" 0012 #include "k3bglobals.h" 0013 #include "k3bmsf.h" 0014 #include "k3b_i18n.h" 0015 0016 #include <KConfig> 0017 #include <KIO/Global> 0018 #include <KMessageBox> 0019 #include <KStandardGuiItem> 0020 0021 #include <QDataStream> 0022 #include <QDebug> 0023 #include <QFile> 0024 #include <QTimer> 0025 #include <QImage> 0026 #include <QApplication> 0027 #include <QDomElement> 0028 0029 0030 #if 0 0031 bool desperate_mode = false; 0032 bool preserve_header = false; 0033 bool print_progress = true; 0034 bool aspect_correction = false; 0035 byte forced_sequence_header = 0; 0036 #endif 0037 0038 K3b::VcdDoc::VcdDoc( QObject* parent ) 0039 : K3b::Doc( parent ) 0040 { 0041 m_tracks = 0L; 0042 m_vcdOptions = new K3b::VcdOptions(); 0043 0044 m_vcdType = NONE; 0045 0046 m_urlAddingTimer = new QTimer( this ); 0047 connect( m_urlAddingTimer, SIGNAL(timeout()), this, SLOT(slotWorkUrlQueue()) ); 0048 0049 // FIXME: remove the newTracks() signal and replace it with the changed signal 0050 connect( this, SIGNAL(newTracks()), this, SIGNAL(changed()) ); 0051 connect( this, SIGNAL(trackRemoved(K3b::VcdTrack*)), this, SIGNAL(changed()) ); 0052 } 0053 0054 K3b::VcdDoc::~VcdDoc() 0055 { 0056 if ( m_tracks ) { 0057 qDeleteAll( *m_tracks ); 0058 delete m_tracks; 0059 } 0060 0061 delete m_vcdOptions; 0062 } 0063 0064 bool K3b::VcdDoc::newDocument() 0065 { 0066 clear(); 0067 if ( !m_tracks ) 0068 m_tracks = new QList<K3b::VcdTrack*>; 0069 0070 return K3b::Doc::newDocument(); 0071 } 0072 0073 0074 void K3b::VcdDoc::clear() 0075 { 0076 if ( m_tracks ) 0077 while ( !m_tracks->isEmpty() ) 0078 removeTrack( m_tracks->first() ); 0079 } 0080 0081 0082 QString K3b::VcdDoc::name() const 0083 { 0084 return m_vcdOptions->volumeId(); 0085 } 0086 0087 0088 KIO::filesize_t K3b::VcdDoc::calcTotalSize() const 0089 { 0090 unsigned long long sum = 0; 0091 if ( m_tracks ) { 0092 Q_FOREACH( K3b::VcdTrack* track, *m_tracks ) { 0093 sum += track->size(); 0094 } 0095 } 0096 return sum; 0097 } 0098 0099 KIO::filesize_t K3b::VcdDoc::size() const 0100 { 0101 // mode2 -> mode1 int(( n+2047 ) / 2048) * 2352 0102 // mode1 -> mode2 int(( n+2351 ) / 2352) * 2048 0103 long tracksize = long( ( calcTotalSize() + 2351 ) / 2352 ) * 2048; 0104 return tracksize + ISOsize(); 0105 } 0106 0107 KIO::filesize_t K3b::VcdDoc::ISOsize() const 0108 { 0109 // 136000b for vcd iso reserved 0110 long long iso_size = 136000; 0111 if ( vcdOptions() ->CdiSupport() ) { 0112 iso_size += vcdOptions() ->CDIsize(); 0113 } 0114 0115 return iso_size; 0116 } 0117 0118 K3b::Msf K3b::VcdDoc::length() const 0119 { 0120 return K3b::Msf( size() / 2048 ); 0121 } 0122 0123 0124 bool K3b::VcdDoc::isImage( const QUrl& url ) 0125 { 0126 QImage p; 0127 return p.load( QFile::encodeName( url.toLocalFile() ) ); 0128 } 0129 0130 void K3b::VcdDoc::addUrls( const QList<QUrl>& urls ) 0131 { 0132 // make sure we add them at the end even if urls are in the queue 0133 addTracks( urls, 99 ); 0134 } 0135 0136 void K3b::VcdDoc::addTracks( const QList<QUrl>& urls, uint position ) 0137 { 0138 QList<QUrl>::ConstIterator end( urls.end() ); 0139 for ( QList<QUrl>::ConstIterator it = urls.begin(); it != end; ++it ) { 0140 urlsToAdd.enqueue( new PrivateUrlToAdd( K3b::convertToLocalUrl(*it), position++ ) ); 0141 } 0142 0143 m_urlAddingTimer->start( 0 ); 0144 } 0145 0146 void K3b::VcdDoc::slotWorkUrlQueue() 0147 { 0148 if ( !urlsToAdd.isEmpty() ) { 0149 PrivateUrlToAdd * item = urlsToAdd.dequeue(); 0150 lastAddedPosition = item->position; 0151 0152 // append at the end by default 0153 if ( lastAddedPosition > m_tracks->count() ) 0154 lastAddedPosition = m_tracks->count(); 0155 0156 if ( !item->url.isLocalFile() ) { 0157 qDebug() << item->url.toLocalFile() << " no local file"; 0158 return ; 0159 } 0160 0161 if ( !QFile::exists( item->url.toLocalFile() ) ) { 0162 qDebug() << "(K3b::VcdDoc) file not found: " << item->url.toLocalFile(); 0163 m_notFoundFiles.append( item->url.toLocalFile() ); 0164 return ; 0165 } 0166 0167 if ( K3b::VcdTrack * newTrack = createTrack( item->url ) ) 0168 addTrack( newTrack, lastAddedPosition ); 0169 0170 delete item; 0171 0172 emit newTracks(); 0173 } else { 0174 m_urlAddingTimer->stop(); 0175 0176 emit newTracks(); 0177 0178 // reorder pbc tracks 0179 setPbcTracks(); 0180 0181 informAboutNotFoundFiles(); 0182 } 0183 } 0184 0185 K3b::VcdTrack* K3b::VcdDoc::createTrack( const QUrl& url ) 0186 { 0187 char filename[ 255 ]; 0188 QString error_string = ""; 0189 strcpy( filename, QFile::encodeName( url.toLocalFile() ) ); 0190 K3b::MpegInfo* Mpeg = new K3b::MpegInfo( filename ); 0191 0192 if ( Mpeg ) { 0193 int mpegVersion = Mpeg->version(); 0194 if ( mpegVersion > 0 ) { 0195 0196 if ( vcdType() == NONE && mpegVersion < 2 ) { 0197 m_urlAddingTimer->stop(); 0198 setVcdType( vcdTypes( mpegVersion ) ); 0199 // FIXME: properly convert the mpeg version 0200 vcdOptions() ->setMpegVersion( ( K3b::VcdOptions::MPEGVersion )mpegVersion ); 0201 KMessageBox::information( qApp->activeWindow(), 0202 i18n( "K3b will create a %1 image from the given MPEG " 0203 "files, but these files must already be in %1 " 0204 "format. K3b does not yet resample MPEG files.", 0205 i18n( "VCD" ) ), 0206 i18n( "Information" ) ); 0207 m_urlAddingTimer->start( 0 ); 0208 } else if ( vcdType() == NONE ) { 0209 m_urlAddingTimer->stop(); 0210 vcdOptions() ->setMpegVersion( ( K3b::VcdOptions::MPEGVersion )mpegVersion ); 0211 bool force = KMessageBox::questionTwoActions(qApp->activeWindow(), 0212 i18n( "K3b will create a %1 image from the given MPEG " 0213 "files, but these files must already be in %1 " 0214 "format. K3b does not yet resample MPEG files.", 0215 i18n( "SVCD" ) ) 0216 + "\n\n" 0217 + i18n( "Note: Forcing MPEG2 as VCD is not supported by " 0218 "some standalone DVD players." ), 0219 i18n( "Information" ), 0220 KGuiItem( i18n( "Force VCD" ) ), 0221 KGuiItem( i18n( "Do not force VCD" ) ) ) == KMessageBox::PrimaryAction; 0222 if ( force ) { 0223 setVcdType( vcdTypes( 1 ) ); 0224 vcdOptions() ->setAutoDetect( false ); 0225 } else 0226 setVcdType( vcdTypes( mpegVersion ) ); 0227 0228 m_urlAddingTimer->start( 0 ); 0229 } 0230 0231 0232 if ( numOfTracks() > 0 && vcdOptions() ->mpegVersion() != mpegVersion ) { 0233 KMessageBox::error( qApp->activeWindow(), '(' + url.toLocalFile() + ")\n" + 0234 i18n( "You cannot mix MPEG1 and MPEG2 video files.\nPlease start a new Project for this filetype.\nResample not implemented in K3b yet." ), 0235 i18n( "Wrong File Type for This Project" ) ); 0236 0237 delete Mpeg; 0238 return 0; 0239 } 0240 0241 K3b::VcdTrack* newTrack = new K3b::VcdTrack( m_tracks, url.toLocalFile() ); 0242 *( newTrack->mpeg_info ) = *( Mpeg->mpeg_info ); 0243 0244 if ( newTrack->isSegment() && !vcdOptions()->PbcEnabled() ) { 0245 KMessageBox::information( qApp->activeWindow(), 0246 i18n( "PBC (Playback control) enabled.\n" 0247 "Video players cannot reach Segments (MPEG Still Pictures) without Playback control." ) , 0248 i18n( "Information" ) ); 0249 0250 vcdOptions()->setPbcEnabled( true ); 0251 } 0252 0253 // set defaults; 0254 newTrack->setPlayTime( vcdOptions() ->PbcPlayTime() ); 0255 newTrack->setWaitTime( vcdOptions() ->PbcWaitTime() ); 0256 newTrack->setPbcNumKeys( vcdOptions() ->PbcNumkeysEnabled() ); 0257 delete Mpeg; 0258 0259 // debugging output 0260 newTrack->PrintInfo(); 0261 0262 return newTrack; 0263 } 0264 } else if ( isImage( url ) ) { // image track 0265 // working on ... 0266 // for future use 0267 // photoalbum starts here 0268 // return here the new photoalbum track 0269 } 0270 0271 if ( Mpeg ) { 0272 error_string = Mpeg->error_string(); 0273 delete Mpeg; 0274 } 0275 0276 // error (unsupported files) 0277 KMessageBox::error( qApp->activeWindow(), '(' + url.toLocalFile() + ")\n" + 0278 i18n( "Only MPEG1 and MPEG2 video files are supported.\n" ) + error_string , 0279 i18n( "Wrong File Format" ) ); 0280 0281 0282 return 0; 0283 } 0284 0285 void K3b::VcdDoc::addTrack( const QUrl& url, uint position ) 0286 { 0287 urlsToAdd.enqueue( new PrivateUrlToAdd( url, position ) ); 0288 0289 m_urlAddingTimer->start( 0 ); 0290 } 0291 0292 0293 void K3b::VcdDoc::addTrack( K3b::VcdTrack* track, uint position ) 0294 { 0295 if ( m_tracks->count() >= 98 ) { 0296 qDebug() << "(K3b::VcdDoc) VCD Green Book only allows 98 tracks."; 0297 // TODO: show some messagebox 0298 delete track; 0299 return ; 0300 } 0301 0302 lastAddedPosition = position; 0303 0304 emit aboutToAddVCDTracks( position, 1); 0305 0306 m_tracks->insert( position, track ); 0307 0308 if ( track->isSegment() ) 0309 vcdOptions() ->increaseSegments( ); 0310 else 0311 vcdOptions() ->increaseSequence( ); 0312 0313 emit addedVCDTracks(); 0314 0315 emit newTracks(); 0316 0317 setModified( true ); 0318 } 0319 0320 0321 void K3b::VcdDoc::removeTrack( K3b::VcdTrack* track ) 0322 { 0323 if ( !track ) { 0324 return ; 0325 } 0326 0327 // set the current item to track 0328 if ( m_tracks->lastIndexOf( track ) >= 0 ) { 0329 // take the current item 0330 int removedPos = m_tracks->lastIndexOf( track ); 0331 0332 emit aboutToRemoveVCDTracks(removedPos, 1); 0333 0334 track = m_tracks->takeAt( removedPos ); 0335 0336 emit removedVCDTracks(); 0337 0338 // remove all pbc references to us? 0339 if ( track->hasRevRef() ) 0340 track->delRefToUs(); 0341 0342 // remove all pbc references from us? 0343 track->delRefFromUs(); 0344 0345 // emit signal before deleting the track to avoid crashes 0346 // when the view tries to call some of the tracks' methods 0347 emit trackRemoved( track ); 0348 0349 if ( track->isSegment() ) 0350 vcdOptions() ->decreaseSegments( ); 0351 else 0352 vcdOptions() ->decreaseSequence( ); 0353 0354 delete track; 0355 0356 if ( numOfTracks() == 0 ) { 0357 setVcdType( NONE ); 0358 vcdOptions() ->setAutoDetect( true ); 0359 } 0360 0361 // reorder pbc tracks 0362 setPbcTracks(); 0363 } 0364 } 0365 0366 void K3b::VcdDoc::moveTrack( K3b::VcdTrack* track, K3b::VcdTrack* before ) 0367 { 0368 if ( track == before ) 0369 return ; 0370 0371 // take the current item 0372 int removedPos = m_tracks->lastIndexOf( track ); 0373 0374 emit aboutToRemoveVCDTracks(removedPos, 1); 0375 0376 m_tracks->removeAt(removedPos); 0377 0378 emit removedVCDTracks(); 0379 0380 if( before != 0 ) { 0381 int pos = m_tracks->lastIndexOf( before ); 0382 emit aboutToAddVCDTracks(pos, 1); 0383 m_tracks->insert( pos, track ); 0384 } 0385 else { 0386 emit aboutToAddVCDTracks( m_tracks->count(), 1 ); 0387 m_tracks->append( track ); 0388 } 0389 0390 emit addedVCDTracks(); 0391 0392 // reorder pbc tracks 0393 setPbcTracks(); 0394 0395 emit changed(); 0396 } 0397 0398 0399 K3b::BurnJob* K3b::VcdDoc::newBurnJob( K3b::JobHandler* hdl, QObject* parent ) 0400 { 0401 return new K3b::VcdJob( this, hdl, parent ); 0402 } 0403 0404 void K3b::VcdDoc::informAboutNotFoundFiles() 0405 { 0406 if ( !m_notFoundFiles.isEmpty() ) { 0407 KMessageBox::informationList( view(), i18n( "Could not find the following files:" ), 0408 m_notFoundFiles, i18n( "Not Found" ) ); 0409 0410 m_notFoundFiles.clear(); 0411 } 0412 } 0413 0414 void K3b::VcdDoc::setVcdType( int type ) 0415 { 0416 m_vcdType = type; 0417 switch ( type ) { 0418 case 0: 0419 //vcd 1.1 0420 vcdOptions() ->setVcdClass( "vcd" ); 0421 vcdOptions() ->setVcdVersion( "1.1" ); 0422 break; 0423 case 1: 0424 //vcd 2.0 0425 vcdOptions() ->setVcdClass( "vcd" ); 0426 vcdOptions() ->setVcdVersion( "2.0" ); 0427 break; 0428 case 2: 0429 //svcd 1.0 0430 vcdOptions() ->setVcdClass( "svcd" ); 0431 vcdOptions() ->setVcdVersion( "1.0" ); 0432 break; 0433 case 3: 0434 //hqvcd 1.0 0435 vcdOptions() ->setVcdClass( "hqvcd" ); 0436 vcdOptions() ->setVcdVersion( "1.0" ); 0437 break; 0438 0439 } 0440 } 0441 0442 void K3b::VcdDoc::setPbcTracks() 0443 { 0444 // reorder pbc tracks 0445 /* 0446 if ( !vcdOptions()->PbcEnabled() ) 0447 return; 0448 */ 0449 0450 if ( m_tracks ) { 0451 int count = m_tracks->count(); 0452 qDebug() << QString( "K3b::VcdDoc::setPbcTracks() - we have %1 tracks in list." ).arg( count ); 0453 0454 Q_FOREACH( K3b::VcdTrack* track, *m_tracks ) { 0455 Q_FOREACH( VcdTrack::PbcTracks pbc, VcdTrack::trackPlaybackValues() ) { 0456 // do not change userdefined tracks 0457 if ( !track->isPbcUserDefined( pbc ) ) { 0458 if ( track->getPbcTrack( pbc ) ) 0459 track->getPbcTrack( pbc ) ->delFromRevRefList( track ); 0460 0461 K3b::VcdTrack* t = 0L; 0462 int index = track->index(); 0463 0464 // we are the last track 0465 if ( index == count - 1 ) { 0466 switch ( pbc ) { 0467 case K3b::VcdTrack::PREVIOUS: 0468 // we are not alone :) 0469 if ( count > 1 ) { 0470 t = m_tracks->at( index - 1 ); 0471 t->addToRevRefList( track ); 0472 track->setPbcTrack( pbc, t ); 0473 } else { 0474 track->setPbcTrack( pbc ); 0475 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0476 } 0477 break; 0478 case K3b::VcdTrack::AFTERTIMEOUT: 0479 case K3b::VcdTrack::NEXT: 0480 track->setPbcTrack( pbc ); 0481 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0482 break; 0483 case K3b::VcdTrack::RETURN: 0484 track->setPbcTrack( pbc ); 0485 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0486 break; 0487 case K3b::VcdTrack::DEFAULT: 0488 track->setPbcTrack( pbc ); 0489 track->setPbcNonTrack( pbc, K3b::VcdTrack::DISABLED ); 0490 break; 0491 } 0492 } 0493 // we are the first track 0494 else if ( index == 0 ) { 0495 switch ( pbc ) { 0496 case K3b::VcdTrack::PREVIOUS: 0497 track->setPbcTrack( pbc ); 0498 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0499 break; 0500 case K3b::VcdTrack::AFTERTIMEOUT: 0501 case K3b::VcdTrack::NEXT: 0502 t = m_tracks->at( index + 1 ); 0503 t->addToRevRefList( track ); 0504 track->setPbcTrack( pbc, t ); 0505 break; 0506 case K3b::VcdTrack::RETURN: 0507 track->setPbcTrack( pbc ); 0508 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0509 break; 0510 case K3b::VcdTrack::DEFAULT: 0511 track->setPbcTrack( pbc ); 0512 track->setPbcNonTrack( pbc, K3b::VcdTrack::DISABLED ); 0513 break; 0514 } 0515 } 0516 // we are one of the other tracks and have PREVIOUS and NEXT Track 0517 else { 0518 switch ( pbc ) { 0519 case K3b::VcdTrack::PREVIOUS: 0520 t = m_tracks->at( index - 1 ); 0521 t->addToRevRefList( track ); 0522 track->setPbcTrack( pbc, t ); 0523 break; 0524 case K3b::VcdTrack::AFTERTIMEOUT: 0525 case K3b::VcdTrack::NEXT: 0526 t = m_tracks->at( index + 1 ); 0527 t->addToRevRefList( track ); 0528 track->setPbcTrack( pbc, t ); 0529 break; 0530 case K3b::VcdTrack::RETURN: 0531 track->setPbcTrack( pbc ); 0532 track->setPbcNonTrack( pbc, K3b::VcdTrack::VIDEOEND ); 0533 break; 0534 case K3b::VcdTrack::DEFAULT: 0535 track->setPbcTrack( pbc ); 0536 track->setPbcNonTrack( pbc, K3b::VcdTrack::DISABLED ); 0537 break; 0538 } 0539 } 0540 } 0541 } 0542 } 0543 } 0544 } 0545 0546 0547 bool K3b::VcdDoc::loadDocumentData( QDomElement* root ) 0548 { 0549 newDocument(); 0550 0551 QDomNodeList nodes = root->childNodes(); 0552 0553 if ( nodes.length() < 3 ) 0554 return false; 0555 0556 if ( nodes.item( 0 ).nodeName() != "general" ) 0557 return false; 0558 if ( !readGeneralDocumentData( nodes.item( 0 ).toElement() ) ) 0559 return false; 0560 0561 if ( nodes.item( 1 ).nodeName() != "vcd" ) 0562 return false; 0563 0564 if ( nodes.item( 2 ).nodeName() != "contents" ) 0565 return false; 0566 0567 0568 // vcd Label 0569 QDomNodeList vcdNodes = nodes.item( 1 ).childNodes(); 0570 0571 for ( int i = 0; i < vcdNodes.count(); i++ ) { 0572 QDomNode item = vcdNodes.item( i ); 0573 QString name = item.nodeName(); 0574 0575 qDebug() << QString( "(K3b::VcdDoc::loadDocumentData) nodeName = '%1'" ).arg( name ); 0576 0577 if ( name == "volumeId" ) 0578 vcdOptions() ->setVolumeId( item.toElement().text() ); 0579 else if ( name == "albumId" ) 0580 vcdOptions() ->setAlbumId( item.toElement().text() ); 0581 else if ( name == "volumeSetId" ) 0582 vcdOptions() ->setVolumeSetId( item.toElement().text() ); 0583 else if ( name == "preparer" ) 0584 vcdOptions() ->setPreparer( item.toElement().text() ); 0585 else if ( name == "publisher" ) 0586 vcdOptions() ->setPublisher( item.toElement().text() ); 0587 else if ( name == "vcdType" ) 0588 setVcdType( vcdTypes( item.toElement().text().toInt() ) ); 0589 else if ( name == "mpegVersion" ) 0590 vcdOptions() ->setMpegVersion( ( K3b::VcdOptions::MPEGVersion )item.toElement().text().toInt() ); 0591 else if ( name == "PreGapLeadout" ) 0592 vcdOptions() ->setPreGapLeadout( item.toElement().text().toInt() ); 0593 else if ( name == "PreGapTrack" ) 0594 vcdOptions() ->setPreGapTrack( item.toElement().text().toInt() ); 0595 else if ( name == "FrontMarginTrack" ) 0596 vcdOptions() ->setFrontMarginTrack( item.toElement().text().toInt() ); 0597 else if ( name == "RearMarginTrack" ) 0598 vcdOptions() ->setRearMarginTrack( item.toElement().text().toInt() ); 0599 else if ( name == "FrontMarginTrackSVCD" ) 0600 vcdOptions() ->setFrontMarginTrackSVCD( item.toElement().text().toInt() ); 0601 else if ( name == "RearMarginTrackSVCD" ) 0602 vcdOptions() ->setRearMarginTrackSVCD( item.toElement().text().toInt() ); 0603 else if ( name == "volumeCount" ) 0604 vcdOptions() ->setVolumeCount( item.toElement().text().toInt() ); 0605 else if ( name == "volumeNumber" ) 0606 vcdOptions() ->setVolumeNumber( item.toElement().text().toInt() ); 0607 else if ( name == "AutoDetect" ) 0608 vcdOptions() ->setAutoDetect( item.toElement().text().toInt() ); 0609 else if ( name == "CdiSupport" ) 0610 vcdOptions() ->setCdiSupport( item.toElement().text().toInt() ); 0611 else if ( name == "NonCompliantMode" ) 0612 vcdOptions() ->setNonCompliantMode( item.toElement().text().toInt() ); 0613 else if ( name == "Sector2336" ) 0614 vcdOptions() ->setSector2336( item.toElement().text().toInt() ); 0615 else if ( name == "UpdateScanOffsets" ) 0616 vcdOptions() ->setUpdateScanOffsets( item.toElement().text().toInt() ); 0617 else if ( name == "RelaxedAps" ) 0618 vcdOptions() ->setRelaxedAps( item.toElement().text().toInt() ); 0619 else if ( name == "UseGaps" ) 0620 vcdOptions() ->setUseGaps( item.toElement().text().toInt() ); 0621 else if ( name == "PbcEnabled" ) 0622 vcdOptions() ->setPbcEnabled( item.toElement().text().toInt() ); 0623 else if ( name == "SegmentFolder" ) 0624 vcdOptions() ->setSegmentFolder( item.toElement().text().toInt() ); 0625 else if ( name == "Restriction" ) 0626 vcdOptions() ->setRestriction( item.toElement().text().toInt() ); 0627 } 0628 0629 // vcd Tracks 0630 QDomNodeList trackNodes = nodes.item( 2 ).childNodes(); 0631 0632 for ( int i = 0; i < trackNodes.length(); i++ ) { 0633 0634 // check if url is available 0635 QDomElement trackElem = trackNodes.item( i ).toElement(); 0636 QString url = trackElem.attributeNode( "url" ).value(); 0637 if ( !QFile::exists( url ) ) 0638 m_notFoundFiles.append( url ); 0639 else { 0640 QUrl k; 0641 k.setPath( url ); 0642 if ( K3b::VcdTrack * track = createTrack( k ) ) { 0643 track ->setPlayTime( trackElem.attribute( "playtime", "1" ).toInt() ); 0644 track ->setWaitTime( trackElem.attribute( "waittime", "2" ).toInt() ); 0645 track ->setReactivity( trackElem.attribute( "reactivity", "0" ).toInt() ); 0646 track -> setPbcNumKeys( ( trackElem.attribute( "numkeys", "yes" ).contains( "yes" ) ) ? true : false ); 0647 track -> setPbcNumKeysUserdefined( ( trackElem.attribute( "userdefinednumkeys", "no" ).contains( "yes" ) ) ? true : false ); 0648 0649 addTrack( track, m_tracks->count() ); 0650 } 0651 } 0652 } 0653 0654 emit newTracks(); 0655 0656 // do not add saved pbcTrack links when one ore more files missing. 0657 // TODO: add info message to informAboutNotFoundFiles(); 0658 if ( m_notFoundFiles.isEmpty() ) { 0659 VcdTrack::PbcTracks type; 0660 VcdTrack::PbcTypes val; 0661 bool pbctrack; 0662 for ( int trackId = 0; trackId < trackNodes.length(); trackId++ ) { 0663 QDomElement trackElem = trackNodes.item( trackId ).toElement(); 0664 QDomNodeList trackNodes = trackElem.childNodes(); 0665 for ( int i = 0; i < trackNodes.length(); i++ ) { 0666 QDomElement trackElem = trackNodes.item( i ).toElement(); 0667 QString name = trackElem.tagName(); 0668 if ( name.contains( "pbc" ) ) { 0669 if ( trackElem.hasAttribute ( "type" ) ) { 0670 type = static_cast<VcdTrack::PbcTracks>( trackElem.attribute ( "type" ).toInt() ); 0671 if ( trackElem.hasAttribute ( "pbctrack" ) ) { 0672 pbctrack = ( trackElem.attribute ( "pbctrack" ) == "yes" ); 0673 if ( trackElem.hasAttribute ( "val" ) ) { 0674 val = static_cast<VcdTrack::PbcTypes>( trackElem.attribute ( "val" ).toInt() ); 0675 K3b::VcdTrack* track = m_tracks->at( trackId ); 0676 K3b::VcdTrack* pbcTrack = m_tracks->at( val ); 0677 if ( pbctrack ) { 0678 pbcTrack->addToRevRefList( track ); 0679 track->setPbcTrack( type, pbcTrack ); 0680 track->setUserDefined( type, true ); 0681 } else { 0682 track->setPbcTrack( type ); 0683 track->setPbcNonTrack( type, val ); 0684 track->setUserDefined( type, true ); 0685 } 0686 } 0687 } 0688 } 0689 } else if ( name.contains( "numkeys" ) ) { 0690 if ( trackElem.hasAttribute ( "key" ) ) { 0691 int key = trackElem.attribute ( "key" ).toInt(); 0692 if ( trackElem.hasAttribute ( "val" ) ) { 0693 int val = trackElem.attribute ( "val" ).toInt() - 1; 0694 K3b::VcdTrack* track = m_tracks->at( trackId ); 0695 if ( val >= 0 ) { 0696 K3b::VcdTrack * numkeyTrack = m_tracks->at( val ); 0697 track->setDefinedNumKey( key, numkeyTrack ); 0698 } else { 0699 track->setDefinedNumKey( key, 0L ); 0700 } 0701 } 0702 } 0703 } 0704 0705 } 0706 0707 } 0708 setPbcTracks(); 0709 setModified( false ); 0710 } 0711 0712 informAboutNotFoundFiles(); 0713 return true; 0714 } 0715 0716 0717 0718 bool K3b::VcdDoc::saveDocumentData( QDomElement * docElem ) 0719 { 0720 QDomDocument doc = docElem->ownerDocument(); 0721 saveGeneralDocumentData( docElem ); 0722 0723 // save Vcd Label 0724 QDomElement vcdMain = doc.createElement( "vcd" ); 0725 0726 QDomElement vcdElem = doc.createElement( "volumeId" ); 0727 vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeId() ) ); 0728 vcdMain.appendChild( vcdElem ); 0729 0730 vcdElem = doc.createElement( "albumId" ); 0731 vcdElem.appendChild( doc.createTextNode( vcdOptions() ->albumId() ) ); 0732 vcdMain.appendChild( vcdElem ); 0733 0734 vcdElem = doc.createElement( "volumeSetId" ); 0735 vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeSetId() ) ); 0736 vcdMain.appendChild( vcdElem ); 0737 0738 vcdElem = doc.createElement( "preparer" ); 0739 vcdElem.appendChild( doc.createTextNode( vcdOptions() ->preparer() ) ); 0740 vcdMain.appendChild( vcdElem ); 0741 0742 vcdElem = doc.createElement( "publisher" ); 0743 vcdElem.appendChild( doc.createTextNode( vcdOptions() ->publisher() ) ); 0744 vcdMain.appendChild( vcdElem ); 0745 0746 // applicationId() 0747 // systemId() 0748 0749 vcdElem = doc.createElement( "vcdType" ); 0750 vcdElem.appendChild( doc.createTextNode( QString::number( vcdType() ) ) ); 0751 vcdMain.appendChild( vcdElem ); 0752 0753 vcdElem = doc.createElement( "mpegVersion" ); 0754 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->mpegVersion() ) ) ); 0755 vcdMain.appendChild( vcdElem ); 0756 0757 vcdElem = doc.createElement( "PreGapLeadout" ); 0758 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapLeadout() ) ) ); 0759 vcdMain.appendChild( vcdElem ); 0760 0761 vcdElem = doc.createElement( "PreGapTrack" ); 0762 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapTrack() ) ) ); 0763 vcdMain.appendChild( vcdElem ); 0764 0765 vcdElem = doc.createElement( "FrontMarginTrack" ); 0766 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrack() ) ) ); 0767 vcdMain.appendChild( vcdElem ); 0768 0769 vcdElem = doc.createElement( "RearMarginTrack" ); 0770 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrack() ) ) ); 0771 vcdMain.appendChild( vcdElem ); 0772 0773 vcdElem = doc.createElement( "FrontMarginTrackSVCD" ); 0774 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrackSVCD() ) ) ); 0775 vcdMain.appendChild( vcdElem ); 0776 0777 vcdElem = doc.createElement( "RearMarginTrackSVCD" ); 0778 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrackSVCD() ) ) ); 0779 vcdMain.appendChild( vcdElem ); 0780 0781 vcdElem = doc.createElement( "volumeCount" ); 0782 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeCount() ) ) ); 0783 vcdMain.appendChild( vcdElem ); 0784 0785 vcdElem = doc.createElement( "volumeNumber" ); 0786 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeNumber() ) ) ); 0787 vcdMain.appendChild( vcdElem ); 0788 0789 vcdElem = doc.createElement( "AutoDetect" ); 0790 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->AutoDetect() ) ) ); 0791 vcdMain.appendChild( vcdElem ); 0792 0793 vcdElem = doc.createElement( "CdiSupport" ); 0794 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->CdiSupport() ) ) ); 0795 vcdMain.appendChild( vcdElem ); 0796 0797 vcdElem = doc.createElement( "NonCompliantMode" ); 0798 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->NonCompliantMode() ) ) ); 0799 vcdMain.appendChild( vcdElem ); 0800 0801 vcdElem = doc.createElement( "Sector2336" ); 0802 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Sector2336() ) ) ); 0803 vcdMain.appendChild( vcdElem ); 0804 0805 vcdElem = doc.createElement( "UpdateScanOffsets" ); 0806 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UpdateScanOffsets() ) ) ); 0807 vcdMain.appendChild( vcdElem ); 0808 0809 vcdElem = doc.createElement( "RelaxedAps" ); 0810 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RelaxedAps() ) ) ); 0811 vcdMain.appendChild( vcdElem ); 0812 0813 vcdElem = doc.createElement( "UseGaps" ); 0814 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UseGaps() ) ) ); 0815 vcdMain.appendChild( vcdElem ); 0816 0817 vcdElem = doc.createElement( "PbcEnabled" ); 0818 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PbcEnabled() ) ) ); 0819 vcdMain.appendChild( vcdElem ); 0820 0821 vcdElem = doc.createElement( "SegmentFolder" ); 0822 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->SegmentFolder() ) ) ); 0823 vcdMain.appendChild( vcdElem ); 0824 0825 vcdElem = doc.createElement( "Restriction" ); 0826 vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Restriction() ) ) ); 0827 vcdMain.appendChild( vcdElem ); 0828 0829 docElem->appendChild( vcdMain ); 0830 0831 // save the tracks 0832 // ------------------------------------------------------------- 0833 QDomElement contentsElem = doc.createElement( "contents" ); 0834 0835 Q_FOREACH( K3b::VcdTrack* track, *m_tracks ) { 0836 QDomElement trackElem = doc.createElement( "track" ); 0837 trackElem.setAttribute( "url", KIO::decodeFileName( track->absolutePath() ) ); 0838 trackElem.setAttribute( "playtime", track->getPlayTime() ); 0839 trackElem.setAttribute( "waittime", track->getWaitTime() ); 0840 trackElem.setAttribute( "reactivity", track->Reactivity() ); 0841 trackElem.setAttribute( "numkeys", ( track->PbcNumKeys() ) ? "yes" : "no" ); 0842 trackElem.setAttribute( "userdefinednumkeys", ( track->PbcNumKeysUserdefined() ) ? "yes" : "no" ); 0843 0844 Q_FOREACH( VcdTrack::PbcTracks pbc, VcdTrack::trackPlaybackValues() ) { 0845 if ( track->isPbcUserDefined( pbc ) ) { 0846 // save pbcTracks 0847 QDomElement pbcElem = doc.createElement( "pbc" ); 0848 pbcElem.setAttribute( "type", pbc ); 0849 if ( track->getPbcTrack( pbc ) ) { 0850 pbcElem.setAttribute( "pbctrack", "yes" ); 0851 pbcElem.setAttribute( "val", track->getPbcTrack( pbc ) ->index() ); 0852 } else { 0853 pbcElem.setAttribute( "pbctrack", "no" ); 0854 pbcElem.setAttribute( "val", track->getNonPbcTrack( pbc ) ); 0855 } 0856 trackElem.appendChild( pbcElem ); 0857 } 0858 } 0859 QMap<int, K3b::VcdTrack*> numKeyMap = track->DefinedNumKey(); 0860 QMap<int, K3b::VcdTrack*>::const_iterator trackIt; 0861 0862 for ( trackIt = numKeyMap.constBegin(); 0863 trackIt != numKeyMap.constEnd(); 0864 ++trackIt ) { 0865 QDomElement numElem = doc.createElement( "numkeys" ); 0866 if ( *trackIt ) { 0867 numElem.setAttribute( "key", trackIt.key() ); 0868 numElem.setAttribute( "val", trackIt.value() ->index() + 1 ); 0869 } else { 0870 numElem.setAttribute( "key", trackIt.key() ); 0871 numElem.setAttribute( "val", 0 ); 0872 } 0873 trackElem.appendChild( numElem ); 0874 } 0875 0876 contentsElem.appendChild( trackElem ); 0877 } 0878 // ------------------------------------------------------------- 0879 0880 docElem->appendChild( contentsElem ); 0881 0882 return true; 0883 } 0884 0885 0886 K3b::Device::MediaTypes K3b::VcdDoc::supportedMediaTypes() const 0887 { 0888 return K3b::Device::MEDIA_WRITABLE_CD; 0889 } 0890 0891 #include "moc_k3bvcddoc.cpp"