started work on multi-threading more of the program

The goal is to create threads for the reader, que runner/espeak
processing and signal handling.
As of this commit, this code is still being worked on, so it is broken.
This commit is contained in:
William Hubbs 2009-06-24 20:03:31 -05:00
commit 9d1cabdd0d
5 changed files with 108 additions and 71 deletions

View file

@ -13,6 +13,7 @@ SRCS = \
cli.c \
espeakup.c \
queue.c \
signal.c \
softsynth.c \
synth.c

View file

@ -43,6 +43,7 @@ char *defaultVoice = NULL;
int debug = 0;
volatile int stopped = 0;
volatile int should_run = 1;
espeak_AUDIO_OUTPUT audio_mode;
int espeakup_is_running(void)
@ -75,27 +76,14 @@ int create_pid_file(void)
return 0;
}
void espeakup_sighandler(int sig)
{
if (debug)
printf("Caught signal %i\n", sig);
/* clear the queue */
stop_runner();
/* shut down espeak and close the softsynth */
espeak_Terminate();
close_softsynth();
if (!debug)
unlink(pidPath);
exit(0);
}
int main(int argc, char **argv)
{
sigset_t sigset;
int rate;
int err;
pthread_t signal_thread_id;
pthread_t queue_thread_id;
pthread_t softsynth_thread_id;
struct synth_t s = {
.voice = "",
};
@ -115,54 +103,37 @@ int main(int argc, char **argv)
return 3;
}
/* register signal handler */
signal(SIGINT, espeakup_sighandler);
signal(SIGTERM, espeakup_sighandler);
/*
* If we are not in debug mode, become a daemon and store the pid.
*/
if (!debug) {
/* become a daemon */
daemon(0, 1);
/* write our pid file. */
if (create_pid_file() < 0) {
perror("Unable to create pid file");
return 2;
}
}
/* initialize espeak */
select_audio_mode();
rate = espeak_Initialize(audio_mode, 0, NULL, 0);
if (rate < 0) {
fprintf(stderr, "Unable to initialize espeak.\n");
return 5;
}
if (init_audio((unsigned int) rate) < 0) {
return 6;
}
/* Setup initial voice parameters */
if (defaultVoice) {
set_voice(&s, defaultVoice);
free(defaultVoice);
defaultVoice = NULL;
}
set_frequency(&s, defaultFrequency, ADJ_SET);
set_pitch(&s, defaultPitch, ADJ_SET);
set_rate(&s, defaultRate, ADJ_SET);
set_volume(&s, defaultVolume, ADJ_SET);
espeak_SetParameter(espeakCAPITALS, 0, 0);
/* Spawn our queue-processing thread. */
int err = pthread_create(&queue_thread_id, NULL, &queue_runner, &s);
/* create the signal processing thread here. */
err = pthread_create(&signal_thread_id, NULL, &signal_thread, NULL);
if (err != 0) {
return 4;
}
/* run the main loop */
main_loop(&s);
/*
* Set up the signal mask which will be the default for all threads.
* We are handling sigint and sigterm, so block them.
*/
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* Spawn our queue-processing thread. */
err = pthread_create(&queue_thread_id, NULL, &queue_runner, &s);
if (err != 0) {
return 4;
}
return 0;
}

View file

@ -76,9 +76,10 @@ extern espeak_ERROR stop_speech(void);
extern espeak_ERROR speak_text(struct synth_t *s);
extern int open_softsynth(void);
extern void close_softsynth(void);
extern void *reader_thread(void *arg);
extern void stop_runner(void);
extern void main_loop(struct synth_t *s);
extern void *queue_runner(void *arg);
extern void *signal_thread(void *arg);
extern void select_audio_mode(void);
extern int init_audio(unsigned int rate);
extern void lock_audio_mutex(void);

62
signal.c Normal file
View file

@ -0,0 +1,62 @@
/*
* espeakup - interface which allows speakup to use espeak
*
* Copyright (C) 2008 William Hubbs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <signal.h>
#include <stdio.h>
#include "espeakup.h"
/*
* We install a dummy signal handler to let the o/s know that we
* do not want the default action to be performed since we are
* handling the signal.
*/
static void dummy_handler(int sig)
{
}
void *signal_thread(void *arg)
{
struct sigaction temp;
sigset_t sigset;
int sig;
int should_run = 1;
/* install dummy handlers for the signals we want to process */
temp.sa_handler = dummy_handler;
sigemptyset(&temp.sa_mask);
sigaction(SIGINT, &temp, NULL);
sigaction(SIGTERM, &temp, NULL);
while(should_run) {
sigfillset(&sigset);
sigwait(&sigset, &sig);
switch (sig) {
case SIGINT:
case SIGTERM:
printf("This is where we shut down.\n");
should_run = 0;
break;
default:
printf("espeakup caught signal %d\n", sig);
break;
}
}
return NULL;
}

View file

@ -35,6 +35,23 @@ const int synthFlushChar = 0x18;
static int softFD = 0;
int open_softsynth(void)
{
int rc;
softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK);
if (softFD < 0)
rc = 0;
else
rc = 1;
return rc;
}
void close_softsynth(void)
{
close(softFD);
}
static int process_command(struct synth_t *s, char *buf, int start)
{
char *cp;
@ -125,34 +142,18 @@ static void process_buffer(struct synth_t *s, char *buf, ssize_t length)
}
}
int open_softsynth(void)
{
int rc;
softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK);
if (softFD < 0)
rc = 0;
else
rc = 1;
return rc;
}
void close_softsynth(void)
{
close(softFD);
}
void main_loop(struct synth_t *s)
void *reader_thread(void *arg)
{
struct synth_t *s = (struct synth_t *) arg;
fd_set set;
ssize_t length;
char buf[maxBufferSize];
char *cp;
while (1) {
while (should_run) {
FD_ZERO(&set);
FD_SET(softFD, &set);
if (select(softFD + 1, &set, NULL, NULL, NULL) < 0) {
if (errno == EINTR)
continue;
@ -179,4 +180,5 @@ void main_loop(struct synth_t *s)
}
process_buffer(s, buf, length);
}
return NULL;
}