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