+//------------------------------------------------------------------------
+
+// update keyer parameters via text input from stdin
+// <wpm xxx> -> set keyer speed to xxx
+// <gain xxx> -> set gain to xxx (dB)
+// <freq xxx> -> set freq to xxx
+// <ramp xxx> -> set attack/decay times to xxx ms
+
+#define MAX_ESC (512)
+#define ESC_L '<'
+#define ESC_R '>'
+
+void
+updater(void) {
+ for (;;) {
+ int c;
+
+ // get or wait for next input char
+ if ((c = getchar()) == EOF) goto finish;
+
+ // if we see the beginning of a command,
+ if (c == ESC_L) {
+ int i = 0;
+ char buf[MAX_ESC];
+
+ // gather up the remainder
+ while ((c = getchar()) != EOF) {
+ if (c == ESC_R) break;
+ buf[i] = c;
+ if (++i >= (MAX_ESC - 1)) break;
+ }
+ if (c == EOF) goto finish;
+ buf[i] = 0;
+
+ // wait until changes are safe
+ sem_wait(&update_ok);
+
+ if (!strncmp(buf, "wpm", 3))
+ ks->wpm = wpm = atof(buf + 3);
+ else if (!strncmp(buf, "ramp", 4)) {
+ ramp = atof(buf + 4);
+ setCWToneGenVals(gen, gain, freq, ramp, ramp);
+ } else if (!strncmp(buf, "freq", 4)) {
+ freq = atof(buf + 4);
+ setCWToneGenVals(gen, gain, freq, ramp, ramp);
+ } else if (!strncmp(buf, "gain", 4)) {
+ gain = atof(buf + 4);
+ setCWToneGenVals(gen, gain, freq, ramp, ramp);
+ } else if (!strncmp(buf, "quit", 4))
+ goto finish;
+
+ } // otherwise go around again
+ }
+
+ // we saw an EOF or quit; kill other threads and exit neatly
+
+ finish:
+ pthread_cancel(play);
+ pthread_cancel(key);
+ pthread_exit(0);
+}
+
+//------------------------------------------------------------------------
+