|
|
|
/*
|
|
|
|
*
|
|
|
|
* $Id: k3bvcddoc.cpp 619556 2007-01-03 17:38:12Z trueg $
|
|
|
|
* Copyright (C) 2003-2005 Christian Kvasny <chris@k3b.org>
|
|
|
|
*
|
|
|
|
* This file is part of the K3b project.
|
|
|
|
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
* See the file "COPYING" for the exact licensing terms.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// QT-includes
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqdatastream.h>
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
|
|
|
|
// KDE-includes
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kurl.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <tdeio/global.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kstdguiitem.h>
|
|
|
|
|
|
|
|
// K3b-includes
|
|
|
|
#include "k3bvcddoc.h"
|
|
|
|
#include "k3bvcdtrack.h"
|
|
|
|
#include "k3bvcdjob.h"
|
|
|
|
#include <k3bglobals.h>
|
|
|
|
#include <k3bmsf.h>
|
|
|
|
|
|
|
|
|
|
|
|
bool desperate_mode = false;
|
|
|
|
bool preserve_header = false;
|
|
|
|
bool print_progress = true;
|
|
|
|
bool aspect_correction = false;
|
|
|
|
byte forced_sequence_header = 0;
|
|
|
|
|
|
|
|
K3bVcdDoc::K3bVcdDoc( TQObject* parent )
|
|
|
|
: K3bDoc( parent )
|
|
|
|
{
|
|
|
|
m_tracks = 0L;
|
|
|
|
m_vcdOptions = new K3bVcdOptions();
|
|
|
|
|
|
|
|
m_docType = VCD;
|
|
|
|
m_vcdType = NONE;
|
|
|
|
|
|
|
|
m_urlAddingTimer = new TQTimer( this );
|
|
|
|
connect( m_urlAddingTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotWorkUrlQueue() ) );
|
|
|
|
|
|
|
|
// FIXME: remove the newTracks() signal and replace it with the changed signal
|
|
|
|
connect( this, TQT_SIGNAL( newTracks() ), this, TQT_SIGNAL( changed() ) );
|
|
|
|
connect( this, TQT_SIGNAL( trackRemoved( K3bVcdTrack* ) ), this, TQT_SIGNAL( changed() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
K3bVcdDoc::~K3bVcdDoc()
|
|
|
|
{
|
|
|
|
if ( m_tracks ) {
|
|
|
|
m_tracks->setAutoDelete( true );
|
|
|
|
delete m_tracks;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete m_vcdOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool K3bVcdDoc::newDocument()
|
|
|
|
{
|
|
|
|
if ( m_tracks )
|
|
|
|
while ( m_tracks->first() )
|
|
|
|
removeTrack( m_tracks->first() );
|
|
|
|
else
|
|
|
|
m_tracks = new TQPtrList<K3bVcdTrack>;
|
|
|
|
m_tracks->setAutoDelete( false );
|
|
|
|
|
|
|
|
return K3bDoc::newDocument();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString K3bVcdDoc::name() const
|
|
|
|
{
|
|
|
|
return m_vcdOptions->volumeId();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TDEIO::filesize_t K3bVcdDoc::calcTotalSize() const
|
|
|
|
{
|
|
|
|
unsigned long long sum = 0;
|
|
|
|
if ( m_tracks ) {
|
|
|
|
for ( K3bVcdTrack * track = m_tracks->first(); track; track = m_tracks->next() ) {
|
|
|
|
sum += track->size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEIO::filesize_t K3bVcdDoc::size() const
|
|
|
|
{
|
|
|
|
// mode2 -> mode1 int(( n+2047 ) / 2048) * 2352
|
|
|
|
// mode1 -> mode2 int(( n+2351 ) / 2352) * 2048
|
|
|
|
long tracksize = long( ( calcTotalSize() + 2351 ) / 2352 ) * 2048;
|
|
|
|
return tracksize + ISOsize();
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEIO::filesize_t K3bVcdDoc::ISOsize() const
|
|
|
|
{
|
|
|
|
// 136000b for vcd iso reseved
|
|
|
|
long long iso_size = 136000;
|
|
|
|
if ( vcdOptions() ->CdiSupport() ) {
|
|
|
|
iso_size += vcdOptions() ->CDIsize();
|
|
|
|
}
|
|
|
|
|
|
|
|
return iso_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
K3b::Msf K3bVcdDoc::length() const
|
|
|
|
{
|
|
|
|
return K3b::Msf( size() / 2048 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool K3bVcdDoc::isImage( const KURL& url )
|
|
|
|
{
|
|
|
|
TQImage p;
|
|
|
|
return p.load( TQFile::encodeName( url.path() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::addUrls( const KURL::List& urls )
|
|
|
|
{
|
|
|
|
// make sure we add them at the end even if urls are in the queue
|
|
|
|
addTracks( urls, 99 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::addTracks( const KURL::List& urls, uint position )
|
|
|
|
{
|
|
|
|
KURL::List::ConstIterator end( urls.end() );
|
|
|
|
for ( KURL::List::ConstIterator it = urls.begin(); it != end; ++it ) {
|
|
|
|
urlsToAdd.enqueue( new PrivateUrlToAdd( K3b::convertToLocalUrl(*it), position++ ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_urlAddingTimer->start( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::slotWorkUrlQueue()
|
|
|
|
{
|
|
|
|
if ( !urlsToAdd.isEmpty() ) {
|
|
|
|
PrivateUrlToAdd * item = urlsToAdd.dequeue();
|
|
|
|
lastAddedPosition = item->position;
|
|
|
|
|
|
|
|
// append at the end by default
|
|
|
|
if ( lastAddedPosition > m_tracks->count() )
|
|
|
|
lastAddedPosition = m_tracks->count();
|
|
|
|
|
|
|
|
if ( !item->url.isLocalFile() ) {
|
|
|
|
kdDebug() << item->url.path() << " no local file" << endl;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !TQFile::exists( item->url.path() ) ) {
|
|
|
|
kdDebug() << "(K3bVcdDoc) file not found: " << item->url.path() << endl;
|
|
|
|
m_notFoundFiles.append( item->url.path() );
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( K3bVcdTrack * newTrack = createTrack( item->url ) )
|
|
|
|
addTrack( newTrack, lastAddedPosition );
|
|
|
|
|
|
|
|
delete item;
|
|
|
|
|
|
|
|
emit newTracks();
|
|
|
|
} else {
|
|
|
|
m_urlAddingTimer->stop();
|
|
|
|
|
|
|
|
emit newTracks();
|
|
|
|
|
|
|
|
// reorder pbc tracks
|
|
|
|
setPbcTracks();
|
|
|
|
|
|
|
|
informAboutNotFoundFiles();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
K3bVcdTrack* K3bVcdDoc::createTrack( const KURL& url )
|
|
|
|
{
|
|
|
|
char filename[ 255 ];
|
|
|
|
TQString error_string = "";
|
|
|
|
strcpy( filename, TQFile::encodeName( url.path() ) );
|
|
|
|
K3bMpegInfo* Mpeg = new K3bMpegInfo( filename );
|
|
|
|
|
|
|
|
if ( Mpeg ) {
|
|
|
|
int mpegVersion = Mpeg->version();
|
|
|
|
if ( mpegVersion > 0 ) {
|
|
|
|
|
|
|
|
if ( vcdType() == NONE && mpegVersion < 2 ) {
|
|
|
|
m_urlAddingTimer->stop();
|
|
|
|
setVcdType( vcdTypes( mpegVersion ) );
|
|
|
|
vcdOptions() ->setMpegVersion( mpegVersion );
|
|
|
|
KMessageBox::information( kapp->mainWidget(),
|
|
|
|
i18n( "K3b will create a %1 image from the given MPEG "
|
|
|
|
"files, but these files must already be in %2 "
|
|
|
|
"format. K3b does not yet resample MPEG files." )
|
|
|
|
.arg( i18n( "VCD" ) )
|
|
|
|
.arg( i18n( "VCD" ) ),
|
|
|
|
i18n( "Information" ) );
|
|
|
|
m_urlAddingTimer->start( 0 );
|
|
|
|
} else if ( vcdType() == NONE ) {
|
|
|
|
m_urlAddingTimer->stop();
|
|
|
|
vcdOptions() ->setMpegVersion( mpegVersion );
|
|
|
|
bool force = false;
|
|
|
|
force = ( KMessageBox::questionYesNo( kapp->mainWidget(),
|
|
|
|
i18n( "K3b will create a %1 image from the given MPEG "
|
|
|
|
"files, but these files must already be in %2 "
|
|
|
|
"format. K3b does not yet resample MPEG files." )
|
|
|
|
.arg( i18n( "SVCD" ) )
|
|
|
|
.arg( i18n( "SVCD" ) )
|
|
|
|
+ "\n\n"
|
|
|
|
+ i18n( "Note: Forcing MPEG2 as VCD is not supported by "
|
|
|
|
"some standalone DVD players." ),
|
|
|
|
i18n( "Information" ),
|
|
|
|
KStdGuiItem::ok().text(),
|
|
|
|
i18n( "Forcing VCD" ) ) == KMessageBox::No );
|
|
|
|
if ( force ) {
|
|
|
|
setVcdType( vcdTypes( 1 ) );
|
|
|
|
vcdOptions() ->setAutoDetect( false );
|
|
|
|
} else
|
|
|
|
setVcdType( vcdTypes( mpegVersion ) );
|
|
|
|
|
|
|
|
m_urlAddingTimer->start( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( numOfTracks() > 0 && vcdOptions() ->mpegVersion() != mpegVersion ) {
|
|
|
|
KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" +
|
|
|
|
i18n( "You cannot mix MPEG1 and MPEG2 video files.\nPlease start a new Project for this filetype.\nResample not implemented in K3b yet." ),
|
|
|
|
i18n( "Wrong File Type for This Project" ) );
|
|
|
|
|
|
|
|
delete Mpeg;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
K3bVcdTrack* newTrack = new K3bVcdTrack( m_tracks, url.path() );
|
|
|
|
*( newTrack->mpeg_info ) = *( Mpeg->mpeg_info );
|
|
|
|
|
|
|
|
if ( newTrack->isSegment() && !vcdOptions()->PbcEnabled() ) {
|
|
|
|
KMessageBox::information( kapp->mainWidget(),
|
|
|
|
i18n( "PBC (Playback control) enabled.\n"
|
|
|
|
"Videoplayers can not reach Segments (Mpeg Still Pictures) without Playback control ." ) ,
|
|
|
|
i18n( "Information" ) );
|
|
|
|
|
|
|
|
vcdOptions()->setPbcEnabled( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
// set defaults;
|
|
|
|
newTrack->setPlayTime( vcdOptions() ->PbcPlayTime() );
|
|
|
|
newTrack->setWaitTime( vcdOptions() ->PbcWaitTime() );
|
|
|
|
newTrack->setPbcNumKeys( vcdOptions() ->PbcNumkeysEnabled() );
|
|
|
|
delete Mpeg;
|
|
|
|
|
|
|
|
// debugging output
|
|
|
|
newTrack->PrintInfo();
|
|
|
|
|
|
|
|
return newTrack;
|
|
|
|
}
|
|
|
|
} else if ( isImage( url ) ) { // image track
|
|
|
|
// woking on ...
|
|
|
|
// for future use
|
|
|
|
// photoalbum starts here
|
|
|
|
// return here the new photoalbum track
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( Mpeg ) {
|
|
|
|
error_string = Mpeg->error_string();
|
|
|
|
delete Mpeg;
|
|
|
|
}
|
|
|
|
|
|
|
|
// error (unsupported files)
|
|
|
|
KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" +
|
|
|
|
i18n( "Only MPEG1 and MPEG2 video files are supported.\n" ) + error_string ,
|
|
|
|
i18n( "Wrong File Format" ) );
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::addTrack( const KURL& url, uint position )
|
|
|
|
{
|
|
|
|
urlsToAdd.enqueue( new PrivateUrlToAdd( url, position ) );
|
|
|
|
|
|
|
|
m_urlAddingTimer->start( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bVcdDoc::addTrack( K3bVcdTrack* track, uint position )
|
|
|
|
{
|
|
|
|
if ( m_tracks->count() >= 98 ) {
|
|
|
|
kdDebug() << "(K3bVcdDoc) VCD Green Book only allows 98 tracks." << endl;
|
|
|
|
// TODO: show some messagebox
|
|
|
|
delete track;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
lastAddedPosition = position;
|
|
|
|
|
|
|
|
if ( !m_tracks->insert( position, track ) ) {
|
|
|
|
lastAddedPosition = m_tracks->count();
|
|
|
|
m_tracks->insert( m_tracks->count(), track );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( track->isSegment() )
|
|
|
|
vcdOptions() ->increaseSegments( );
|
|
|
|
else
|
|
|
|
vcdOptions() ->increaseSequence( );
|
|
|
|
|
|
|
|
emit newTracks();
|
|
|
|
|
|
|
|
setModified( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bVcdDoc::removeTrack( K3bVcdTrack* track )
|
|
|
|
{
|
|
|
|
if ( !track ) {
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the current item to track
|
|
|
|
if ( m_tracks->findRef( track ) >= 0 ) {
|
|
|
|
// take the current item
|
|
|
|
track = m_tracks->take();
|
|
|
|
|
|
|
|
// remove all pbc references to us?
|
|
|
|
if ( track->hasRevRef() )
|
|
|
|
track->delRefToUs();
|
|
|
|
|
|
|
|
// remove all pbc references from us?
|
|
|
|
track->delRefFromUs();
|
|
|
|
|
|
|
|
// emit signal before deleting the track to avoid crashes
|
|
|
|
// when the view tries to call some of the tracks' methods
|
|
|
|
emit trackRemoved( track );
|
|
|
|
|
|
|
|
if ( track->isSegment() )
|
|
|
|
vcdOptions() ->decreaseSegments( );
|
|
|
|
else
|
|
|
|
vcdOptions() ->decreaseSequence( );
|
|
|
|
|
|
|
|
delete track;
|
|
|
|
|
|
|
|
if ( numOfTracks() == 0 ) {
|
|
|
|
setVcdType( NONE );
|
|
|
|
vcdOptions() ->setAutoDetect( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
// reorder pbc tracks
|
|
|
|
setPbcTracks();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::moveTrack( const K3bVcdTrack* track, const K3bVcdTrack* after )
|
|
|
|
{
|
|
|
|
if ( track == after )
|
|
|
|
return ;
|
|
|
|
|
|
|
|
// set the current item to track
|
|
|
|
m_tracks->findRef( track );
|
|
|
|
// take the current item
|
|
|
|
track = m_tracks->take();
|
|
|
|
|
|
|
|
// if after == 0 findRef returnes -1
|
|
|
|
int pos = m_tracks->findRef( after );
|
|
|
|
m_tracks->insert( pos + 1, track );
|
|
|
|
|
|
|
|
// reorder pbc tracks
|
|
|
|
setPbcTracks();
|
|
|
|
|
|
|
|
emit changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString K3bVcdDoc::typeString() const
|
|
|
|
{
|
|
|
|
return "vcd";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
K3bBurnJob* K3bVcdDoc::newBurnJob( K3bJobHandler* hdl, TQObject* parent )
|
|
|
|
{
|
|
|
|
return new K3bVcdJob( this, hdl, parent );
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::informAboutNotFoundFiles()
|
|
|
|
{
|
|
|
|
if ( !m_notFoundFiles.isEmpty() ) {
|
|
|
|
KMessageBox::informationList( view(), i18n( "Could not find the following files:" ),
|
|
|
|
m_notFoundFiles, i18n( "Not Found" ) );
|
|
|
|
|
|
|
|
m_notFoundFiles.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::setVcdType( int type )
|
|
|
|
{
|
|
|
|
m_vcdType = type;
|
|
|
|
switch ( type ) {
|
|
|
|
case 0:
|
|
|
|
//vcd 1.1
|
|
|
|
vcdOptions() ->setVcdClass( "vcd" );
|
|
|
|
vcdOptions() ->setVcdVersion( "1.1" );
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//vcd 2.0
|
|
|
|
vcdOptions() ->setVcdClass( "vcd" );
|
|
|
|
vcdOptions() ->setVcdVersion( "2.0" );
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
//svcd 1.0
|
|
|
|
vcdOptions() ->setVcdClass( "svcd" );
|
|
|
|
vcdOptions() ->setVcdVersion( "1.0" );
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
//hqvcd 1.0
|
|
|
|
vcdOptions() ->setVcdClass( "hqvcd" );
|
|
|
|
vcdOptions() ->setVcdVersion( "1.0" );
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void K3bVcdDoc::setPbcTracks()
|
|
|
|
{
|
|
|
|
// reorder pbc tracks
|
|
|
|
/*
|
|
|
|
if ( !vcdOptions()->PbcEnabled() )
|
|
|
|
return;
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ( m_tracks ) {
|
|
|
|
int count = m_tracks->count();
|
|
|
|
kdDebug() << TQString( "K3bVcdDoc::setPbcTracks() - we have %1 tracks in list." ).arg( count ) << endl;
|
|
|
|
|
|
|
|
TQPtrListIterator<K3bVcdTrack> iterTrack( *m_tracks );
|
|
|
|
K3bVcdTrack* track;
|
|
|
|
while ( ( track = iterTrack.current() ) != 0 ) {
|
|
|
|
++iterTrack;
|
|
|
|
for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) {
|
|
|
|
// do not change userdefined tracks
|
|
|
|
if ( !track->isPbcUserDefined( i ) ) {
|
|
|
|
if ( track->getPbcTrack( i ) )
|
|
|
|
track->getPbcTrack( i ) ->delFromRevRefList( track );
|
|
|
|
|
|
|
|
K3bVcdTrack* t = 0L;
|
|
|
|
int index = track->index();
|
|
|
|
|
|
|
|
// we are the last track
|
|
|
|
if ( index == count - 1 ) {
|
|
|
|
switch ( i ) {
|
|
|
|
case K3bVcdTrack::PREVIOUS:
|
|
|
|
// we are not alone :)
|
|
|
|
if ( count > 1 ) {
|
|
|
|
t = at( index - 1 );
|
|
|
|
t->addToRevRefList( track );
|
|
|
|
track->setPbcTrack( i, t );
|
|
|
|
} else {
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::AFTERTIMEOUT:
|
|
|
|
case K3bVcdTrack::NEXT:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::RETURN:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::DEFAULT:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// we are the first track
|
|
|
|
else if ( index == 0 ) {
|
|
|
|
switch ( i ) {
|
|
|
|
case K3bVcdTrack::PREVIOUS:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::AFTERTIMEOUT:
|
|
|
|
case K3bVcdTrack::NEXT:
|
|
|
|
t = at( index + 1 );
|
|
|
|
t->addToRevRefList( track );
|
|
|
|
track->setPbcTrack( i, t );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::RETURN:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::DEFAULT:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// we are one of the other tracks and have PREVIOUS and NEXT Track
|
|
|
|
else {
|
|
|
|
switch ( i ) {
|
|
|
|
case K3bVcdTrack::PREVIOUS:
|
|
|
|
t = at( index - 1 );
|
|
|
|
t->addToRevRefList( track );
|
|
|
|
track->setPbcTrack( i, t );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::AFTERTIMEOUT:
|
|
|
|
case K3bVcdTrack::NEXT:
|
|
|
|
t = at( index + 1 );
|
|
|
|
t->addToRevRefList( track );
|
|
|
|
track->setPbcTrack( i, t );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::RETURN:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
|
|
|
|
break;
|
|
|
|
case K3bVcdTrack::DEFAULT:
|
|
|
|
track->setPbcTrack( i );
|
|
|
|
track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool K3bVcdDoc::loadDocumentData( TQDomElement* root )
|
|
|
|
{
|
|
|
|
newDocument();
|
|
|
|
|
|
|
|
TQDomNodeList nodes = root->childNodes();
|
|
|
|
|
|
|
|
if ( nodes.length() < 3 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( nodes.item( 0 ).nodeName() != "general" )
|
|
|
|
return false;
|
|
|
|
if ( !readGeneralDocumentData( nodes.item( 0 ).toElement() ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( nodes.item( 1 ).nodeName() != "vcd" )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( nodes.item( 2 ).nodeName() != "contents" )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// vcd Label
|
|
|
|
TQDomNodeList vcdNodes = nodes.item( 1 ).childNodes();
|
|
|
|
|
|
|
|
for ( uint i = 0; i < vcdNodes.count(); i++ ) {
|
|
|
|
TQDomNode item = vcdNodes.item( i );
|
|
|
|
TQString name = item.nodeName();
|
|
|
|
|
|
|
|
kdDebug() << TQString( "(K3bVcdDoc::loadDocumentData) nodeName = '%1'" ).arg( name ) << endl;
|
|
|
|
|
|
|
|
if ( name == "volumeId" )
|
|
|
|
vcdOptions() ->setVolumeId( item.toElement().text() );
|
|
|
|
else if ( name == "albumId" )
|
|
|
|
vcdOptions() ->setAlbumId( item.toElement().text() );
|
|
|
|
else if ( name == "volumeSetId" )
|
|
|
|
vcdOptions() ->setVolumeSetId( item.toElement().text() );
|
|
|
|
else if ( name == "preparer" )
|
|
|
|
vcdOptions() ->setPreparer( item.toElement().text() );
|
|
|
|
else if ( name == "publisher" )
|
|
|
|
vcdOptions() ->setPublisher( item.toElement().text() );
|
|
|
|
else if ( name == "vcdType" )
|
|
|
|
setVcdType( vcdTypes( item.toElement().text().toInt() ) );
|
|
|
|
else if ( name == "mpegVersion" )
|
|
|
|
vcdOptions() ->setMpegVersion( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "PreGapLeadout" )
|
|
|
|
vcdOptions() ->setPreGapLeadout( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "PreGapTrack" )
|
|
|
|
vcdOptions() ->setPreGapTrack( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "FrontMarginTrack" )
|
|
|
|
vcdOptions() ->setFrontMarginTrack( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "RearMarginTrack" )
|
|
|
|
vcdOptions() ->setRearMarginTrack( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "FrontMarginTrackSVCD" )
|
|
|
|
vcdOptions() ->setFrontMarginTrackSVCD( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "RearMarginTrackSVCD" )
|
|
|
|
vcdOptions() ->setRearMarginTrackSVCD( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "volumeCount" )
|
|
|
|
vcdOptions() ->setVolumeCount( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "volumeNumber" )
|
|
|
|
vcdOptions() ->setVolumeNumber( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "AutoDetect" )
|
|
|
|
vcdOptions() ->setAutoDetect( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "CdiSupport" )
|
|
|
|
vcdOptions() ->setCdiSupport( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "NonCompliantMode" )
|
|
|
|
vcdOptions() ->setNonCompliantMode( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "Sector2336" )
|
|
|
|
vcdOptions() ->setSector2336( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "UpdateScanOffsets" )
|
|
|
|
vcdOptions() ->setUpdateScanOffsets( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "RelaxedAps" )
|
|
|
|
vcdOptions() ->setRelaxedAps( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "UseGaps" )
|
|
|
|
vcdOptions() ->setUseGaps( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "PbcEnabled" )
|
|
|
|
vcdOptions() ->setPbcEnabled( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "SegmentFolder" )
|
|
|
|
vcdOptions() ->setSegmentFolder( item.toElement().text().toInt() );
|
|
|
|
else if ( name == "Restriction" )
|
|
|
|
vcdOptions() ->setRestriction( item.toElement().text().toInt() );
|
|
|
|
}
|
|
|
|
|
|
|
|
// vcd Tracks
|
|
|
|
TQDomNodeList trackNodes = nodes.item( 2 ).childNodes();
|
|
|
|
|
|
|
|
for ( uint i = 0; i < trackNodes.length(); i++ ) {
|
|
|
|
|
|
|
|
// check if url is available
|
|
|
|
TQDomElement trackElem = trackNodes.item( i ).toElement();
|
|
|
|
TQString url = trackElem.attributeNode( "url" ).value();
|
|
|
|
if ( !TQFile::exists( url ) )
|
|
|
|
m_notFoundFiles.append( url );
|
|
|
|
else {
|
|
|
|
KURL k;
|
|
|
|
k.setPath( url );
|
|
|
|
if ( K3bVcdTrack * track = createTrack( k ) ) {
|
|
|
|
track ->setPlayTime( trackElem.attribute( "playtime", "1" ).toInt() );
|
|
|
|
track ->setWaitTime( trackElem.attribute( "waittime", "2" ).toInt() );
|
|
|
|
track ->setReactivity( trackElem.attribute( "reactivity", "0" ).toInt() );
|
|
|
|
track -> setPbcNumKeys( ( trackElem.attribute( "numkeys", "yes" ).contains( "yes" ) ) ? true : false );
|
|
|
|
track -> setPbcNumKeysUserdefined( ( trackElem.attribute( "userdefinednumkeys", "no" ).contains( "yes" ) ) ? true : false );
|
|
|
|
|
|
|
|
addTrack( track, m_tracks->count() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit newTracks();
|
|
|
|
|
|
|
|
// do not add saved pbcTrack links when one ore more files missing.
|
|
|
|
// TODO: add info message to informAboutNotFoundFiles();
|
|
|
|
if ( m_notFoundFiles.isEmpty() ) {
|
|
|
|
int type;
|
|
|
|
int val;
|
|
|
|
bool pbctrack;
|
|
|
|
for ( uint trackId = 0; trackId < trackNodes.length(); trackId++ ) {
|
|
|
|
TQDomElement trackElem = trackNodes.item( trackId ).toElement();
|
|
|
|
TQDomNodeList trackNodes = trackElem.childNodes();
|
|
|
|
for ( uint i = 0; i < trackNodes.length(); i++ ) {
|
|
|
|
TQDomElement trackElem = trackNodes.item( i ).toElement();
|
|
|
|
TQString name = trackElem.tagName();
|
|
|
|
if ( name.contains( "pbc" ) ) {
|
|
|
|
if ( trackElem.hasAttribute ( "type" ) ) {
|
|
|
|
type = trackElem.attribute ( "type" ).toInt();
|
|
|
|
if ( trackElem.hasAttribute ( "pbctrack" ) ) {
|
|
|
|
pbctrack = ( trackElem.attribute ( "pbctrack" ) == "yes" );
|
|
|
|
if ( trackElem.hasAttribute ( "val" ) ) {
|
|
|
|
val = trackElem.attribute ( "val" ).toInt();
|
|
|
|
K3bVcdTrack* track = m_tracks->at( trackId );
|
|
|
|
K3bVcdTrack* pbcTrack = m_tracks->at( val );
|
|
|
|
if ( pbctrack ) {
|
|
|
|
pbcTrack->addToRevRefList( track );
|
|
|
|
track->setPbcTrack( type, pbcTrack );
|
|
|
|
track->setUserDefined( type, true );
|
|
|
|
} else {
|
|
|
|
track->setPbcTrack( type );
|
|
|
|
track->setPbcNonTrack( type, val );
|
|
|
|
track->setUserDefined( type, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( name.contains( "numkeys" ) ) {
|
|
|
|
if ( trackElem.hasAttribute ( "key" ) ) {
|
|
|
|
int key = trackElem.attribute ( "key" ).toInt();
|
|
|
|
if ( trackElem.hasAttribute ( "val" ) ) {
|
|
|
|
int val = trackElem.attribute ( "val" ).toInt() - 1;
|
|
|
|
K3bVcdTrack* track = m_tracks->at( trackId );
|
|
|
|
if ( val >= 0 ) {
|
|
|
|
K3bVcdTrack * numkeyTrack = m_tracks->at( val );
|
|
|
|
track->setDefinedNumKey( key, numkeyTrack );
|
|
|
|
} else {
|
|
|
|
track->setDefinedNumKey( key, 0L );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
setPbcTracks();
|
|
|
|
setModified( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
informAboutNotFoundFiles();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool K3bVcdDoc::saveDocumentData( TQDomElement * docElem )
|
|
|
|
{
|
|
|
|
TQDomDocument doc = docElem->ownerDocument();
|
|
|
|
saveGeneralDocumentData( docElem );
|
|
|
|
|
|
|
|
// save Vcd Label
|
|
|
|
TQDomElement vcdMain = doc.createElement( "vcd" );
|
|
|
|
|
|
|
|
TQDomElement vcdElem = doc.createElement( "volumeId" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeId() ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "albumId" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( vcdOptions() ->albumId() ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "volumeSetId" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeSetId() ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "preparer" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( vcdOptions() ->preparer() ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "publisher" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( vcdOptions() ->publisher() ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
// applicationId()
|
|
|
|
// systemId()
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "vcdType" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdType() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "mpegVersion" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->mpegVersion() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "PreGapLeadout" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->PreGapLeadout() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "PreGapTrack" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->PreGapTrack() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "FrontMarginTrack" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->FrontMarginTrack() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "RearMarginTrack" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->RearMarginTrack() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "FrontMarginTrackSVCD" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->FrontMarginTrackSVCD() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "RearMarginTrackSVCD" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->RearMarginTrackSVCD() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "volumeCount" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->volumeCount() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "volumeNumber" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->volumeNumber() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "AutoDetect" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->AutoDetect() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "CdiSupport" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->CdiSupport() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "NonCompliantMode" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->NonCompliantMode() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "Sector2336" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->Sector2336() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "UpdateScanOffsets" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->UpdateScanOffsets() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "RelaxedAps" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->RelaxedAps() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "UseGaps" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->UseGaps() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "PbcEnabled" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->PbcEnabled() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "SegmentFolder" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->SegmentFolder() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
vcdElem = doc.createElement( "Restriction" );
|
|
|
|
vcdElem.appendChild( doc.createTextNode( TQString::number( vcdOptions() ->Restriction() ) ) );
|
|
|
|
vcdMain.appendChild( vcdElem );
|
|
|
|
|
|
|
|
docElem->appendChild( vcdMain );
|
|
|
|
|
|
|
|
// save the tracks
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
TQDomElement contentsElem = doc.createElement( "contents" );
|
|
|
|
|
|
|
|
TQPtrListIterator<K3bVcdTrack> iterTrack( *m_tracks );
|
|
|
|
K3bVcdTrack* track;
|
|
|
|
|
|
|
|
while ( ( track = iterTrack.current() ) != 0 ) {
|
|
|
|
++iterTrack;
|
|
|
|
|
|
|
|
TQDomElement trackElem = doc.createElement( "track" );
|
|
|
|
trackElem.setAttribute( "url", TDEIO::decodeFileName( track->absPath() ) );
|
|
|
|
trackElem.setAttribute( "playtime", track->getPlayTime() );
|
|
|
|
trackElem.setAttribute( "waittime", track->getWaitTime() );
|
|
|
|
trackElem.setAttribute( "reactivity", track->Reactivity() );
|
|
|
|
trackElem.setAttribute( "numkeys", ( track->PbcNumKeys() ) ? "yes" : "no" );
|
|
|
|
trackElem.setAttribute( "userdefinednumkeys", ( track->PbcNumKeysUserdefined() ) ? "yes" : "no" );
|
|
|
|
|
|
|
|
for ( int i = 0;
|
|
|
|
i < K3bVcdTrack::_maxPbcTracks;
|
|
|
|
i++ ) {
|
|
|
|
if ( track->isPbcUserDefined( i ) ) {
|
|
|
|
// save pbcTracks
|
|
|
|
TQDomElement pbcElem = doc.createElement( "pbc" );
|
|
|
|
pbcElem.setAttribute( "type", i );
|
|
|
|
if ( track->getPbcTrack( i ) ) {
|
|
|
|
pbcElem.setAttribute( "pbctrack", "yes" );
|
|
|
|
pbcElem.setAttribute( "val", track->getPbcTrack( i ) ->index() );
|
|
|
|
} else {
|
|
|
|
pbcElem.setAttribute( "pbctrack", "no" );
|
|
|
|
pbcElem.setAttribute( "val", track->getNonPbcTrack( i ) );
|
|
|
|
}
|
|
|
|
trackElem.appendChild( pbcElem );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQMap<int, K3bVcdTrack*> numKeyMap = track->DefinedNumKey();
|
|
|
|
TQMap<int, K3bVcdTrack*>::const_iterator trackIt;
|
|
|
|
|
|
|
|
for ( trackIt = numKeyMap.begin();
|
|
|
|
trackIt != numKeyMap.end();
|
|
|
|
++trackIt ) {
|
|
|
|
TQDomElement numElem = doc.createElement( "numkeys" );
|
|
|
|
if ( trackIt.data() ) {
|
|
|
|
numElem.setAttribute( "key", trackIt.key() );
|
|
|
|
numElem.setAttribute( "val", trackIt.data() ->index() + 1 );
|
|
|
|
} else {
|
|
|
|
numElem.setAttribute( "key", trackIt.key() );
|
|
|
|
numElem.setAttribute( "val", 0 );
|
|
|
|
}
|
|
|
|
trackElem.appendChild( numElem );
|
|
|
|
}
|
|
|
|
|
|
|
|
contentsElem.appendChild( trackElem );
|
|
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
|
|
|
|
|
|
docElem->appendChild( contentsElem );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "k3bvcddoc.moc"
|