mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-11 00:26:08 +00:00
Merge remote-tracking branch 'ragb/feature/osxBuild'
This commit is contained in:
+40
-47
@@ -23,7 +23,6 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@@ -39,9 +38,12 @@
|
||||
|
||||
// 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;
|
||||
static pthread_cond_t my_cond_start_is_required;
|
||||
static int my_start_is_required = 0;
|
||||
static pthread_cond_t my_cond_stop_is_required;
|
||||
static int my_stop_is_required = 0;
|
||||
static pthread_cond_t my_cond_stop_is_acknowledged;
|
||||
static int my_stop_is_acknowledged = 0;
|
||||
// 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;
|
||||
@@ -81,9 +83,9 @@ void event_init(void)
|
||||
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL);
|
||||
init();
|
||||
|
||||
assert(-1 != sem_init(&my_sem_start_is_required, 0, 0));
|
||||
assert(-1 != sem_init(&my_sem_stop_is_required, 0, 0));
|
||||
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0));
|
||||
assert(-1 != pthread_cond_init(&my_cond_start_is_required, NULL));
|
||||
assert(-1 != pthread_cond_init(&my_cond_stop_is_required, NULL));
|
||||
assert(-1 != pthread_cond_init(&my_cond_stop_is_acknowledged, NULL));
|
||||
|
||||
pthread_attr_t a_attrib;
|
||||
|
||||
@@ -203,7 +205,7 @@ espeak_ng_STATUS event_declare(espeak_EVENT *event)
|
||||
|
||||
espeak_ng_STATUS status;
|
||||
if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) {
|
||||
sem_post(&my_sem_start_is_required);
|
||||
my_start_is_required = 1;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -211,10 +213,12 @@ espeak_ng_STATUS event_declare(espeak_EVENT *event)
|
||||
if ((status = push(a_event)) != ENS_OK) {
|
||||
event_delete(a_event);
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
} else
|
||||
} else {
|
||||
my_start_is_required = 1;
|
||||
pthread_cond_signal(&my_cond_start_is_required);
|
||||
status = pthread_mutex_unlock(&my_mutex);
|
||||
}
|
||||
|
||||
sem_post(&my_sem_start_is_required);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -227,7 +231,8 @@ espeak_ng_STATUS event_clear_all()
|
||||
|
||||
int a_event_is_running = 0;
|
||||
if (my_event_is_running) {
|
||||
sem_post(&my_sem_stop_is_required);
|
||||
my_stop_is_required = 1;
|
||||
pthread_cond_signal(&my_cond_stop_is_required);
|
||||
a_event_is_running = 1;
|
||||
} else
|
||||
init(); // clear pending events
|
||||
@@ -236,7 +241,8 @@ espeak_ng_STATUS event_clear_all()
|
||||
return status;
|
||||
|
||||
if (a_event_is_running) {
|
||||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
|
||||
while(my_stop_is_acknowledged == 0)
|
||||
while((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
}
|
||||
|
||||
@@ -252,27 +258,19 @@ static void *polling_thread(void *p)
|
||||
|
||||
int a_status = pthread_mutex_lock(&my_mutex);
|
||||
my_event_is_running = 0;
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
|
||||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR)
|
||||
while(my_start_is_required == 0)
|
||||
while((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
|
||||
a_status = pthread_mutex_lock(&my_mutex);
|
||||
my_event_is_running = 1;
|
||||
a_stop_is_required = 0;
|
||||
my_start_is_required = 0;
|
||||
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
|
||||
a_stop_is_required = 0;
|
||||
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)) {
|
||||
while (0 == sem_trywait(&my_sem_stop_is_required))
|
||||
;
|
||||
} else
|
||||
a_stop_is_required = 0;
|
||||
|
||||
// In this loop, my_event_is_running = 1
|
||||
while (head && (a_stop_is_required <= 0)) {
|
||||
while (0 == sem_trywait(&my_sem_start_is_required))
|
||||
;
|
||||
while (head && (a_stop_is_required == 0)) {
|
||||
|
||||
espeak_EVENT *event = (espeak_EVENT *)(head->data);
|
||||
assert(event);
|
||||
@@ -287,40 +285,35 @@ static void *polling_thread(void *p)
|
||||
|
||||
a_status = pthread_mutex_lock(&my_mutex);
|
||||
event_delete((espeak_EVENT *)pop());
|
||||
a_stop_is_required = my_stop_is_required;
|
||||
if(a_stop_is_required > 0)
|
||||
my_stop_is_required = 0;
|
||||
|
||||
a_status = pthread_mutex_unlock(&my_mutex);
|
||||
|
||||
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 > 0)) {
|
||||
while (0 == sem_trywait(&my_sem_stop_is_required))
|
||||
;
|
||||
} else
|
||||
a_stop_is_required = 0;
|
||||
}
|
||||
|
||||
a_status = pthread_mutex_lock(&my_mutex);
|
||||
|
||||
my_event_is_running = 0;
|
||||
|
||||
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 > 0)) {
|
||||
while (0 == sem_trywait(&my_sem_stop_is_required))
|
||||
;
|
||||
} else
|
||||
a_stop_is_required = 0;
|
||||
if (a_stop_is_required == 0) {
|
||||
a_stop_is_required = my_stop_is_required;
|
||||
if (a_stop_is_required > 0)
|
||||
my_stop_is_required = 0;
|
||||
}
|
||||
|
||||
a_status = pthread_mutex_unlock(&my_mutex);
|
||||
|
||||
if (a_stop_is_required > 0) {
|
||||
// no mutex required since the stop command is synchronous
|
||||
// and waiting for my_sem_stop_is_acknowledged
|
||||
// and waiting for my_cond_stop_is_acknowledged
|
||||
init();
|
||||
|
||||
// acknowledge the stop request
|
||||
a_status = sem_post(&my_sem_stop_is_acknowledged);
|
||||
espeak_ng_STATUS a_status = pthread_mutex_lock(&my_mutex);
|
||||
my_stop_is_acknowledged = 1;
|
||||
a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged);
|
||||
a_status = pthread_mutex_unlock(&my_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,9 +387,9 @@ void event_terminate()
|
||||
pthread_cancel(my_thread);
|
||||
pthread_join(my_thread, NULL);
|
||||
pthread_mutex_destroy(&my_mutex);
|
||||
sem_destroy(&my_sem_start_is_required);
|
||||
sem_destroy(&my_sem_stop_is_required);
|
||||
sem_destroy(&my_sem_stop_is_acknowledged);
|
||||
pthread_cond_destroy(&my_cond_start_is_required);
|
||||
pthread_cond_destroy(&my_cond_stop_is_required);
|
||||
pthread_cond_destroy(&my_cond_stop_is_acknowledged);
|
||||
init(); // purge event
|
||||
thread_inited = 0;
|
||||
}
|
||||
|
||||
+76
-49
@@ -23,7 +23,6 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -43,12 +42,17 @@
|
||||
// my_stop_is_required, and the command fifo
|
||||
static pthread_mutex_t my_mutex;
|
||||
static int my_command_is_running = 0;
|
||||
static pthread_cond_t my_cond_command_is_running;
|
||||
static int my_stop_is_required = 0;
|
||||
|
||||
// my_thread: reads commands from the fifo, and runs them.
|
||||
static pthread_t my_thread;
|
||||
static sem_t my_sem_start_is_required;
|
||||
static sem_t my_sem_stop_is_acknowledged;
|
||||
|
||||
static pthread_cond_t my_cond_start_is_required;
|
||||
static int my_start_is_required = 0;
|
||||
|
||||
static pthread_cond_t my_cond_stop_is_acknowledged;
|
||||
static int my_stop_is_acknowledged = 0;
|
||||
|
||||
static void *say_thread(void *);
|
||||
|
||||
@@ -69,8 +73,9 @@ void fifo_init()
|
||||
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL);
|
||||
init(0);
|
||||
|
||||
assert(-1 != sem_init(&my_sem_start_is_required, 0, 0));
|
||||
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0));
|
||||
assert(-1 != pthread_cond_init(&my_cond_command_is_running, NULL));
|
||||
assert(-1 != pthread_cond_init(&my_cond_start_is_required, NULL));
|
||||
assert(-1 != pthread_cond_init(&my_cond_stop_is_acknowledged, NULL));
|
||||
|
||||
pthread_attr_t a_attrib;
|
||||
if (pthread_attr_init(&a_attrib)
|
||||
@@ -85,8 +90,12 @@ void fifo_init()
|
||||
pthread_attr_destroy(&a_attrib);
|
||||
|
||||
// leave once the thread is actually started
|
||||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
assert(-1 != pthread_mutex_lock(&my_mutex));
|
||||
while (my_stop_is_acknowledged == 0)
|
||||
while((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR)
|
||||
;
|
||||
my_stop_is_acknowledged = 0;
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
}
|
||||
|
||||
espeak_ng_STATUS fifo_add_command(t_espeak_command *the_command)
|
||||
@@ -99,20 +108,18 @@ espeak_ng_STATUS fifo_add_command(t_espeak_command *the_command)
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
return status;
|
||||
}
|
||||
|
||||
my_start_is_required = 1;
|
||||
pthread_cond_signal(&my_cond_start_is_required);
|
||||
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
if (!my_command_is_running) {
|
||||
// quit when command is actually started
|
||||
// (for possible forthcoming 'end of command' checks)
|
||||
sem_post(&my_sem_start_is_required);
|
||||
int val = 1;
|
||||
while (val > 0) {
|
||||
usleep(50000); // TBD: event?
|
||||
sem_getvalue(&my_sem_start_is_required, &val);
|
||||
while (!my_command_is_running) {
|
||||
if((status = pthread_cond_wait(&my_cond_command_is_running, &my_mutex)) != ENS_OK && errno != EINTR) {
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
return ENS_OK;
|
||||
}
|
||||
@@ -138,19 +145,17 @@ espeak_ng_STATUS fifo_add_commands(t_espeak_command *command1, t_espeak_command
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
if (!my_command_is_running) {
|
||||
// quit when one command is actually started
|
||||
// (for possible forthcoming 'end of command' checks)
|
||||
sem_post(&my_sem_start_is_required);
|
||||
int val = 1;
|
||||
while (val > 0) {
|
||||
usleep(50000); // TBD: event?
|
||||
sem_getvalue(&my_sem_start_is_required, &val);
|
||||
my_start_is_required = 1;
|
||||
pthread_cond_signal(&my_cond_start_is_required);
|
||||
|
||||
while (!my_command_is_running) {
|
||||
if((status = pthread_cond_wait(&my_cond_command_is_running, &my_mutex)) != ENS_OK && errno != EINTR) {
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
return ENS_OK;
|
||||
}
|
||||
@@ -167,15 +172,15 @@ espeak_ng_STATUS fifo_stop()
|
||||
my_stop_is_required = 1;
|
||||
}
|
||||
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
if (a_command_is_running) {
|
||||
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
while (my_stop_is_acknowledged == 0)
|
||||
while((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
}
|
||||
|
||||
my_stop_is_required = 0;
|
||||
if ((status = pthread_mutex_unlock(&my_mutex)) != ENS_OK)
|
||||
return status;
|
||||
|
||||
return ENS_OK;
|
||||
}
|
||||
@@ -189,7 +194,7 @@ static int sleep_until_start_request_or_inactivity()
|
||||
{
|
||||
int a_start_is_required = 0;
|
||||
|
||||
// Wait for the start request (my_sem_start_is_required).
|
||||
// Wait for the start request (my_cond_start_is_required).
|
||||
// Besides this, if the audio stream is still busy,
|
||||
// check from time to time its end.
|
||||
// The end of the stream is confirmed by several checks
|
||||
@@ -206,8 +211,10 @@ static int sleep_until_start_request_or_inactivity()
|
||||
clock_gettime2(&ts);
|
||||
|
||||
add_time_in_ms(&ts, INACTIVITY_TIMEOUT);
|
||||
err = pthread_mutex_lock(&my_mutex);
|
||||
assert(err != -1);
|
||||
|
||||
while ((err = sem_timedwait(&my_sem_start_is_required, &ts)) == -1
|
||||
while ((err = pthread_cond_timedwait(&my_cond_start_is_required, &my_mutex, &ts)) == -1
|
||||
&& errno == EINTR)
|
||||
continue;
|
||||
|
||||
@@ -216,6 +223,7 @@ static int sleep_until_start_request_or_inactivity()
|
||||
if (err == 0)
|
||||
a_start_is_required = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
return a_start_is_required;
|
||||
}
|
||||
|
||||
@@ -245,9 +253,17 @@ static espeak_ng_STATUS close_stream()
|
||||
|
||||
if (a_stop_is_required) {
|
||||
// acknowledge the stop request
|
||||
a_status = sem_post(&my_sem_stop_is_acknowledged);
|
||||
if((a_status = pthread_mutex_lock(&my_mutex)) != ENS_OK)
|
||||
return a_status;
|
||||
|
||||
my_stop_is_acknowledged = 1;
|
||||
a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged);
|
||||
if(a_status != ENS_OK)
|
||||
return a_status;
|
||||
a_status = pthread_mutex_unlock(&my_mutex);
|
||||
if (status == ENS_OK)
|
||||
status = a_status;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +275,10 @@ static void *say_thread(void *p)
|
||||
(void)p; // unused
|
||||
|
||||
// announce that thread is started
|
||||
sem_post(&my_sem_stop_is_acknowledged);
|
||||
assert(-1 != pthread_mutex_lock(&my_mutex));
|
||||
my_stop_is_acknowledged = 1;
|
||||
assert(-1 != pthread_cond_signal(&my_cond_stop_is_acknowledged));
|
||||
assert(-1 != pthread_mutex_unlock(&my_mutex));
|
||||
|
||||
int look_for_inactivity = 0;
|
||||
|
||||
@@ -272,13 +291,21 @@ static void *say_thread(void *p)
|
||||
}
|
||||
look_for_inactivity = 1;
|
||||
|
||||
int a_status = pthread_mutex_lock(&my_mutex);
|
||||
assert(!a_status);
|
||||
|
||||
if (!a_start_is_required) {
|
||||
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR)
|
||||
while (my_start_is_required == 0)
|
||||
while((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR)
|
||||
continue; // Restart when interrupted by handler
|
||||
}
|
||||
|
||||
|
||||
my_command_is_running = 1;
|
||||
|
||||
assert(-1 != pthread_cond_broadcast(&my_cond_command_is_running));
|
||||
assert(-1 != pthread_mutex_unlock(&my_mutex));
|
||||
|
||||
while (my_command_is_running) {
|
||||
int a_status = pthread_mutex_lock(&my_mutex);
|
||||
assert(!a_status);
|
||||
@@ -288,9 +315,7 @@ static void *say_thread(void *p)
|
||||
a_status = pthread_mutex_unlock(&my_mutex);
|
||||
my_command_is_running = 0;
|
||||
} else {
|
||||
// purge start semaphore
|
||||
while (0 == sem_trywait(&my_sem_start_is_required))
|
||||
;
|
||||
my_start_is_required = 0;
|
||||
|
||||
if (my_stop_is_required)
|
||||
my_command_is_running = 0;
|
||||
@@ -304,16 +329,18 @@ static void *say_thread(void *p)
|
||||
|
||||
if (my_stop_is_required) {
|
||||
// no mutex required since the stop command is synchronous
|
||||
// and waiting for my_sem_stop_is_acknowledged
|
||||
// and waiting for my_cond_stop_is_acknowledged
|
||||
init(1);
|
||||
|
||||
// purge start semaphore
|
||||
while (0 == sem_trywait(&my_sem_start_is_required))
|
||||
;
|
||||
assert(-1 != pthread_mutex_lock(&my_mutex));
|
||||
my_start_is_required = 0;
|
||||
|
||||
// acknowledge the stop request
|
||||
int a_status = sem_post(&my_sem_stop_is_acknowledged);
|
||||
my_stop_is_acknowledged = 1;
|
||||
int a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged);
|
||||
assert(a_status != -1);
|
||||
pthread_mutex_unlock(&my_mutex);
|
||||
|
||||
}
|
||||
// and wait for the next start
|
||||
}
|
||||
@@ -404,8 +431,8 @@ void fifo_terminate()
|
||||
pthread_cancel(my_thread);
|
||||
pthread_join(my_thread, NULL);
|
||||
pthread_mutex_destroy(&my_mutex);
|
||||
sem_destroy(&my_sem_start_is_required);
|
||||
sem_destroy(&my_sem_stop_is_acknowledged);
|
||||
pthread_cond_destroy(&my_cond_start_is_required);
|
||||
pthread_cond_destroy(&my_cond_stop_is_acknowledged);
|
||||
|
||||
init(0); // purge fifo
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user