Remove unneded transcoding option map_meta_data
[amarok:orangejuliuss-amarok.git] / src / transcoding / TranscodingJob.cpp
1 /****************************************************************************************
2  * Copyright (c) 2010 Téo Mrnjavac <teo@kde.org>                                        *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16
17 #include "TranscodingJob.h"
18
19 #include "src/core/transcoding/TranscodingController.h"
20 #include "src/core/support/Debug.h"
21
22 #include <KProcess>
23
24 namespace Transcoding
25 {
26
27 Job::Job( const KUrl &src,
28                             const KUrl &dest,
29                             const Transcoding::Configuration &configuration,
30                             QObject *parent )
31     : KJob( parent )
32     , m_src( src )
33     , m_dest( dest )
34     , m_configuration( configuration )
35     , m_duration( -1 )
36 {
37     DEBUG_BLOCK
38     init();
39 }
40
41 Job::Job( KUrl &src,
42                             const Transcoding::Configuration &configuration,
43                             QObject *parent )
44     : KJob( parent )
45     , m_src( src )
46     , m_dest( src )
47     , m_configuration( configuration )
48     , m_duration( -1 )
49 {
50     DEBUG_BLOCK
51     debug() << "Transcoding::Job ctor!!";
52     debug()<< src;
53     debug()<< src.path();
54     QString fileExtension = Amarok::Components::transcodingController()->format( configuration.encoder() )->fileExtension();
55     if( !( fileExtension.isEmpty() ) )
56     {
57         QString destPath = src.path();
58         destPath.truncate( destPath.lastIndexOf( '.' ) + 1 );
59         destPath.append( fileExtension );
60         m_dest.setPath( destPath );
61     }
62     init();
63 }
64
65 void
66 Job::init()
67 {
68     DEBUG_BLOCK
69     m_transcoder = new KProcess( this );
70
71     m_transcoder->setOutputChannelMode( KProcess::MergedChannels );
72
73     //First the executable...
74     m_transcoder->setProgram( "ffmpeg" );
75     //... then we'd have the infile configuration followed by "-i" and the infile path...
76     *m_transcoder << QString( "-i" )
77                   << m_src.path();
78     //... and finally, outfile configuration followed by the outfile path.
79     const Transcoding::Format *format = Amarok::Components::transcodingController()->format( m_configuration.encoder() );
80     *m_transcoder << format->ffmpegParameters( m_configuration )
81                   << m_dest.path();
82
83     //debug spam follows
84     debug() << format->ffmpegParameters( m_configuration );
85     debug() << QString( "FFMPEG call is " ) << m_transcoder->program().join(" ");
86
87     connect( m_transcoder, SIGNAL( readyRead() ),
88              this, SLOT( processOutput() ) );
89     connect( m_transcoder, SIGNAL( finished( int, QProcess::ExitStatus ) ),
90              this, SLOT( transcoderDone( int, QProcess::ExitStatus ) ) );
91 }
92
93 void
94 Job::start()
95 {
96     DEBUG_BLOCK
97     debug()<< "starting ffmpeg";
98     debug()<< "call is " << m_transcoder->program().join(" ");
99     m_transcoder->start();
100     debug() << m_transcoder->readAllStandardOutput();
101     debug()<< "ffmpeg started";
102 }
103
104 void
105 Job::transcoderDone( int exitCode, QProcess::ExitStatus exitStatus ) //SLOT
106 {
107     DEBUG_BLOCK
108     Q_UNUSED( exitStatus );
109     debug() << m_transcoder->readAll();
110     if( !exitCode )
111     {
112         debug() << "YAY, transcoding done!";
113         emitResult();
114     }
115     else
116     {
117         debug() << "NAY, transcoding fail!";
118         emitResult();
119     }
120 }
121
122 void
123 Job::processOutput()
124 {
125     QString output = m_transcoder->readAllStandardOutput().data();
126     if( output.simplified().isEmpty() )
127         return;
128
129     if( m_duration == -1 )
130     {
131         m_duration = computeDuration( output );
132         if( m_duration >= 0 )
133             setTotalAmount( KJob::Bytes, m_duration ); //Nothing better than bytes I can think of
134     }
135
136     qint64 progress = computeProgress( output  );
137     if( progress > -1 )
138         setProcessedAmount( KJob::Bytes, progress );
139 }
140
141 inline qint64
142 Job::computeDuration( const QString &output )
143 {
144     //We match something like "Duration: 00:04:33.60"
145     QRegExp matchDuration( "Duration: (\\d{2,}):(\\d{2}):(\\d{2})\\.(\\d{2})" );
146
147     if( output.contains( matchDuration ) )
148     {
149         //duration is in csec
150         qint64 duration = matchDuration.cap( 1 ).toLong() * 60 * 60 * 100 +
151                           matchDuration.cap( 2 ).toInt()  * 60 * 100 +
152                           matchDuration.cap( 3 ).toInt()  * 100 +
153                           matchDuration.cap( 4 ).toInt();
154         return duration;
155     }
156     else
157         return -1;
158 }
159
160 inline qint64
161 Job::computeProgress( const QString &output )
162 {
163     //Output is like size=     323kB time=18.10 bitrate= 146.0kbits/s
164     //We're going to use the "time" column, which counts the elapsed time in seconds.
165     QRegExp matchTime( "time=(\\d+)\\.(\\d{2})" );
166
167     if( output.contains( matchTime ) )
168     {
169         qint64 time = matchTime.cap( 1 ).toLong() * 100 +
170                       matchTime.cap( 2 ).toInt();
171         return time;
172     }
173     else
174         return -1;
175 }
176
177 } //namespace Transcoding