From 4889572ad18a8be877916d131d9a101b6563773c Mon Sep 17 00:00:00 2001 From: William Hubbs Date: Sat, 27 Jun 2009 13:20:43 -0500 Subject: [PATCH] use user_data to detect old events When espeak_Cancel is called, change the value of user_data that is passed to the events, and, in the callback, use this to test to see if cancel was received. If the value of user_data has changed, discarde events that have the old value. This patch is from Chris Brannon. --- alsa.c | 34 +++++++++++++++++++++++++++++----- espeak_sound.c | 7 ++++++- espeakup.h | 3 ++- synth.c | 3 ++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/alsa.c b/alsa.c index ef0a4cf..e1174ac 100644 --- a/alsa.c +++ b/alsa.c @@ -53,20 +53,41 @@ int minimum(int x, int y) static int alsa_callback(short *audio, int numsamples, espeak_EVENT * events) { + static int discarding_packets = 0; + static int user_data_old = 0; int samples_written = 0; int avail; int to_write; snd_pcm_state_t state; + int user_data_new; pthread_mutex_lock(&audio_mutex); + user_data_new = *(int *) events->user_data; if (stop_requested) { snd_pcm_drop(handle); stop_requested = 0; - pthread_mutex_unlock(&audio_mutex); - return 1; + discarding_packets = 1; } + pthread_mutex_unlock(&audio_mutex); + /* + * If discarding_packets is true, then do the following. + * Compare user_data_old and user_data_new. If they are equal, + * then espeak is still sending stale data through the callback. + * Keep on discarding it, and return 1. + * If they are different, a new stream has started. We can stop + * discarding. Just process the new data. + */ + + if (discarding_packets) { + if (user_data_new == user_data_old) + return 1; /* Discard stale data. */ + else + discarding_packets = 0; + } + + user_data_old = user_data_new; snd_pcm_status(handle, status); state = snd_pcm_status_get_state(status); if (state != SND_PCM_STATE_RUNNING) @@ -76,7 +97,7 @@ static int alsa_callback(short *audio, int numsamples, espeak_EVENT * events) avail = snd_pcm_avail_update(handle); if (avail == 0) continue; - if(avail < 0) { + if (avail < 0) { /* Apparently this also can fail on buffer underrun. */ snd_pcm_prepare(handle); continue; @@ -166,9 +187,12 @@ void stop_audio(void) pthread_mutex_unlock(&audio_mutex); } -void allow_audio(void) +void lock_audio_mutex(void) { pthread_mutex_lock(&audio_mutex); - stop_requested = 0; +} + +void unlock_audio_mutex(void) +{ pthread_mutex_unlock(&audio_mutex); } diff --git a/espeak_sound.c b/espeak_sound.c index b20f0e2..6cba147 100644 --- a/espeak_sound.c +++ b/espeak_sound.c @@ -15,7 +15,12 @@ void stop_audio(void) return; } -void allow_audio(void) +void lock_audio_mutex(void) +{ + return; +} + +void unlock_audio_mutex(void) { return; } diff --git a/espeakup.h b/espeakup.h index 37ae8fd..9650bb6 100644 --- a/espeakup.h +++ b/espeakup.h @@ -78,7 +78,8 @@ extern void *softsynth_thread(void *arg); extern void select_audio_mode(void); extern int init_audio(unsigned int rate); extern void stop_audio(void); -extern void allow_audio(void); +extern void lock_audio_mutex(void); +extern void unlock_audio_mutex(void); extern volatile int should_run; extern volatile int runner_must_stop; extern int self_pipe_fds[2]; diff --git a/synth.c b/synth.c index e3dbab5..77e5a5c 100644 --- a/synth.c +++ b/synth.c @@ -130,7 +130,9 @@ static espeak_ERROR stop_speech(void) stop_audio(); rc = espeak_Cancel(); + lock_audio_mutex(); user_data = (user_data + 1) % 100; + unlock_audio_mutex(); return rc; } @@ -138,7 +140,6 @@ static espeak_ERROR speak_text(struct synth_t * s) { espeak_ERROR rc; - allow_audio(); rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, 0, NULL, &user_data); return rc;