cinera: Increase precision to milliseconds
This commit simply adds millisecond precision of timecodes. It includes small changes to hmmlib.h, cinera.c and the frontend JS files.
This commit is contained in:
parent
026585e50b
commit
df93674bf7
|
@ -23,7 +23,7 @@ typedef struct
|
||||||
version CINERA_APP_VERSION = {
|
version CINERA_APP_VERSION = {
|
||||||
.Major = 0,
|
.Major = 0,
|
||||||
.Minor = 10,
|
.Minor = 10,
|
||||||
.Patch = 26
|
.Patch = 27
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __USE_XOPEN2K8 // NOTE(matt): O_NOFOLLOW
|
#define __USE_XOPEN2K8 // NOTE(matt): O_NOFOLLOW
|
||||||
|
@ -210,7 +210,12 @@ typedef struct
|
||||||
int C;
|
int C;
|
||||||
int Seconds;
|
int Seconds;
|
||||||
};
|
};
|
||||||
} v3;
|
union
|
||||||
|
{
|
||||||
|
int D;
|
||||||
|
int Milliseconds;
|
||||||
|
};
|
||||||
|
} v4;
|
||||||
|
|
||||||
void
|
void
|
||||||
Clear(void *V, uint64_t Size)
|
Clear(void *V, uint64_t Size)
|
||||||
|
@ -2167,7 +2172,7 @@ IndexingError(string Filename, uint64_t LineNumber, severity Severity, char *Mes
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PrintTimecode(FILE *Dest, v3 Timecode)
|
PrintTimecode(FILE *Dest, v4 Timecode)
|
||||||
{
|
{
|
||||||
Colourise(CS_BLUE_BOLD);
|
Colourise(CS_BLUE_BOLD);
|
||||||
if(Timecode.Hours)
|
if(Timecode.Hours)
|
||||||
|
@ -2182,7 +2187,7 @@ PrintTimecode(FILE *Dest, v3 Timecode)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IndexingChronologyError(string *Filename, uint64_t LineNumber, v3 ThisTimecode, v3 PrevTimecode)
|
IndexingChronologyError(string *Filename, uint64_t LineNumber, v4 ThisTimecode, v4 PrevTimecode)
|
||||||
{
|
{
|
||||||
severity Severity = S_ERROR;
|
severity Severity = S_ERROR;
|
||||||
ErrorFilenameAndLineNumber(Filename, LineNumber, Severity, ED_INDEXING);
|
ErrorFilenameAndLineNumber(Filename, LineNumber, Severity, ED_INDEXING);
|
||||||
|
@ -4304,7 +4309,7 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
v3 Timecode;
|
v4 Timecode;
|
||||||
int Identifier;
|
int Identifier;
|
||||||
} identifier;
|
} identifier;
|
||||||
|
|
||||||
|
@ -4430,7 +4435,7 @@ CopyStringToBuffer_(int LineNumber, buffer *Dest, char *Format, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
DigitsInTimecode(v3 Timecode)
|
DigitsInTimecode(v4 Timecode)
|
||||||
{
|
{
|
||||||
int Result = 0;
|
int Result = 0;
|
||||||
int ColonChar = 1;
|
int ColonChar = 1;
|
||||||
|
@ -4453,7 +4458,7 @@ DigitsInTimecode(v3 Timecode)
|
||||||
|
|
||||||
#define CopyTimecodeToBuffer(Dest, Timecode) CopyTimecodeToBuffer_(__LINE__, Dest, Timecode)
|
#define CopyTimecodeToBuffer(Dest, Timecode) CopyTimecodeToBuffer_(__LINE__, Dest, Timecode)
|
||||||
void
|
void
|
||||||
CopyTimecodeToBuffer_(int LineNumber, buffer *Dest, v3 Timecode)
|
CopyTimecodeToBuffer_(int LineNumber, buffer *Dest, v4 Timecode)
|
||||||
{
|
{
|
||||||
if(DigitsInTimecode(Timecode) + (Dest->Ptr - Dest->Location) >= Dest->Size)
|
if(DigitsInTimecode(Timecode) + (Dest->Ptr - Dest->Location) >= Dest->Size)
|
||||||
{
|
{
|
||||||
|
@ -5463,17 +5468,17 @@ InitTemplate(template *Template, string Location, template_type Type)
|
||||||
Template->Metadata.NavBuffer = InitBook(sizeof(navigation_buffer), 4);
|
Template->Metadata.NavBuffer = InitBook(sizeof(navigation_buffer), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
v3
|
v4
|
||||||
V3(int A, int B, int C)
|
V4(int A, int B, int C, int D)
|
||||||
{
|
{
|
||||||
v3 Result = { .A = A, .B = B, .C = C };
|
v4 Result = { .A = A, .B = B, .C = C, .D = D };
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
float
|
||||||
TimecodeToSeconds(v3 Timecode)
|
TimecodeToDottedSeconds(v4 Timecode)
|
||||||
{
|
{
|
||||||
return Timecode.Hours * SECONDS_PER_HOUR + Timecode.Minutes * SECONDS_PER_MINUTE + Timecode.Seconds;
|
return (float)Timecode.Hours * SECONDS_PER_HOUR + (float)Timecode.Minutes * SECONDS_PER_MINUTE + (float)Timecode.Seconds + (float)Timecode.Milliseconds / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -10816,9 +10821,9 @@ HMMLOutputLocationIs(neighbourhood *N, char *OutputLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TimecodeIs(v3 Timecode, int Hours, int Minutes, int Seconds)
|
TimecodeIs(v4 Timecode, int Hours, int Minutes, int Seconds, int Milliseconds)
|
||||||
{
|
{
|
||||||
return Timecode.Hours == Hours && Timecode.Minutes == Minutes && Timecode.Seconds == Seconds;
|
return Timecode.Hours == Hours && Timecode.Minutes == Minutes && Timecode.Seconds == Seconds && Timecode.Milliseconds == Milliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc
|
rc
|
||||||
|
@ -10829,14 +10834,14 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m
|
||||||
bool *HasQuoteMenu, bool *HasReferenceMenu, bool *HasFilterMenu, bool *RequiresCineraJS,
|
bool *HasQuoteMenu, bool *HasReferenceMenu, bool *HasFilterMenu, bool *RequiresCineraJS,
|
||||||
int *QuoteIdentifier, int *RefIdentifier,
|
int *QuoteIdentifier, int *RefIdentifier,
|
||||||
_memory_book(category_info) *Topics, _memory_book(category_info) *Media,
|
_memory_book(category_info) *Topics, _memory_book(category_info) *Media,
|
||||||
HMML_Timestamp *Timestamp, v3 *PreviousTimecode)
|
HMML_Timestamp *Timestamp, v4 *PreviousTimecode)
|
||||||
{
|
{
|
||||||
MEM_TEST_TOP();
|
MEM_TEST_TOP();
|
||||||
// TODO(matt): Introduce and use a SystemError() in here
|
// TODO(matt): Introduce and use a SystemError() in here
|
||||||
rc Result = RC_SUCCESS;
|
rc Result = RC_SUCCESS;
|
||||||
|
|
||||||
v3 Timecode = V3(Timestamp->h, Timestamp->m, Timestamp->s);
|
v4 Timecode = V4(Timestamp->h, Timestamp->m, Timestamp->s, Timestamp->ms);
|
||||||
if(TimecodeToSeconds(Timecode) >= TimecodeToSeconds(*PreviousTimecode))
|
if(TimecodeToDottedSeconds(Timecode) >= TimecodeToDottedSeconds(*PreviousTimecode))
|
||||||
{
|
{
|
||||||
*PreviousTimecode = Timecode;
|
*PreviousTimecode = Timecode;
|
||||||
|
|
||||||
|
@ -10857,8 +10862,8 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m
|
||||||
|
|
||||||
|
|
||||||
CopyStringToBuffer(&IndexBuffers->Header,
|
CopyStringToBuffer(&IndexBuffers->Header,
|
||||||
" <div data-timestamp=\"%d\"",
|
" <div data-timestamp=\"%.3f\"",
|
||||||
TimecodeToSeconds(Timecode));
|
TimecodeToDottedSeconds(Timecode));
|
||||||
|
|
||||||
CopyStringToBuffer(&IndexBuffers->Class,
|
CopyStringToBuffer(&IndexBuffers->Class,
|
||||||
" class=\"marker");
|
" class=\"marker");
|
||||||
|
@ -11115,10 +11120,10 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m
|
||||||
" <div class=\"quote_byline\">—%.*s, %.*s</div>\n"
|
" <div class=\"quote_byline\">—%.*s, %.*s</div>\n"
|
||||||
" </span>\n"
|
" </span>\n"
|
||||||
" <div class=\"ref_indices\">\n"
|
" <div class=\"ref_indices\">\n"
|
||||||
" <span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">",
|
" <span data-timestamp=\"%.3f\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">",
|
||||||
(int)QuoteUsername.Length, QuoteUsername.Base,
|
(int)QuoteUsername.Length, QuoteUsername.Base,
|
||||||
(int)DateString.Length, DateString.Base, // TODO(matt): Convert Unixtime to date-string
|
(int)DateString.Length, DateString.Base, // TODO(matt): Convert Unixtime to date-string
|
||||||
TimecodeToSeconds(Timecode),
|
TimecodeToDottedSeconds(Timecode),
|
||||||
*QuoteIdentifier);
|
*QuoteIdentifier);
|
||||||
CopyTimecodeToBuffer(&MenuBuffers->Quote, Timecode);
|
CopyTimecodeToBuffer(&MenuBuffers->Quote, Timecode);
|
||||||
CopyStringToBuffer(&MenuBuffers->Quote, "</span></span>\n"
|
CopyStringToBuffer(&MenuBuffers->Quote, "</span></span>\n"
|
||||||
|
@ -11142,7 +11147,7 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m
|
||||||
|
|
||||||
if(Result == RC_SUCCESS)
|
if(Result == RC_SUCCESS)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\"%d\": \"", TimecodeToSeconds(Timecode));
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\"%.3f\": \"", TimecodeToDottedSeconds(Timecode));
|
||||||
if(Timestamp->quote.present && !Timestamp->text[0])
|
if(Timestamp->quote.present && !Timestamp->text[0])
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\u201C");
|
CopyStringToBuffer(&CollationBuffers->SearchEntry, "\u201C");
|
||||||
|
@ -11831,7 +11836,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
Print(stdout, "\n\n --- Entering Timestamps Loop ---\n\n\n\n");
|
Print(stdout, "\n\n --- Entering Timestamps Loop ---\n\n\n\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v3 PreviousTimecode = {};
|
v4 PreviousTimecode = {};
|
||||||
for(int TimestampIndex = 0; TimestampIndex < HMML.timestamp_count; ++TimestampIndex)
|
for(int TimestampIndex = 0; TimestampIndex < HMML.timestamp_count; ++TimestampIndex)
|
||||||
{
|
{
|
||||||
// TODO(matt): Thoroughly test this reorganisation
|
// TODO(matt): Thoroughly test this reorganisation
|
||||||
|
@ -11918,7 +11923,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF
|
||||||
{
|
{
|
||||||
identifier *ThisIdentifier = GetPlaceInBook(&This->Identifier, j);
|
identifier *ThisIdentifier = GetPlaceInBook(&This->Identifier, j);
|
||||||
CopyStringToBuffer(&MenuBuffers.Reference,
|
CopyStringToBuffer(&MenuBuffers.Reference,
|
||||||
"<span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[%d]</span><span class=\"time\">", TimecodeToSeconds(ThisIdentifier->Timecode), ThisIdentifier->Identifier);
|
"<span data-timestamp=\"%.3f\" class=\"timecode\"><span class=\"ref_index\">[%d]</span><span class=\"time\">", TimecodeToDottedSeconds(ThisIdentifier->Timecode), ThisIdentifier->Identifier);
|
||||||
CopyTimecodeToBuffer(&MenuBuffers.Reference, ThisIdentifier->Timecode);
|
CopyTimecodeToBuffer(&MenuBuffers.Reference, ThisIdentifier->Timecode);
|
||||||
CopyStringToBuffer(&MenuBuffers.Reference, "</span></span>");
|
CopyStringToBuffer(&MenuBuffers.Reference, "</span></span>");
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,9 +163,9 @@ function Player(cineraElement, refsCallback) {
|
||||||
for (var i = 0; i < markerEls.length; ++i) {
|
for (var i = 0; i < markerEls.length; ++i) {
|
||||||
var markerEl = markerEls[i];
|
var markerEl = markerEls[i];
|
||||||
var marker = {
|
var marker = {
|
||||||
timestamp: parseInt(markerEl.getAttribute("data-timestamp"), 10),
|
timestamp: parseFloat(markerEl.getAttribute("data-timestamp")),
|
||||||
ref: markerEl.getAttribute("data-ref"),
|
ref: markerEl.getAttribute("data-ref"),
|
||||||
endTime: (i < markerEls.length - 1 ? parseInt(markerEls[i+1].getAttribute("data-timestamp"), 10) : null),
|
endTime: (i < markerEls.length - 1 ? parseFloat(markerEls[i+1].getAttribute("data-timestamp")) : null),
|
||||||
el: markerEl,
|
el: markerEl,
|
||||||
fadedProgress: markerEl.querySelector(".progress.faded"),
|
fadedProgress: markerEl.querySelector(".progress.faded"),
|
||||||
progress: markerEl.querySelector(".progress.main"),
|
progress: markerEl.querySelector(".progress.main"),
|
||||||
|
@ -2015,12 +2015,12 @@ Player.prototype.handleKey = function(key) {
|
||||||
case menu_id.MARKERS:
|
case menu_id.MARKERS:
|
||||||
{
|
{
|
||||||
var time = this.MenusFocused.Item.getAttribute("data-timestamp");
|
var time = this.MenusFocused.Item.getAttribute("data-timestamp");
|
||||||
this.setTimeThenPlay(parseInt(time));
|
this.setTimeThenPlay(parseFloat(time));
|
||||||
} break;
|
} break;
|
||||||
case menu_id.QUOTES:
|
case menu_id.QUOTES:
|
||||||
{
|
{
|
||||||
var time = this.MenusFocused.Item.querySelector(".timecode").getAttribute("data-timestamp");
|
var time = this.MenusFocused.Item.querySelector(".timecode").getAttribute("data-timestamp");
|
||||||
this.setTimeThenPlay(parseInt(time));
|
this.setTimeThenPlay(parseFloat(time));
|
||||||
if(this.currentMarker)
|
if(this.currentMarker)
|
||||||
{
|
{
|
||||||
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
||||||
|
@ -2030,7 +2030,7 @@ Player.prototype.handleKey = function(key) {
|
||||||
case menu_id.REFERENCES:
|
case menu_id.REFERENCES:
|
||||||
{
|
{
|
||||||
var time = this.MenusFocused.Identifier.getAttribute("data-timestamp");
|
var time = this.MenusFocused.Identifier.getAttribute("data-timestamp");
|
||||||
this.setTimeThenPlay(parseInt(time));
|
this.setTimeThenPlay(parseFloat(time));
|
||||||
if(this.currentMarker)
|
if(this.currentMarker)
|
||||||
{
|
{
|
||||||
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
||||||
|
@ -2052,7 +2052,7 @@ Player.prototype.handleKey = function(key) {
|
||||||
if(this.currentMarker && this.currentMarker.el)
|
if(this.currentMarker && this.currentMarker.el)
|
||||||
{
|
{
|
||||||
var time = this.currentMarker.el.getAttribute("data-timestamp");
|
var time = this.currentMarker.el.getAttribute("data-timestamp");
|
||||||
this.setTimeThenPlay(parseInt(time));
|
this.setTimeThenPlay(parseFloat(time));
|
||||||
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
this.setScroller(this.Menus[menu_id.MARKERS], this.currentMarker.el, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2912,7 +2912,7 @@ Player.prototype.mouseOverCredits = function(item) {
|
||||||
|
|
||||||
function mouseSkipToTimecode(player, time, ev)
|
function mouseSkipToTimecode(player, time, ev)
|
||||||
{
|
{
|
||||||
player.setTimeThenPlay(parseInt(time, 10));
|
player.setTimeThenPlay(parseFloat(time));
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -213,11 +213,11 @@ function prepareToParseIndexFile(project)
|
||||||
mode = "markers";
|
mode = "markers";
|
||||||
episode.markers = [];
|
episode.markers = [];
|
||||||
} else if (mode == "markers") {
|
} else if (mode == "markers") {
|
||||||
var match = line.match(/"(\d+)": "(.+)"/);
|
var match = line.match(/"(\d+.\d+)": "(.+)"/);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
console.log(name, line);
|
console.log(name, line);
|
||||||
} else {
|
} else {
|
||||||
var totalTime = parseInt(line.slice(1));
|
var totalTime = parseFloat(line.slice(1));
|
||||||
var marker = {
|
var marker = {
|
||||||
totalTime: totalTime,
|
totalTime: totalTime,
|
||||||
prettyTime: markerTime(totalTime),
|
prettyTime: markerTime(totalTime),
|
||||||
|
@ -292,7 +292,7 @@ function markerTime(totalTime) {
|
||||||
var markTime = "(";
|
var markTime = "(";
|
||||||
var hours = Math.floor(totalTime / 60 / 60);
|
var hours = Math.floor(totalTime / 60 / 60);
|
||||||
var minutes = Math.floor(totalTime / 60) % 60;
|
var minutes = Math.floor(totalTime / 60) % 60;
|
||||||
var seconds = totalTime % 60;
|
var seconds = Math.floor(totalTime) % 60;
|
||||||
if (hours > 0) {
|
if (hours > 0) {
|
||||||
markTime += padTimeComponent(hours) + ":";
|
markTime += padTimeComponent(hours) + ":";
|
||||||
}
|
}
|
||||||
|
@ -460,7 +460,7 @@ function runSearch(refresh) {
|
||||||
Search.ResultsSummary.style.display = "none";
|
Search.ResultsSummary.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalTime = Math.floor(totalSeconds/60/60) + "h " + Math.floor(totalSeconds/60)%60 + "m " + totalSeconds%60 + "s ";
|
var totalTime = Math.floor(totalSeconds/60/60) + "h " + Math.floor(totalSeconds/60)%60 + "m " + Math.floor(totalSeconds)%60 + "s ";
|
||||||
|
|
||||||
Search.ResultsSummary.textContent = "Found: " + numEpisodes + " episodes, " + numMarkers + " markers, " + totalTime + "total.";
|
Search.ResultsSummary.textContent = "Found: " + numEpisodes + " episodes, " + numMarkers + " markers, " + totalTime + "total.";
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
int h, m, s;
|
int h, m, s, ms;
|
||||||
|
|
||||||
char* text;
|
char* text;
|
||||||
char* author;
|
char* author;
|
||||||
|
@ -471,7 +471,7 @@ next_attr:
|
||||||
|
|
||||||
static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
||||||
{
|
{
|
||||||
unsigned int h = 0, m = 0, s = 0;
|
unsigned int h = 0, m = 0, s = 0, ms = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int count = sscanf(p->cursor, "[%u:%u%n", &m, &s, &offset);
|
int count = sscanf(p->cursor, "[%u:%u%n", &m, &s, &offset);
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
||||||
if(c == ':') {
|
if(c == ':') {
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if(sscanf(p->cursor, ":%u]%n", &tmp, &offset) != 1 || offset == 0) {
|
if(sscanf(p->cursor, ":%u%n", &tmp, &offset) != 1 || offset == 0) {
|
||||||
_hmml_err(p, "Unable to parse 3-part timecode");
|
_hmml_err(p, "Unable to parse 3-part timecode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +494,27 @@ static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
||||||
s = tmp;
|
s = tmp;
|
||||||
|
|
||||||
p->cursor += offset;
|
p->cursor += offset;
|
||||||
|
c = *p->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '.') {
|
||||||
|
unsigned int tmp;
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
int non_number_chars = 2;
|
||||||
|
int digits_in_100 = 3;
|
||||||
|
int max_chars_to_parse = non_number_chars + digits_in_100;
|
||||||
|
|
||||||
|
if(sscanf(p->cursor, ".%u]%n", &tmp, &offset) != 1 || offset == 0 || offset > max_chars_to_parse) {
|
||||||
|
_hmml_err(p, "Unable to parse %u.5-part timecode", h ? 3 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = offset - non_number_chars; i < digits_in_100; ++i) {
|
||||||
|
tmp *= 10;
|
||||||
|
}
|
||||||
|
ms = tmp;
|
||||||
|
|
||||||
|
p->cursor += offset;
|
||||||
|
|
||||||
} else if(c != ']') {
|
} else if(c != ']') {
|
||||||
_hmml_err(p, "Unable to parse timecode");
|
_hmml_err(p, "Unable to parse timecode");
|
||||||
|
@ -501,6 +522,10 @@ static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
||||||
++p->cursor;
|
++p->cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ms >= 1000) {
|
||||||
|
_hmml_err(p, "Milliseconds cannot exceed 999");
|
||||||
|
}
|
||||||
|
|
||||||
if(s >= 60) {
|
if(s >= 60) {
|
||||||
_hmml_err(p, "Seconds cannot exceed 59");
|
_hmml_err(p, "Seconds cannot exceed 59");
|
||||||
}
|
}
|
||||||
|
@ -512,6 +537,7 @@ static void _hmml_parse_timecode(struct _hmml_parser* p, HMML_Timestamp* ts)
|
||||||
ts->h = h;
|
ts->h = h;
|
||||||
ts->m = m;
|
ts->m = m;
|
||||||
ts->s = s;
|
ts->s = s;
|
||||||
|
ts->ms = ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _hmml_store_marker(struct _hmml_parser* p, HMML_Timestamp* ts, char** out, char* text_mem, size_t text_mem_size)
|
static void _hmml_store_marker(struct _hmml_parser* p, HMML_Timestamp* ts, char** out, char* text_mem, size_t text_mem_size)
|
||||||
|
@ -824,7 +850,7 @@ void hmml_free(HMML_Output* out)
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct HMML_Version hmml_version = {
|
const struct HMML_Version hmml_version = {
|
||||||
2, 0, 14
|
2, 0, 15
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef HSTX
|
#undef HSTX
|
||||||
|
|
Loading…
Reference in New Issue