]> git.sesse.net Git - kdenlive/blob - src/timecode.cpp
code cleanup
[kdenlive] / src / timecode.cpp
1 /***************************************************************************
2                           timecode  -  description
3                              -------------------
4     begin                : Wed Dec 17 2003
5     copyright            : (C) 2003 by Jason Wood
6     email                : jasonwood@blueyonder.co.uk
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #include "timecode.h"
18
19 #include <kdebug.h>
20 #include <klocale.h>
21
22 Timecode::Timecode(Formats format, double framesPerSecond, bool dropFrame) :
23         m_format(format),
24         m_dropFrame(dropFrame),
25         m_displayedFramesPerSecond(framesPerSecond + 0.5),
26         m_realFps(framesPerSecond)
27 {
28 }
29
30 Timecode::~Timecode()
31 {
32 }
33
34 double Timecode::fps() const
35 {
36     return m_realFps; //m_displayedFramesPerSecond;
37 }
38
39
40 int Timecode::getDisplayFrameCount(const QString duration, bool frameDisplay) const
41 {
42     if (frameDisplay) return duration.toInt();
43     return getFrameCount(duration);
44 }
45
46 int Timecode::getFrameCount(const QString duration) const
47 {
48     if (m_dropFrame) {
49         // calculate how many frames need to be dropped every minute.
50         int frames;
51         int toDrop = (int) floor(600.0 * (m_displayedFramesPerSecond - m_realFps)  + 0.5);
52
53         int perMinute = toDrop / 9;
54         int tenthMinute = toDrop % 9;
55
56         // calculate how many frames are in a normal minute, and how many are in a tenth minute.
57         int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute;
58         int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;;
59
60         // Number of actual frames in a 10 minute interval :
61         int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames;
62         frames = 6 * duration.section(':', 0, 0).toInt() * tenMinutes;
63         int minutes = duration.section(':', 1, 1).toInt();
64         frames += ((int) minutes / 10) * tenMinutes;
65         int mins = minutes % 10;
66         if (mins > 0) {
67             frames += tenthMinuteFrames;
68             mins--;
69             if (mins > 0) frames += mins * normalMinuteFrames;
70         }
71         if (minutes % 10 > 0) frames -= perMinute;
72         frames += duration.section(':', 2, 2).toInt() * m_displayedFramesPerSecond + duration.section(':', 3, 3).toInt();
73         return frames;
74     }
75     return (int)((duration.section(':', 0, 0).toInt()*3600.0 + duration.section(':', 1, 1).toInt()*60.0 + duration.section(':', 2, 2).toInt()) * m_realFps + duration.section(':', 3, 3).toInt());
76 }
77
78 QString Timecode::getDisplayTimecode(const GenTime & time, bool frameDisplay) const
79 {
80     if (frameDisplay) return QString::number((int) time.frames(m_realFps));
81     return getTimecode(time);
82 }
83
84 QString Timecode::getTimecode(const GenTime & time) const
85 {
86     switch (m_format) {
87     case HH_MM_SS_FF:
88         return getTimecodeHH_MM_SS_FF(time);
89         break;
90     case HH_MM_SS_HH:
91         return getTimecodeHH_MM_SS_HH(time);
92         break;
93     case Frames:
94         return getTimecodeFrames(time);
95         break;
96     case Seconds:
97         return getTimecodeSeconds(time);
98         break;
99     default:
100         kWarning() <<
101         "Unknown timecode format specified, defaulting to HH_MM_SS_FF"
102         << endl;
103         return getTimecodeHH_MM_SS_FF(time);
104     }
105 }
106
107 const QString Timecode::getDisplayTimecodeFromFrames(int frames, bool frameDisplay) const
108 {
109     if (frameDisplay) return QString::number(frames);
110     return getTimecodeHH_MM_SS_FF(frames);
111 }
112
113 const QString Timecode::getTimecodeFromFrames(int frames) const
114 {
115     return getTimecodeHH_MM_SS_FF(frames);
116 }
117
118
119 //static
120 QString Timecode::getStringTimecode(int frames, const double &fps)
121 {
122     // Returns the timecode in an hh:mm:ss format
123     int seconds = (int)(frames / fps);
124     int minutes = seconds / 60;
125     seconds = seconds % 60;
126     int hours = minutes / 60;
127     minutes = minutes % 60;
128     QString text;
129     text.append(QString::number(hours).rightJustified(2, '0', false));
130     text.append(':');
131     text.append(QString::number(minutes).rightJustified(2, '0', false));
132     text.append(':');
133     text.append(QString::number(seconds).rightJustified(2, '0', false));
134     return text;
135 }
136
137
138 //static
139 QString Timecode::getEasyTimecode(const GenTime & time, const double &fps)
140 {
141     // Returns the timecode in an easily read display, like 3 min. 5 sec.
142     int frames = (int) time.frames(fps);
143     int seconds = (int)(frames / fps);
144     frames = frames - ((int)(fps * seconds));
145
146     int minutes = seconds / 60;
147     seconds = seconds % 60;
148     int hours = minutes / 60;
149     minutes = minutes % 60;
150
151     QString text;
152     bool trim = false;
153
154     if (hours != 0) {
155         text.append(QString::number(hours).rightJustified(2, '0', false));
156         text.append(' ' + i18n("hour") + ' ');
157         trim = true;
158     }
159     if (minutes != 0 || trim) {
160         if (!trim) {
161             text.append(QString::number(minutes));
162         } else
163             text.append(QString::number(minutes).rightJustified(2, '0', false));
164         text.append(' ' + i18n("min.") + ' ');
165         trim = true;
166     }
167     if (seconds != 0 || trim) {
168         if (!trim) {
169             text.append(QString::number(seconds));
170         } else
171             text.append(QString::number(seconds).rightJustified(2, '0', false));
172         text.append(' ' + i18n("sec."));
173         trim = true;
174     }
175     if (!trim) {
176         text.append(QString::number(frames));
177         text.append(' ' + i18n("frames"));
178     }
179
180     return text;
181 }
182
183
184 const QString Timecode::getTimecodeHH_MM_SS_FF(const GenTime & time) const
185 {
186     if (m_dropFrame)
187         return getTimecodeDropFrame(time);
188
189     return getTimecodeHH_MM_SS_FF((int) time.frames(m_realFps));
190 }
191
192 const QString Timecode::getTimecodeHH_MM_SS_FF(int frames) const
193 {
194     if (m_dropFrame) {
195         return getTimecodeDropFrame(frames);
196     }
197     int seconds = frames / m_displayedFramesPerSecond;
198     frames = frames % m_displayedFramesPerSecond;
199
200     int minutes = seconds / 60;
201     seconds = seconds % 60;
202     int hours = minutes / 60;
203     minutes = minutes % 60;
204
205     QString text;
206     text.append(QString::number(hours).rightJustified(2, '0', false));
207     text.append(':');
208     text.append(QString::number(minutes).rightJustified(2, '0', false));
209     text.append(':');
210     text.append(QString::number(seconds).rightJustified(2, '0', false));
211     text.append(':');
212     text.append(QString::number(frames).rightJustified(2, '0', false));
213
214     return text;
215 }
216
217 QString Timecode::getTimecodeHH_MM_SS_HH(const GenTime & time) const
218 {
219     int hundredths = (int)(time.seconds() * 100);
220     int seconds = hundredths / 100;
221     hundredths = hundredths % 100;
222     int minutes = seconds / 60;
223     seconds = seconds % 60;
224     int hours = minutes / 60;
225     minutes = minutes % 60;
226
227     QString text;
228
229     text.append(QString::number(hours).rightJustified(2, '0', false));
230     text.append(':');
231     text.append(QString::number(minutes).rightJustified(2, '0', false));
232     text.append(':');
233     text.append(QString::number(seconds).rightJustified(2, '0', false));
234     text.append(':');
235     text.append(QString::number(hundredths).rightJustified(2, '0', false));
236
237     return text;
238 }
239
240 QString Timecode::getTimecodeFrames(const GenTime & time) const
241 {
242     return QString::number(time.frames(m_realFps));
243 }
244
245 QString Timecode::getTimecodeSeconds(const GenTime & time) const
246 {
247     return QString::number(time.seconds());
248 }
249
250 QString Timecode::getTimecodeDropFrame(const GenTime & time) const
251 {
252     return getTimecodeDropFrame((int)time.frames(m_realFps));
253 }
254
255 QString Timecode::getTimecodeDropFrame(int frames) const
256 {
257     // Calculate the timecode using dropframes to remove the difference in fps. Note that this algorithm should work
258     // for NTSC times, but is untested for any others - it is in no way an "official" algorithm, unless it's by fluke.
259
260     // calculate how many frames need to be dropped every minute.
261     int toDrop = (int) floor(600.0 * (m_displayedFramesPerSecond - m_realFps)  + 0.5);
262
263     int perMinute = toDrop / 9;
264     int tenthMinute = toDrop % 9;
265
266     // calculate how many frames are in a normal minute, and how many are in a tenth minute.
267     int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute;
268     int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;;
269
270     // Number of actual frames in a 10 minute interval :
271     int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames;
272
273     int tenMinuteIntervals = frames / tenMinutes;
274     frames = frames % tenMinutes;
275
276     int hours = tenMinuteIntervals / 6;
277     tenMinuteIntervals = tenMinuteIntervals % 6;
278
279     // At the point, we have figured out HH:M?:??:??
280
281     int numMinutes;
282
283     if (frames < tenthMinuteFrames) {
284         // tenth minute logic applies.
285         numMinutes = 0;
286     } else {
287         // normal minute logic applies.
288         numMinutes = 1 + (frames - tenthMinuteFrames) / normalMinuteFrames;
289         frames = (frames - tenthMinuteFrames) % normalMinuteFrames;
290         frames +=  tenthMinute + perMinute;
291     }
292     // We now have HH:MM:??:??
293
294     int seconds = frames / m_displayedFramesPerSecond;
295     frames = frames % m_displayedFramesPerSecond;
296
297     // We now have HH:MM:SS:FF
298
299     // THANK FUCK FOR THAT.
300
301     QString text;
302     text.append(QString::number(hours).rightJustified(2, '0', false));
303     text.append(':');
304     text.append(QString::number(tenMinuteIntervals));
305     text.append(QString::number(numMinutes));
306     text.append(':');
307     text.append(QString::number(seconds).rightJustified(2, '0', false));
308     text.append(':');
309     text.append(QString::number(frames).rightJustified(2, '0', false));
310
311     return text;
312 }