mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
2.7 KiB
124 lines
2.7 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
#include <linux/console.h> |
|
#include <linux/types.h> |
|
#include <linux/wait.h> |
|
|
|
#include "speakup.h" |
|
#include "spk_priv.h" |
|
|
|
#define SYNTH_BUF_SIZE 8192 /* currently 8K bytes */ |
|
|
|
static u16 synth_buffer[SYNTH_BUF_SIZE]; /* guess what this is for! */ |
|
static u16 *buff_in = synth_buffer; |
|
static u16 *buff_out = synth_buffer; |
|
static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1; |
|
|
|
/* These try to throttle applications by stopping the TTYs |
|
* Note: we need to make sure that we will restart them eventually, which is |
|
* usually not possible to do from the notifiers. TODO: it should be possible |
|
* starting from linux 2.6.26. |
|
* |
|
* So we only stop when we know alive == 1 (else we discard the data anyway), |
|
* and the alive synth will eventually call start_ttys from the thread context. |
|
*/ |
|
void speakup_start_ttys(void) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < MAX_NR_CONSOLES; i++) { |
|
if (speakup_console[i] && speakup_console[i]->tty_stopped) |
|
continue; |
|
if (vc_cons[i].d && vc_cons[i].d->port.tty) |
|
start_tty(vc_cons[i].d->port.tty); |
|
} |
|
} |
|
EXPORT_SYMBOL_GPL(speakup_start_ttys); |
|
|
|
static void speakup_stop_ttys(void) |
|
{ |
|
int i; |
|
|
|
for (i = 0; i < MAX_NR_CONSOLES; i++) |
|
if (vc_cons[i].d && vc_cons[i].d->port.tty) |
|
stop_tty(vc_cons[i].d->port.tty); |
|
} |
|
|
|
static int synth_buffer_free(void) |
|
{ |
|
int chars_free; |
|
|
|
if (buff_in >= buff_out) |
|
chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out); |
|
else |
|
chars_free = buff_out - buff_in; |
|
return chars_free; |
|
} |
|
|
|
int synth_buffer_empty(void) |
|
{ |
|
return (buff_in == buff_out); |
|
} |
|
EXPORT_SYMBOL_GPL(synth_buffer_empty); |
|
|
|
void synth_buffer_add(u16 ch) |
|
{ |
|
if (!synth->alive) { |
|
/* This makes sure that we won't stop TTYs if there is no synth |
|
* to restart them |
|
*/ |
|
return; |
|
} |
|
if (synth_buffer_free() <= 100) { |
|
synth_start(); |
|
speakup_stop_ttys(); |
|
} |
|
if (synth_buffer_free() <= 1) |
|
return; |
|
*buff_in++ = ch; |
|
if (buff_in > buffer_end) |
|
buff_in = synth_buffer; |
|
/* We have written something to the speech synthesis, so we are not |
|
* paused any more. |
|
*/ |
|
spk_paused = false; |
|
} |
|
|
|
u16 synth_buffer_getc(void) |
|
{ |
|
u16 ch; |
|
|
|
if (buff_out == buff_in) |
|
return 0; |
|
ch = *buff_out++; |
|
if (buff_out > buffer_end) |
|
buff_out = synth_buffer; |
|
return ch; |
|
} |
|
EXPORT_SYMBOL_GPL(synth_buffer_getc); |
|
|
|
u16 synth_buffer_peek(void) |
|
{ |
|
if (buff_out == buff_in) |
|
return 0; |
|
return *buff_out; |
|
} |
|
EXPORT_SYMBOL_GPL(synth_buffer_peek); |
|
|
|
void synth_buffer_skip_nonlatin1(void) |
|
{ |
|
while (buff_out != buff_in) { |
|
if (*buff_out < 0x100) |
|
return; |
|
buff_out++; |
|
if (buff_out > buffer_end) |
|
buff_out = synth_buffer; |
|
} |
|
} |
|
EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1); |
|
|
|
void synth_buffer_clear(void) |
|
{ |
|
buff_in = synth_buffer; |
|
buff_out = synth_buffer; |
|
} |
|
EXPORT_SYMBOL_GPL(synth_buffer_clear);
|
|
|