void module_close(int status) { DBG("Espeak: close()."); DBG("Espeak: Terminating threads"); espeak_stop_requested = TRUE; espeak_close_requested =TRUE; pthread_mutex_lock(&playback_queue_mutex); pthread_cond_broadcast(&playback_queue_condition); pthread_mutex_unlock(&playback_queue_mutex); sem_post(espeak_play_semaphore); sem_post(espeak_stop_or_pause_semaphore); /* Give threads a chance to quit on their own terms. */ g_usleep(25000); /* Make sure threads have really exited */ pthread_cancel(espeak_play_thread); pthread_cancel(espeak_stop_or_pause_thread); DBG("Joining play thread."); pthread_join(espeak_play_thread, NULL); DBG("Joinging stop thread."); pthread_join(espeak_stop_or_pause_thread, NULL); DBG("Espeak: terminating synthesis."); espeak_Terminate(); DBG("Espeak: Closing audio output"); if (module_audio_id) { spd_audio_close(module_audio_id); } DBG("Freeing resources."); espeak_clear_playback_queue(); espeak_free_voice_list(); pthread_mutex_destroy(&espeak_state_mutex); pthread_mutex_destroy(&espeak_play_suspended_mutex); pthread_mutex_destroy(&espeak_stop_or_pause_suspended_mutex); pthread_mutex_destroy(&playback_queue_mutex); pthread_cond_destroy(&playback_queue_condition); sem_destroy(espeak_play_semaphore); sem_destroy(espeak_stop_or_pause_semaphore); exit(status); }
/* Stop or Pause thread. */ static void *_espeak_stop_or_pause(void *nothing) { int ret; log_msg(OTTS_LOG_INFO, "Espeak: Stop or pause thread starting......."); /* Block all signals to this thread. */ set_speaking_thread_parameters(); while (!espeak_close_requested) { /* If semaphore not set, set suspended lock and suspend until it is signaled. */ if (0 != sem_trywait(espeak_stop_or_pause_semaphore)) { pthread_mutex_lock (&espeak_stop_or_pause_suspended_mutex); sem_wait(espeak_stop_or_pause_semaphore); pthread_mutex_unlock (&espeak_stop_or_pause_suspended_mutex); } log_msg(OTTS_LOG_INFO, "Espeak: Stop or pause semaphore on."); if (espeak_close_requested) break; if (!espeak_stop_requested) { /* This sometimes happens after wake-up from suspend-to-disk. */ log_msg(OTTS_LOG_WARN, "Espeak: Warning: spurious wake-up of stop thread."); continue; } pthread_mutex_lock(&playback_queue_mutex); pthread_cond_broadcast(&playback_queue_condition); pthread_mutex_unlock(&playback_queue_mutex); if (module_audio_id) { log_msg(OTTS_LOG_WARN, "Espeak: Stopping audio."); ret = opentts_audio_stop(module_audio_id); DBG_WARN(ret == 0, "spd_audio_stop returned non-zero value."); while (is_thread_busy(&espeak_play_suspended_mutex)) { ret = opentts_audio_stop(module_audio_id); DBG_WARN(ret == 0, "spd_audio_stop returned non-zero value."); g_usleep(5000); } } else { while (is_thread_busy(&espeak_play_suspended_mutex)) { g_usleep(5000); } } log_msg(OTTS_LOG_INFO, "Espeak: Waiting for synthesis to stop."); ret = espeak_Cancel(); DBG_WARN(ret == EE_OK, "Espeak: error in espeak_Cancel()."); log_msg(OTTS_LOG_DEBUG, "Espeak: Clearing playback queue."); espeak_clear_playback_queue(); int save_pause_state = espeak_pause_state; pthread_mutex_lock(&espeak_state_mutex); espeak_state_reset(); pthread_mutex_unlock(&espeak_state_mutex); if (save_pause_state == ESPEAK_PAUSE_MARK_REPORTED) { module_report_event_pause(); } else { module_report_event_stop(); } log_msg(OTTS_LOG_INFO, "Espeak: Stop or pause thread ended.......\n"); } pthread_exit(NULL); }