2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2008 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Joshua Leung
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/blenlib/intern/timecode.c
30 * Time-Code string formatting
36 #include "BLI_utildefines.h"
37 #include "BLI_string.h"
40 #include "BLI_timecode.h" /* own include */
42 #include "DNA_userdef_types.h" /* for eTimecodeStyles only */
44 #include "BLI_strict_flags.h"
47 * Generate timecode/frame number string and store in \a str
49 * \param str destination string
50 * \param maxncpy maximum number of characters to copy ``sizeof(str)``
51 * \param power special setting for #View2D grid drawing,
52 * used to specify how detailed we need to be
53 * \param time_seconds time total time in seconds
54 * \param fps frames per second, typically from the #FPS macro
55 * \param timecode_style enum from eTimecodeStyles
56 * \return length of \a str
59 size_t BLI_timecode_string_from_time(
60 char *str, const size_t maxncpy, const int power, const float time_seconds,
61 const double fps, const short timecode_style)
63 int hours = 0, minutes = 0, seconds = 0, frames = 0;
64 float time = time_seconds;
70 /* correction for negative cfraues */
77 /* XXX should we only display a single digit for hours since clips are
78 * VERY UNLIKELY to be more than 1-2 hours max? However, that would
79 * go against conventions...
81 hours = (int)time / 3600;
82 time = (float)fmod(time, 3600);
87 minutes = (int)time / 60;
88 time = (float)fmod(time, 60);
93 * Frames are derived from 'fraction' of second. We need to perform some additional rounding
94 * to cope with 'half' frames, etc., which should be fine in most cases
97 frames = iroundf((float)(((double)time - (double)seconds) * fps));
100 /* seconds (with pixel offset rounding) */
101 seconds = iroundf(time);
104 switch (timecode_style) {
105 case USER_TIMECODE_MINIMAL:
107 /* - In general, minutes and seconds should be shown, as most clips will be
108 * within this length. Hours will only be included if relevant.
109 * - Only show frames when zoomed in enough for them to be relevant
110 * (using separator of '+' for frames).
111 * When showing frames, use slightly different display to avoid confusion with mm:ss format
114 /* include "frames" in display */
116 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
119 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
122 rlen = BLI_snprintf(str, maxncpy, "%s%d+%02d", neg, seconds, frames);
126 /* don't include 'frames' in display */
128 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
131 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
136 case USER_TIMECODE_SMPTE_MSF:
138 /* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */
140 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
143 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
147 case USER_TIMECODE_MILLISECONDS:
149 /* reduced SMPTE. Instead of frames, milliseconds are shown */
151 /* precision of decimal part */
152 const int ms_dp = (power <= 0) ? (1 - power) : 1;
154 /* to get 2 digit whole-number part for seconds display
155 * (i.e. 3 is for 2 digits + radix, on top of full length) */
156 const int s_pad = ms_dp + 3;
159 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
162 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
166 case USER_TIMECODE_SECONDS_ONLY:
168 /* only show the original seconds display */
169 /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
171 rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
174 rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));
178 case USER_TIMECODE_SMPTE_FULL:
181 /* full SMPTE format */
182 rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
192 * Generate time string and store in \a str
194 * \param str destination string
195 * \param maxncpy maximum number of characters to copy ``sizeof(str)``
196 * \param power special setting for #View2D grid drawing,
197 * used to specify how detailed we need to be
198 * \param time_seconds time total time in seconds
199 * \param seconds time in seconds.
200 * \return length of \a str
202 * \note in some cases this is used to print non-seconds values.
204 size_t BLI_timecode_string_from_time_simple(
205 char *str, const size_t maxncpy, const int power, const float time_seconds)
209 /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */
211 rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds);
214 rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds));