forked from mia/Aegisub
Delete SubtitleFormat::FPSRational and just use FractionalTime
Originally committed to SVN as r6117.
This commit is contained in:
parent
ac6e9fd022
commit
3b83b9e31b
8 changed files with 67 additions and 88 deletions
|
@ -251,11 +251,10 @@ int AssTime::GetTimeMiliseconds() { return (time % 1000); }
|
||||||
///
|
///
|
||||||
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
||||||
|
|
||||||
FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe, char sep)
|
FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe)
|
||||||
: num(numerator)
|
: num(numerator)
|
||||||
, den(denominator)
|
, den(denominator)
|
||||||
, drop(dropframe)
|
, drop(dropframe)
|
||||||
, sep(sep)
|
|
||||||
{
|
{
|
||||||
if (drop) {
|
if (drop) {
|
||||||
// no dropframe for any other framerates
|
// no dropframe for any other framerates
|
||||||
|
@ -268,7 +267,7 @@ FractionalTime::FractionalTime(int numerator, int denominator, bool dropframe, c
|
||||||
throw "FractionalTime: nonsensical enumerator or denominator";
|
throw "FractionalTime: nonsensical enumerator or denominator";
|
||||||
}
|
}
|
||||||
|
|
||||||
int FractionalTime::ToMillisecs(wxString text) {
|
int FractionalTime::ToMillisecs(wxString text, char sep) {
|
||||||
text.Trim(false);
|
text.Trim(false);
|
||||||
text.Trim(true);
|
text.Trim(true);
|
||||||
|
|
||||||
|
@ -318,15 +317,15 @@ int FractionalTime::ToMillisecs(wxString text) {
|
||||||
return msecs_f;
|
return msecs_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssTime FractionalTime::ToAssTime(wxString text) {
|
AssTime FractionalTime::ToAssTime(wxString text, char sep) {
|
||||||
return AssTime(ToMillisecs(text));
|
return AssTime(ToMillisecs(text, sep));
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString FractionalTime::FromAssTime(AssTime time) {
|
wxString FractionalTime::FromAssTime(AssTime time, char sep) {
|
||||||
return FromMillisecs(time.GetMS());
|
return FromMillisecs(time.GetMS(), sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString FractionalTime::FromMillisecs(int64_t msec) {
|
wxString FractionalTime::FromMillisecs(int64_t msec, char sep) {
|
||||||
int h=0, m=0, s=0, f=0; // hours, minutes, seconds, fractions
|
int h=0, m=0, s=0, f=0; // hours, minutes, seconds, fractions
|
||||||
int fn = (msec*(int64_t)num) / (1000*den); // frame number
|
int fn = (msec*(int64_t)num) / (1000*den); // frame number
|
||||||
|
|
||||||
|
|
|
@ -91,21 +91,24 @@ class FractionalTime {
|
||||||
int num; ///< Numerator
|
int num; ///< Numerator
|
||||||
int den; ///< Denominator
|
int den; ///< Denominator
|
||||||
bool drop; ///< Enable SMPTE dropframe handling
|
bool drop; ///< Enable SMPTE dropframe handling
|
||||||
char sep; ///< Timecode component separator
|
|
||||||
|
|
||||||
/// How often to drop frames when enabled
|
/// How often to drop frames when enabled
|
||||||
static const int frames_per_period = 17982;
|
static const int frames_per_period = 17982;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FractionalTime(int numerator=30, int denominator=1, bool dropframe=false, char sep=':');
|
FractionalTime(int numerator=30, int denominator=1, bool dropframe=false);
|
||||||
|
|
||||||
|
int Numerator() const { return num; }
|
||||||
|
int Denominator() const { return den; }
|
||||||
|
bool IsDrop() const { return drop; }
|
||||||
|
|
||||||
/// Parse a SMPTE timecode, returning an AssTime
|
/// Parse a SMPTE timecode, returning an AssTime
|
||||||
AssTime ToAssTime(wxString fractime);
|
AssTime ToAssTime(wxString fractime, char sep=':');
|
||||||
/// Parse a SMPTE timecode, returning milliseconds
|
/// Parse a SMPTE timecode, returning milliseconds
|
||||||
int ToMillisecs(wxString fractime);
|
int ToMillisecs(wxString fractime, char sep=':');
|
||||||
|
|
||||||
/// Convert an AssTime to a SMPTE timecode
|
/// Convert an AssTime to a SMPTE timecode
|
||||||
wxString FromAssTime(AssTime time);
|
wxString FromAssTime(AssTime time, char sep=':');
|
||||||
/// Convert milliseconds to a SMPTE timecode
|
/// Convert milliseconds to a SMPTE timecode
|
||||||
wxString FromMillisecs(int64_t msec);
|
wxString FromMillisecs(int64_t msec, char sep=':');
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,19 +109,22 @@ void SubtitleFormat::AddLine(wxString data, wxString group, int &version, wxStri
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Ask the user to enter the FPS
|
/// @brief Ask the user to enter the FPS
|
||||||
SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
FractionalTime SubtitleFormat::AskForFPS(bool showSMPTE) {
|
||||||
wxArrayString choices;
|
wxArrayString choices;
|
||||||
FPSRational fps_rat;
|
bool drop = false;
|
||||||
fps_rat.smpte_dropframe = false; // ensure it's false by default
|
int num;
|
||||||
|
int den;
|
||||||
|
|
||||||
// Video FPS
|
// Video FPS
|
||||||
VideoContext *context = VideoContext::Get();
|
VideoContext *context = VideoContext::Get();
|
||||||
bool vidLoaded = context->TimecodesLoaded();
|
bool vidLoaded = context->TimecodesLoaded();
|
||||||
if (vidLoaded) {
|
if (vidLoaded) {
|
||||||
wxString vidFPS;
|
wxString vidFPS;
|
||||||
if (context->FPS().IsVFR()) vidFPS = "VFR";
|
if (context->FPS().IsVFR())
|
||||||
else vidFPS = wxString::Format("%.3f", context->FPS().FPS());
|
vidFPS = "VFR";
|
||||||
choices.Add(wxString::Format("From video (%s)", vidFPS));
|
else
|
||||||
|
vidFPS = wxString::Format("%.3f", context->FPS().FPS());
|
||||||
|
choices.Add(wxString::Format(_("From video (%s)"), vidFPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard FPS values
|
// Standard FPS values
|
||||||
|
@ -141,51 +144,31 @@ SubtitleFormat::FPSRational SubtitleFormat::AskForFPS(bool showSMPTE) {
|
||||||
|
|
||||||
// Ask
|
// Ask
|
||||||
int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"), _("FPS"), choices);
|
int choice = wxGetSingleChoiceIndex(_("Please choose the appropriate FPS for the subtitles:"), _("FPS"), choices);
|
||||||
if (choice == -1) {
|
if (choice == -1)
|
||||||
fps_rat.num = 0;
|
return FractionalTime(0, 0);
|
||||||
fps_rat.den = 0;
|
|
||||||
|
|
||||||
return fps_rat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get FPS from choice
|
// Get FPS from choice
|
||||||
if (vidLoaded) choice--;
|
if (vidLoaded) choice--;
|
||||||
// dropframe was displayed, that means all choices >4 are bumped up by 1
|
// dropframe was displayed, that means all choices >4 are bumped up by 1
|
||||||
if (showSMPTE) {
|
if (!showSMPTE && choice > 4) ++choice;
|
||||||
|
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case -1: fps_rat.num = -1; fps_rat.den = 1; break; // VIDEO
|
case -1: num = -1; den = 1; break; // VIDEO
|
||||||
case 0: fps_rat.num = 15; fps_rat.den = 1; break;
|
case 0: num = 15; den = 1; break;
|
||||||
case 1: fps_rat.num = 24000; fps_rat.den = 1001; break;
|
case 1: num = 24000; den = 1001; break;
|
||||||
case 2: fps_rat.num = 24; fps_rat.den = 1; break;
|
case 2: num = 24; den = 1; break;
|
||||||
case 3: fps_rat.num = 25; fps_rat.den = 1; break;
|
case 3: num = 25; den = 1; break;
|
||||||
case 4: fps_rat.num = 30000; fps_rat.den = 1001; break;
|
case 4: num = 30000; den = 1001; break;
|
||||||
case 5: fps_rat.num = 30000; fps_rat.den = 1001; fps_rat.smpte_dropframe = true; break;
|
case 5: num = 30000; den = 1001; drop = true; break;
|
||||||
case 6: fps_rat.num = 30; fps_rat.den = 1; break;
|
case 6: num = 30; den = 1; break;
|
||||||
case 7: fps_rat.num = 50; fps_rat.den = 1; break;
|
case 7: num = 50; den = 1; break;
|
||||||
case 8: fps_rat.num = 60000; fps_rat.den = 1001; break;
|
case 8: num = 60000; den = 1001; break;
|
||||||
case 9: fps_rat.num = 60; fps_rat.den = 1; break;
|
case 9: num = 60; den = 1; break;
|
||||||
case 10: fps_rat.num = 120000; fps_rat.den = 1001; break;
|
case 10: num = 120000; den = 1001; break;
|
||||||
case 11: fps_rat.num = 120; fps_rat.den = 1; break;
|
case 11: num = 120; den = 1; break;
|
||||||
}
|
|
||||||
return fps_rat;
|
|
||||||
} else {
|
|
||||||
// dropframe wasn't displayed
|
|
||||||
switch (choice) {
|
|
||||||
case -1: fps_rat.num = -1; fps_rat.den = 1; break; // VIDEO
|
|
||||||
case 0: fps_rat.num = 15; fps_rat.den = 1; break;
|
|
||||||
case 1: fps_rat.num = 24000; fps_rat.den = 1001; break;
|
|
||||||
case 2: fps_rat.num = 24; fps_rat.den = 1; break;
|
|
||||||
case 3: fps_rat.num = 25; fps_rat.den = 1; break;
|
|
||||||
case 4: fps_rat.num = 30000; fps_rat.den = 1001; break;
|
|
||||||
case 5: fps_rat.num = 30; fps_rat.den = 1; break;
|
|
||||||
case 6: fps_rat.num = 50; fps_rat.den = 1; break;
|
|
||||||
case 7: fps_rat.num = 60000; fps_rat.den = 1001; break;
|
|
||||||
case 8: fps_rat.num = 60; fps_rat.den = 1; break;
|
|
||||||
case 9: fps_rat.num = 120000; fps_rat.den = 1001; break;
|
|
||||||
case 10: fps_rat.num = 120; fps_rat.den = 1; break;
|
|
||||||
}
|
|
||||||
return fps_rat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FractionalTime(num, den, drop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitleFormat::SortLines() {
|
void SubtitleFormat::SortLines() {
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
class AssFile;
|
class AssFile;
|
||||||
class AssEntry;
|
class AssEntry;
|
||||||
|
class FractionalTime;
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class SubtitleFormat
|
/// @class SubtitleFormat
|
||||||
|
@ -67,12 +68,6 @@ class SubtitleFormat {
|
||||||
static std::list<SubtitleFormat*> formats;
|
static std::list<SubtitleFormat*> formats;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct FPSRational {
|
|
||||||
int num;
|
|
||||||
int den;
|
|
||||||
bool smpte_dropframe;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::list<AssEntry*> *Line;
|
std::list<AssEntry*> *Line;
|
||||||
|
|
||||||
/// Copy the input subtitles file; must be called before making any changes
|
/// Copy the input subtitles file; must be called before making any changes
|
||||||
|
@ -112,7 +107,7 @@ protected:
|
||||||
void AddLine(wxString data,wxString group,int &version,wxString *outgroup=NULL);
|
void AddLine(wxString data,wxString group,int &version,wxString *outgroup=NULL);
|
||||||
/// Prompt the user for a framerate to use
|
/// Prompt the user for a framerate to use
|
||||||
/// @param showSMPTE Include SMPTE as an option?
|
/// @param showSMPTE Include SMPTE as an option?
|
||||||
FPSRational AskForFPS(bool showSMPTE=false);
|
FractionalTime AskForFPS(bool showSMPTE=false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
|
|
@ -53,8 +53,8 @@ wxArrayString EncoreSubtitleFormat::GetWriteWildcards() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||||
FPSRational fps_rat = AskForFPS(true);
|
FractionalTime ft = AskForFPS(true);
|
||||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) return;
|
if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return;
|
||||||
|
|
||||||
TextFileWriter file(filename, encoding);
|
TextFileWriter file(filename, encoding);
|
||||||
|
|
||||||
|
@ -71,12 +71,12 @@ void EncoreSubtitleFormat::WriteFile(wxString const& filename, wxString const& e
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
// Encore wants ; instead of : if we're dealing with NTSC dropframe stuff
|
// Encore wants ; instead of : if we're dealing with NTSC dropframe stuff
|
||||||
FractionalTime ft(fps_rat.num, fps_rat.den, fps_rat.smpte_dropframe, fps_rat.smpte_dropframe ? ';' : ':');
|
char sep = ft.IsDrop() ? ';' : ':';
|
||||||
|
|
||||||
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
for (std::list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||||
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
if (AssDialogue *current = dynamic_cast<AssDialogue*>(*cur)) {
|
||||||
++i;
|
++i;
|
||||||
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.FromAssTime(current->Start), ft.FromAssTime(current->End), current->Text));
|
file.WriteLineToFile(wxString::Format("%i %s %s %s", i, ft.FromAssTime(current->Start, sep), ft.FromAssTime(current->End, sep), current->Text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,10 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const&
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it wasn't an fps line, ask the user for it
|
// If it wasn't an fps line, ask the user for it
|
||||||
FPSRational fps_rat = AskForFPS();
|
FractionalTime fps_rat = AskForFPS();
|
||||||
if (fps_rat.num == 0) return;
|
if (fps_rat.Numerator() == 0) return;
|
||||||
else if (fps_rat.num > 0)
|
else if (fps_rat.Numerator() > 0)
|
||||||
fps = agi::vfr::Framerate(fps_rat.num, fps_rat.den);
|
fps = agi::vfr::Framerate(fps_rat.Numerator(), fps_rat.Denominator());
|
||||||
else
|
else
|
||||||
fps = VideoContext::Get()->FPS();
|
fps = VideoContext::Get()->FPS();
|
||||||
}
|
}
|
||||||
|
@ -131,12 +131,12 @@ void MicroDVDSubtitleFormat::ReadFile(wxString const& filename, wxString const&
|
||||||
void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
void MicroDVDSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||||
agi::vfr::Framerate fps;
|
agi::vfr::Framerate fps;
|
||||||
|
|
||||||
FPSRational fps_rat = AskForFPS();
|
FractionalTime fps_rat = AskForFPS();
|
||||||
if (fps_rat.num == 0 || fps_rat.den == 0) return;
|
if (fps_rat.Numerator() == 0 || fps_rat.Denominator() == 0) return;
|
||||||
if (fps_rat.num < 0 || fps_rat.den < 0)
|
if (fps_rat.Numerator() < 0 || fps_rat.Denominator() < 0)
|
||||||
fps = VideoContext::Get()->FPS();
|
fps = VideoContext::Get()->FPS();
|
||||||
else
|
else
|
||||||
fps = agi::vfr::Framerate(fps_rat.num, fps_rat.den);
|
fps = agi::vfr::Framerate(fps_rat.Numerator(), fps_rat.Denominator());
|
||||||
|
|
||||||
// Convert file
|
// Convert file
|
||||||
CreateCopy();
|
CreateCopy();
|
||||||
|
|
|
@ -60,8 +60,8 @@ wxArrayString TranStationSubtitleFormat::GetWriteWildcards() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString const& encoding) {
|
||||||
FPSRational fps_rat = AskForFPS(true);
|
FractionalTime ft = AskForFPS(true);
|
||||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) return;
|
if (ft.Numerator() <= 0 || ft.Denominator() <= 0) return;
|
||||||
|
|
||||||
TextFileWriter file(filename, encoding);
|
TextFileWriter file(filename, encoding);
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con
|
||||||
AssDialogue *cur = dynamic_cast<AssDialogue*>(*it);
|
AssDialogue *cur = dynamic_cast<AssDialogue*>(*it);
|
||||||
|
|
||||||
if (prev && cur) {
|
if (prev && cur) {
|
||||||
file.WriteLineToFile(ConvertLine(prev, &fps_rat, cur->Start.GetMS()));
|
file.WriteLineToFile(ConvertLine(prev, &ft, cur->Start.GetMS()));
|
||||||
file.WriteLineToFile("");
|
file.WriteLineToFile("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con
|
||||||
|
|
||||||
// flush last line
|
// flush last line
|
||||||
if (prev)
|
if (prev)
|
||||||
file.WriteLineToFile(ConvertLine(prev, &fps_rat, -1));
|
file.WriteLineToFile(ConvertLine(prev, &ft, -1));
|
||||||
|
|
||||||
// Every file must end with this line
|
// Every file must end with this line
|
||||||
file.WriteLineToFile("SUB[");
|
file.WriteLineToFile("SUB[");
|
||||||
|
@ -95,7 +95,7 @@ void TranStationSubtitleFormat::WriteFile(wxString const& filename, wxString con
|
||||||
ClearCopy();
|
ClearCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRational *fps_rat, int nextl_start) {
|
wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FractionalTime *ft, int nextl_start) {
|
||||||
int valign = 0;
|
int valign = 0;
|
||||||
const char *halign = " "; // default is centered
|
const char *halign = " "; // default is centered
|
||||||
const char *type = "N"; // no special style
|
const char *type = "N"; // no special style
|
||||||
|
@ -119,10 +119,9 @@ wxString TranStationSubtitleFormat::ConvertLine(AssDialogue *current, FPSRationa
|
||||||
// start of next one, since the end timestamp is inclusive and the lines
|
// start of next one, since the end timestamp is inclusive and the lines
|
||||||
// would overlap if left as is.
|
// would overlap if left as is.
|
||||||
if (nextl_start > 0 && end.GetMS() == nextl_start)
|
if (nextl_start > 0 && end.GetMS() == nextl_start)
|
||||||
end.SetMS(end.GetMS() - ((1000*fps_rat->den)/fps_rat->num));
|
end.SetMS(end.GetMS() - ((1000*ft->Denominator())/ft->Numerator()));
|
||||||
|
|
||||||
FractionalTime ft(fps_rat->num, fps_rat->den, fps_rat->smpte_dropframe);
|
wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft->FromAssTime(start) + ">" + ft->FromAssTime(end) + "]\r\n";
|
||||||
wxString header = wxString::Format("SUB[%i%s%s ", valign, halign, type) + ft.FromAssTime(start) + ">" + ft.FromAssTime(end) + "]\r\n";
|
|
||||||
|
|
||||||
// Process text
|
// Process text
|
||||||
wxString lineEnd = "\r\n";
|
wxString lineEnd = "\r\n";
|
||||||
|
|
|
@ -44,7 +44,7 @@ class AssDialogue;
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class TranStationSubtitleFormat : public SubtitleFormat {
|
class TranStationSubtitleFormat : public SubtitleFormat {
|
||||||
wxString ConvertLine(AssDialogue *line, FPSRational *fps_rat, int nextl_start);
|
wxString ConvertLine(AssDialogue *line, FractionalTime *ft, int nextl_start);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TranStationSubtitleFormat();
|
TranStationSubtitleFormat();
|
||||||
|
|
Loading…
Reference in a new issue