initial commit for new format

This commit is contained in:
2023-04-04 01:57:29 +10:00
parent 577e88551d
commit 65414c2d64
4 changed files with 924 additions and 0 deletions

118
src2/client.c Normal file
View File

@ -0,0 +1,118 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
char commandcode;
if (argc < 2) {
fprintf(stderr,"usage %s command\n", argv[0]);
exit(0);
}
portno = 8101;
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname("localhost");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
if (!strcmp(argv[1], "time")) {
commandcode = 1;
} else if (!strcmp(argv[1], "start")) {
commandcode = 2;
} else if (!strcmp(argv[1], "stop")) {
commandcode = 3;
} else if (!strcmp(argv[1], "kill")) {
commandcode = 4;
} else if (!strcmp(argv[1], "split")) {
commandcode = 5;
} else if (!strcmp(argv[1], "skip")) {
commandcode = 6;
} else if (!strcmp(argv[1], "pause")) {
commandcode = 7;
} else if (!strcmp(argv[1], "resume")) {
commandcode = 8;
} else if (!strcmp(argv[1], "undo")) {
commandcode = 9;
} else if (!strcmp(argv[1], "redo")) {
commandcode = 10;
} else if (!strcmp(argv[1], "foreground")) {
commandcode = 11;
} else if (!strcmp(argv[1], "background")) {
commandcode = 12;
} else {
perror("No valid command given");
exit(1);
}
/* Send message to the server */
n = write(sockfd, &commandcode, 1);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
//bzero(buffer,256);
//read an int response
if (commandcode < 11) {
int x = -1;
n = read(sockfd, &x, sizeof(int));
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (x != -1)
printf("%d\n",x);
}
//read a string response
else {
bzero(buffer,256);
n = read(sockfd, &buffer, 255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (buffer != NULL)
printf("%s", buffer);
}
return 0;
}

415
src2/server.c Normal file
View File

