1 /*
2 SPDX-FileCopyrightText: 2003-2004 Christian Kvasny <chris@k3b.org>
3 SPDX-FileCopyrightText: 2008 Sebastian Trueg <trueg@k3b.org>
4 SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl>
5 SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "k3bvcdtrack.h"
11 #include "k3bglobals.h"
12 #include "k3b_i18n.h"
13
14 #include <KConfig>
15
16 #include <QDebug>
17 #include <QString>
18 #include <QFileInfo>
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24
VcdTrack(QList<K3b::VcdTrack * > * parent,const QString & filename)25 K3b::VcdTrack::VcdTrack( QList<K3b::VcdTrack*>* parent, const QString& filename )
26 : mpeg_info(Q_NULLPTR),
27 m_pbcnumkeys( true ),
28 m_pbcnumkeysuserdefined( false ),
29 m_file( filename )
30 {
31 m_parent = parent;
32 m_title = QFileInfo( m_file ).completeBaseName();
33
34 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) {
35 m_pbctrackmap.insert( playback, 0L );
36 m_pbcnontrackmap.insert( playback, DISABLED );
37 m_pbcusrdefmap.insert( playback, false );
38 }
39
40 m_reactivity = false;
41
42 m_definedkeysmap.clear();
43
44 mpeg_info = new Mpeginfo();
45 }
46
47
~VcdTrack()48 K3b::VcdTrack::~VcdTrack()
49 {
50 if (mpeg_info) {
51 delete mpeg_info;
52 mpeg_info = Q_NULLPTR;
53 }
54 }
55
56
size() const57 KIO::filesize_t K3b::VcdTrack::size() const
58 {
59 return m_file.size();
60 }
61
index() const62 int K3b::VcdTrack::index() const
63 {
64 // (trueg): I have no idea why I need to const cast here!
65 int i = m_parent->indexOf( const_cast<K3b::VcdTrack*>( this ) );
66 if ( i < 0 )
67 qDebug() << "(K3b::VcdTrack) I'm not part of my parent!";
68 return i;
69 }
70
71
trackPlaybackValues()72 QList<K3b::VcdTrack::PbcTracks> K3b::VcdTrack::trackPlaybackValues()
73 {
74 QList<PbcTracks> playbacks;
75 playbacks << PREVIOUS << NEXT << RETURN << DEFAULT << AFTERTIMEOUT;
76 return playbacks;
77 }
78
79
addToRevRefList(K3b::VcdTrack * revreftrack)80 void K3b::VcdTrack::addToRevRefList( K3b::VcdTrack* revreftrack )
81 {
82 qDebug() << "K3b::VcdTrack::addToRevRefList: track = " << revreftrack;
83
84 m_revreflist.append( revreftrack );
85
86 qDebug() << "K3b::VcdTrack::hasRevRef count = " << m_revreflist.count() << " empty = " << m_revreflist.isEmpty();
87 }
88
delFromRevRefList(K3b::VcdTrack * revreftrack)89 void K3b::VcdTrack::delFromRevRefList( K3b::VcdTrack* revreftrack )
90 {
91 m_revreflist.removeAll( revreftrack );
92 }
93
hasRevRef()94 bool K3b::VcdTrack::hasRevRef()
95 {
96 return !m_revreflist.isEmpty() ;
97 }
98
delRefToUs()99 void K3b::VcdTrack::delRefToUs()
100 {
101 Q_FOREACH( K3b::VcdTrack* track, m_revreflist ) {
102 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) {
103 qDebug() << "K3b::VcdTrack::delRefToUs count = " << m_revreflist.count() << " empty = " << m_revreflist.isEmpty() << " track = " << track << " this = " << this;
104 if( this == track->getPbcTrack( playback ) ) {
105 track->setPbcTrack( playback );
106 track->setUserDefined( playback, false );
107 track->delFromRevRefList( this );
108 }
109 }
110 }
111 }
112
delRefFromUs()113 void K3b::VcdTrack::delRefFromUs()
114 {
115 Q_FOREACH( PbcTracks playback, trackPlaybackValues() ) {
116 if ( this->getPbcTrack( playback ) ) {
117 this->getPbcTrack( playback ) ->delFromRevRefList( this );
118 }
119 }
120 }
121
setPbcTrack(PbcTracks which,K3b::VcdTrack * pbctrack)122 void K3b::VcdTrack::setPbcTrack( PbcTracks which, K3b::VcdTrack* pbctrack )
123 {
124 qDebug() << "K3b::VcdTrack::setPbcTrack " << which << ", " << pbctrack;
125 m_pbctrackmap[which] = pbctrack;
126 }
127
setPbcNonTrack(PbcTracks which,PbcTypes type)128 void K3b::VcdTrack::setPbcNonTrack( PbcTracks which, PbcTypes type )
129 {
130 qDebug() << "K3b::VcdTrack::setNonPbcTrack " << which << ", " << type;
131 m_pbcnontrackmap[which] = type;
132 }
133
setUserDefined(PbcTracks which,bool ud)134 void K3b::VcdTrack::setUserDefined( PbcTracks which, bool ud )
135 {
136 m_pbcusrdefmap[which] = ud;
137 }
138
getPbcTrack(PbcTracks which)139 K3b::VcdTrack* K3b::VcdTrack::getPbcTrack( PbcTracks which )
140 {
141 if ( m_pbctrackmap.find( which ) == m_pbctrackmap.end() )
142 return 0;
143 else
144 return m_pbctrackmap[ which ];
145 }
146
getNonPbcTrack(PbcTracks which)147 int K3b::VcdTrack::getNonPbcTrack( PbcTracks which )
148 {
149 if ( m_pbcnontrackmap.find( which ) == m_pbcnontrackmap.end() )
150 return 0;
151 else
152 return m_pbcnontrackmap[ which ];
153 }
154
isPbcUserDefined(PbcTracks which)155 bool K3b::VcdTrack::isPbcUserDefined( PbcTracks which )
156 {
157 return m_pbcusrdefmap[ which ];
158 }
159
resolution()160 QString K3b::VcdTrack::resolution()
161 {
162 if ( mpeg_info->has_video ) {
163 for ( int i = 0; i < 2; i++ ) {
164 if ( mpeg_info->video[ i ].seen ) {
165 return QString( "%1 x %2" ).arg( mpeg_info->video[ i ].hsize ).arg( mpeg_info->video[ i ].vsize );
166 }
167 }
168 }
169
170 return i18n( "n/a" );
171 }
172
highresolution()173 QString K3b::VcdTrack::highresolution()
174 {
175 if ( mpeg_info->has_video ) {
176 if ( mpeg_info->video[ 2 ].seen ) {
177 return QString( "%1 x %2" ).arg( mpeg_info->video[ 2 ].hsize ).arg( mpeg_info->video[ 2 ].vsize );
178 }
179 }
180 return i18n( "n/a" );
181 }
182
video_frate()183 QString K3b::VcdTrack::video_frate()
184 {
185 if ( mpeg_info->has_video ) {
186 for ( int i = 0; i < 2; i++ ) {
187 if ( mpeg_info->video[ i ].seen ) {
188 return QString::number( mpeg_info->video[ i ].frate );
189 }
190 }
191 }
192
193 return i18n( "n/a" );
194 }
195
video_bitrate()196 QString K3b::VcdTrack::video_bitrate()
197 {
198 if ( mpeg_info->has_video ) {
199 for ( int i = 0; i < 2; i++ ) {
200 if ( mpeg_info->video[ i ].seen ) {
201 return i18np( "1 bit/s", "%1 bits/s" , mpeg_info->video[ i ].bitrate ) ;
202 }
203 }
204 }
205
206 return i18n( "n/a" );
207 }
208
209
210
video_format()211 QString K3b::VcdTrack::video_format()
212 {
213 if ( mpeg_info->has_video ) {
214 for ( int i = 0; i < 2; i++ ) {
215 if ( mpeg_info->video[ i ].seen ) {
216 switch ( mpeg_info->video[ i ].video_format ) {
217 case 0 :
218 return i18n( "Component" );
219 break;
220 case 1 :
221 return "PAL";
222 break;
223 case 2 :
224 return "NTSC";
225 break;
226 case 3 :
227 return "SECAM";
228 break;
229 case 4 :
230 return "MAC";
231 break;
232 case 5 :
233 default:
234 return i18n( "Unspecified" );
235 qDebug() << "K3b::VcdTrack::video_format() :" << mpeg_info->video[ i ].video_format;
236 break;
237 }
238 }
239 }
240 }
241 return i18n( "n/a" );
242 }
243
video_chroma()244 QString K3b::VcdTrack::video_chroma()
245 {
246 if ( mpeg_info->has_video ) {
247 // MPEG1 only supports 4:2:0 Format
248 if ( version() == K3b::MpegInfo::MPEG_VERS_MPEG1 )
249 return QString( "4:2:0" );
250
251 for ( int i = 0; i < 2; i++ ) {
252 if ( mpeg_info->video[ i ].seen ) {
253 switch ( mpeg_info->video[ i ].chroma_format ) {
254 case 1 :
255 return QString( "4:2:0" );
256 break;
257 case 2 :
258 return QString( "4:2:2" );
259 break;
260 case 3 :
261 return QString( "4:4:4" );
262 break;
263
264 }
265 }
266 }
267 }
268
269 return i18n( "n/a" );
270 }
271
audio_layer()272 QString K3b::VcdTrack::audio_layer()
273 {
274 if ( mpeg_info->has_audio ) {
275 for ( int i = 0; i < 2; i++ ) {
276 if ( mpeg_info->audio[ i ].seen ) {
277 return QString::number( mpeg_info->audio[ i ].layer );
278 }
279 }
280 }
281
282 return i18n( "n/a" );
283 }
284
audio_bitrate()285 QString K3b::VcdTrack::audio_bitrate()
286 {
287 if ( mpeg_info->has_audio ) {
288 for ( int i = 0; i < 2; i++ ) {
289 if ( mpeg_info->audio[ i ].seen ) {
290 return i18np( "1 bit/s", "%1 bits/s" , mpeg_info->audio[ i ].bitrate ) ;
291 }
292 }
293 }
294
295 return i18n( "n/a" );
296 }
297
audio_sampfreq()298 QString K3b::VcdTrack::audio_sampfreq()
299 {
300 if ( mpeg_info->has_audio ) {
301 for ( int i = 0; i < 2; i++ ) {
302 if ( mpeg_info->audio[ i ].seen ) {
303 return i18n( "%1 Hz" , mpeg_info->audio[ i ].sampfreq ) ;
304 }
305 }
306 }
307
308 return i18n( "n/a" );
309 }
310
audio_mode()311 QString K3b::VcdTrack::audio_mode( )
312 {
313 if ( mpeg_info->has_audio ) {
314 for ( int i = 2; i >= 0; i-- )
315 if ( mpeg_info->audio[ i ].seen )
316 return QString( audio_type2str( mpeg_info->audio[ i ].version, mpeg_info->audio[ i ].mode, i ) );
317
318 }
319
320 return i18n( "n/a" );
321 }
322
audio_copyright()323 QString K3b::VcdTrack::audio_copyright( )
324 {
325 if ( mpeg_info->has_audio ) {
326 for ( int i = 2; i >= 0; i-- ) {
327 if ( mpeg_info->audio[ i ].seen )
328 {
329 if ( mpeg_info->audio[ i ].copyright )
330 return QString( "(c) " ) + ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) );
331 else
332 return ( mpeg_info->audio[ i ].original ? i18n( "original" ) : i18n( "duplicate" ) );
333 }
334 }
335 }
336
337 return i18n( "n/a" );
338 }
339
mpegTypeS(bool audio)340 QString K3b::VcdTrack::mpegTypeS( bool audio )
341 {
342 if ( mpeg_info->has_video && !audio ) {
343 for ( int i = 0; i < 3; i++ )
344 if ( mpeg_info->video[ i ].seen ) {
345 if ( i == 0 ) {
346 return QString( "MPEG%1 ").arg(mpeg_info->version ) + i18n( "Motion Picture" );
347 } else {
348 return QString( "MPEG%1 ").arg(mpeg_info->version ) + i18n( "Still Picture" );
349 }
350 }
351 }
352 if ( mpeg_info->has_audio && audio ) {
353 for ( int i = 0; i < 3; i++ )
354 if ( mpeg_info->audio[ i ].seen ) {
355 return QString( "MPEG%1 ").arg(mpeg_info->audio[ i ].version ) + i18n( "Layer %1" , mpeg_info->audio[ i ].layer );
356 }
357 }
358
359 return i18n( "n/a" );
360 }
361
mpegType()362 int K3b::VcdTrack::mpegType( )
363 {
364 if ( mpeg_info->has_video ) {
365 for ( int i = 0; i < 3; i++ )
366 if ( mpeg_info->video[ i ].seen ) {
367 if ( i == 0 ) {
368 return 0; // MPEG_MOTION;
369 } else {
370 return 1; // MPEG_STILL;
371 }
372 }
373 }
374 if ( mpeg_info->has_audio ) {
375 for ( int i = 0; i < 3; i++ )
376 if ( mpeg_info->audio[ i ].seen )
377 return 2; // MPEG_AUDIO;
378 }
379
380 return -1; // MPEG_UNKNOWN;
381 }
382
audio_type2str(unsigned int version,unsigned int audio_mode,unsigned int audio_type)383 QString K3b::VcdTrack::audio_type2str( unsigned int version, unsigned int audio_mode, unsigned int audio_type )
384 {
385 qDebug() << "K3b::VcdTrack::audio_type2str() version:" << version << " audio_mode:" << audio_mode << " audio_type:" << audio_type;
386
387 QString audio_types[ 3 ][ 5 ] = {
388 {
389 i18n( "unknown" ),
390 i18n( "invalid" ),
391 QString(),
392 QString(),
393 QString()
394 },
395 {
396 i18n( "stereo" ),
397 i18n( "joint stereo" ),
398 i18n( "dual channel" ),
399 i18n( "single channel" )
400 },
401 {
402 QString(),
403 i18n( "dual channel" ),
404 i18n( "surround sound" ),
405 QString(),
406 QString()
407 }
408 };
409 switch ( version ) {
410 case K3b::MpegInfo::MPEG_VERS_MPEG1:
411 return audio_types[ 1 ][ audio_mode ];
412 break;
413
414 case K3b::MpegInfo::MPEG_VERS_MPEG2:
415 if ( audio_type > 0 ) {
416 return audio_types[ 2 ][ audio_type ];
417 }
418 return audio_types[ 1 ][ audio_mode ];
419 break;
420 }
421
422 return i18n( "n/a" );
423 }
424
425 // convert a time in second to HH:mm:ss notation
SecsToHMS(double duration)426 QString K3b::VcdTrack::SecsToHMS( double duration )
427 {
428 byte hours = ( byte ) ( duration / 3600 );
429 byte mins = ( byte ) ( ( duration / 60 ) - ( hours * 60 ) );
430 float secs = duration - 60 * mins - 3600 * hours;
431 if ( hours != 0 ) {
432 return QString( "%1:" ).arg( hours ).rightJustified( 3, ' ' ) + QString( "%1:" ).arg( mins ).rightJustified( 3, '0' ) + QString::number( secs, 'f', 2 );
433 }
434 if ( mins != 0 ) {
435 return QString( "%1:" ).arg( mins ).rightJustified( 3, '0' ) + QString::number( secs, 'f', 2 );
436 }
437 return QString::number( secs, 'f', 2 );
438 }
439
PrintInfo()440 void K3b::VcdTrack::PrintInfo()
441 {
442
443 qDebug() << "K3b::VcdTrack::PrintInfo() .....................";
444 qDebug() << " version : MPEG" << version();
445 qDebug() << " duration : " << duration();
446 qDebug() << " muxrate : " << muxrate();
447 qDebug() << " video ......................................";
448 qDebug() << " type : " << mpegTypeS();
449 qDebug() << " resolution : " << resolution();
450 qDebug() << " high resolution: " << highresolution();
451 qDebug() << " frate : " << video_frate();
452 qDebug() << " bitrate : " << video_bitrate();
453 qDebug() << " format : " << video_format( );
454 qDebug() << " chroma : " << video_chroma( );
455 qDebug() << " audio ......................................";
456 qDebug() << " type : " << mpegTypeS( true );
457 qDebug() << " mode : " << audio_mode();
458 qDebug() << " layer : " << audio_layer();
459 qDebug() << " bitrate : " << audio_bitrate();
460 qDebug() << " sampfreq : " << audio_sampfreq();
461
462 }
463