From 1debffddaccbf719e5c1da9f90c74f54d020d687 Mon Sep 17 00:00:00 2001 From: Jonathan Bradley Date: Fri, 24 Apr 2026 11:07:12 -0400 Subject: WPM support, only parameter or SPREED_WPM env --- src/spreed.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'src') 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 #include #include +#include #include +#include +#include #include #include #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; -- cgit v1.2.3