@ -0,0 +1,415 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define NS_PER_S 1000000000
struct timespec finish, delta;
int pausedTime = 0;
bool timerActive = false;
bool paused = false;
bool alive = true;
int timerOffset = 0;
enum event_type {
START,
SPLIT,
SKIP,
PAUSE,
RESUME,
STOP
};
struct run_event {
enum event_type type;
struct timespec time;
};
struct run_event *run;
//Enough to hold a sm64 16 star, can realloc later
int runMaxLength = 12;
int runMarker = 0;
int runMarker2 = 0;
//save file stuff
int files = 0;
char **filePaths = NULL;
char **names, **values;
int valuecount;
void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td)
{
td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
td->tv_sec = t2.tv_sec - t1.tv_sec;
if (td->tv_sec > 0 && td->tv_nsec < 0) {
td->tv_nsec += NS_PER_S;
td->tv_sec--;
} else if (td->tv_sec < 0 && td->tv_nsec > 0) {
td->tv_nsec -= NS_PER_S;
td->tv_sec++;
}
}
void offset_timespec(int milliseconds, struct timespec* t)
{
//this should leave milliseconds with just the remainder
int second_offset = milliseconds / 1000;
milliseconds -= second_offset * 1000;
int nanosecond_offset = milliseconds * 1000000;
t->tv_nsec -= nanosecond_offset;
if (t->tv_nsec < 0) {
second_offset++;
t->tv_nsec += 1000000000;
}
t->tv_sec -= second_offset;
}
int timespecToMS(struct timespec t)
{
return (t.tv_nsec / 1000000) + (t.tv_sec * 1000);
}
void extend_run()
{
runMaxLength *= 2;
run = realloc(run, sizeof(struct run_event) * runMaxLength);
}
void add_event(enum event_type t)
{
if (runMarker == runMaxLength)
extend_run();
run[runMarker].type = t;
clock_gettime(CLOCK_REALTIME, &run[runMarker].time);
if (t == START)
offset_timespec(timerOffset, &run[runMarker].time);
runMarker++;
runMarker2 = runMarker;
}
void start()
{
//TODO: Save the old run to the file before the new one starts,
//the reason to do this here is it gives the runner a chance to undo
//if they accidentally hit the stop button
//TODO: Clear the run data first
timerActive = true;
add_event(START);
}
void stop()
{
timerActive = false;
add_event(STOP);
//this makes sure the time clients recieve from time
//requests match the time on the stop event
finish = run[runMarker - 1].time;
}
void split()
{
add_event(SPLIT);
}
void skip()
{
add_event(SKIP);
}
void addPauseTime()
{
int pauseEvent = 0;
for (int i = runMarker - 2; i >= 1; i--) {
if (run[i].type == PAUSE) {
pauseEvent = i;
break;
}
}
sub_timespec(run[pauseEvent].time, run[runMarker - 1].time, &delta);
pausedTime += timespecToMS(delta);
}
void subtractPauseTime()
{
int pauseEvent = 0;
for (int i = runMarker - 1; i >= i; i--) {
if (run[i].type == PAUSE) {
pauseEvent = i;
break;
}
}
sub_timespec(run[pauseEvent].time, run[runMarker].time, &delta);
pausedTime -= timespecToMS(delta);
}
void undo()
{
if (runMarker > 0) {
runMarker--;
if (run[runMarker].type == STOP)
timerActive = true;
if (run[runMarker].type == START)
timerActive = false;
if (run[runMarker].type == PAUSE)
paused = false;
if (run[runMarker].type == RESUME) {
paused = true;
subtractPauseTime();
}
}
}
void redo()
{
if (runMarker < runMarker2) {
runMarker++;
if (run[runMarker - 1].type == STOP)
timerActive = false;
if (run[runMarker - 1].type == START)
timerActive = true;
if (run[runMarker - 1].type == PAUSE)
paused = true;
if (run[runMarker - 1].type == RESUME) {
paused = false;
addPauseTime();
}
}
}
//this isnt just called pause() because that would overlap with <unistd.h>
void pause_timer()
{
if (!paused) {
add_event(PAUSE);
paused = true;
}
}
void resume()
{
if (paused) {
add_event(RESUME);
paused = false;
addPauseTime();
}
}
void loadFiles()
{
FILE* fp;
//TODO: for now we're just looking for the metadata values
char buff[255];
char buff2[255];
for (int i = 0; i < files; i++) {
fp = fopen(filePaths[i], "r");
while(1) {
char *x = fgets(buff, 255, fp);
if (buff[0] == '/' && buff[1] == '/' || buff[0] == '\n')
continue;
if (!strcmp(buff, "Segment") || !strcmp(buff, "Route") || x == NULL)
break;
fgets(buff2, 255, fp);
if (buff2[0] == '\t') {
valuecount++;
names = realloc(names, sizeof(char*) * valuecount);
names[valuecount - 1] = malloc(strlen(buff) - 1);
strncpy(names[valuecount - 1], buff, strlen(buff) - 1);
names[valuecount - 1][strlen(buff)] = '\0';
values = realloc(values, sizeof(char*) * valuecount);
values[valuecount - 1] = malloc(strlen(buff2) - 2);
strncpy(values[valuecount - 1], buff2 + 1, strlen(buff2) - 1);
values[valuecount - 1][strlen(buff2)] = '\0';
}
}
fclose(fp);
}
//Print metadata arrays
for (int i = 0; i < valuecount; i++) {
printf("%s | %s", names[i], values[i]);
}
}
//TODO: eventually file loading should support loading multiple files
void addFile(char *path)
{
files++;
filePaths = realloc(filePaths, sizeof(char*) * files);
filePaths[files - 1] = path;
loadFiles();
}
void sendTime(int sock)
{
int n, x;
if (timerActive)
clock_gettime(CLOCK_REALTIME, &finish);
if (paused) {
sub_timespec(run[0].time, run[runMarker - 1].time, &delta);
} else {
sub_timespec(run[0].time, finish, &delta);
}
x = timespecToMS(delta) - pausedTime;
n = write(sock, &x, sizeof(int));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
void sendValue(int sock, char* name)
{
int n, x;
bool namefound = false;
for(int i = 0; i < valuecount; i++) {
if (!strcmp(names[i], name)) {
x = i;
namefound = true;
}
}
if (namefound)
n = write(sock, values[x], strlen(values[x]));
else
n = write(sock, "DATA NOT PRESENT", 17);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
void doprocessing (int sock)
{
int n;
char commandcode;
n = read(sock,&commandcode,1);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
if (commandcode == 1) {
//printf("Recieved time command\n");
sendTime(sock);
} else if (commandcode == 2) {
printf("Recieved start command\n");
start();
} else if (commandcode == 3) {
printf("Recieved stop command\n");
stop();
} else if (commandcode == 4) {
printf("Recieved kill command\n");
alive = false;
} else if (commandcode == 5) {
printf("Recieved split command\n");
split();
} else if (commandcode == 6) {
printf("Recieved skip command\n");
skip();
} else if (commandcode == 7) {
printf("Recieved pause command\n");
pause_timer();
} else if (commandcode == 8) {
printf("Recieved resume command\n");
resume();
} else if (commandcode == 9) {
printf("Recieved undo command\n");
undo();
} else if (commandcode == 10) {
printf("Recieved redo command\n");
redo();
} else if (commandcode == 11) {
printf("Recieved request for foreground color\n");
sendValue(sock, "Foreground-Color");
} else if (commandcode == 12) {
printf("Recieved request for background color\n");
sendValue(sock, "Background-Color");
} else {
printf("Recieved invalid command code, ignoring...\n");
}
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
run = malloc(sizeof(struct run_event) * runMaxLength);
//TODO: remove this file testing boilerplate
addFile(argv[1]);
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 8101;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (alive) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
//pid = fork();
pid = 1;
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the child process */
//close(sockfd);
//doprocessing(newsockfd);
//exit(0);
}
else {
doprocessing(newsockfd);
close(newsockfd);
}
} /* end of while */
free(run);
close(sockfd);
}

