File indexing completed on 2024-05-12 04:51:10
0001 /* 0002 SPDX-FileCopyrightText: 2003-2004 Christian Kvasny <chris@k3b.org> 0003 SPDX-FileCopyrightText: 2008 Sebastian Trueg <trueg@k3b.org> 0004 SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl> 0005 SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "k3bvcdtrack.h" 0011 #include "k3bglobals.h" 0012 #include "k3b_i18n.h" 0013 0014 #include <KConfig> 0015 0016 #include <QDebug> 0017 #include <QString> 0018 #include <QFileInfo> 0019 0020 #include <stdio.h> 0021 #include <sys/types.h> 0022 #include <sys/stat.h> 0023 #include <unistd.h> 0024 0025 K3b::VcdTrack::VcdTrack( QList<K3b::VcdTrack*>* parent, const QString& filename ) 0026 : mpeg_info(Q_NULLPTR), 0027 m_pbcnumkeys( true ), 0028 m_pbcnumkeysuserdefined( false ), 0029 m_file( filename ) 0030 { 0031 m_parent = parent; 0032 m_title = QFileInfo( m_file ).completeBaseName(); 0033 0034 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) { 0035 m_pbctrackmap.insert( playback, 0L ); 0036 m_pbcnontrackmap.insert( playback, DISABLED ); 0037 m_pbcusrdefmap.insert( playback, false ); 0038 } 0039 0040 m_reactivity = false; 0041 0042 m_definedkeysmap.clear(); 0043 0044 mpeg_info = new Mpeginfo(); 0045 } 0046 0047 0048 K3b::VcdTrack::~VcdTrack() 0049 { 0050 if (mpeg_info) { 0051 delete mpeg_info; 0052 mpeg_info = Q_NULLPTR; 0053 } 0054 } 0055 0056 0057 KIO::filesize_t K3b::VcdTrack::size() const 0058 { 0059 return m_file.size(); 0060 } 0061 0062 int K3b::VcdTrack::index() const 0063 { 0064 // (trueg): I have no idea why I need to const cast here! 0065 int i = m_parent->indexOf( const_cast<K3b::VcdTrack*>( this ) ); 0066 if ( i < 0 ) 0067 qDebug() << "(K3b::VcdTrack) I'm not part of my parent!"; 0068 return i; 0069 } 0070 0071 0072 QList<K3b::VcdTrack::PbcTracks> K3b::VcdTrack::trackPlaybackValues() 0073 { 0074 QList<PbcTracks> playbacks; 0075 playbacks << PREVIOUS << NEXT << RETURN << DEFAULT << AFTERTIMEOUT; 0076 return playbacks; 0077 } 0078 0079 0080 void K3b::VcdTrack::addToRevRefList( K3b::VcdTrack* revreftrack ) 0081 { 0082 qDebug() << "K3b::VcdTrack::addToRevRefList: track = " << revreftrack; 0083 0084 m_revreflist.append( revreftrack ); 0085 0086 qDebug() << "K3b::VcdTrack::hasRevRef count = " << m_revreflist.count() << " empty = " << m_revreflist.isEmpty(); 0087 } 0088 0089 void K3b::VcdTrack::delFromRevRefList( K3b::VcdTrack* revreftrack ) 0090 { 0091 m_revreflist.removeAll( revreftrack ); 0092 } 0093 0094 bool K3b::VcdTrack::hasRevRef() 0095 { 0096 return !m_revreflist.isEmpty() ; 0097 } 0098 0099 void K3b::VcdTrack::delRefToUs() 0100 { 0101 Q_FOREACH( K3b::VcdTrack* track, m_revreflist ) { 0102 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) { 0103 qDebug() << "K3b::VcdTrack::delRefToUs count = " << m_revreflist.count() << " empty = " << m_revreflist.isEmpty() << " track = " << track << " this = " << this; 0104 if( this == track->getPbcTrack( playback ) ) { 0105 track->setPbcTrack( playback ); 0106 track->setUserDefined( playback, false ); 0107 track->delFromRevRefList( this ); 0108 } 0109 } 0110 } 0111 } 0112 0113 void K3b::VcdTrack::delRefFromUs() 0114 { 0115 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) { 0116 if ( this->getPbcTrack( playback ) ) { 0117 this->getPbcTrack( playback ) ->delFromRevRefList( this ); 0118 } 0119 } 0120 } 0121 0122 void K3b::VcdTrack::setPbcTrack( PbcTracks which, K3b::VcdTrack* pbctrack ) 0123 { 0124 qDebug() << "K3b::VcdTrack::setPbcTrack " << which << ", " << pbctrack; 0125 m_pbctrackmap[which] = pbctrack; 0126 } 0127 0128 void K3b::VcdTrack::setPbcNonTrack( PbcTracks which, PbcTypes type ) 0129 { 0130 qDebug() << "K3b::VcdTrack::setNonPbcTrack " << which << ", " << type; 0131 m_pbcnontrackmap[which] = type; 0132 } 0133 0134 void K3b::VcdTrack::setUserDefined( PbcTracks which, bool ud ) 0135 { 0136 m_pbcusrdefmap[which] = ud; 0137 } 0138 0139 K3b::VcdTrack* K3b::VcdTrack::getPbcTrack( PbcTracks which ) 0140 { 0141 if ( m_pbctrackmap.find( which ) == m_pbctrackmap.end() ) 0142 return 0; 0143 else 0144 return m_pbctrackmap[ which ]; 0145 } 0146 0147 int K3b::VcdTrack::getNonPbcTrack( PbcTracks which ) 0148 { 0149 if ( m_pbcnontrackmap.find( which ) == m_pbcnontrackmap.end() ) 0150 return 0; 0151 else 0152 return m_pbcnontrackmap[ which ]; 0153 } 0154 0155 bool K3b::VcdTrack::isPbcUserDefined( PbcTracks which ) 0156 { 0157 return m_pbcusrdefmap[ which ]; 0158 } 0159 0160 QString K3b::VcdTrack::resolution() 0161 { 0162 if ( mpeg_info->has_video ) { 0163 for ( int i = 0; i < 2; i++ ) { 0164 if ( mpeg_info->video[ i ].seen ) { 0165 return QString( "%1 x %2" ).arg( mpeg_info->video[ i ].hsize ).arg( mpeg_info->video[ i ].vsize ); 0166 } 0167 } 0168 } 0169 0170 return i18n( "n/a" ); 0171 } 0172 0173 QString K3b::VcdTrack::highresolution() 0174 { 0175 if ( mpeg_info->has_video ) { 0176 if ( mpeg_info->video[ 2 ].seen ) { 0177 return QString( "%1 x %2" ).arg( mpeg_info->video[ 2 ].hsize ).arg( mpeg_info->video[ 2 ].vsize ); 0178 } 0179 } 0180 return i18n( "n/a" ); 0181 } 0182 0183 QString K3b::VcdTrack::video_frate() 0184 { 0185 if ( mpeg_info->has_video ) { 0186 for ( int i = 0; i < 2; i++ ) { 0187 if ( mpeg_info->video[ i ].seen ) { 0188 return QString::number( mpeg_info->video[ i ].frate ); 0189 } 0190 } 0191 } 0192 0193 return i18n( "n/a" ); 0194 } 0195 0196 QString K3b::VcdTrack::video_bitrate() 0197 { 0198 if ( mpeg_info->has_video ) { 0199 for ( int i = 0; i < 2; i++ ) { 0200 if ( mpeg_info->video[ i ].seen ) { 0201 return i18np( "1 bit/s", "%1 bits/s" , mpeg_info->video[ i ].bitrate ) ; 0202 } 0203 } 0204 } 0205 0206 return i18n( "n/a" ); 0207 } 0208 0209 0210 0211 QString K3b::VcdTrack::video_format() 0212 { 0213 if ( mpeg_info->has_video ) { 0214 for ( int i = 0; i < 2; i++ ) { 0215 if ( mpeg_info->video[ i ].seen ) { 0216 switch ( mpeg_info->video[ i ].video_format ) { 0217 case 0 : 0218 return i18n( "Component" ); 0219 break; 0220 case 1 : 0221 return "PAL"; 0222 break; 0223 case 2 : 0224 return "NTSC"; 0225 break; 0226 case 3 : 0227 return "SECAM"; 0228 break; 0229 case 4 : 0230 return "MAC"; 0231 break; 0232 case 5 : 0233 default: 0234 return i18n( "Unspecified" ); 0235 qDebug() << "K3b::VcdTrack::video_format() :" << mpeg_info->video[ i ].video_format; 0236 break; 0237 } 0238 } 0239 } 0240 } 0241 return i18n( "n/a" ); 0242 } 0243 0244 QString K3b::VcdTrack::video_chroma() 0245 { 0246 if ( mpeg_info->has_video ) { 0247 // MPEG1 only supports 4:2:0 Format 0248 if ( version() == K3b::MpegInfo::MPEG_VERS_MPEG1 ) 0249 return QString( "4:2:0" ); 0250 0251 for ( int i = 0; i < 2; i++ ) { 0252 if ( mpeg_info->video[ i ].seen ) { 0253 switch ( mpeg_info->video[ i ].chroma_format ) { 0254 case 1 : 0255 return QString( "4:2:0" ); 0256 break; 0257 case 2 : 0258 return QString( "4:2:2" ); 0259 break; 0260 case 3 : 0261 return QString( "4:4:4" ); 0262 break; 0263 0264 } 0265 } 0266 } 0267 } 0268 0269 return i18n( "n/a" ); 0270 } 0271 0272 QString K3b::VcdTrack::audio_layer() 0273 { 0274 if ( mpeg_info->has_audio ) { 0275 for ( int i = 0; i < 2; i++ ) { 0276 if ( mpeg_info->audio[ i ].seen ) { 0277 return QString::number( mpeg_info->audio[ i ].layer ); 0278 } 0279 } 0280 } 0281 0282 return i18n( "n/a" ); 0283 } 0284 0285 QString K3b::VcdTrack::audio_bitrate() 0286 { 0287 if ( mpeg_info->has_audio ) { 0288 for ( int i = 0; i < 2; i++ ) { 0289 if ( mpeg_info->audio[ i ].seen ) { 0290 return i18np( "1 bit/s", "%1 bits/s" , mpeg_info->audio[ i ].bitrate ) ; 0291 } 0292 } 0293 } 0294 0295 return i18n( "n/a" ); 0296 } 0297 0298 QString K3b::VcdTrack::audio_sampfreq() 0299 { 0300 if ( mpeg_info->has_audio ) { 0301 for ( int i = 0; i < 2; i++ ) { 0302 if ( mpeg_info->audio[ i ].seen ) { 0303 return i18n( "%1 Hz" , mpeg_info->audio[ i ].sampfreq ) ; 0304 } 0305 } 0306 } 0307 0308 return i18n( "n/a" ); 0309 } 0310 0311 QString K3b::VcdTrack::audio_mode( ) 0312 { 0313 if ( mpeg_info->has_audio ) { 0314 for ( int i = 2; i >= 0; i-- ) 0315 if ( mpeg_info->audio[ i ].seen ) 0316 return QString( audio_type2str( mpeg_info->audio[ i ].version, mpeg_info->audio[ i ].mode, i ) ); 0317 0318 } 0319 0320 return i18n( "n/a" ); 0321 } 0322 0323 QString K3b::VcdTrack::audio_copyright( ) 0324 { 0325 if ( mpeg_info->has_audio ) { 0326 for ( int i = 2; i >= 0; i-- ) { 0327 if ( mpeg_info->audio[ i ].seen ) 0328 { 0329 if ( mpeg_info->audio[ i ].copyright ) 0330 return QString( "(c) " ) + ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) ); 0331 else 0332 return ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) ); 0333 } 0334 } 0335 } 0336 0337 return i18n( "n/a" ); 0338 } 0339 0340 QString K3b::VcdTrack::mpegTypeS( bool audio ) 0341 { 0342 if ( mpeg_info->has_video && !audio ) { 0343 for ( int i = 0; i < 3; i++ ) 0344 if ( mpeg_info->video[ i ].seen ) { 0345 if ( i == 0 ) { 0346 return QString( "MPEG%1 ").arg(mpeg_info->version ) + i18n( "Motion Picture" ); 0347 } else { 0348 return QString( "MPEG%1 ").arg(mpeg_info->version ) + i18n( "Still Picture" ); 0349 } 0350 } 0351 } 0352 if ( mpeg_info->has_audio && audio ) { 0353 for ( int i = 0; i < 3; i++ ) 0354 if ( mpeg_info->audio[ i ].seen ) { 0355 return QString( "MPEG%1 ").arg(mpeg_info->audio[ i ].version ) + i18n( "Layer %1" , mpeg_info->audio[ i ].layer ); 0356 } 0357 } 0358 0359 return i18n( "n/a" ); 0360 } 0361 0362 int K3b::VcdTrack::mpegType( ) 0363 { 0364 if ( mpeg_info->has_video ) { 0365 for ( int i = 0; i < 3; i++ ) 0366 if ( mpeg_info->video[ i ].seen ) { 0367 if ( i == 0 ) { 0368 return 0; // MPEG_MOTION; 0369 } else { 0370 return 1; // MPEG_STILL; 0371 } 0372 } 0373 } 0374 if ( mpeg_info->has_audio ) { 0375 for ( int i = 0; i < 3; i++ ) 0376 if ( mpeg_info->audio[ i ].seen ) 0377 return 2; // MPEG_AUDIO; 0378 } 0379 0380 return -1; // MPEG_UNKNOWN; 0381 } 0382 0383 QString K3b::VcdTrack::audio_type2str( unsigned int version, unsigned int audio_mode, unsigned int audio_type ) 0384 { 0385 qDebug() << "K3b::VcdTrack::audio_type2str() version:" << version << " audio_mode:" << audio_mode << " audio_type:" << audio_type; 0386 0387 QString audio_types[ 3 ][ 5 ] = { 0388 { 0389 i18n( "unknown" ), 0390 i18n( "invalid" ), 0391 QString(), 0392 QString(), 0393 QString() 0394 }, 0395 { 0396 i18n( "stereo" ), 0397 i18n( "joint stereo" ), 0398 i18n( "dual channel" ), 0399 i18n( "single channel" ) 0400 }, 0401 { 0402 QString(), 0403 i18n( "dual channel" ), 0404 i18n( "surround sound" ), 0405 QString(), 0406 QString() 0407 } 0408 }; 0409 switch ( version ) { 0410 case K3b::MpegInfo::MPEG_VERS_MPEG1: 0411 return audio_types[ 1 ][ audio_mode ]; 0412 break; 0413 0414 case K3b::MpegInfo::MPEG_VERS_MPEG2: 0415 if ( audio_type > 0 ) { 0416 return audio_types[ 2 ][ audio_type ]; 0417 } 0418 return audio_types[ 1 ][ audio_mode ]; 0419 break; 0420 } 0421 0422 return i18n( "n/a" ); 0423 } 0424 0425 // convert a time in second to HH:mm:ss notation 0426 QString K3b::VcdTrack::SecsToHMS( double duration ) 0427 { 0428 byte hours = ( byte ) ( duration / 3600 ); 0429 byte mins = ( byte ) ( ( duration / 60 ) - ( hours * 60 ) ); 0430 float secs = duration - 60 * mins - 3600 * hours; 0431 if ( hours != 0 ) { 0432 return QString( "%1:" ).arg( hours ).rightJustified( 3, ' ' ) + QString( "%1:" ).arg( mins ).rightJustified( 3, '0' ) + QString::number( secs, 'f', 2 ); 0433 } 0434 if ( mins != 0 ) { 0435 return QString( "%1:" ).arg( mins ).rightJustified( 3, '0' ) + QString::number( secs, 'f', 2 ); 0436 } 0437 return QString::number( secs, 'f', 2 ); 0438 } 0439 0440 void K3b::VcdTrack::PrintInfo() 0441 { 0442 0443 qDebug() << "K3b::VcdTrack::PrintInfo() ....................."; 0444 qDebug() << " version : MPEG" << version(); 0445 qDebug() << " duration : " << duration(); 0446 qDebug() << " muxrate : " << muxrate(); 0447 qDebug() << " video ......................................"; 0448 qDebug() << " type : " << mpegTypeS(); 0449 qDebug() << " resolution : " << resolution(); 0450 qDebug() << " high resolution: " << highresolution(); 0451 qDebug() << " frate : " << video_frate(); 0452 qDebug() << " bitrate : " << video_bitrate(); 0453 qDebug() << " format : " << video_format( ); 0454 qDebug() << " chroma : " << video_chroma( ); 0455 qDebug() << " audio ......................................"; 0456 qDebug() << " type : " << mpegTypeS( true ); 0457 qDebug() << " mode : " << audio_mode(); 0458 qDebug() << " layer : " << audio_layer(); 0459 qDebug() << " bitrate : " << audio_bitrate(); 0460 qDebug() << " sampfreq : " << audio_sampfreq(); 0461 0462 }