@@ 3,7 3,7 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
-#include <pthread.h>
+#include <termios.h>
#include "HsFFI.h"
#include <espeak-ng/espeak_ng.h>
@@ 56,19 56,16 @@ int read_mono(SNDFILE *fd, SF_INFO *info, short *out) {
return i;
}
-pthread_mutex_t marker_mutex = PTHREAD_MUTEX_INITIALIZER;
-int paragraph_no, section_no;
-int tablerow, tablecol, tableno, in_table;
+int paragraph_no = 0, section_no = 0;
+int tablerow = 0, tablecol = 0, tableno = 0, in_table = 0;
int capture_marks(short *wav, int numsamples, espeak_EVENT *events) {
while (events->type != 0) {
if (events->type == espeakEVENT_MARK) {
- pthread_mutex_lock(&marker_mutex);
in_table = 0;
if (sscanf(events->id.name, "-rhaps-paragraph%i", ¶graph_no) == 1) {}
else if (sscanf(events->id.name, "-rhaps-section%i", §ion_no) == 1) {}
else if (sscanf(events->id.name, "-rhaps-tablecell%i:%ix%i",
&tableno, &tablerow, &tablecol) == 3) {in_table = 1;}
- pthread_mutex_unlock(&marker_mutex);
}
events++;
}
@@ 124,13 121,37 @@ void speak(char *ssml) {
int flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE | espeakCHARS_UTF8 | espeakSSML;
espeak_Synth(ssml, strlen(ssml)+1, 0, POS_CHARACTER, 0, flags, NULL, NULL);
}
+int read_keyboard = 0;
int speak_finalize() {
+ while (read_keyboard) {
+ char c = getc(stdin);
+ if (c == '\033') {
+ espeak_Cancel();
+ c = getc(stdin);
+ if (c == 0 || c == -1 || c == '\033' || c == 'q') goto close; // skip [
+ switch (getc(stdin)) {
+ case 'A':
+ printf("🠕");
+ break;
+ case 'B':
+ printf("🠗");
+ break;
+ case 'C':
+ printf("➔");
+ break;
+ case 'D':
+ printf("🠔");
+ break;
+ }
+ }
+ }
espeak_ng_STATUS result = espeak_ng_Synchronize();
if (result != ENS_OK) {
espeak_ng_PrintStatusCodeMessage(result, stderr, context);
return 4;
}
+close:
if (path_wav != NULL) sf_close(fd_wav);
espeak_ng_Terminate();
return 0;
@@ 153,6 174,7 @@ FILE *parse_opt_file() {
return ret;
}
+struct termios stored_settings;
int main(int argc, char **argv) {
int speak_err = 0;
hs_init(&argc, &argv);
@@ 161,10 183,11 @@ int main(int argc, char **argv) {
FILE *fd_ssml = NULL;
FILE *fd_links = NULL;
int use_espeak = 0;
+ tcgetattr(0, &stored_settings);
int c;
opterr = 0;
- while ((c = getopt(argc, argv, "xs::l::w::h")) != -1) {
+ while ((c = getopt(argc, argv, "xs::l::kw::h")) != -1) {
switch (c) {
case 'x':
mimes = "text/xml application/xml application/xhtml+xml text/html text/plain";
@@ 175,6 198,16 @@ int main(int argc, char **argv) {
case 'l':
fd_links = parse_opt_file();
break;
+ case 'k':
+ read_keyboard = 1;
+ // Read input character by character, not line by line.
+ struct termios new_settings = stored_settings;
+ new_settings.c_lflag &= (~ICANON);
+ new_settings.c_lflag &= (~ECHO);
+ new_settings.c_cc[VTIME] = 1;
+ new_settings.c_cc[VMIN] = 0;
+ tcsetattr(0, TCSANOW, &new_settings);
+ break;
case 'w':
use_espeak = 1;
path_wav = optarg;
@@ 220,6 253,7 @@ int main(int argc, char **argv) {
c_freePage(referer);
c_freeSession(session);
hs_exit();
+ tcsetattr(0, TCSANOW, &stored_settings);
return speak_err;
}
@@ 5,6 5,7 @@ datalist, template {speak: never}
counter-reset: -rhaps-table, -rhaps-section, -rhaps-paragraph
}
[lang] {-rhaps-lang: attr(lang)} /* Pass this info through styletree into output */
+:target {-rhaps-marker: "main"}
/** Forms **/
button, select, textarea, input, output {speak: never} /* Leave to special form entry mode */