332 lines
10 KiB
C
332 lines
10 KiB
C
#if 0
|
|
ctime -begin ${0%.*}.ctm
|
|
gcc -g -fsanitize=address $0 -o ${0%.*} hmml.a
|
|
ctime -end ${0%.*}.ctm
|
|
exit
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "hmmlib.h"
|
|
|
|
#ifndef bool
|
|
typedef bool unsigned int;
|
|
#endif
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
typedef struct
|
|
{
|
|
char *Location;
|
|
char *Ptr;
|
|
int Size;
|
|
} buffer;
|
|
|
|
int
|
|
TimecodeToSeconds(char *Timecode)
|
|
{
|
|
int HMS[3] = { 0, 0, 0 }; // 0 == Seconds; 1 == Minutes; 2 == Hours
|
|
int Colons = 0;
|
|
while(*Timecode)
|
|
{
|
|
if((*Timecode < '0' || *Timecode > '9') && *Timecode != ':') { return FALSE; }
|
|
|
|
if(*Timecode == ':')
|
|
{
|
|
++Colons;
|
|
if(Colons > 2) { return FALSE; }
|
|
for(int i = 0; i < Colons; ++i)
|
|
{
|
|
HMS[Colons - i] = HMS[Colons - (i + 1)];
|
|
}
|
|
HMS[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
HMS[0] = HMS[0] * 10 + *Timecode - '0';
|
|
}
|
|
|
|
++Timecode;
|
|
}
|
|
|
|
if(HMS[0] > 59 || HMS[1] > 59 || Timecode[-1] == ':') { return FALSE; }
|
|
|
|
return HMS[2] * 60 * 60 + HMS[1] * 60 + HMS[0];
|
|
}
|
|
|
|
int
|
|
main(int ArgC, char **Args)
|
|
{
|
|
if(ArgC < 2)
|
|
{
|
|
fprintf(stderr, "Usage: %s filename(s)\n", Args[0]);
|
|
return 1;
|
|
}
|
|
|
|
// NOTE(matt): Init MemoryArena
|
|
char *MemoryArena;
|
|
int ArenaSize = 1024 * 64;
|
|
if(!(MemoryArena = calloc(ArenaSize, 1)))
|
|
{
|
|
perror(Args[0]);
|
|
return 1;
|
|
}
|
|
int ClaimedMemory = 0;
|
|
|
|
// NOTE(matt): Setup buffers and ptrs
|
|
char *InPtr;
|
|
buffer Template;
|
|
buffer Working;
|
|
buffer Out;
|
|
|
|
FILE *TemplateFile;
|
|
if(!(TemplateFile = fopen("style.css", "r")))
|
|
{
|
|
perror(Args[0]);
|
|
return 1;
|
|
}
|
|
|
|
fseek(TemplateFile, 0, SEEK_END);
|
|
Template.Size = ftell(TemplateFile);
|
|
fseek(TemplateFile, 0, SEEK_SET);
|
|
|
|
Template.Location = MemoryArena + ClaimedMemory;
|
|
ClaimedMemory += Template.Size;
|
|
fread(Template.Location, Template.Size, 1, TemplateFile);
|
|
fclose(TemplateFile);
|
|
|
|
Out.Location = MemoryArena + ClaimedMemory;
|
|
Out.Size = 1024 * 32;
|
|
ClaimedMemory += Out.Size;
|
|
|
|
for(int FileIndex = 1; FileIndex < ArgC; ++FileIndex)
|
|
{
|
|
FILE *InFile;
|
|
if(!(InFile = fopen(Args[FileIndex], "r")))
|
|
{
|
|
perror(Args[0]);
|
|
free(MemoryArena);
|
|
return 1;
|
|
}
|
|
|
|
HMML_Output HMML = hmml_parse_file(InFile);
|
|
fclose(InFile);
|
|
|
|
if(HMML.well_formed)
|
|
{
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 351;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
sprintf(Working.Location,
|
|
"<html>\n"
|
|
" <head>\n"
|
|
" <meta charset=\"UTF-8\">\n"
|
|
"\n"
|
|
" <!-- Load the player -->\n"
|
|
" <script type=\"text/javascript\" src=\"player.js\"></script>\n"
|
|
" <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n"
|
|
" </head>\n"
|
|
" <body>\n"
|
|
" <div class=\"title\">\n"
|
|
" <span class=\"episode_name\">%s</span>\n", HMML.metadata.title);
|
|
|
|
Working.Ptr = Working.Location;
|
|
Out.Ptr = Out.Location;
|
|
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
Working.Location = '\0';
|
|
ClaimedMemory -= Working.Size;
|
|
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 1024;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
int AnnotationIndex = 0;
|
|
while(AnnotationIndex < HMML.annotation_count)
|
|
{
|
|
if(HMML.annotations[AnnotationIndex].reference_count)
|
|
{
|
|
sprintf(Working.Location,
|
|
" <div class=\"refs_container\">\n"
|
|
" <span>References ▼</span>\n"
|
|
" <div class=\"mouse_catcher\"></div>\n"
|
|
" <div class=\"refs\">\n");
|
|
|
|
Working.Ptr = Working.Location;
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
while(AnnotationIndex < HMML.annotation_count)
|
|
{
|
|
for(int i = 0; i < HMML.annotations[AnnotationIndex].reference_count; ++i)
|
|
{
|
|
sprintf(Working.Location,
|
|
" <a href=\"%s\" target=\"_blank\" class=\"ref\">\n"
|
|
" <span data-timestamp=\"%d\" class=\"timecode\">(<span class=\"time\">%s</span>)</span>\n"
|
|
" <span class=\"ref_content\">\n"
|
|
" <div class=\"source\">%s</div>\n"
|
|
" <div class=\"ref_title\">%s</div>\n"
|
|
" </span>\n"
|
|
" </a>\n",
|
|
HMML.annotations[AnnotationIndex].references[i].url,
|
|
TimecodeToSeconds(HMML.annotations[AnnotationIndex].time),
|
|
HMML.annotations[AnnotationIndex].time,
|
|
HMML.annotations[AnnotationIndex].references[i].site ? HMML.annotations[AnnotationIndex].references[i].site : HMML.annotations[AnnotationIndex].references[i].author,
|
|
HMML.annotations[AnnotationIndex].references[i].page ? HMML.annotations[AnnotationIndex].references[i].page : HMML.annotations[AnnotationIndex].references[i].title);
|
|
|
|
Working.Ptr = Working.Location;
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
}
|
|
++AnnotationIndex;
|
|
}
|
|
}
|
|
++AnnotationIndex;
|
|
}
|
|
|
|
Working.Location = '\0';
|
|
ClaimedMemory -= Working.Size;
|
|
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 256;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
Working.Location = '\0';
|
|
ClaimedMemory -= Working.Size;
|
|
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 1024;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
sprintf(Working.Location,
|
|
" </div>\n"
|
|
" </div>\n"
|
|
" <span class=\"annotator_container\">Annotator: <span class=\"annotator\">%s</span></span>\n"
|
|
"</div>\n"
|
|
"<div class=\"player_container\">\n"
|
|
" <div class=\"video_container\" data-videoId=\"%s\"></div>\n"
|
|
" <div class=\"markers_container\">\n", HMML.metadata.annotator, HMML.metadata.id);
|
|
|
|
Working.Ptr = Working.Location;
|
|
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
Working.Location = '\0';
|
|
ClaimedMemory -= Working.Size;
|
|
|
|
int DataRef = 0;
|
|
|
|
for(int AnnotationIndex = 0; AnnotationIndex < HMML.annotation_count; ++AnnotationIndex)
|
|
{
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 1024;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
if(HMML.annotations[AnnotationIndex].reference_count || HMML.annotations[AnnotationIndex].is_quote)
|
|
{
|
|
sprintf(Working.Location, "<div class=\"marker\" data-timestamp=\"%d\" data-ref=\"%d\">\n", TimecodeToSeconds(HMML.annotations[AnnotationIndex].time), DataRef);
|
|
++DataRef;
|
|
}
|
|
else
|
|
{
|
|
sprintf(Working.Location, "<div class=\"marker\" data-timestamp=\"%d\">\n", TimecodeToSeconds(HMML.annotations[AnnotationIndex].time));
|
|
}
|
|
|
|
Working.Ptr = Working.Location;
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
sprintf(Working.Location, "<div class=\"content\"><span class=\"timecode\">%s</span>%s</div>\n"
|
|
"<div class=\"progress faded\">\n"
|
|
"<div class=\"content\"><span class=\"timecode\">%s</span>%s</div>\n"
|
|
"</div>\n"
|
|
"<div class=\"progress main\">\n"
|
|
"<div class=\"content\"><span class=\"timecode\">%s</span>%s</div>\n"
|
|
"</div>\n"
|
|
"</div>\n",
|
|
HMML.annotations[AnnotationIndex].time,
|
|
HMML.annotations[AnnotationIndex].text,
|
|
HMML.annotations[AnnotationIndex].time,
|
|
HMML.annotations[AnnotationIndex].text,
|
|
HMML.annotations[AnnotationIndex].time,
|
|
HMML.annotations[AnnotationIndex].text);
|
|
Working.Ptr = Working.Location;
|
|
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
Working.Location = '\0';
|
|
ClaimedMemory -= Working.Size;
|
|
|
|
*Out.Ptr++ = '\n';
|
|
}
|
|
|
|
Working.Location = MemoryArena + ClaimedMemory;
|
|
Working.Size = 256;
|
|
ClaimedMemory += Working.Size;
|
|
|
|
sprintf(Working.Location, "</div>\n"
|
|
"</div>\n"
|
|
"<script>\n"
|
|
"var player = new Player(document.querySelector(\".player_container\"));\n"
|
|
"window.addEventListener(\"resize\", function() { player.updateSize(); });\n"
|
|
"document.addEventListener(\"keypress\", function(ev) {\n"
|
|
" switch (ev.key) {\n"
|
|
" case 'n':\n"
|
|
" case 'd':\n"
|
|
" case 's': {\n"
|
|
" player.jumpToNextMarker();\n"
|
|
" } break;\n"
|
|
"\n"
|
|
" case 'p':\n"
|
|
" case 'a':\n"
|
|
" case 'w': {\n"
|
|
" player.jumpToPrevMarker();\n"
|
|
" } break;\n"
|
|
" }\n"
|
|
"});\n"
|
|
"</script>\n"
|
|
"</body>\n"
|
|
"</html>\n");
|
|
|
|
Working.Ptr = Working.Location;
|
|
while(*Working.Ptr)
|
|
{
|
|
*Out.Ptr++ = *Working.Ptr++;
|
|
}
|
|
|
|
hmml_free(&HMML);
|
|
|
|
FILE *OutFile;
|
|
//char *OutFilename;
|
|
//sprintf(OutFilename, "%s.html", Args[FileIndex]);
|
|
if(!(OutFile = fopen("out.html", "w")))
|
|
{
|
|
perror(Args[0]);
|
|
return 1;
|
|
}
|
|
|
|
fwrite(Out.Location, Out.Ptr - Out.Location, 1, OutFile);
|
|
fclose(OutFile);
|
|
}
|
|
}
|
|
free(MemoryArena);
|
|
}
|