1 /* === S Y N F I G ========================================================= */
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
10 ** Copyright (c) 2008 Gerco Ballintijn
11 ** Copyright (c) 2008 Carlos López
13 ** This package is free software; you can redistribute it and/or
14 ** modify it under the terms of the GNU General Public License as
15 ** published by the Free Software Foundation; either version 2 of
16 ** the License, or (at your option) any later version.
18 ** This package is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 ** General Public License for more details.
24 /* ========================================================================= */
26 /* === H E A D E R S ======================================================= */
36 #include <ETL/stringf>
50 extern "C" { int _isnan(double x); }
55 // For some reason isnan() isn't working on macosx any more.
56 // This is a quick fix.
57 #if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
61 inline bool isnan(double x) { return x != x; }
62 inline bool isnan(float x) { return x != x; }
63 #define SYNFIG_ISNAN_FIX 1
69 /* === U S I N G =========================================================== */
73 using namespace synfig;
75 #define tolower ::tolower
77 /* === M A C R O S ========================================================= */
79 /* === G L O B A L S ======================================================= */
81 /* === M E T H O D S ======================================================= */
83 Time::Time(const String &str_, float fps):
87 std::transform(str.begin(),str.end(),str.begin(),&tolower);
89 // Start/Begin Of Time
90 if(str=="sot" || str=="bot")
107 // Now try to read it in the letter-abbreviated format
108 while(pos<str.size() && sscanf(String(str,pos).c_str(),"%f%n",&amount,&read))
111 if(pos>=str.size() || read==0)
113 // Throw up a warning if there are no units
114 // and the amount isn't zero. There is no need
115 // to warn about units if the value is zero
116 // it is the only case where units are irrelevant.
119 synfig::warning(_("Time(): No unit provided in time code, assuming FRAMES (\"%s\")"),str.c_str());
124 synfig::warning(_("Time(): No unit provided in time code and frame rate is unknown! Assuming SECONDS"));
148 synfig::warning("Time(): Individual frames referenced, but frame rate is unknown");
151 // try to read it in as a traditional time format
153 int hour,minute,second;
155 if(fps && sscanf(str.c_str(),"%d:%d:%d.%f",&hour,&minute,&second,&frame)==4)
157 value_=frame/fps+(hour*3600+minute*60+second);
161 if(sscanf(str.c_str(),"%d:%d:%d",&hour,&minute,&second)==3)
163 value_=hour*3600+minute*60+second;
167 synfig::warning("Time(): Bad time format");
172 synfig::warning("Time(): Unexpected character '%c' when parsing time string \"%s\"",str[pos],str.c_str());
181 Time::get_string(float fps, Time::Format format)const
186 return "SOT"; // Start Of Time
188 return "EOT"; // End Of Time
192 if(ceil(time.value_)-time.value_<epsilon_())
193 time.value_=ceil(time.value_);
195 int hour = 0, minute = 0;
196 if(!(format<=FORMAT_FRAMES))
198 hour=time/3600;time-=hour*3600;
199 minute=time/60;time-=minute*60;
201 // <= is redefined, so this means "is the FORMAT_VIDEO bit set in the format?"
202 if(format<=FORMAT_VIDEO)
205 second=time;time-=second;
210 frame=round_to_int(time*fps);
212 return strprintf("%02d:%02d:%02d.%02d",hour,minute,second,frame);
215 return strprintf("%02d:%02d:%02d",hour,minute,second);
218 if (format <= FORMAT_FRAMES)
221 return strprintf("%df", round_to_int(time * fps));
223 return strprintf("%ds", round_to_int(time * 1));
227 bool started = false;
229 if(format<=FORMAT_FULL || hour)
231 ret+=strprintf("%dh",hour);
235 if(format<=FORMAT_FULL || minute)
237 if (!(format<=FORMAT_NOSPACES) && started)
240 ret += strprintf("%dm", minute);
248 second=time;time-=second;
251 if(format<=FORMAT_FULL || second)
253 if (!(format<=FORMAT_NOSPACES) && started)
256 ret += strprintf("%ds", (int)second);
260 if(format<=FORMAT_FULL || abs(frame) > epsilon_() || !started)
262 if (!(format<=FORMAT_NOSPACES) && started)
265 if(abs(frame-floor(frame) >= epsilon_()))
266 ret += strprintf("%0.3ff", frame);
268 ret += strprintf("%0.0ff", frame);
275 if(format<=FORMAT_FULL || second || !started)
277 if (!(format<=FORMAT_NOSPACES) && started)
280 if(abs(second-floor(second))>=epsilon_())
282 String seconds(strprintf("%0.8f",second));
284 // skip trailing zeros
286 String::reverse_iterator i = seconds.rbegin();
287 for ( ; (*i) == '0'; i++)
290 // if we removed too many, go back one place, leaving one zero
291 if (*i < '0' || *i > '9') count--;
293 ret += seconds.substr(0, seconds.size()-count) + "s";
296 ret+=strprintf("%0.0fs",second);
304 Time::round(float fps)const
308 value_type time(*this);
312 if(abs(time-floor(time))<0.5)
313 return floor(time)/fps;
315 return ceil(time)/fps;
322 return get_string().c_str();
328 Time::is_valid()const
330 return !isnan(value_);