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 }