From 9d1cabdd0d513c45bafdf7cc9c62b503f4a0f31d Mon Sep 17 00:00:00 2001 From: William Hubbs Date: Wed, 24 Jun 2009 20:03:31 -0500 Subject: [PATCH] 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. --- Makefile | 1 + espeakup.c | 77 +++++++++++++++++------------------------------------ espeakup.h | 3 ++- signal.c | 62 ++++++++++++++++++++++++++++++++++++++++++ softsynth.c | 42 +++++++++++++++-------------- 5 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 signal.c diff --git a/Makefile b/Makefile index 059db6b..f784aac 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ SRCS = \ cli.c \ espeakup.c \ queue.c \ + signal.c \ softsynth.c \ synth.c diff --git a/espeakup.c b/espeakup.c index 34c1257..db86232 100644 --- a/espeakup.c +++ b/espeakup.c @@ -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; } diff --git a/espeakup.h b/espeakup.h index 5433a77..dc1f567 100644 --- a/espeakup.h +++ b/espeakup.h @@ -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); diff --git a/signal.c b/signal.c new file mode 100644 index 0000000..10e0b90 --- /dev/null +++ b/signal.c @@ -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 . + */ + +#include +#include + +#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; +} diff --git a/softsynth.c b/softsynth.c index 1a93edb..d04f6e4 100644 --- a/softsynth.c +++ b/softsynth.c @@ -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; }