summaryrefslogtreecommitdiff
path: root/src/spreed.c
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2026-04-24 11:07:12 -0400
committerJonathan Bradley <jcb@pikum.xyz>2026-04-24 11:07:12 -0400
commit1debffddaccbf719e5c1da9f90c74f54d020d687 (patch)
treea905b2c967f853c5f5e41235040bd10070ca7529 /src/spreed.c
parent975e972e65fc14c6e383acd5a34e6006bd557c2a (diff)
WPM support, only parameter or SPREED_WPM env
Diffstat (limited to 'src/spreed.c')
-rwxr-xr-xsrc/spreed.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/src/spreed.c b/src/spreed.c
index 623fe4f..b6a6403 100755
--- a/src/spreed.c
+++ b/src/spreed.c
@@ -3,15 +3,24 @@ ${CC:-gcc} -s -O2 -std=c99 -Wall -o ${SPREED_INSTALL_DIR:-.}/spreed src/spreed.c
exit
#endif
+#define _POSIX_C_SOURCE 200809L
+
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <time.h>
+#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#define CLR_FG L"\033[31m"
#define CLR_RESET L"\033[0m"
+#define SPRD_CLOCK CLOCK_MONOTONIC
+#define MS_PER_MIN (60llu * 1000000000llu)
+
+#define SPRD_CLOCK_DIFF(t1, t2) ((((uint64_t)t1.tv_sec * 1000000000llu) + (uint64_t)t1.tv_nsec) - (((uint64_t)t2.tv_sec * 1000000000llu) + (uint64_t)t2.tv_nsec))
const uint8_t orps[9] = {0,0,0,1,1,2,2,2,2};
@@ -22,23 +31,62 @@ inline uint8_t get_optimal_recognition_point(size_t len) {
int main(int argc, char *argv[])
{
+ struct timespec ts_last, ts_current, ts_sleep;
wchar_t word[37];
wchar_t wc;
+ char *str;
+ uint64_t u64, wpm_ns;
int c;
char chararr[4];
uint8_t u, uu, ichar, iword, b_word_break;
+ setlocale(LC_ALL, "");
+ fwide(stdout, 1);
+
+ clock_getres(SPRD_CLOCK, &ts_last);
+ memset(word, 0, 37 * sizeof(wchar_t));
+ u64 = 0;
+ wpm_ns = MS_PER_MIN / 250;
+ memset(chararr, 0, sizeof(chararr));
ichar = 0;
iword = 0;
b_word_break = 0;
- memset(word, 0, 37 * sizeof(wchar_t));
- memset(chararr, 0, sizeof(chararr));
- setlocale(LC_ALL, "");
- fwide(stdout, 1);
+ str = getenv("SPREED_WPM");
+ if (str == NULL && argc > 1) {
+ str = argv[1];
+ }
+ if (str != NULL) {
+ wpm_ns = strtoull(str, NULL, 10);
+ if (wpm_ns == 0) {
+ fwprintf(stdout, L"Error: parsed '%s' as %llu, setting to default of 250\n", str, wpm_ns);
+ wpm_ns = 250;
+ } else if (wpm_ns > (60 * 30)) {
+ wpm_ns = 60 * 30;
+ fwprintf(stdout, L"Limiting to 30 fps\n");
+ }
+ wpm_ns = MS_PER_MIN / wpm_ns;
+ }
+
+ fwprintf(stdout, L"Clock (%i) accuracy: %llu.%09llus\n", SPRD_CLOCK, ts_last.tv_sec, ts_last.tv_nsec);
fwprintf(stdout, L" V\n");
+ clock_gettime(SPRD_CLOCK, &ts_current);
+ ts_last = ts_current;
+ ts_last.tv_sec -= 60;
do {
+ while (u64 < wpm_ns) {
+ clock_gettime(SPRD_CLOCK, &ts_current);
+ u64 = SPRD_CLOCK_DIFF(ts_current, ts_last);
+ if (u64 >= wpm_ns) {
+ break;
+ }
+ u64 = wpm_ns - u64;
+ ts_sleep.tv_sec = 0;
+ ts_sleep.tv_nsec = u64 > 1000000000llu ? 999999999 : u64;
+ nanosleep(&ts_sleep, NULL);
+ u64 = 0;
+ }
b_word_break = 0;
c = getchar();
if (c == EOF) {
@@ -115,10 +163,12 @@ END_OF_WORD:
}
putwchar(L' ');
}
- putwchar('\n');
iword = 0;
memset(word, 0, 37 * sizeof(wchar_t));
+ u64 = 0;
+ ts_last = ts_current;
+ fflush(stdout);
}
ichar = 0;