|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file time.cpp
|
|
Carlos Lopez |
a09598 |
** \brief Template File
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2007, 2008 Chris Moore
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2008 Gerco Ballintijn
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2008 Carlos Lรณpez
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
/* ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
|
6eb56a |
#include <cassert></cassert>
|
|
|
6eb56a |
#include <cctype></cctype>
|
|
|
6eb56a |
#include <cmath></cmath>
|
|
|
6eb56a |
#include <cstdio></cstdio>
|
|
|
6eb56a |
|
|
|
6eb56a |
#include <algorithm></algorithm>
|
|
|
6eb56a |
|
|
Carlos Lopez |
a09598 |
#include <etl stringf=""></etl>
|
|
Carlos Lopez |
a09598 |
#include <etl misc=""></etl>
|
|
|
6eb56a |
|
|
Carlos Lopez |
a09598 |
#include "general.h"
|
|
|
6eb56a |
#include "real.h"
|
|
|
6eb56a |
|
|
|
6eb56a |
#include "time.h"
|
|
|
6eb56a |
|
|
bw |
94d8a6 |
#include <synfig localization.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === U S I N G =========================================================== */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace std;
|
|
Carlos Lopez |
a09598 |
using namespace etl;
|
|
Carlos Lopez |
a09598 |
using namespace synfig;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#define tolower ::tolower
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Time::Time(const String &str_, float fps):
|
|
Carlos Lopez |
a09598 |
value_(0)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
String str(str_);
|
|
Carlos Lopez |
a09598 |
std::transform(str.begin(),str.end(),str.begin(),&tolower);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Start/Begin Of Time
|
|
Carlos Lopez |
a09598 |
if(str=="sot" || str=="bot")
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
operator=(begin());
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
// End Of Time
|
|
Carlos Lopez |
a09598 |
if(str=="eot")
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
operator=(end());
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
unsigned int pos=0;
|
|
Carlos Lopez |
a09598 |
int read;
|
|
Carlos Lopez |
a09598 |
float amount;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Now try to read it in the letter-abbreviated format
|
|
Carlos Lopez |
a09598 |
while(pos
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
pos+=read;
|
|
Carlos Lopez |
a09598 |
if(pos>=str.size() || read==0)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// Throw up a warning if there are no units
|
|
Carlos Lopez |
a09598 |
// and the amount isn't zero. There is no need
|
|
Carlos Lopez |
a09598 |
// to warn about units if the value is zero
|
|
Carlos Lopez |
a09598 |
// it is the only case where units are irrelevant.
|
|
Carlos Lopez |
40bd85 |
if(amount!=0 && fps)
|
|
Carlos Lopez |
40bd85 |
{
|
|
Carlos Lopez |
40bd85 |
synfig::warning(_("Time(): No unit provided in time code, assuming FRAMES (\"%s\")"),str.c_str());
|
|
Carlos Lopez |
40bd85 |
value_+=amount/fps;
|
|
Carlos Lopez |
40bd85 |
}
|
|
Carlos Lopez |
40bd85 |
else
|
|
Carlos Lopez |
40bd85 |
{
|
|
Carlos Lopez |
40bd85 |
synfig::warning(_("Time(): No unit provided in time code and frame rate is unknown! Assuming SECONDS"));
|
|
Carlos Lopez |
40bd85 |
value_+=amount;
|
|
Carlos Lopez |
40bd85 |
}
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
switch(str[pos])
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
case 'h':
|
|
Carlos Lopez |
a09598 |
case 'H':
|
|
Carlos Lopez |
a09598 |
value_+=amount*3600;
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
case 'm':
|
|
Carlos Lopez |
a09598 |
case 'M':
|
|
Carlos Lopez |
a09598 |
value_+=amount*60;
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
case 's':
|
|
Carlos Lopez |
a09598 |
case 'S':
|
|
Carlos Lopez |
a09598 |
value_+=amount;
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
case 'f':
|
|
Carlos Lopez |
a09598 |
case 'F':
|
|
Carlos Lopez |
a09598 |
if(fps)
|
|
Carlos Lopez |
a09598 |
value_+=amount/fps;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
synfig::warning("Time(): Individual frames referenced, but frame rate is unknown");
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
case ':':
|
|
Carlos Lopez |
a09598 |
// try to read it in as a traditional time format
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int hour,minute,second;
|
|
Carlos Lopez |
a09598 |
float frame;
|
|
Carlos Lopez |
a09598 |
if(fps && sscanf(str.c_str(),"%d:%d:%d.%f",&hour,&minute,&second,&frame)==4)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
value_=frame/fps+(hour*3600+minute*60+second);
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(sscanf(str.c_str(),"%d:%d:%d",&hour,&minute,&second)==3)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
value_=hour*3600+minute*60+second;
|
|
Carlos Lopez |
a09598 |
return;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
synfig::warning("Time(): Bad time format");
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
default:
|
|
Carlos Lopez |
a09598 |
value_+=amount;
|
|
Carlos Lopez |
a09598 |
synfig::warning("Time(): Unexpected character '%c' when parsing time string \"%s\"",str[pos],str.c_str());
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
pos++;
|
|
Carlos Lopez |
a09598 |
amount=0;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
ff1868 |
// This functions suggests what time is in seconds
|
|
|
ff1868 |
std::string Time::get_string(Time::Format format) const
|
|
|
ff1868 |
{
|
|
|
ff1868 |
Time time(*this);
|
|
|
ff1868 |
if (time <= begin())
|
|
|
ff1868 |
return "SOT"; // Start Of Time
|
|
|
ff1868 |
if (time >= end())
|
|
|
ff1868 |
return "EOT"; // End Of Time
|
|
|
ff1868 |
|
|
|
ff1868 |
if(format <= FORMAT_NORMAL)
|
|
|
ff1868 |
{
|
|
|
ff1868 |
synfig::ChangeLocale change_locale(LC_NUMERIC, "C");
|
|
|
ff1868 |
return strprintf("%.3f", (float)time);
|
|
|
ff1868 |
}
|
|
|
ff1868 |
|
|
|
ff1868 |
|
|
|
ff1868 |
if(format<=FORMAT_VIDEO)
|
|
|
ff1868 |
{
|
|
|
ff1868 |
int hours, minutes, seconds, microseconds;
|
|
|
ff1868 |
hours = time / 3600;
|
|
|
ff1868 |
time -= hours*3600;
|
|
|
ff1868 |
|
|
|
ff1868 |
minutes = time / 60;
|
|
|
ff1868 |
time -= minutes*60;
|
|
|
ff1868 |
|
|
|
ff1868 |
seconds=time;
|
|
|
ff1868 |
time -= seconds;
|
|
|
ff1868 |
|
|
|
ff1868 |
microseconds = time*1000;
|
|
|
ff1868 |
|
|
|
ff1868 |
return strprintf("%02d:%02d:%02d.%02d", hours, minutes, seconds, microseconds);
|
|
|
ff1868 |
}
|
|
|
ff1868 |
|
|
|
ff1868 |
synfig::error(_("Translating Time to unknown format (not implemented)"));
|
|
|
ff1868 |
|
|
|
ff1868 |
return "";
|
|
|
ff1868 |
}
|
|
|
ff1868 |
|
|
Carlos Lopez |
a09598 |
String
|
|
Carlos Lopez |
a09598 |
Time::get_string(float fps, Time::Format format)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Time time(*this);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(time<=begin())
|
|
Carlos Lopez |
a09598 |
return "SOT"; // Start Of Time
|
|
Carlos Lopez |
a09598 |
if(time>=end())
|
|
Carlos Lopez |
a09598 |
return "EOT"; // End Of Time
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(fps<0)fps=0;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(ceil(time.value_)-time.value_
|
|
Carlos Lopez |
a09598 |
time.value_=ceil(time.value_);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
int hour = 0, minute = 0;
|
|
Carlos Lopez |
a09598 |
if(!(format<=FORMAT_FRAMES))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
hour=time/3600;time-=hour*3600;
|
|
Carlos Lopez |
a09598 |
minute=time/60;time-=minute*60;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
// <= is redefined, so this means "is the FORMAT_VIDEO bit set in the format?"
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_VIDEO)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int second;
|
|
Carlos Lopez |
a09598 |
second=time;time-=second;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(fps && fps>1)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int frame;
|
|
Carlos Lopez |
a09598 |
frame=round_to_int(time*fps);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return strprintf("%02d:%02d:%02d.%02d",hour,minute,second,frame);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
return strprintf("%02d:%02d:%02d",hour,minute,second);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if (format <= FORMAT_FRAMES)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if (fps && fps>0)
|
|
Carlos Lopez |
a09598 |
return strprintf("%df", round_to_int(time * fps));
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
return strprintf("%ds", round_to_int(time * 1));
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
String ret;
|
|
Carlos Lopez |
a09598 |
bool started = false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_FULL || hour)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
ret+=strprintf("%dh",hour);
|
|
Carlos Lopez |
a09598 |
started = true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_FULL || minute)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if (!(format<=FORMAT_NOSPACES) && started)
|
|
Carlos Lopez |
a09598 |
ret += " ";
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret += strprintf("%dm", minute);
|
|
Carlos Lopez |
a09598 |
started = true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(fps && fps>1)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
int second;
|
|
Carlos Lopez |
a09598 |
float frame;
|
|
Carlos Lopez |
a09598 |
second=time;time-=second;
|
|
Carlos Lopez |
a09598 |
frame=time*fps;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_FULL || second)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if (!(format<=FORMAT_NOSPACES) && started)
|
|
Carlos Lopez |
a09598 |
ret += " ";
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret += strprintf("%ds", (int)second);
|
|
Carlos Lopez |
a09598 |
started = true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_FULL || abs(frame) > epsilon_() || !started)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if (!(format<=FORMAT_NOSPACES) && started)
|
|
Carlos Lopez |
a09598 |
ret += " ";
|
|
Carlos Lopez |
a09598 |
|
|
|
3b709a |
if (fabs(frame-floor(frame)) >= epsilon_())
|
|
Carlos Lopez |
a09598 |
ret += strprintf("%0.3ff", frame);
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
ret += strprintf("%0.0ff", frame);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
float second;
|
|
Carlos Lopez |
a09598 |
second=time;
|
|
Carlos Lopez |
a09598 |
if(format<=FORMAT_FULL || second || !started)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if (!(format<=FORMAT_NOSPACES) && started)
|
|
Carlos Lopez |
a09598 |
ret += " ";
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(abs(second-floor(second))>=epsilon_())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
String seconds(strprintf("%0.8f",second));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// skip trailing zeros
|
|
Carlos Lopez |
a09598 |
int count = 0;
|
|
Carlos Lopez |
a09598 |
String::reverse_iterator i = seconds.rbegin();
|
|
Carlos Lopez |
a09598 |
for ( ; (*i) == '0'; i++)
|
|
Carlos Lopez |
a09598 |
count++;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// if we removed too many, go back one place, leaving one zero
|
|
Carlos Lopez |
a09598 |
if (*i < '0' || *i > '9') count--;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret += seconds.substr(0, seconds.size()-count) + "s";
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
ret+=strprintf("%0.0fs",second);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return ret;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Time
|
|
Carlos Lopez |
a09598 |
Time::round(float fps)const
|
|
Carlos Lopez |
a09598 |
{
|
|
|
6eb56a |
// the aim is to make results for the same frame are absolutelly idential
|
|
|
6eb56a |
assert(approximate_greater_lp(fps, 0.f));
|
|
|
6eb56a |
if (!approximate_greater_lp(fps, 0.f)) return *this;
|
|
|
6eb56a |
return Time(floor(value_*fps + 0.5)/fps);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef _DEBUG
|
|
Carlos Lopez |
a09598 |
const char *
|
|
Carlos Lopez |
a09598 |
Time::c_str()const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
return get_string().c_str();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
//! \writeme
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Time::is_valid()const
|
|
Carlos Lopez |
a09598 |
{
|
|
[d.j.a.y] Jerome Blanchi |
c14c8d |
return !std::isnan(value_);
|
|
Carlos Lopez |
a09598 |
}
|