forked from mia/Aegisub
Move the SMPTE timecode stuff out of the AssTime class and put it in a class of its own, FractionalTime. The AssTime to SMPTE part is tested and verified to work (in fact it looks like I unintentionally fixed an overlap bug in the TranStation export filter), while the SMPTE to AssTime part is completely untested (but it's currently not used anywhere so it's not like it matters).
Originally committed to SVN as r2909.
This commit is contained in:
parent
61a3c5657a
commit
ebcdf0ce46
4 changed files with 97 additions and 15 deletions
|
@ -38,6 +38,7 @@
|
||||||
// Includes
|
// Includes
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <wx/regex.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
|
@ -244,15 +245,6 @@ wxString AssTime::GetSRTFormated () {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////
|
|
||||||
// SMPTE formatted
|
|
||||||
wxString AssTime::GetSMPTE(double fps)
|
|
||||||
{
|
|
||||||
int f = int(GetTimeMiliseconds() * fps / 1000.0);
|
|
||||||
return wxString::Format(_T("%02i:%02i:%02i:%02i"),GetTimeHours(),GetTimeMinutes(),GetTimeSeconds(),f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// AssTime comparison
|
// AssTime comparison
|
||||||
bool operator < (AssTime &t1, AssTime &t2) {
|
bool operator < (AssTime &t1, AssTime &t2) {
|
||||||
|
@ -292,3 +284,69 @@ int AssTime::GetTimeMinutes() { return (time % 3600000)/60000; }
|
||||||
int AssTime::GetTimeSeconds() { return (time % 60000)/1000; }
|
int AssTime::GetTimeSeconds() { return (time % 60000)/1000; }
|
||||||
int AssTime::GetTimeMiliseconds() { return (time % 1000); }
|
int AssTime::GetTimeMiliseconds() { return (time % 1000); }
|
||||||
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
int AssTime::GetTimeCentiseconds() { return (time % 1000)/10; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FractionalTime::FractionalTime (wxString separator, double numerator, double denominator) {
|
||||||
|
num = numerator;
|
||||||
|
den = denominator;
|
||||||
|
sep = separator;
|
||||||
|
|
||||||
|
// fractions < 1 are not welcome here
|
||||||
|
if ((num <= 0 || den <= 0) || (num < den))
|
||||||
|
throw _T("FractionalTime: nonsensical enumerator or denominator");
|
||||||
|
if (sep.IsEmpty())
|
||||||
|
throw _T("FractionalTime: no separator specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
FractionalTime::~FractionalTime () {
|
||||||
|
sep.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t FractionalTime::ToMillisecs (wxString _text) {
|
||||||
|
wxString text = _text;
|
||||||
|
wxString re_str = _T("");
|
||||||
|
wxString sep_e = _T("\\") + sep; // escape this just in case it may be a reserved regex character
|
||||||
|
text.Trim(false);
|
||||||
|
text.Trim(true);
|
||||||
|
long h=0,m=0,s=0,ms=0,f=0;
|
||||||
|
|
||||||
|
// hour minute second fraction
|
||||||
|
re_str << _T("(\\d+)") << sep_e << _T("(\\d+)") << sep_e << _T("(\\d+)") << sep_e << _T("(\\d+)");
|
||||||
|
|
||||||
|
wxRegEx re(re_str, wxRE_ADVANCED);
|
||||||
|
if (!re.IsValid())
|
||||||
|
throw _T("FractionalTime: regex failure");
|
||||||
|
if (!re.Matches(text))
|
||||||
|
return 0; // FIXME: throw here too?
|
||||||
|
|
||||||
|
re.GetMatch(text, 1).ToLong(&h);
|
||||||
|
re.GetMatch(text, 2).ToLong(&m);
|
||||||
|
re.GetMatch(text, 3).ToLong(&s);
|
||||||
|
re.GetMatch(text, 4).ToLong(&f);
|
||||||
|
// FIXME: find out how to do this in a sane way
|
||||||
|
//if ((double)f >= ((double)num/(double)den) // overflow?
|
||||||
|
// f = (num/den - 1);
|
||||||
|
ms = long((1000.0 / (num/den)) * (double)f);
|
||||||
|
|
||||||
|
return (int64_t)((h * 3600000) + (m * 60000) + (s * 1000) + ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssTime FractionalTime::ToAssTime (wxString _text) {
|
||||||
|
AssTime time;
|
||||||
|
time.SetMS((int)ToMillisecs(_text));
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString FractionalTime::FromAssTime(AssTime time) {
|
||||||
|
return FromMillisecs((int64_t)time.GetMS());
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString FractionalTime::FromMillisecs(int64_t msec) {
|
||||||
|
int h = msec / 3600000;
|
||||||
|
int m = (msec % 3600000)/60000;
|
||||||
|
int s = (msec % 60000)/1000;
|
||||||
|
int f = int((msec % 1000) * ((num/den) / 1000.0));
|
||||||
|
return wxString::Format(_T("%02i") + sep + _T("%02i") + sep + _T("%02i") + sep + _T("%02i"),h,m,s,f);
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
// Headers
|
// Headers
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
@ -66,7 +67,6 @@ public:
|
||||||
void ParseSRT(const wxString text); // Sets value to text-form time, in SRT format
|
void ParseSRT(const wxString text); // Sets value to text-form time, in SRT format
|
||||||
wxString GetASSFormated(bool ms=false); // Returns the ASS representation of time
|
wxString GetASSFormated(bool ms=false); // Returns the ASS representation of time
|
||||||
wxString GetSRTFormated(); // Returns the SRT representation of time
|
wxString GetSRTFormated(); // Returns the SRT representation of time
|
||||||
wxString GetSMPTE(double fps); // Returns the SMPTE timecodes for the given frame rate
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Comparison operators
|
// Comparison operators
|
||||||
|
@ -76,3 +76,24 @@ bool operator < (AssTime &t1, AssTime &t2);
|
||||||
bool operator > (AssTime &t1, AssTime &t2);
|
bool operator > (AssTime &t1, AssTime &t2);
|
||||||
bool operator <= (AssTime &t1, AssTime &t2);
|
bool operator <= (AssTime &t1, AssTime &t2);
|
||||||
bool operator >= (AssTime &t1, AssTime &t2);
|
bool operator >= (AssTime &t1, AssTime &t2);
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////
|
||||||
|
// Class for that annoying SMPTE format timecodes stuff
|
||||||
|
class FractionalTime {
|
||||||
|
private:
|
||||||
|
int64_t time; // milliseconds, like in AssTime
|
||||||
|
double num, den; // numerator/denominator
|
||||||
|
wxString sep; // separator; someone might have separators of more than one character :V
|
||||||
|
|
||||||
|
public:
|
||||||
|
// dumb assumption? I give no fuck
|
||||||
|
FractionalTime(wxString separator, double numerator=30.0, double denominator=1.0);
|
||||||
|
~FractionalTime();
|
||||||
|
|
||||||
|
AssTime ToAssTime(wxString fractime);
|
||||||
|
int64_t ToMillisecs(wxString fractime);
|
||||||
|
|
||||||
|
wxString FromAssTime(AssTime time);
|
||||||
|
wxString FromMillisecs(int64_t msec);
|
||||||
|
};
|
||||||
|
|
|
@ -87,14 +87,15 @@ void EncoreSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||||
// Write lines
|
// Write lines
|
||||||
using std::list;
|
using std::list;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
// Encore wants ; instead of : if we're dealing with NTSC
|
||||||
|
FractionalTime fp(fps > 26.0 ? _T(";") : _T(":"), fps);
|
||||||
|
|
||||||
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
for (list<AssEntry*>::iterator cur=Line->begin();cur!=Line->end();cur++) {
|
||||||
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
AssDialogue *current = AssEntry::GetAsDialogue(*cur);
|
||||||
if (current && !current->Comment) {
|
if (current && !current->Comment) {
|
||||||
// Time stamps
|
// Time stamps
|
||||||
wxString timeStamps = wxString::Format(_T("%i "),++i) + current->Start.GetSMPTE(fps) + _T(" ") + current->End.GetSMPTE(fps);
|
wxString timeStamps = wxString::Format(_T("%i "),++i) + fp.FromAssTime(current->Start) + _T(" ") + fp.FromAssTime(current->End);
|
||||||
|
|
||||||
// Convert : to ; if it's NTSC
|
|
||||||
if (fps > 26.0) timeStamps.Replace(_T(":"),_T(";"));
|
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
file.WriteLineToFile(timeStamps + current->Text);
|
file.WriteLineToFile(timeStamps + current->Text);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_style.h"
|
#include "ass_style.h"
|
||||||
|
#include "ass_time.h"
|
||||||
#include "subtitle_format_transtation.h"
|
#include "subtitle_format_transtation.h"
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -115,7 +116,8 @@ void TranStationSubtitleFormat::WriteFile(wxString _filename,wxString encoding)
|
||||||
// and we otherwise run the risk of having two lines overlap in a
|
// and we otherwise run the risk of having two lines overlap in a
|
||||||
// frame, when they should run right into each other.
|
// frame, when they should run right into each other.
|
||||||
end.SetMS(end.GetMS() - (int)(500.0/fps));
|
end.SetMS(end.GetMS() - (int)(500.0/fps));
|
||||||
wxString header = wxString::Format(_T("SUB[%i%s%s "),valign,halign,type) + start.GetSMPTE(fps) + _T(">") + end.GetSMPTE(fps) + _T("]");
|
FractionalTime ft(_T(":"),fps);
|
||||||
|
wxString header = wxString::Format(_T("SUB[%i%s%s "),valign,halign,type) + ft.FromAssTime(start) + _T(">") + ft.FromAssTime(end) + _T("]");
|
||||||
file.WriteLineToFile(header);
|
file.WriteLineToFile(header);
|
||||||
|
|
||||||
// Process text
|
// Process text
|
||||||
|
|
Loading…
Reference in a new issue