diff options
Diffstat (limited to 'navit/support/espeak/event.c')
| -rw-r--r-- | navit/support/espeak/event.c | 145 |
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; } } |
