~alcinnz/rhapsode

a8275ac6e1b33655bcf65df0a81a162a5e111e80 — Adrian Cochrane 4 years ago afc9cc5
Receive keyboard input.
2 files changed, 42 insertions(+), 7 deletions(-)

M src/main.c
M useragent.css
M src/main.c => src/main.c +41 -7
@@ 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", &paragraph_no) == 1) {}
            else if (sscanf(events->id.name, "-rhaps-section%i", &section_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;
}

M useragent.css => useragent.css +1 -0
@@ 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 */