diff --git a/espeakup.c b/espeakup.c index abcc66b..34c1257 100644 --- a/espeakup.c +++ b/espeakup.c @@ -81,7 +81,7 @@ void espeakup_sighandler(int sig) printf("Caught signal %i\n", sig); /* clear the queue */ - queue_clear(); + stop_runner(); /* shut down espeak and close the softsynth */ espeak_Terminate(); diff --git a/espeakup.h b/espeakup.h index feafa6f..5433a77 100644 --- a/espeakup.h +++ b/espeakup.h @@ -76,6 +76,7 @@ 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 stop_runner(void); extern void main_loop(struct synth_t *s); extern void *queue_runner(void *arg); extern void select_audio_mode(void); @@ -83,6 +84,7 @@ extern int init_audio(unsigned int rate); extern void lock_audio_mutex(void); extern void unlock_audio_mutex(void); extern volatile int stopped; +extern volatile int runner_must_stop; extern espeak_AUDIO_OUTPUT audio_mode; #endif diff --git a/queue.c b/queue.c index 5e96c91..002ad61 100644 --- a/queue.c +++ b/queue.c @@ -26,7 +26,9 @@ #include "espeakup.h" pthread_cond_t runner_awake = PTHREAD_COND_INITIALIZER; +pthread_cond_t stop_acknowledged = PTHREAD_COND_INITIALIZER; pthread_mutex_t queue_guard = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t stop_guard = PTHREAD_MUTEX_INITIALIZER; struct queue_entry_t { enum command_t cmd; @@ -37,6 +39,7 @@ struct queue_entry_t { struct queue_entry_t *next; }; +volatile int runner_must_stop = 0; static struct queue_entry_t *first = NULL; static struct queue_entry_t *last = NULL; @@ -67,7 +70,7 @@ static void free_entry(struct queue_entry_t *entry) /* Remove and return the entry at the head of the queue. * Return NULL if queue is empty. */ -static void queue_remove(void) +static void queue_remove(void) { struct queue_entry_t *temp; @@ -84,12 +87,10 @@ void queue_clear(void) { struct queue_entry_t *temp; - pthread_mutex_lock(&queue_guard); while (last) { temp = last->next; queue_remove(); } - pthread_mutex_unlock(&queue_guard); /* We aren't adding data to the queue, so no need to signal. */ } @@ -132,42 +133,58 @@ void queue_add_text(char *txt, size_t length) static void queue_process_entry(struct synth_t *s) { espeak_ERROR error; + struct queue_entry_t *current = last; pthread_mutex_unlock(&queue_guard); /* So "reader" can go. */ - - if (last) { - switch (last->cmd) { + if (current) { + switch (current->cmd) { case CMD_SET_FREQUENCY: - error = set_frequency(s, last->value, last->adjust); + error = set_frequency(s, current->value, current->adjust); break; case CMD_SET_PITCH: - error = set_pitch(s, last->value, last->adjust); + error = set_pitch(s, current->value, current->adjust); break; case CMD_SET_PUNCTUATION: - error = set_punctuation(s, last->value, last->adjust); + error = set_punctuation(s, current->value, current->adjust); break; case CMD_SET_RATE: - error = set_rate(s, last->value, last->adjust); + error = set_rate(s, current->value, current->adjust); break; case CMD_SET_VOICE: break; case CMD_SET_VOLUME: - error = set_volume(s, last->value, last->adjust); + error = set_volume(s, current->value, current->adjust); break; case CMD_SPEAK_TEXT: - s->buf = last->buf; - s->len = last->len; + s->buf = current->buf; + s->len = current->len; error = speak_text(s); break; default: break; } + pthread_mutex_lock(&queue_guard); if (error == EE_OK) queue_remove(); + pthread_mutex_unlock(&queue_guard); } } +/* + * Tell the runner to stop speech and clear its queue. + */ +void stop_runner(void) +{ + pthread_mutex_lock(&stop_guard); + pthread_mutex_lock(&queue_guard); + runner_must_stop = 1; + pthread_mutex_unlock(&queue_guard); + pthread_cond_signal(&runner_awake); /* Wake runner, if necessary. */ + pthread_cond_wait(&stop_acknowledged, &stop_guard); + pthread_mutex_unlock(&stop_guard); +} + /* queue_runner is the "main" function of our secondary (queue-processing) * thread. * First, lock queue_guard, because it needs to be locked when we call @@ -195,10 +212,19 @@ void *queue_runner(void *arg) while (1) { pthread_cond_wait(&runner_awake, &queue_guard); - while (last) { + while (last && ! runner_must_stop ) { queue_process_entry(synth); pthread_mutex_lock(&queue_guard); } + + if (runner_must_stop) { + pthread_mutex_lock(&stop_guard); + queue_clear(); + stop_speech(); + runner_must_stop = 0; + pthread_mutex_unlock(&stop_guard); + pthread_cond_signal(&stop_acknowledged); + } } return NULL; diff --git a/softsynth.c b/softsynth.c index f10f000..1a93edb 100644 --- a/softsynth.c +++ b/softsynth.c @@ -173,8 +173,7 @@ void main_loop(struct synth_t *s) *(buf + length) = 0; cp = strrchr(buf, synthFlushChar); if (cp) { - queue_clear(); - stop_speech(); + stop_runner(); memmove(buf, cp + 1, strlen(cp + 1) + 1); length = strlen(buf); }