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.
This commit is contained in:
William Hubbs 2009-06-27 13:20:43 -05:00
commit 4889572ad1
4 changed files with 39 additions and 8 deletions

34
alsa.c
View file

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

View file

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

View file

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

View file

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