1 /*
2  * module_utils_speak_queue.c - Speak queue helper for Speech Dispatcher modules
3  *
4  * Copyright (C) 2007 Brailcom, o.p.s.
5  * Copyright (C) 2019-2020 Samuel Thibault <samuel.thibault@ens-lyon.org>
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  * Based on espeak.c
21  *
22  * @author Lukas Loehrer
23  * Based on ibmtts.c.
24  */
25 
26 #include "module_utils_speak_queue.h"
27 
28 #define DBG_MODNAME "speak_queue"
29 
30 #include "module_utils.h"
31 
32 typedef enum {
33 	IDLE,
34 	BEFORE_SYNTH,
35 	BEFORE_PLAY,
36 	SPEAKING
37 } speak_queue_state_t;
38 
39 typedef enum {
40 	SPEAK_QUEUE_PAUSE_OFF,
41 	SPEAK_QUEUE_PAUSE_REQUESTED,
42 	SPEAK_QUEUE_PAUSE_MARK_REPORTED
43 } speak_queue_pause_state_t;
44 
45 /* Thread and process control. */
46 /* Global mutex for the whole speak queue mechanism */
47 static pthread_mutex_t speak_queue_mutex;
48 
49 static speak_queue_state_t speak_queue_state = IDLE;
50 static gboolean speak_queue_configured = FALSE; /* Whether we have configured audio */
51 
52 static pthread_t speak_queue_play_thread;
53 static pthread_t speak_queue_stop_or_pause_thread;
54 
55 /* Used to wake the stop_or_pause thread from main */
56 static pthread_cond_t speak_queue_stop_or_pause_cond;
57 
58 static pthread_cond_t speak_queue_stop_or_pause_sleeping_cond;
59 static int speak_queue_stop_or_pause_sleeping;
60 
61 /* Used to wake the play thread from main */
62 static pthread_cond_t speak_queue_play_cond;
63 /* Used to wait for the play thread to go sleeping */
64 static pthread_cond_t speak_queue_play_sleeping_cond;
65 static int speak_queue_play_sleeping;
66 
67 static gboolean speak_queue_close_requested = FALSE;
68 static speak_queue_pause_state_t speak_queue_pause_state = SPEAK_QUEUE_PAUSE_OFF;
69 static gboolean speak_queue_stop_requested = FALSE;
70 
71 static void module_speak_queue_reset(void);
72 
73 /* The playback queue. */
74 
75 static int speak_queue_maxsize;
76 
77 typedef enum {
78 	SPEAK_QUEUE_QET_AUDIO,	/* Chunk of audio. */
79 	SPEAK_QUEUE_QET_INDEX_MARK,	/* Index mark event. */
80 	SPEAK_QUEUE_QET_SOUND_ICON,	/* A Sound Icon */
81 	SPEAK_QUEUE_QET_BEGIN,	/* Beginning of speech. */
82 	SPEAK_QUEUE_QET_END		/* Speech completed. */
83 } speak_queue_entry_type;
84 
85 typedef struct {
86 	AudioTrack track;
87 	AudioFormat format;
88 } speak_queue_audio_chunk;
89 
90 typedef struct {
91 	speak_queue_entry_type type;
92 	union {
93 		char *markId;
94 		speak_queue_audio_chunk audio;
95 		char *sound_icon_filename;
96 	} data;
97 } speak_queue_entry;
98 
99 static GSList *playback_queue = NULL;
100 static int playback_queue_size = 0;	/* Number of audio frames currently in queue */
101 
102 /* Use to wait for queue room availability. Theoretically several threads might
103  * be wanting to push, so use broadcast. */
104 static pthread_cond_t playback_queue_room_condition;
105 /* Use to wait for queue data availability */
106 static pthread_cond_t playback_queue_data_condition;
107 
108 /* Internal function prototypes for playback thread. */
109 static gboolean speak_queue_add_flag_to_playback_queue(speak_queue_entry_type type);
110 static void speak_queue_delete_playback_queue_entry(speak_queue_entry *
111 					       playback_queue_entry);
112 static gboolean speak_queue_send_to_audio(speak_queue_entry *
113 				     playback_queue_entry);
114 
115 /* Miscellaneous internal function prototypes. */
116 static void speak_queue_clear_playback_queue();
117 
118 /* The playback thread start routine. */
119 static void *speak_queue_play(void *);
120 /* The stop_or_pause start routine. */
121 static void *speak_queue_stop_or_pause(void *);
122 
module_speak_queue_init(int maxsize,char ** status_info)123 int module_speak_queue_init(int maxsize, char **status_info)
124 {
125 	int ret;
126 
127 	speak_queue_maxsize = maxsize;
128 
129 	/* Reset global state */
130 	module_speak_queue_reset();
131 
132 	/* This mutex mediates all accesses */
133 	pthread_mutex_init(&speak_queue_mutex, NULL);
134 
135 	pthread_cond_init(&playback_queue_room_condition, NULL);
136 	pthread_cond_init(&playback_queue_data_condition, NULL);
137 
138 	DBG(DBG_MODNAME " Creating new thread for stop or pause.");
139 	pthread_cond_init(&speak_queue_stop_or_pause_cond, NULL);
140 	pthread_cond_init(&speak_queue_stop_or_pause_sleeping_cond, NULL);
141 	speak_queue_stop_or_pause_sleeping = 0;
142 
143 	ret =
144 	    pthread_create(&speak_queue_stop_or_pause_thread, NULL,
145 			   speak_queue_stop_or_pause, NULL);
146 	if (0 != ret) {
147 		DBG("Failed to create stop-or-pause thread.");
148 		*status_info =
149 		    g_strdup("Failed to create stop-or-pause thread.");
150 		return -1;
151 	}
152 
153 	pthread_cond_init(&speak_queue_play_cond, NULL);
154 	pthread_cond_init(&speak_queue_play_sleeping_cond, NULL);
155 	speak_queue_play_sleeping = 0;
156 
157 	DBG(DBG_MODNAME " Creating new thread for playback.");
158 	ret = pthread_create(&speak_queue_play_thread, NULL, speak_queue_play, NULL);
159 	if (ret != 0) {
160 		DBG("Failed to create playback thread.");
161 		*status_info = g_strdup("Failed to create playback thread.");
162 		return -1;
163 	}
164 
165 	return 0;
166 }
167 
module_speak_queue_reset(void)168 void module_speak_queue_reset(void)
169 {
170 	speak_queue_state = IDLE;
171 	speak_queue_pause_state = SPEAK_QUEUE_PAUSE_OFF;
172 	speak_queue_stop_requested = FALSE;
173 }
174 
module_speak_queue_before_synth(void)175 int module_speak_queue_before_synth(void)
176 {
177 	pthread_mutex_lock(&speak_queue_mutex);
178 	if (speak_queue_state != IDLE) {
179 		DBG(DBG_MODNAME " Warning, module_speak called when not ready.");
180 		pthread_mutex_unlock(&speak_queue_mutex);
181 		return FALSE;
182 	}
183 
184 	module_speak_queue_reset();
185 	speak_queue_state = BEFORE_SYNTH;
186 	pthread_mutex_unlock(&speak_queue_mutex);
187 	return TRUE;
188 }
189 
module_speak_queue_before_play(void)190 int module_speak_queue_before_play(void)
191 {
192 	int ret = 0;
193 	pthread_mutex_lock(&speak_queue_mutex);
194 	if (speak_queue_state == BEFORE_SYNTH) {
195 		ret = 1;
196 		speak_queue_state = BEFORE_PLAY;
197 		speak_queue_add_flag_to_playback_queue(SPEAK_QUEUE_QET_BEGIN);
198 		/* Wake up playback thread */
199 		pthread_cond_signal(&speak_queue_play_cond);
200 	}
201 	pthread_mutex_unlock(&speak_queue_mutex);
202 	return ret;
203 }
204 
module_speak_queue_add_end(void)205 gboolean module_speak_queue_add_end(void)
206 {
207 	pthread_mutex_lock(&speak_queue_mutex);
208 	gboolean ret = speak_queue_add_flag_to_playback_queue(SPEAK_QUEUE_QET_END);
209 	pthread_mutex_unlock(&speak_queue_mutex);
210 	return ret;
211 }
212 
playback_queue_pop()213 static speak_queue_entry *playback_queue_pop()
214 {
215 	speak_queue_entry *result = NULL;
216 	pthread_mutex_lock(&speak_queue_mutex);
217 	while (!speak_queue_stop_requested && playback_queue == NULL) {
218 		pthread_cond_wait(&playback_queue_data_condition,
219 				  &speak_queue_mutex);
220 	}
221 	if (!speak_queue_stop_requested) {
222 		result = (speak_queue_entry *) playback_queue->data;
223 		playback_queue =
224 		    g_slist_remove(playback_queue, playback_queue->data);
225 		if (result->type == SPEAK_QUEUE_QET_AUDIO) {
226 			playback_queue_size -= result->data.audio.track.num_samples;
227 			pthread_cond_broadcast(&playback_queue_room_condition);
228 		}
229 	}
230 	pthread_mutex_unlock(&speak_queue_mutex);
231 	return result;
232 }
233 
playback_queue_push(speak_queue_entry * entry)234 static gboolean playback_queue_push(speak_queue_entry * entry)
235 {
236 	playback_queue = g_slist_append(playback_queue, entry);
237 	if (entry->type == SPEAK_QUEUE_QET_AUDIO) {
238 		playback_queue_size += entry->data.audio.track.num_samples;
239 	}
240 	pthread_cond_signal(&playback_queue_data_condition);
241 	return TRUE;
242 }
243 
244 /* Adds a chunk of pcm audio to the audio playback queue.
245    Waits until there is enough space in the queue. */
246 gboolean
module_speak_queue_add_audio(const AudioTrack * track,AudioFormat format)247 module_speak_queue_add_audio(const AudioTrack *track, AudioFormat format)
248 {
249 	pthread_mutex_lock(&speak_queue_mutex);
250 	while (playback_queue_size > speak_queue_maxsize) {
251 		if (speak_queue_state == IDLE || speak_queue_stop_requested) {
252 			pthread_mutex_unlock(&speak_queue_mutex);
253 			return FALSE;
254 		}
255 		pthread_cond_wait(&playback_queue_room_condition,
256 				  &speak_queue_mutex);
257 	}
258 	if (speak_queue_state == IDLE || speak_queue_stop_requested) {
259 		pthread_mutex_unlock(&speak_queue_mutex);
260 		return FALSE;
261 	}
262 
263 	speak_queue_entry *playback_queue_entry =
264 	    g_new(speak_queue_entry, 1);
265 
266 	playback_queue_entry->type = SPEAK_QUEUE_QET_AUDIO;
267 	playback_queue_entry->data.audio.track = *track;
268 	gint nbytes = track->bits / 8 * track->num_samples;
269 	playback_queue_entry->data.audio.track.samples = g_memdup(track->samples, nbytes);
270 	playback_queue_entry->data.audio.format = format;
271 
272 	playback_queue_push(playback_queue_entry);
273 	pthread_mutex_unlock(&speak_queue_mutex);
274 	return TRUE;
275 }
276 
277 /* Adds an Index Mark to the audio playback queue. */
module_speak_queue_add_mark(const char * markId)278 gboolean module_speak_queue_add_mark(const char *markId)
279 {
280 	speak_queue_entry *playback_queue_entry =
281 	    (speak_queue_entry *) g_malloc(sizeof(speak_queue_entry));
282 
283 	playback_queue_entry->type = SPEAK_QUEUE_QET_INDEX_MARK;
284 	playback_queue_entry->data.markId = g_strdup(markId);
285 	pthread_mutex_lock(&speak_queue_mutex);
286 	gboolean ret = playback_queue_push(playback_queue_entry);
287 	pthread_mutex_unlock(&speak_queue_mutex);
288 	return ret;
289 }
290 
291 /* Adds a begin or end flag to the playback queue. */
speak_queue_add_flag_to_playback_queue(speak_queue_entry_type type)292 static gboolean speak_queue_add_flag_to_playback_queue(speak_queue_entry_type type)
293 {
294 	speak_queue_entry *playback_queue_entry =
295 	    (speak_queue_entry *) g_malloc(sizeof(speak_queue_entry));
296 
297 	playback_queue_entry->type = type;
298 	return playback_queue_push(playback_queue_entry);
299 }
300 
301 /* Add a sound icon to the playback queue. */
module_speak_queue_add_sound_icon(const char * filename)302 gboolean module_speak_queue_add_sound_icon(const char *filename)
303 {
304 	speak_queue_entry *playback_queue_entry =
305 	    (speak_queue_entry *) g_malloc(sizeof(speak_queue_entry));
306 
307 	playback_queue_entry->type = SPEAK_QUEUE_QET_SOUND_ICON;
308 	playback_queue_entry->data.sound_icon_filename = g_strdup(filename);
309 	pthread_mutex_lock(&speak_queue_mutex);
310 	gboolean ret = playback_queue_push(playback_queue_entry);
311 	pthread_mutex_unlock(&speak_queue_mutex);
312 	return ret;
313 }
314 
315 /* Deletes an entry from the playback audio queue, freeing memory. */
316 static void
speak_queue_delete_playback_queue_entry(speak_queue_entry * playback_queue_entry)317 speak_queue_delete_playback_queue_entry(speak_queue_entry * playback_queue_entry)
318 {
319 	switch (playback_queue_entry->type) {
320 	case SPEAK_QUEUE_QET_AUDIO:
321 		g_free(playback_queue_entry->data.audio.track.samples);
322 		break;
323 	case SPEAK_QUEUE_QET_INDEX_MARK:
324 		g_free(playback_queue_entry->data.markId);
325 		break;
326 	case SPEAK_QUEUE_QET_SOUND_ICON:
327 		g_free(playback_queue_entry->data.sound_icon_filename);
328 		break;
329 	default:
330 		break;
331 	}
332 	g_free(playback_queue_entry);
333 }
334 
335 /* Erases the entire playback queue, freeing memory. */
speak_queue_clear_playback_queue()336 static void speak_queue_clear_playback_queue()
337 {
338 	pthread_mutex_lock(&speak_queue_mutex);
339 
340 	while (NULL != playback_queue) {
341 		speak_queue_entry *playback_queue_entry =
342 		    playback_queue->data;
343 		speak_queue_delete_playback_queue_entry(playback_queue_entry);
344 		playback_queue =
345 		    g_slist_remove(playback_queue, playback_queue->data);
346 	}
347 	playback_queue = NULL;
348 	playback_queue_size = 0;
349 	pthread_cond_broadcast(&playback_queue_room_condition);
350 	pthread_mutex_unlock(&speak_queue_mutex);
351 }
352 
353 /* Sends a chunk of audio to the audio player and waits for completion or error. */
speak_queue_send_to_audio(speak_queue_entry * playback_queue_entry)354 static gboolean speak_queue_send_to_audio(speak_queue_entry * playback_queue_entry)
355 {
356 	int ret = 0;
357 	DBG(DBG_MODNAME " Sending %i samples to audio.",
358 	    playback_queue_entry->data.audio.track.num_samples);
359 	if (!speak_queue_configured)
360 	{
361 		spd_audio_begin(module_audio_id,
362 				playback_queue_entry->data.audio.track,
363 				playback_queue_entry->data.audio.format);
364 		speak_queue_configured = TRUE;
365 	}
366 	ret = spd_audio_feed_sync_overlap(module_audio_id,
367 			     playback_queue_entry->data.audio.track,
368 			     playback_queue_entry->data.audio.format);
369 	if (ret < 0) {
370 		DBG("ERROR: Can't play track for unknown reason.");
371 		return FALSE;
372 	}
373 	DBG(DBG_MODNAME " Sent to audio.");
374 	return TRUE;
375 }
376 
377 /* Playback thread. */
speak_queue_play(void * nothing)378 static void *speak_queue_play(void *nothing)
379 {
380 	char *markId;
381 	speak_queue_entry *playback_queue_entry = NULL;
382 
383 	DBG(DBG_MODNAME " Playback thread starting.......");
384 
385 	/* Block all signals to this thread. */
386 	set_speaking_thread_parameters();
387 
388 	pthread_mutex_lock(&speak_queue_mutex);
389 	while (!speak_queue_close_requested) {
390 		speak_queue_play_sleeping = 1;
391 		pthread_cond_signal(&speak_queue_play_sleeping_cond);
392 		while (speak_queue_state < BEFORE_PLAY && !speak_queue_close_requested) {
393 			pthread_cond_wait(&speak_queue_play_cond, &speak_queue_mutex);
394 		}
395 		speak_queue_play_sleeping = 0;
396 		pthread_cond_signal(&speak_queue_play_sleeping_cond);
397 		DBG(DBG_MODNAME " Playback.");
398 		if (speak_queue_close_requested)
399 			break;
400 		pthread_mutex_unlock(&speak_queue_mutex);
401 
402 		while (1) {
403 			gboolean finished = FALSE;
404 			playback_queue_entry = playback_queue_pop();
405 			if (playback_queue_entry == NULL) {
406 				DBG(DBG_MODNAME " playback thread detected stop.");
407 				break;
408 			}
409 
410 			switch (playback_queue_entry->type) {
411 			case SPEAK_QUEUE_QET_AUDIO:
412 				speak_queue_send_to_audio(playback_queue_entry);
413 				break;
414 			case SPEAK_QUEUE_QET_INDEX_MARK:
415 				markId = playback_queue_entry->data.markId;
416 				DBG(DBG_MODNAME " reporting index mark |%s|.",
417 				    markId);
418 				module_report_index_mark(markId);
419 				DBG(DBG_MODNAME " index mark reported.");
420 				pthread_mutex_lock(&speak_queue_mutex);
421 				if (speak_queue_state == SPEAKING
422 				    && speak_queue_pause_state ==
423 				    SPEAK_QUEUE_PAUSE_REQUESTED
424 				    && speak_queue_stop_or_pause_sleeping
425 				    && g_str_has_prefix(markId, "__spd_")) {
426 					DBG(DBG_MODNAME " Pause requested in playback thread.  Stopping.");
427 					speak_queue_stop_requested = TRUE;
428 					speak_queue_pause_state =
429 					    SPEAK_QUEUE_PAUSE_MARK_REPORTED;
430 					pthread_cond_signal
431 					    (&speak_queue_stop_or_pause_cond);
432 					finished = TRUE;
433 				}
434 				pthread_mutex_unlock(&speak_queue_mutex);
435 				break;
436 			case SPEAK_QUEUE_QET_SOUND_ICON:
437 				if (speak_queue_configured) {
438 					spd_audio_end(module_audio_id);
439 					speak_queue_configured = FALSE;
440 				}
441 				module_play_file(playback_queue_entry->
442 						 data.sound_icon_filename);
443 				break;
444 			case SPEAK_QUEUE_QET_BEGIN:{
445 					gboolean report_begin = FALSE;
446 					pthread_mutex_lock(&speak_queue_mutex);
447 					if (speak_queue_state == BEFORE_PLAY) {
448 						speak_queue_state = SPEAKING;
449 						report_begin = TRUE;
450 					}
451 					pthread_mutex_unlock
452 					    (&speak_queue_mutex);
453 					if (report_begin)
454 						module_report_event_begin();
455 					break;
456 				}
457 			case SPEAK_QUEUE_QET_END:
458 				if (speak_queue_configured) {
459 					spd_audio_end(module_audio_id);
460 					speak_queue_configured = FALSE;
461 				}
462 				pthread_mutex_lock(&speak_queue_mutex);
463 				DBG(DBG_MODNAME " playback thread got END from queue.");
464 				if (speak_queue_state == SPEAKING) {
465 					if (!speak_queue_stop_requested) {
466 						DBG(DBG_MODNAME " playback thread reporting end.");
467 						speak_queue_state = IDLE;
468 						speak_queue_pause_state =
469 						    SPEAK_QUEUE_PAUSE_OFF;
470 					}
471 					finished = TRUE;
472 				}
473 				pthread_mutex_unlock(&speak_queue_mutex);
474 				if (finished)
475 					module_report_event_end();
476 				break;
477 			}
478 
479 			speak_queue_delete_playback_queue_entry
480 			    (playback_queue_entry);
481 			if (finished)
482 				break;
483 		}
484 		if (speak_queue_configured) {
485 			spd_audio_end(module_audio_id);
486 			speak_queue_configured = FALSE;
487 		}
488 		pthread_mutex_lock(&speak_queue_mutex);
489 	}
490 	speak_queue_play_sleeping = 1;
491 	pthread_mutex_unlock(&speak_queue_mutex);
492 	DBG(DBG_MODNAME " Playback thread ended.......");
493 	return 0;
494 }
495 
module_speak_queue_stop_requested(void)496 int module_speak_queue_stop_requested(void)
497 {
498 	return speak_queue_stop_requested;
499 }
500 
module_speak_queue_stop(void)501 void module_speak_queue_stop(void)
502 {
503 	pthread_mutex_lock(&speak_queue_mutex);
504 	if (speak_queue_state != IDLE &&
505 	    !speak_queue_stop_requested &&
506 	    speak_queue_stop_or_pause_sleeping) {
507 		DBG(DBG_MODNAME " stopping...");
508 		speak_queue_stop_requested = TRUE;
509 		/* Wake the stop_or_pause thread. */
510 		pthread_cond_signal(&speak_queue_stop_or_pause_cond);
511 	} else {
512 		DBG(DBG_MODNAME " Cannot stop now.");
513 	}
514 	pthread_mutex_unlock(&speak_queue_mutex);
515 }
516 
module_speak_queue_pause(void)517 void module_speak_queue_pause(void)
518 {
519 	pthread_mutex_lock(&speak_queue_mutex);
520 	if (speak_queue_pause_state == SPEAK_QUEUE_PAUSE_OFF && !speak_queue_stop_requested) {
521 		speak_queue_pause_state = SPEAK_QUEUE_PAUSE_REQUESTED;
522 	}
523 	pthread_mutex_unlock(&speak_queue_mutex);
524 }
525 
module_speak_queue_terminate(void)526 void module_speak_queue_terminate(void)
527 {
528 	pthread_mutex_lock(&speak_queue_mutex);
529 	speak_queue_stop_requested = TRUE;
530 	speak_queue_close_requested = TRUE;
531 
532 	pthread_cond_broadcast(&playback_queue_room_condition);
533 	pthread_cond_signal(&playback_queue_data_condition);
534 
535 	pthread_cond_signal(&speak_queue_play_cond);
536 	pthread_cond_signal(&speak_queue_stop_or_pause_cond);
537 	pthread_mutex_unlock(&speak_queue_mutex);
538 
539 	DBG(DBG_MODNAME " Joining play thread.");
540 	pthread_join(speak_queue_play_thread, NULL);
541 	DBG(DBG_MODNAME " Joining stop thread.");
542 	pthread_join(speak_queue_stop_or_pause_thread, NULL);
543 }
544 
module_speak_queue_free(void)545 void module_speak_queue_free(void)
546 {
547 	DBG(DBG_MODNAME " Freeing resources.");
548 	speak_queue_clear_playback_queue();
549 
550 	pthread_mutex_destroy(&speak_queue_mutex);
551 	pthread_cond_destroy(&playback_queue_room_condition);
552 	pthread_cond_destroy(&playback_queue_data_condition);
553 	pthread_cond_destroy(&speak_queue_play_cond);
554 	pthread_cond_destroy(&speak_queue_play_sleeping_cond);
555 	pthread_cond_destroy(&speak_queue_stop_or_pause_cond);
556 	pthread_cond_destroy(&speak_queue_stop_or_pause_sleeping_cond);
557 }
558 
559 /* Stop or Pause thread. */
speak_queue_stop_or_pause(void * nothing)560 static void *speak_queue_stop_or_pause(void *nothing)
561 {
562 	int ret;
563 
564 	DBG(DBG_MODNAME " Stop or pause thread starting.......");
565 
566 	/* Block all signals to this thread. */
567 	set_speaking_thread_parameters();
568 
569 	pthread_mutex_lock(&speak_queue_mutex);
570 	while (!speak_queue_close_requested) {
571 		speak_queue_stop_or_pause_sleeping = 1;
572 		pthread_cond_signal(&speak_queue_stop_or_pause_sleeping_cond);
573 		while (!speak_queue_stop_requested)
574 			pthread_cond_wait(&speak_queue_stop_or_pause_cond, &speak_queue_mutex);
575 		speak_queue_stop_or_pause_sleeping = 0;
576 		pthread_cond_signal(&speak_queue_stop_or_pause_sleeping_cond);
577 
578 		DBG(DBG_MODNAME " Stop or pause.");
579 		if (speak_queue_close_requested)
580 			break;
581 
582 		pthread_cond_signal(&playback_queue_data_condition);
583 		pthread_cond_broadcast(&playback_queue_room_condition);
584 		pthread_mutex_unlock(&speak_queue_mutex);
585 
586 		if (module_audio_id) {
587 			pthread_mutex_lock(&speak_queue_mutex);
588 			speak_queue_state = IDLE;
589 			pthread_mutex_unlock(&speak_queue_mutex);
590 			DBG(DBG_MODNAME " Stopping audio.");
591 			ret = spd_audio_stop(module_audio_id);
592 			if (ret != 0)
593 				DBG("spd_audio_stop returned non-zero value.");
594 			pthread_mutex_lock(&speak_queue_mutex);
595 			while (!speak_queue_play_sleeping) {
596 				ret = spd_audio_stop(module_audio_id);
597 				if (ret != 0)
598 					DBG("spd_audio_stop returned non-zero value.");
599 				pthread_mutex_unlock(&speak_queue_mutex);
600 				g_usleep(5000);
601 				pthread_mutex_lock(&speak_queue_mutex);
602 			}
603 			pthread_mutex_unlock(&speak_queue_mutex);
604 		} else {
605 			pthread_mutex_lock(&speak_queue_mutex);
606 			while (!speak_queue_play_sleeping)
607 				pthread_cond_wait(&speak_queue_play_sleeping_cond, &speak_queue_mutex);
608 			pthread_mutex_unlock(&speak_queue_mutex);
609 		}
610 
611 		DBG(DBG_MODNAME " Waiting for synthesis to stop.");
612 
613 		module_speak_queue_cancel();
614 
615 		DBG(DBG_MODNAME " Clearing playback queue.");
616 		speak_queue_clear_playback_queue();
617 
618 		int save_pause_state = speak_queue_pause_state;
619 		pthread_mutex_lock(&speak_queue_mutex);
620 		module_speak_queue_reset();
621 		pthread_mutex_unlock(&speak_queue_mutex);
622 
623 		if (save_pause_state == SPEAK_QUEUE_PAUSE_MARK_REPORTED) {
624 			module_report_event_pause();
625 		} else {
626 			module_report_event_stop();
627 		}
628 
629 		DBG(DBG_MODNAME " Stop or pause thread ended.......\n");
630 		pthread_mutex_lock(&speak_queue_mutex);
631 	}
632 	pthread_mutex_unlock(&speak_queue_mutex);
633 	pthread_exit(NULL);
634 }
635