204
src2/tui.c Normal file
View File

@ -0,0 +1,204 @@
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <signal.h>
//Big numbies
char bignumbers[4][126] = {
//char bignumbers[4][55] = {
"▄▀▀▄ ▄█ ▄▀▀▄ ▄▀▀▄ ▄ █ █▀▀▀ ▄▀▀ ▀▀▀█ ▄▀▀▄ ▄▀▀▄ ",
"█ █ █ ▄▀ ▄▀ █▄▄█ █▄▄ █▄▄ ▐▌ ▀▄▄▀ ▀▄▄█ ▀ ",
"█ █ █ ▄▀ ▄ █ █ █ █ █ █ █ █ █ ▀ ",
" ▀▀ ▀▀▀ ▀▀▀▀ ▀▀ ▀ ▀▀▀ ▀▀ ▀ ▀▀ ▀▀ ▀ "
};
struct termios base;
int fps = 60;
struct color {
int r;
int g;
int b;
};
struct color b = { 47, 53, 66}; //Background color
struct color f = {247, 248, 242}; //Text foreground color
struct color g = {249, 255, 79}; //Best ever segment time color
struct color ag = { 24, 240, 31}; //Ahead, and gaining time segment color
struct color al = { 79, 255, 85}; //Ahead, but losing time segment color
struct color bg = {255, 79, 79}; //Behind, but gaining time segment color
struct color bl = {224, 34, 34}; //Behind, and losing time segment color
int w, h;
int timestringDigits(int ms)
{
int chars = 4;
if (ms >= 10000)
chars += 1;
if (ms >= 60000)
chars += 2;
if (ms >= 600000)
chars += 1;
if (ms >= 3600000)
chars += 2;
if (ms >= 36000000)
chars += 1;
if (ms >= 360000000)
chars += 1;
return chars;
}
//This function needs an x and y coordinate because the resulting string
//is supposed to be printed across 4 rows so it cant really just return the
//resulting string
void printbigtimestring(int ms, int x, int y)
{
//convert the single cell per character string length into the same
//thing for the big time string, it cant just be a simple multiplication
//because the : and . digits arent as wide as the numbers
//Example string, printing a blank timer with all digits at x=65, y=40.
//\033[40;65H▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄ ▄▀▀▄
//\033[41;65H█ █ █ █ █ █ ▀ █ █ █ █ ▀ █ █ █ █ █ █ █ █
//\033[42;65H█ █ █ █ █ █ ▀ █ █ █ █ ▀ █ █ █ █ █ █ █ █
//\033[43;65H ▀▀ ▀▀ ▀▀ ▀▀ ▀▀ ▀▀ ▀▀ ▀ ▀▀ ▀▀
char buffer[256];
}
void timestring(char *str, int ms)
{
int msdigits = (ms / 10) % 100;
int seconds = (ms / 1000) % 60;
int minutes = ((ms / 1000) / 60) % 60;
int hours = ((ms / 1000) / 60) / 60;
sprintf(str, "%03d:%02d:%02d.%02d", hours, minutes, seconds, msdigits);
}
void resize(int i)
{
struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);
w = ws.ws_col;
h = ws.ws_row;
}
void initScreen()
{
struct termios t;
tcgetattr(1, &base);
t = base;
t.c_lflag &= (~ECHO & ~ICANON);
tcsetattr(1, TCSANOW, &t);
//TODO:Figure out why i did this
dup(0);
fcntl(0, F_SETFL, O_NONBLOCK);
printf("\033[?1049h\n"); //Switch to TUI mode (alternate buffer)
printf("\033[?25l\n"); //Hide text cursor
printf("\033[2J\n"); //Clear screen
}
void resetScreen()
{
tcsetattr(1, TCSANOW, &base);
printf("\033[2J\n"); //Clear screen
printf("\033[?1049l\n"); //Switch back to regular mode
printf("\033[?25h\n"); //Show cursor
}
void die(int i)
{
exit(1);
}
void processColorString(struct color *c, char* s)
{
int i = 0;
int length = strlen(s);
char comp[4];
int compcount = 0;
int colorcompsdone = 0;
//TODO: if we know the length now that we're not doing fgetc we dont
//need a while loop; convert to for loop
while (1) {
char x = s[i++];
if (x >= 48 && x <= 57) {
comp[compcount] = x;
compcount++;
}
if (x == 44 || i == length) {
comp[compcount] = '\0';
switch(colorcompsdone) {
case 0:
c->r = atoi(comp);
break;
case 1:
c->g = atoi(comp);
break;
case 2:
c->b = atoi(comp);
}
colorcompsdone++;
compcount = 0;
}
if (i == length)
break;
}
}
int main (int argc, char *argv[])
{
initScreen();
atexit(resetScreen);
signal(SIGTERM, die);
signal(SIGINT, die);
signal(SIGWINCH, resize);
resize(0);
FILE *fp;
char path[1000];
char ti[13];
//Request foreground color from config file
fp = popen("./quest-log foreground", "r");
fgets(path, sizeof(path), fp);
if (strcmp(path, "DATA NOT PRESENT"))
processColorString(&f, path);
printf("\033[38;2;%d;%d;%dm", f.r, f.g, f.b);
pclose(fp);
//Request background color from config file
fp = popen("./quest-log background", "r");
fgets(path, sizeof(path), fp);
if (strcmp(path, "DATA NOT PRESENT"))
processColorString(&b, path);
printf("\033[48;2;%d;%d;%dm", b.r, b.g, b.b);
pclose(fp);
//Set fps from command line argument
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-fps"))
fps = atoi(argv[i + 1]);
}
while (1) {
int time = 0;
fp = popen("./quest-log time", "r");
if (fp == NULL) {
printf("Failed to run command\n");
exit(1);
}
while (fgets(path, sizeof(path), fp) != NULL) {
time = atoi(path);
printf("\033[2J\n");
timestring(&ti, time);
printf("%s\n", ti + (12 - timestringDigits(time)));
}
pclose(fp);
usleep(1000000 / fps);
}
}