summaryrefslogtreecommitdiff
path: root/navit/support/espeak/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'navit/support/espeak/event.c')
-rw-r--r--navit/support/espeak/event.c145
1 files changed, 78 insertions, 67 deletions
diff --git a/navit/support/espeak/event.c b/navit/support/espeak/event.c
index cc696272d..f41c65950 100644
--- a/navit/support/espeak/event.c
+++ b/navit/support/espeak/event.c
@@ -24,7 +24,9 @@
//<includes
+#ifndef PLATFORM_WINDOWS
#include <unistd.h>
+#endif
#include <assert.h>
#include <string.h>
#include <stdlib.h>
@@ -41,20 +43,21 @@
//<decls and function prototypes
-// my_mutex: protects my_thread_is_talking,
+// my_mutex: protects my_thread_is_talking,
static pthread_mutex_t my_mutex;
static sem_t my_sem_start_is_required;
static sem_t my_sem_stop_is_required;
static sem_t my_sem_stop_is_acknowledged;
// my_thread: polls the audio duration and compares it to the duration of the first event.
static pthread_t my_thread;
+static bool thread_inited;
static t_espeak_callback* my_callback = NULL;
static int my_event_is_running=0;
enum {MIN_TIMEOUT_IN_MS=10,
ACTIVITY_TIMEOUT=50, // in ms, check that the stream is active
- MAX_ACTIVITY_CHECK=6
+ MAX_ACTIVITY_CHECK=6
};
@@ -94,17 +97,17 @@ void event_init(void)
assert(-1 != sem_init(&my_sem_stop_is_required, 0, 0));
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0));
- pthread_attr_t a_attrib;
- if (pthread_attr_init (& a_attrib)
- || pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE)
- || pthread_create( &my_thread,
- & a_attrib,
- polling_thread,
- (void*)NULL))
- {
- assert(0);
- }
-
+ pthread_attr_t a_attrib;
+
+ if (pthread_attr_init (&a_attrib) == 0
+ && pthread_attr_setdetachstate(&a_attrib, PTHREAD_CREATE_JOINABLE) == 0)
+ {
+ thread_inited = (0 == pthread_create(&my_thread,
+ &a_attrib,
+ polling_thread,
+ (void*)NULL));
+ }
+ assert(thread_inited);
pthread_attr_destroy(&a_attrib);
}
//>
@@ -127,7 +130,10 @@ ENTER("event_display");
"MARK",
"PLAY",
"END",
- "MSG_TERMINATED"
+ "MSG_TERMINATED",
+ "PHONEME",
+ "SAMPLERATE",
+ "??"
};
SHOW("event_display > event=0x%x\n",event);
@@ -147,17 +153,17 @@ ENTER("event_display");
static espeak_EVENT* event_copy (espeak_EVENT* event)
{
ENTER("event_copy");
-
+
if (event==NULL)
{
return NULL;
}
-
+
espeak_EVENT* a_event=(espeak_EVENT*)malloc(sizeof(espeak_EVENT));
if (a_event)
{
memcpy(a_event, event, sizeof(espeak_EVENT));
-
+
switch(event->type)
{
case espeakEVENT_MARK:
@@ -167,14 +173,14 @@ static espeak_EVENT* event_copy (espeak_EVENT* event)
a_event->id.name = strdup(event->id.name);
}
break;
-
+
default:
break;
}
}
-
+
event_display(a_event);
-
+
return a_event;
}
@@ -288,7 +294,7 @@ ENTER("event_declare");
return EE_INTERNAL_ERROR;
}
- int a_status = pthread_mutex_lock(&my_mutex);
+ int a_status = pthread_mutex_lock(&my_mutex);
espeak_ERROR a_error = EE_OK;
if (!a_status)
@@ -310,7 +316,7 @@ ENTER("event_declare");
//
// if (!a_status && !my_event_is_running && (a_error == EE_OK))
// {
-// // quit when command is actually started
+// // quit when command is actually started
// // (for possible forthcoming 'end of command' checks)
SHOW_TIME("event_declare > post my_sem_start_is_required\n");
sem_post(&my_sem_start_is_required);
@@ -386,28 +392,32 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms)
ENTER("sleep_until_timeout_or_stop_request");
int a_stop_is_required=0;
- struct timespec ts, to;
+ struct timespec ts;
struct timeval tv;
int err=0;
clock_gettime2( &ts);
+
+#ifdef DEBUG_ENABLED
+ struct timespec to;
to.tv_sec = ts.tv_sec;
to.tv_nsec = ts.tv_nsec;
+#endif
add_time_in_ms( &ts, time_in_ms);
- SHOW("polling_thread > sleep_until_timeout_or_stop_request > start sem_timedwait from %d.%09lu to %d.%09lu \n",
+ SHOW("polling_thread > sleep_until_timeout_or_stop_request > start sem_timedwait from %d.%09lu to %d.%09lu \n",
to.tv_sec, to.tv_nsec,
ts.tv_sec, ts.tv_nsec);
- while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1
+ while ((err = sem_timedwait(&my_sem_stop_is_required, &ts)) == -1
&& errno == EINTR)
{
continue; // Restart when interrupted by handler
}
assert (gettimeofday(&tv, NULL) != -1);
- SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n",
+ SHOW("polling_thread > sleep_until_timeout_or_stop_request > stop sem_timedwait %d.%09lu \n",
tv.tv_sec, tv.tv_usec*1000);
if (err == 0)
@@ -421,7 +431,7 @@ ENTER("sleep_until_timeout_or_stop_request");
//>
//<get_remaining_time
// Asked for the time interval required for reaching the sample.
-// If the stream is opened but the audio samples are not played,
+// If the stream is opened but the audio samples are not played,
// a timeout is started.
static int get_remaining_time(uint32_t sample, uint32_t* time_in_ms, int* stop_is_required)
@@ -445,18 +455,18 @@ ENTER("get_remaining_time");
// stream opened but not active
//
- // Several possible states:
- // * the stream is opened but not yet started:
+ // Several possible states:
+ // * the stream is opened but not yet started:
//
// wait for the start of stream
//
- // * some samples have already been played,
+ // * some samples have already been played,
// ** the end of stream is reached
// ** or there is an underrun
- //
+ //
// wait for the close of stream
- *stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT);
+ *stop_is_required = sleep_until_timeout_or_stop_request( ACTIVITY_TIMEOUT);
}
return err;
@@ -496,8 +506,8 @@ ENTER("polling_thread");
SHOW_TIME("polling_thread > unlocked\n");
a_stop_is_required=0;
- a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required);
- if ((a_status==0) && a_stop_is_required)
+ a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1
+ if ((a_status==0) && (a_stop_is_required > 0))
{
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
@@ -510,27 +520,27 @@ ENTER("polling_thread");
}
// In this loop, my_event_is_running = 1
- while (head && !a_stop_is_required)
+ while (head && (a_stop_is_required <= 0))
{
SHOW_TIME("polling_thread > check head\n");
while(0 == sem_trywait(&my_sem_start_is_required))
{
};
-
+
espeak_EVENT* event = (espeak_EVENT*)(head->data);
assert(event);
-
+
uint32_t time_in_ms = 0;
-
- int err = get_remaining_time((uint32_t)event->sample,
- &time_in_ms,
+
+ int err = get_remaining_time((uint32_t)event->sample,
+ &time_in_ms,
&a_stop_is_required);
- if (a_stop_is_required)
+ if (a_stop_is_required > 0)
{
break;
}
else if (err != 0)
- {
+ {
// No available time: the event is deleted.
SHOW("polling_thread > %s\n","audio device down");
a_status = pthread_mutex_lock(&my_mutex);
@@ -544,22 +554,22 @@ ENTER("polling_thread");
if (my_callback)
{
event_notify(event);
- // the user_data (and the type) are cleaned to be sure
+ // the user_data (and the type) are cleaned to be sure
// that MSG_TERMINATED is called twice (at delete time too).
event->type=espeakEVENT_LIST_TERMINATED;
event->user_data=NULL;
}
-
+
a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n");
event_delete( (espeak_EVENT*)pop());
a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");
-
+
a_stop_is_required=0;
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required);
-
- if ((a_status==0) && a_stop_is_required)
+
+ if ((a_status==0) && (a_stop_is_required > 0))
{
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
@@ -576,17 +586,17 @@ ENTER("polling_thread");
a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms);
}
}
-
+
a_status = pthread_mutex_lock(&my_mutex);
SHOW_TIME("polling_thread > locked\n");
-
+
SHOW_TIME("polling_thread > my_event_is_running = 0\n");
my_event_is_running = 0;
-
- if(!a_stop_is_required)
+
+ if(a_stop_is_required <= 0)
{
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required);
- if ((a_status==0) && a_stop_is_required)
+ if ((a_status==0) && (a_stop_is_required > 0))
{
SHOW("polling_thread > stop required (%d)\n", __LINE__);
while(0 == sem_trywait(&my_sem_stop_is_required))
@@ -602,8 +612,8 @@ ENTER("polling_thread");
a_status = pthread_mutex_unlock(&my_mutex);
SHOW_TIME("polling_thread > unlocked\n");
- if (a_stop_is_required)
- {
+ if (a_stop_is_required > 0)
+ {
SHOW("polling_thread > %s\n","stop required!");
// no mutex required since the stop command is synchronous
// and waiting for my_sem_stop_is_acknowledged
@@ -639,13 +649,13 @@ static espeak_ERROR push(void* the_data)
SHOW("event > push > %s\n", "EE_BUFFER_FULL");
return EE_BUFFER_FULL;
}
-
+
node *n = (node *)malloc(sizeof(node));
if (n == NULL)
{
return EE_INTERNAL_ERROR;
}
-
+
if (head == NULL)
{
head = n;
@@ -656,13 +666,13 @@ static espeak_ERROR push(void* the_data)
tail->next = n;
tail = n;
}
-
+
tail->next = NULL;
tail->data = the_data;
-
+
node_counter++;
SHOW("event > push > counter=%d (uid=%d)\n",node_counter,((espeak_EVENT*)the_data)->unique_identifier);
-
+
return EE_OK;
}
@@ -670,9 +680,9 @@ static void* pop()
{
ENTER("event > pop");
void* the_data = NULL;
-
+
assert((!head && !tail) || (head && tail));
-
+
if (head != NULL)
{
node* n = head;
@@ -682,12 +692,12 @@ static void* pop()
node_counter--;
SHOW("event > pop > event=0x%x (counter=%d, uid=%d)\n",the_data, node_counter,((espeak_EVENT*)the_data)->unique_identifier);
}
-
+
if(head == NULL)
{
tail = NULL;
}
-
+
return the_data;
}
@@ -695,10 +705,10 @@ static void* pop()
static void init()
{
ENTER("event > init");
-
+
while (event_delete( (espeak_EVENT*)pop() ))
{}
-
+
node_counter = 0;
}
@@ -707,8 +717,8 @@ static void init()
void event_terminate()
{
ENTER("event_terminate");
-
- if (my_thread)
+
+ if (thread_inited)
{
pthread_cancel(my_thread);
pthread_join(my_thread,NULL);
@@ -717,6 +727,7 @@ ENTER("event_terminate");
sem_destroy(&my_sem_stop_is_required);
sem_destroy(&my_sem_stop_is_acknowledged);
init(); // purge event
+ thread_inited = 0;
}
}