mirror of
https://github.com/linux-speakup/espeakup.git
synced 2026-08-09 09:19:09 +02:00
support adapters using the acsint module
This commit is contained in:
parent
70f74657c2
commit
c06f18c454
5 changed files with 181 additions and 7 deletions
6
cli.c
6
cli.c
|
|
@ -31,10 +31,11 @@ extern char *pidPath;
|
|||
extern char *defaultVoice;
|
||||
|
||||
/* command line options */
|
||||
const char *shortOptions = "P:V:dhv";
|
||||
const char *shortOptions = "P:V:adhv";
|
||||
const struct option longOptions[] = {
|
||||
{"pid-path", required_argument, NULL, 'P'},
|
||||
{"default-voice", required_argument, NULL, 'V'},
|
||||
{"acsint", no_argument, NULL, 'a'},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
|
|
@ -79,6 +80,9 @@ void process_cli(int argc, char **argv)
|
|||
case 'V':
|
||||
defaultVoice = strdup(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
espeakup_mode = ESPEAKUP_MODE_ACSINT;
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
|
|
|
|||
27
espeak.c
27
espeak.c
|
|
@ -40,6 +40,21 @@ const int volumeMultiplier = 22;
|
|||
|
||||
volatile int stop_requested = 0;
|
||||
|
||||
static int acsint_callback(short *wav, int numsamples, espeak_EVENT * events)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; events[i].type != espeakEVENT_LIST_TERMINATED; i++) {
|
||||
if (events[i].type == espeakEVENT_MARK) {
|
||||
int mark = atoi(events[i].id.name);
|
||||
if ((mark < 0) || (mark > 255))
|
||||
continue;
|
||||
putchar(mark);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static espeak_ERROR set_frequency(struct synth_t *s, int freq,
|
||||
enum adjust_t adj)
|
||||
{
|
||||
|
|
@ -139,9 +154,13 @@ static espeak_ERROR stop_speech(void)
|
|||
static espeak_ERROR speak_text(struct synth_t *s)
|
||||
{
|
||||
espeak_ERROR rc;
|
||||
int synth_mode = 0;
|
||||
|
||||
rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, 0, NULL,
|
||||
NULL);
|
||||
if (espeakup_mode == ESPEAKUP_MODE_ACSINT)
|
||||
synth_mode |= espeakSSML;
|
||||
|
||||
rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, synth_mode,
|
||||
NULL, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +238,10 @@ int initialize_espeak(struct synth_t *s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* We need a callback in acsint mode, but not in speakup mode. */
|
||||
if (espeakup_mode == ESPEAKUP_MODE_ACSINT)
|
||||
espeak_SetSynthCallback(acsint_callback);
|
||||
|
||||
/* Setup initial voice parameters */
|
||||
if (defaultVoice) {
|
||||
set_voice(s, defaultVoice);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
char *pidPath = "/var/run/espeakup.pid";
|
||||
|
||||
int debug = 0;
|
||||
enum espeakup_mode_t espeakup_mode = ESPEAKUP_MODE_SPEAKUP;
|
||||
struct queue_t *synth_queue = NULL;
|
||||
|
||||
int self_pipe_fds[2];
|
||||
|
|
@ -99,7 +100,7 @@ int main(int argc, char **argv)
|
|||
/*
|
||||
* If we are not in debug mode, become a daemon and store the pid.
|
||||
*/
|
||||
if (!debug) {
|
||||
if (espeakup_mode != ESPEAKUP_MODE_ACSINT && !debug) {
|
||||
daemon(0, 1);
|
||||
if (create_pid_file() < 0) {
|
||||
perror("Unable to create pid file");
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
#define PACKAGE_VERSION "0.80-dev"
|
||||
#define PACKAGE_BUGREPORT "http://github.com/williamh/espeakup/issues"
|
||||
|
||||
enum espeakup_mode_t {
|
||||
ESPEAKUP_MODE_SPEAKUP,
|
||||
ESPEAKUP_MODE_ACSINT
|
||||
};
|
||||
|
||||
enum command_t {
|
||||
CMD_SET_FREQUENCY,
|
||||
CMD_SET_PITCH,
|
||||
|
|
@ -70,6 +75,7 @@ struct synth_t {
|
|||
|
||||
extern struct queue_t *synth_queue;
|
||||
extern int debug;
|
||||
extern enum espeakup_mode_t espeakup_mode;
|
||||
|
||||
extern void process_cli(int argc, char **argv);
|
||||
extern void *signal_thread(void *arg);
|
||||
|
|
|
|||
146
softsynth.c
146
softsynth.c
|
|
@ -28,13 +28,103 @@
|
|||
#include "espeakup.h"
|
||||
|
||||
/* max buffer size */
|
||||
static const size_t maxBufferSize = 1025;
|
||||
/* A big fat buffer. */
|
||||
static const size_t maxBufferSize = 16 * 1024 + 1;
|
||||
|
||||
/* synth flush character */
|
||||
static const int synthFlushChar = 0x18;
|
||||
|
||||
|
||||
static int softFD = 0;
|
||||
|
||||
/* Text accumulator: */
|
||||
char *textAccumulator;
|
||||
int textAccumulator_l;
|
||||
|
||||
/* String routines, borrowed from edbrowse: */
|
||||
char *EMPTYSTRING = "";
|
||||
|
||||
void *allocMem(size_t n)
|
||||
{
|
||||
void *s;
|
||||
if (!n)
|
||||
return EMPTYSTRING;
|
||||
if (!(s = malloc(n))) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
return s;
|
||||
} /* allocMem */
|
||||
|
||||
void *reallocMem(void *p, size_t n)
|
||||
{
|
||||
void *s;
|
||||
if (!n) {
|
||||
fprintf(stderr, "Trying to reallocate memory with size of 0.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!p) {
|
||||
fprintf(stderr, "realloc called with a NULL pointer!\n");
|
||||
exit(1);
|
||||
}
|
||||
if (p == EMPTYSTRING)
|
||||
return allocMem(n);
|
||||
if (!(s = realloc(p, n))) {
|
||||
fprintf(stderr, "Failed to allocate memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
return s;
|
||||
} /* reallocMem */
|
||||
|
||||
char *initString(int *l)
|
||||
{
|
||||
*l = 0;
|
||||
return EMPTYSTRING;
|
||||
}
|
||||
|
||||
void stringAndString(char **s, int *l, const char *t)
|
||||
{
|
||||
char *p = *s;
|
||||
int oldlen, newlen, x;
|
||||
oldlen = *l;
|
||||
newlen = oldlen + strlen(t);
|
||||
*l = newlen;
|
||||
++newlen; /* room for the 0 */
|
||||
x = oldlen ^ newlen;
|
||||
if (x > oldlen) { /* must realloc */
|
||||
newlen |= (newlen >> 1);
|
||||
newlen |= (newlen >> 2);
|
||||
newlen |= (newlen >> 4);
|
||||
newlen |= (newlen >> 8);
|
||||
newlen |= (newlen >> 16);
|
||||
p = reallocMem(p, newlen);
|
||||
*s = p;
|
||||
}
|
||||
strcpy(p + oldlen, t);
|
||||
} /* stringAndString */
|
||||
|
||||
void stringAndBytes(char **s, int *l, const char *t, int cnt)
|
||||
{
|
||||
char *p = *s;
|
||||
int oldlen, newlen, x;
|
||||
oldlen = *l;
|
||||
newlen = oldlen + cnt;
|
||||
*l = newlen;
|
||||
++newlen;
|
||||
x = oldlen ^ newlen;
|
||||
if (x > oldlen) { /* must realloc */
|
||||
newlen |= (newlen >> 1);
|
||||
newlen |= (newlen >> 2);
|
||||
newlen |= (newlen >> 4);
|
||||
newlen |= (newlen >> 8);
|
||||
newlen |= (newlen >> 16);
|
||||
p = reallocMem(p, newlen);
|
||||
*s = p;
|
||||
}
|
||||
memcpy(p + oldlen, t, cnt);
|
||||
p[oldlen + cnt] = 0;
|
||||
} /* stringAndBytes */
|
||||
|
||||
static void queue_add_cmd(enum command_t cmd, enum adjust_t adj, int value)
|
||||
{
|
||||
struct espeak_entry_t *entry;
|
||||
|
|
@ -147,8 +237,15 @@ static int process_command(struct synth_t *s, char *buf, int start)
|
|||
break;
|
||||
}
|
||||
|
||||
if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN)
|
||||
if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN) {
|
||||
if (espeakup_mode == ESPEAKUP_MODE_ACSINT
|
||||
&& textAccumulator_l != 0) {
|
||||
queue_add_text(textAccumulator, textAccumulator_l);
|
||||
free(textAccumulator);
|
||||
textAccumulator = initString(&textAccumulator_l);
|
||||
}
|
||||
queue_add_cmd(cmd, adj, value);
|
||||
}
|
||||
|
||||
return cp - (buf + start);
|
||||
}
|
||||
|
|
@ -178,6 +275,38 @@ static void process_buffer(struct synth_t *s, char *buf, ssize_t length)
|
|||
}
|
||||
}
|
||||
|
||||
static void process_buffer_acsint(struct synth_t *s, char *buf,
|
||||
ssize_t length)
|
||||
{
|
||||
int start = 0;
|
||||
int i;
|
||||
int flushIt = 0;
|
||||
|
||||
while (start < length) {
|
||||
for (i = start; i < length; i++) {
|
||||
if (buf[i] == '\r' || buf[i] == '\n')
|
||||
flushIt = 1;
|
||||
if (buf[i] >= 0 && buf[i] < ' ')
|
||||
break;
|
||||
}
|
||||
if (i > start)
|
||||
stringAndBytes(&textAccumulator, &textAccumulator_l,
|
||||
buf + start, i - start);
|
||||
if (flushIt) {
|
||||
if (textAccumulator != EMPTYSTRING) {
|
||||
queue_add_text(textAccumulator, textAccumulator_l);
|
||||
free(textAccumulator);
|
||||
textAccumulator = initString(&textAccumulator_l);
|
||||
}
|
||||
flushIt = 0;
|
||||
}
|
||||
if (i < length)
|
||||
start = i = i + process_command(s, buf, i);
|
||||
else
|
||||
start = length;
|
||||
}
|
||||
}
|
||||
|
||||
static void request_espeak_stop(void)
|
||||
{
|
||||
pthread_mutex_lock(&queue_guard);
|
||||
|
|
@ -191,6 +320,12 @@ static void request_espeak_stop(void)
|
|||
int open_softsynth(void)
|
||||
{
|
||||
int rc = 0;
|
||||
/* If we're in acsint mode, we read from stdin. No need to open. */
|
||||
if (espeakup_mode == ESPEAKUP_MODE_ACSINT) {
|
||||
softFD = STDIN_FILENO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open the softsynth. */
|
||||
softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK);
|
||||
if (softFD < 0) {
|
||||
|
|
@ -216,6 +351,8 @@ void *softsynth_thread(void *arg)
|
|||
int terminalFD = PIPE_READ_FD;
|
||||
int greatestFD;
|
||||
|
||||
textAccumulator = initString(&textAccumulator_l);
|
||||
|
||||
if (terminalFD > softFD)
|
||||
greatestFD = terminalFD;
|
||||
else
|
||||
|
|
@ -264,7 +401,10 @@ void *softsynth_thread(void *arg)
|
|||
memmove(buf, cp + 1, strlen(cp + 1) + 1);
|
||||
length = strlen(buf);
|
||||
}
|
||||
process_buffer(s, buf, length);
|
||||
if (espeakup_mode == ESPEAKUP_MODE_SPEAKUP)
|
||||
process_buffer(s, buf, length);
|
||||
else
|
||||
process_buffer_acsint(s, buf, length);
|
||||
pthread_mutex_lock(&queue_guard);
|
||||
}
|
||||
pthread_cond_signal(&runner_awake);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue