From 5f8e048768a4bec23e5770d7334c29bfb76ed726 Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sun, 08 Mar 2009 05:59:36 +0000 Subject: Fix poping from in_queue --- diff --git a/src/espeak.c b/src/espeak.c index 63c11e6..2457769 100644 --- a/src/espeak.c +++ b/src/espeak.c @@ -29,6 +29,7 @@ #include "espeak.h" #include "text.h" +#include "slist.h" typedef enum { @@ -66,7 +67,8 @@ struct _Econtext Espin *process; Espin *out; - GSList *in_queue; + SList in_queue; + GSList *process_chunk; volatile gint rate; @@ -133,6 +135,8 @@ espeak_new(GstElement *emitter) self->process = self->queue; self->out = self->queue; + slist_new(&self->in_queue); + self->process_chunk = g_slist_alloc(); self->process_chunk->data = self; @@ -142,7 +146,6 @@ espeak_new(GstElement *emitter) self->emitter = emitter; gst_object_ref(self->emitter); - self->bus = NULL; GST_DEBUG("[%p]", self); @@ -168,14 +171,7 @@ espeak_unref(Econtext *self) g_array_free(self->queue[i].events, TRUE); } - if (self->in_queue) - { - GSList *i; - for (i = self->in_queue; i; i = g_slist_next(i)) - text_unref(i->data); - g_slist_free(self->in_queue); - } - + slist_free(&self->in_queue); g_slist_free(self->process_chunk); gst_object_unref(self->bus); @@ -188,20 +184,22 @@ espeak_unref(Econtext *self) // in/out ---------------------------------------------------------------------- static void -in_spinning(Econtext *self, Text *text) +in_spinning(Econtext *self, Espin **spin, Text *text) { GST_DEBUG("[%p] text.body=%s text.offset=%ld text.frame_len=%ld", self, text->body, text->offset, text->frame_len); gboolean chunked = FALSE; - while (!text_eot(text) && g_atomic_int_get(&self->in->state) == IN) + while (!text_eot(text)) { - Espin *spin = self->in; - text_chunk(text, &spin->text, SPIN_FRAME_SIZE); - g_atomic_int_set(&spin->state, PROCESS); - spinning(self->queue, &self->in); + text_chunk(text, &(*spin)->text, SPIN_FRAME_SIZE); + g_atomic_int_set(&(*spin)->state, PROCESS); + spinning(self->queue, spin); chunked = TRUE; + + if (g_atomic_int_get(&(*spin)->state) != IN) + break; } if (chunked) @@ -221,18 +219,19 @@ espeak_in(Econtext *self, const gchar *str_) Text *text = text_new(str_); - if (self->in_queue) + if (g_atomic_int_get(&self->in->state) != IN) { - self->in_queue = g_slist_append(self->in_queue, text); + // in_queue should be not empty at this point + slist_push(&self->in_queue, text); return; } - in_spinning(self, text); + in_spinning(self, &self->in, text); if (!text_eot(text)) { GST_DEBUG("[%p] text_len=%d", self, text_len(text)); - self->in_queue = g_slist_append(self->in_queue, text); + slist_push(&self->in_queue, text); } } @@ -330,7 +329,8 @@ espeak_out(Econtext *self, gsize size_to_play) g_mutex_lock(process_lock); while ((g_atomic_int_get(&self->out->state) & (PLAY|OUT)) == 0) { - if ((self->state & INPROCESS) == 0) + if ((self->state & INPROCESS) == 0 && + slist_empty(&self->in_queue)) { GST_DEBUG("[%p]", self); g_mutex_unlock(process_lock); @@ -344,31 +344,35 @@ espeak_out(Econtext *self, gsize size_to_play) Espin *spin = self->out; gsize spin_size = g_memory_output_stream_get_data_size(spin->sound); - GST_DEBUG("[%p] spin->sound_offset=%ld spin_size=%ld", self, - spin->sound_offset, spin_size); + GST_DEBUG("[%p] spin->sound_offset=%ld spin_size=%ld spin->body=%s", + self, spin->sound_offset, spin_size, + spin->text.body + spin->text.frame_len); if (g_atomic_int_get(&spin->state) == PLAY && spin->sound_offset >= spin_size) { - g_atomic_int_set(&spin->state, IN); text_unref(&spin->text); - spinning(self->queue, &self->out); - if (self->in_queue) + GSList *text_link = slist_pop_link(&self->in_queue); + + if (text_link) { - Text *text = self->in_queue->data; - in_spinning(self, text); + Text *text = text_link->data; + in_spinning(self, &self->out, text); + + GST_DEBUG("[%p] text_eot=%d", self, text_eot(text)); if (text_eot(text)) - { - self->in_queue = g_slist_delete_link(self->in_queue, - self->in_queue); - GST_DEBUG("[%p] in_queue=%d", self, - g_slist_length(self->in_queue)); - } + g_slist_free(text_link); + else + slist_push_link(&self->in_queue, text_link); + } + else + { + GST_DEBUG("[%p]", self); + g_atomic_int_set(&spin->state, IN); + spinning(self->queue, &self->out); } - - GST_DEBUG("[%p]", self); continue; } diff --git a/src/slist.h b/src/slist.h new file mode 100644 index 0000000..f7c7ae9 --- /dev/null +++ b/src/slist.h @@ -0,0 +1,84 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SLIST_H +#define SLIST_H + +typedef struct +{ + GSList *list; + GMutex *lock; +} SList; + +inline void +slist_new(SList *self) +{ + self->list = NULL; + self->lock = g_mutex_new(); +} + +inline void +slist_free(SList *self) +{ + GSList *i; + + for (i = self->list; i; i = g_slist_next(i)) + text_unref(i->data); + + g_slist_free(self->list); + g_mutex_free(self->lock); +} + +inline gboolean +slist_empty(SList *self) +{ + g_mutex_lock(self->lock); + gboolean out = self->list == NULL; + g_mutex_unlock(self->lock); + return out; +} + +inline GSList* +slist_pop_link(SList *self) +{ + GSList *out = NULL; + + g_mutex_lock(self->lock); + out = self->list; + self->list = g_slist_remove_link(self->list, self->list); + g_mutex_unlock(self->lock); + + return out; +} + +inline void +slist_push(SList *self, Text *data) +{ + g_mutex_lock(self->lock); + self->list = g_slist_append(self->list, data); + g_mutex_unlock(self->lock); +} + +inline void +slist_push_link(SList *self, GSList *link) +{ + g_mutex_lock(self->lock); + self->list = g_slist_concat(link, self->list); + g_mutex_unlock(self->lock); +} + +#endif diff --git a/src/text.h b/src/text.h index 0a83985..0e65e18 100644 --- a/src/text.h +++ b/src/text.h @@ -76,9 +76,10 @@ text_chunk(Text *src, Text *dst, gsize len) src->offset += dst->frame_len; src->frame_len -= dst->frame_len; - GST_DEBUG("[%p] len=%ld dst_len=%ld dst_last=%ld " - "src->offset=%ld src->frame_len=%ld", src, len, dst_len, - dst_last-dst->body, src->offset, src->frame_len); + GST_DEBUG("[%p] dst_len=%ld dst_last=%ld " + "src->offset=%ld src->frame_len=%ld dst->body=%s", src, dst_len, + dst_last-dst->body, src->offset, src->frame_len, + dst->body + dst->offset); } inline gchar* -- cgit v0.9.1