support adapters using the acsint module

This commit is contained in:
Christopher Brannon 2011-05-01 15:40:44 +00:00 committed by William Hubbs
commit c06f18c454
5 changed files with 181 additions and 7 deletions

6
cli.c
View file

@ -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;

View file

@ -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);

View file

@ -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");

View 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);

View file

@ -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);