hmml_to_html.c: Complete credits [#4]
Support multiple co-hosts, guests and annotators
This commit is contained in:
parent
bcaa6d63db
commit
6e1f6a4faa
|
@ -171,12 +171,16 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.title > .menu > .credits_container .credit {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.title > .menu > .credits_container .credit .person {
|
||||
flex-grow: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title > .menu > .credits_container .credit .support {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
padding: 16px;
|
||||
}
|
||||
|
@ -409,6 +413,7 @@
|
|||
|
||||
/* CUSTOM PAGE STYLE */
|
||||
|
||||
/*
|
||||
body {
|
||||
background-color: #000;
|
||||
font-family: sans-serif;
|
||||
|
@ -416,6 +421,7 @@ body {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Open menu: ▾ ▾
|
||||
|
|
|
@ -73,7 +73,16 @@ typedef struct
|
|||
} category_info;
|
||||
|
||||
// TODO(matt): Parse this stuff out of a config file
|
||||
char *Credentials[ ][5] =
|
||||
typedef struct
|
||||
{
|
||||
char *Username;
|
||||
char *CreditedName;
|
||||
char *HomepageURL;
|
||||
char *SupportIcon;
|
||||
char *SupportURL;
|
||||
} credential_info;
|
||||
|
||||
credential_info Credentials[] =
|
||||
{
|
||||
{ "Miblo", "Matt Mascarenhas", "http://miblodelcarpio.co.uk", "cinera_icon_patreon.png", "https://patreon.com/miblo"},
|
||||
{ "miotatsu", "Mio Iwakura", "http://riscy.tv/", "cinera_icon_patreon.png", "https://patreon.com/miotatsu"},
|
||||
|
@ -81,6 +90,31 @@ char *Credentials[ ][5] =
|
|||
{ "cmuratori", "Casey Muratori", "https://handmadehero.org", "cinera_icon_patreon.png", "https://patreon.com/cmuratori"},
|
||||
{ "fierydrake", "Mike Tunnicliffe", "", "", ""},
|
||||
{ "abnercoimbre", "Abner Coimbre", "https://handmade.network/m/abnercoimbre", "cinera_icon_patreon.png", "https://patreon.com/handmade_dev"},
|
||||
{ "/y_lee", "Yunsup Lee", "https://www.linkedin.com/in/yunsup-lee-385b692b/", "", ""},
|
||||
{ "/a_waterman", "Andrew Waterman", "https://www.linkedin.com/in/andrew-waterman-76805788", "", ""},
|
||||
{ "debiatan", "Miguel Lechón", "http://blog.debiatan.net/", "", ""},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *Medium;
|
||||
char *Icon;
|
||||
char *WrittenName;
|
||||
} category_medium;
|
||||
|
||||
category_medium CategoryMedium[] =
|
||||
{
|
||||
// medium icon written name
|
||||
{ "afk", "…" , "Away from Keyboard"}, // TODO(matt): Filter this out by default
|
||||
{ "authored", "🗪", "Chat Comment"}, // TODO(matt): Conditionally handle Chat vs Guest Comments
|
||||
{ "blackboard", "🖌", "Blackboard"},
|
||||
{ "experience", "🍷", "Experience"},
|
||||
{ "owl", "🦉", "Owl of Shame"},
|
||||
{ "programming", "🖮", "Programming"}, // TODO(matt): Potentially make this configurable per project
|
||||
{ "rant", "💢", "Rant"},
|
||||
{ "research", "📖", "Research"},
|
||||
{ "run", "🏃", "In-Game"}, // TODO(matt): Potentially make this configurable per project
|
||||
{ "trivia", "🎲", "Trivia"},
|
||||
};
|
||||
|
||||
#define EDITION EDITION_SINGLE
|
||||
|
@ -205,6 +239,19 @@ CopyStringNoFormat(char *Dest, char *String)
|
|||
return Length;
|
||||
}
|
||||
|
||||
int
|
||||
CopyStringNoFormatT(char *Dest, char *String, char Terminator)
|
||||
{
|
||||
int Length = 0;
|
||||
while(*String != Terminator)
|
||||
{
|
||||
*Dest++ = *String++;
|
||||
++Length;
|
||||
}
|
||||
*Dest = '\0';
|
||||
return Length;
|
||||
}
|
||||
|
||||
int
|
||||
StringLength(char *String)
|
||||
{
|
||||
|
@ -423,118 +470,157 @@ SanitisePunctuation(char *String)
|
|||
return String;
|
||||
}
|
||||
|
||||
int
|
||||
BuildCredits(buffer *CreditsMenu, buffer *HostInfo, buffer *AnnotatorInfo, bool *HasCreditsMenu, char *ImagesDir, char *Host, char *Annotator)
|
||||
enum
|
||||
{
|
||||
// TODO(matt): Handle co-hosts and guests
|
||||
bool FoundHost = FALSE;
|
||||
bool FoundAnnotator = FALSE;
|
||||
CreditsError_NoHost = 1 << 0,
|
||||
CreditsError_NoAnnotator = 1 << 1,
|
||||
CreditsError_NoCredentials = 1 << 2
|
||||
} CreditsErrorCodes;
|
||||
|
||||
int
|
||||
SearchCredentials(buffer *CreditsMenu, bool *HasCreditsMenu, char *ImagesDir, char *Person, char* Role)
|
||||
{
|
||||
bool Found = FALSE;
|
||||
for(int CredentialIndex = 0; CredentialIndex < ArrayCount(Credentials); ++CredentialIndex)
|
||||
{
|
||||
if(!StringsDiffer(Host, Credentials[CredentialIndex][0]))
|
||||
if(!StringsDiffer(Person, Credentials[CredentialIndex].Username))
|
||||
{
|
||||
FoundHost = TRUE; // TODO(matt): Check if this is actually necessary...
|
||||
CopyStringToBuffer(HostInfo,
|
||||
" <span class=\"credit\">\n");
|
||||
if(*Credentials[CredentialIndex][2])
|
||||
Found = TRUE;
|
||||
if(*HasCreditsMenu == FALSE)
|
||||
{
|
||||
CopyStringToBuffer(HostInfo,
|
||||
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
|
||||
" <div class=\"role\">Host</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </a>\n",
|
||||
Credentials[CredentialIndex][2],
|
||||
Credentials[CredentialIndex][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyStringToBuffer(HostInfo,
|
||||
" <div class=\"person\">\n"
|
||||
" <div class=\"role\">Host</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </div>\n",
|
||||
Credentials[CredentialIndex][1]);
|
||||
}
|
||||
|
||||
if(*Credentials[CredentialIndex][4] && *Credentials[CredentialIndex][3])
|
||||
{
|
||||
CopyStringToBuffer(HostInfo,
|
||||
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
|
||||
Credentials[CredentialIndex][4],
|
||||
ImagesDir,
|
||||
Credentials[CredentialIndex][3]);
|
||||
}
|
||||
|
||||
CopyStringToBuffer(HostInfo,
|
||||
" </span>\n");
|
||||
}
|
||||
|
||||
if(!StringsDiffer(Annotator, Credentials[CredentialIndex][0]))
|
||||
{
|
||||
FoundAnnotator = TRUE; // TODO(matt): Check if this is actually necessary...
|
||||
CopyStringToBuffer(AnnotatorInfo,
|
||||
" <span class=\"credit\">\n");
|
||||
if(*Credentials[CredentialIndex][2])
|
||||
{
|
||||
CopyStringToBuffer(AnnotatorInfo,
|
||||
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
|
||||
" <div class=\"role\">Annotator</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </a>\n",
|
||||
Credentials[CredentialIndex][2],
|
||||
Credentials[CredentialIndex][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyStringToBuffer(AnnotatorInfo,
|
||||
" <div class=\"person\">\n"
|
||||
" <div class=\"role\">Annotator</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </div>\n",
|
||||
Credentials[CredentialIndex][1]);
|
||||
}
|
||||
|
||||
if(*Credentials[CredentialIndex][4] && *Credentials[CredentialIndex][3])
|
||||
{
|
||||
CopyStringToBuffer(AnnotatorInfo,
|
||||
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
|
||||
Credentials[CredentialIndex][4],
|
||||
ImagesDir,
|
||||
Credentials[CredentialIndex][3]);
|
||||
}
|
||||
|
||||
CopyStringToBuffer(AnnotatorInfo,
|
||||
" </span>\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(FoundHost || FoundAnnotator)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" <div class=\"menu credits\">\n"
|
||||
" <div class=\"mouse_catcher\"></div>\n"
|
||||
" <span>Credits</span>\n"
|
||||
" <div class=\"credits_container\">\n");
|
||||
|
||||
if(FoundHost)
|
||||
{
|
||||
CopyBuffer(CreditsMenu, HostInfo);
|
||||
*HasCreditsMenu = TRUE;
|
||||
}
|
||||
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" <span class=\"credit\">\n");
|
||||
if(*Credentials[CredentialIndex].HomepageURL)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" <a class=\"person\" href=\"%s\" target=\"_blank\">\n"
|
||||
" <div class=\"role\">%s</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </a>\n",
|
||||
Credentials[CredentialIndex].HomepageURL,
|
||||
Role,
|
||||
Credentials[CredentialIndex].CreditedName);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" <div class=\"person\">\n"
|
||||
" <div class=\"role\">%s</div>\n"
|
||||
" <div class=\"name\">%s</div>\n"
|
||||
" </div>\n",
|
||||
Role,
|
||||
Credentials[CredentialIndex].CreditedName);
|
||||
}
|
||||
|
||||
if(*Credentials[CredentialIndex].SupportIcon && *Credentials[CredentialIndex].SupportURL)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" <a class=\"support\" href=\"%s\" target=\"_blank\"><img src=\"%s/%s\"></a>\n",
|
||||
Credentials[CredentialIndex].SupportURL,
|
||||
ImagesDir,
|
||||
Credentials[CredentialIndex].SupportIcon);
|
||||
}
|
||||
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" </span>\n");
|
||||
}
|
||||
if(FoundAnnotator)
|
||||
}
|
||||
return Found ? 0 : CreditsError_NoCredentials;
|
||||
}
|
||||
|
||||
int
|
||||
BuildCredits(buffer *CreditsMenu, bool *HasCreditsMenu, char *ImagesDir, HMML_VideoMetaData Metadata)
|
||||
// TODO(matt): Make this take the Credentials, once we are parsing them from a config
|
||||
{
|
||||
if(Metadata.member)
|
||||
{
|
||||
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.member, "Host"))
|
||||
{
|
||||
CopyBuffer(CreditsMenu, AnnotatorInfo);
|
||||
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
|
||||
" Full name\n"
|
||||
" Homepage URL (optional)\n"
|
||||
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.member);
|
||||
}
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" </div>\n"
|
||||
" </div>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
if(*HasCreditsMenu == TRUE)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" </div>\n"
|
||||
" </div>\n");
|
||||
}
|
||||
return CreditsError_NoHost;
|
||||
}
|
||||
|
||||
if(Metadata.co_host_count > 0)
|
||||
{
|
||||
for(int i = 0; i < Metadata.co_host_count; ++i)
|
||||
{
|
||||
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.co_hosts[i], "Co-host"))
|
||||
{
|
||||
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
|
||||
" Full name\n"
|
||||
" Homepage URL (optional)\n"
|
||||
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.co_hosts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Metadata.guest_count > 0)
|
||||
{
|
||||
for(int i = 0; i < Metadata.guest_count; ++i)
|
||||
{
|
||||
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.guests[i], "Guest"))
|
||||
{
|
||||
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
|
||||
" Full name\n"
|
||||
" Homepage URL (optional)\n"
|
||||
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.guests[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Metadata.annotator_count > 0)
|
||||
{
|
||||
for(int i = 0; i < Metadata.annotator_count; ++i)
|
||||
{
|
||||
if(SearchCredentials(CreditsMenu, HasCreditsMenu, ImagesDir, Metadata.annotators[i], "Annotator"))
|
||||
{
|
||||
printf("No credentials for %s. Please contact matt@handmadedev.org with their:\n"
|
||||
" Full name\n"
|
||||
" Homepage URL (optional)\n"
|
||||
" Financial support info, e.g. Patreon URL (optional)\n", Metadata.annotators[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*HasCreditsMenu == TRUE)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" </div>\n"
|
||||
" </div>\n");
|
||||
}
|
||||
return CreditsError_NoAnnotator;
|
||||
}
|
||||
|
||||
if(*HasCreditsMenu == TRUE)
|
||||
{
|
||||
CopyStringToBuffer(CreditsMenu,
|
||||
" </div>\n"
|
||||
" </div>\n");
|
||||
}
|
||||
|
||||
*HasCreditsMenu = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -643,21 +729,6 @@ BuildReference(ref_info *ReferencesArray, int RefIdentifier, int UniqueRefs, HMM
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *CategoryMedium[][3] =
|
||||
{
|
||||
// medium icon written name
|
||||
{ "afk", "…" , "Away from Keyboard"}, // TODO(matt): Filter this out by default
|
||||
{ "authored", "🗪", "Chat Comment"}, // TODO(matt): Conditionally handle Chat vs Guest Comments
|
||||
{ "blackboard", "🖌", "Blackboard"},
|
||||
{ "experience", "🍷", "Experience"},
|
||||
{ "owl", "🦉", "Owl of Shame"},
|
||||
{ "programming", "🖮", "Programming"}, // TODO(matt): Potentially make this configurable per project
|
||||
{ "rant", "💢", "Rant"},
|
||||
{ "research", "📖", "Research"},
|
||||
{ "run", "🏃", "In-Game"}, // TODO(matt): Potentially make this configurable per project
|
||||
{ "trivia", "🎲", "Trivia"},
|
||||
};
|
||||
|
||||
void
|
||||
BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaArray, int *UniqueMedia, char *Marker)
|
||||
{
|
||||
|
@ -666,7 +737,7 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
|
|||
int i = 0;
|
||||
for(i = 0; i < ArrayCount(CategoryMedium); ++i)
|
||||
{
|
||||
if(!StringsDiffer(CategoryMedium[i][0], Marker))
|
||||
if(!StringsDiffer(CategoryMedium[i].Medium, Marker))
|
||||
{
|
||||
IsMedium = TRUE;
|
||||
break;
|
||||
|
@ -679,11 +750,11 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
|
|||
int j = 0;
|
||||
for(j = 0; j < *UniqueMedia; ++j)
|
||||
{
|
||||
if(!StringsDiffer(CategoryMedium[i][0], MediaArray[j].Marker))
|
||||
if(!StringsDiffer(CategoryMedium[i].Medium, MediaArray[j].Marker))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if((Offset = StringsDiffer(CategoryMedium[i][2], MediaArray[j].WrittenText)) < 0)
|
||||
if((Offset = StringsDiffer(CategoryMedium[i].WrittenName, MediaArray[j].WrittenText)) < 0)
|
||||
{
|
||||
int k;
|
||||
for(k = *UniqueMedia; k > j; --k)
|
||||
|
@ -692,16 +763,16 @@ BuildFilter(category_info *TopicsArray, int *UniqueTopics, category_info *MediaA
|
|||
CopyString(MediaArray[k].WrittenText, MediaArray[k-1].WrittenText);
|
||||
}
|
||||
|
||||
CopyString(MediaArray[k].Marker, CategoryMedium[i][0]);
|
||||
CopyString(MediaArray[k].WrittenText, CategoryMedium[i][2]);
|
||||
CopyString(MediaArray[k].Marker, CategoryMedium[i].Medium);
|
||||
CopyString(MediaArray[k].WrittenText, CategoryMedium[i].WrittenName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(j == *UniqueMedia)
|
||||
{
|
||||
CopyString(MediaArray[j].Marker, CategoryMedium[i][0]);
|
||||
CopyString(MediaArray[j].WrittenText, CategoryMedium[i][2]);
|
||||
CopyString(MediaArray[j].Marker, CategoryMedium[i].Medium);
|
||||
CopyString(MediaArray[j].WrittenText, CategoryMedium[i].WrittenName);
|
||||
}
|
||||
|
||||
++*UniqueMedia;
|
||||
|
@ -748,7 +819,7 @@ BuildCategories(buffer *AnnotationClass, buffer *Category, int *MarkerIndex, boo
|
|||
// The code in the "annotation loop" would then have to write both the head and tail of the category stuff
|
||||
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
|
||||
{
|
||||
if(!StringsDiffer(CategoryMedium[i][0], Marker))
|
||||
if(!StringsDiffer(CategoryMedium[i].Medium, Marker))
|
||||
{
|
||||
CopyStringToBuffer(AnnotationClass, " %s", SanitisePunctuation(Marker));
|
||||
*HasMedium = TRUE;
|
||||
|
@ -812,70 +883,6 @@ StringToInt(char *String)
|
|||
return Result;
|
||||
}
|
||||
|
||||
size_t
|
||||
CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr)
|
||||
{
|
||||
int Length = CharLength * Chars;
|
||||
int i;
|
||||
for(i = 0; InPtr[i] && i < Length; ++i)
|
||||
{
|
||||
*((*OutputPtr)++) = InPtr[i];
|
||||
}
|
||||
**OutputPtr = '\0';
|
||||
return Length;
|
||||
};
|
||||
|
||||
int
|
||||
SearchQuotes(buffer QuoteStaging, int CacheSize, quote_info *Info, int ID)
|
||||
{
|
||||
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||
while(QuoteStaging.Ptr - QuoteStaging.Location < CacheSize)
|
||||
{
|
||||
char InID[4] = { 0 };
|
||||
char InTime[16] = { 0 };
|
||||
char *OutPtr = InID;
|
||||
while(*QuoteStaging.Ptr != ',')
|
||||
{
|
||||
*OutPtr++ = *QuoteStaging.Ptr++;
|
||||
}
|
||||
*OutPtr = '\0';
|
||||
|
||||
if(StringToInt(InID) == ID)
|
||||
{
|
||||
QuoteStaging.Ptr += 1;
|
||||
OutPtr = InTime;
|
||||
while(*QuoteStaging.Ptr != ',')
|
||||
{
|
||||
*OutPtr++ = *QuoteStaging.Ptr++;
|
||||
}
|
||||
*OutPtr = '\0';
|
||||
|
||||
long int Time = StringToInt(InTime);
|
||||
strftime(Info->Date, 32, "%d %B, %Y", gmtime(&Time));
|
||||
|
||||
QuoteStaging.Ptr += 1;
|
||||
OutPtr = Info->Text;
|
||||
while(*QuoteStaging.Ptr != '\n')
|
||||
{
|
||||
*OutPtr++ = *QuoteStaging.Ptr++;
|
||||
}
|
||||
*OutPtr = '\0';
|
||||
|
||||
FreeBuffer(&QuoteStaging);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*QuoteStaging.Ptr != '\n')
|
||||
{
|
||||
++QuoteStaging.Ptr;
|
||||
}
|
||||
++QuoteStaging.Ptr;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
MakeDir(char *Path)
|
||||
{
|
||||
|
@ -907,6 +914,19 @@ MakeDir(char *Path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr)
|
||||
{
|
||||
int Length = CharLength * Chars;
|
||||
int i;
|
||||
for(i = 0; InPtr[i] && i < Length; ++i)
|
||||
{
|
||||
*((*OutputPtr)++) = InPtr[i];
|
||||
}
|
||||
**OutputPtr = '\0';
|
||||
return Length;
|
||||
};
|
||||
|
||||
void
|
||||
CurlQuotes(buffer *QuoteStaging, char *QuotesURL)
|
||||
{
|
||||
|
@ -924,6 +944,56 @@ CurlQuotes(buffer *QuoteStaging, char *QuotesURL)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
SearchQuotes(buffer QuoteStaging, int CacheSize, quote_info *Info, int ID)
|
||||
{
|
||||
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||
while(QuoteStaging.Ptr - QuoteStaging.Location < CacheSize)
|
||||
{
|
||||
char InID[4] = { 0 };
|
||||
char InTime[16] = { 0 };
|
||||
char *OutPtr = InID;
|
||||
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, ',');
|
||||
|
||||
if(StringToInt(InID) == ID)
|
||||
{
|
||||
QuoteStaging.Ptr += 1;
|
||||
OutPtr = InTime;
|
||||
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, ',');
|
||||
|
||||
long int Time = StringToInt(InTime);
|
||||
char DayString[3];
|
||||
strftime(DayString, 3, "%d", gmtime(&Time));
|
||||
int Day = StringToInt(DayString);
|
||||
|
||||
char DaySuffix[3]; if(DayString[1] == '1' && Day != 11) { CopyString(DaySuffix, "st"); }
|
||||
else if(DayString[1] == '2' && Day != 12) { CopyString(DaySuffix, "nd"); }
|
||||
else if(DayString[1] == '3' && Day != 13) { CopyString(DaySuffix, "rd"); }
|
||||
else { CopyString(DaySuffix, "th"); }
|
||||
|
||||
char MonthYear[32];
|
||||
strftime(MonthYear, 32, "%B, %Y", gmtime(&Time));
|
||||
CopyString(Info->Date, "%d%s %s", Day, DaySuffix, MonthYear);
|
||||
|
||||
QuoteStaging.Ptr += 1;
|
||||
OutPtr = Info->Text;
|
||||
QuoteStaging.Ptr += CopyStringNoFormatT(OutPtr, QuoteStaging.Ptr, '\n');
|
||||
|
||||
FreeBuffer(&QuoteStaging);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*QuoteStaging.Ptr != '\n')
|
||||
{
|
||||
++QuoteStaging.Ptr;
|
||||
}
|
||||
++QuoteStaging.Ptr;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
BuildQuote(quote_info *Info, char *Speaker, int ID, char *CacheDir)
|
||||
{
|
||||
|
@ -963,7 +1033,7 @@ BuildQuote(quote_info *Info, char *Speaker, int ID, char *CacheDir)
|
|||
QuoteStaging.Size = Kilobytes(256);
|
||||
if(!(QuoteStaging.Location = malloc(QuoteStaging.Size)))
|
||||
{
|
||||
perror("malloc");
|
||||
perror("BuildQuote");
|
||||
}
|
||||
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||
|
||||
|
@ -1016,7 +1086,7 @@ GenerateTopicColours(buffer *Colour, char *Topic, char *TopicsDir)
|
|||
{
|
||||
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
|
||||
{
|
||||
if(!StringsDiffer(Topic, CategoryMedium[i][0]))
|
||||
if(!StringsDiffer(Topic, CategoryMedium[i].Medium))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1482,7 +1552,7 @@ main(int ArgC, char **Args)
|
|||
bool ValidDefaultMedium = FALSE;
|
||||
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
|
||||
{
|
||||
if(!StringsDiffer(DefaultMedium, CategoryMedium[i][0]))
|
||||
if(!StringsDiffer(DefaultMedium, CategoryMedium[i].Medium))
|
||||
{
|
||||
ValidDefaultMedium = TRUE;
|
||||
break;
|
||||
|
@ -1493,7 +1563,7 @@ main(int ArgC, char **Args)
|
|||
fprintf(stderr, "Specified default medium \"%s\" not available. Valid media are:\n", DefaultMedium);
|
||||
for(int i = 0; i < ArrayCount(CategoryMedium); ++i)
|
||||
{
|
||||
fprintf(stderr, " %s\n", CategoryMedium[i][0]);
|
||||
fprintf(stderr, " %s\n", CategoryMedium[i].Medium);
|
||||
}
|
||||
fprintf(stderr, "To have \"%s\" added to the list, contact matt@handmadedev.org\n", DefaultMedium);
|
||||
return 1;
|
||||
|
@ -1714,6 +1784,7 @@ main(int ArgC, char **Args)
|
|||
// FilterMenu
|
||||
// FilterTopics
|
||||
// FilterMedia
|
||||
// CreditsMenu
|
||||
// Player
|
||||
// Colour
|
||||
// Annotation
|
||||
|
@ -1735,8 +1806,6 @@ main(int ArgC, char **Args)
|
|||
buffer FilterTopics;
|
||||
buffer FilterMedia;
|
||||
buffer CreditsMenu;
|
||||
buffer HostInfo;
|
||||
buffer AnnotatorInfo;
|
||||
|
||||
buffer Player;
|
||||
buffer Colour;
|
||||
|
@ -1803,8 +1872,6 @@ main(int ArgC, char **Args)
|
|||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &FilterTopics, "FilterTopics", Kilobytes(8));
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &FilterMedia, "FilterMedia", Kilobytes(8));
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &CreditsMenu, "CreditsMenu", Kilobytes(8));
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &HostInfo, "HostInfo", Kilobytes(1));
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &AnnotatorInfo, "AnnotatorInfo", Kilobytes(1));
|
||||
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &Player, "Player", Kilobytes(256));
|
||||
ClaimBuffer(&MemoryArena, &ClaimedMemory, &Colour, "Colour", 32);
|
||||
|
@ -1840,18 +1907,22 @@ main(int ArgC, char **Args)
|
|||
" <div class=\"video_container\" data-videoId=\"%s\"></div>\n"
|
||||
" <div class=\"markers_container %s\">\n", HMML.metadata.id, HMML.metadata.project);
|
||||
|
||||
// TODO(matt): Handle multiple annotators
|
||||
if(HMML.metadata.annotator_count > 0)
|
||||
int CreditsErrorCode = BuildCredits(&CreditsMenu, &HasCreditsMenu, ImagesDir, HMML.metadata);
|
||||
if(CreditsErrorCode)
|
||||
{
|
||||
BuildCredits(&CreditsMenu, &HostInfo, &AnnotatorInfo, &HasCreditsMenu, ImagesDir, HMML.metadata.member, HMML.metadata.annotators[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s: Missing annotator in [video] node\n", Args[FileIndex]);
|
||||
hmml_free(&HMML);
|
||||
free(MemoryArena.Location);
|
||||
free(Template.Location);
|
||||
return 1;
|
||||
switch(CreditsErrorCode)
|
||||
{
|
||||
case CreditsError_NoHost:
|
||||
fprintf(stderr, "%s: Missing \"member\" in the [video] node. Skipping...\n", Args[FileIndex]);
|
||||
goto Cleanup;
|
||||
break;
|
||||
case CreditsError_NoAnnotator:
|
||||
fprintf(stderr, "%s: Missing \"annotator\" in the [video] node. Skipping...\n", Args[FileIndex]);
|
||||
goto Cleanup;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
@ -2216,20 +2287,6 @@ main(int ArgC, char **Args)
|
|||
free(Template.Location);
|
||||
return 1;
|
||||
}
|
||||
if(BuildQuote(&QuoteInfo,
|
||||
Speaker,
|
||||
Anno->quote.id,
|
||||
CacheDir) == 2)
|
||||
{
|
||||
fprintf(stderr, "%s:%d: Failed to create quote cache at %s/quotes/%s for Quote #%s %d.\n"
|
||||
"Proceeding anyway, without a cache!\n",
|
||||
Args[FileIndex],
|
||||
Anno->line,
|
||||
CacheDir,
|
||||
Speaker,
|
||||
Speaker,
|
||||
Anno->quote.id);
|
||||
}
|
||||
|
||||
CopyStringToBuffer(&QuoteMenu,
|
||||
" <a target=\"_blank\" class=\"ref\" href=\"https://dev.abaines.me.uk/quotes/%s/%d\">\n"
|
||||
|
@ -2478,7 +2535,7 @@ main(int ArgC, char **Args)
|
|||
int j;
|
||||
for(j = 0; j < ArrayCount(CategoryMedium); ++j)
|
||||
{
|
||||
if(!StringsDiffer(MediaArray[i].Marker, CategoryMedium[j][0]))
|
||||
if(!StringsDiffer(MediaArray[i].Marker, CategoryMedium[j].Medium))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -2489,8 +2546,8 @@ main(int ArgC, char **Args)
|
|||
" <span class=\"icon\">%s</span><span class=\"text\">%s</span>\n"
|
||||
" </div>\n",
|
||||
MediaArray[i].Marker,
|
||||
CategoryMedium[j][1],
|
||||
CategoryMedium[j][2]
|
||||
CategoryMedium[j].Icon,
|
||||
CategoryMedium[j].WrittenName
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3158,8 +3215,6 @@ main(int ArgC, char **Args)
|
|||
// Annotation
|
||||
// Colour
|
||||
// Player
|
||||
// AnnotatorInfo
|
||||
// HostInfo
|
||||
// CreditsMenu
|
||||
// FilterMedia
|
||||
// FilterTopics
|
||||
|
@ -3170,14 +3225,13 @@ main(int ArgC, char **Args)
|
|||
// Includes
|
||||
// Master
|
||||
|
||||
Cleanup:
|
||||
DeclaimBuffer(&FilterState, &ClaimedMemory);
|
||||
DeclaimBuffer(&Script, &ClaimedMemory);
|
||||
DeclaimBuffer(&Annotation, &ClaimedMemory);
|
||||
DeclaimBuffer(&Colour, &ClaimedMemory);
|
||||
DeclaimBuffer(&Player, &ClaimedMemory);
|
||||
|
||||
DeclaimBuffer(&AnnotatorInfo, &ClaimedMemory);
|
||||
DeclaimBuffer(&HostInfo, &ClaimedMemory);
|
||||
DeclaimBuffer(&CreditsMenu, &ClaimedMemory);
|
||||
DeclaimBuffer(&FilterMedia, &ClaimedMemory);
|
||||
DeclaimBuffer(&FilterTopics, &ClaimedMemory);
|
||||
|
|
Loading…
Reference in New Issue