speech-dispatcher-0.8.3/0000775000175000017500000000000012536424375012133 500000000000000speech-dispatcher-0.8.3/split-version.sh0000775000175000017500000000070712530733575015233 00000000000000#!/bin/sh # Small script to split out major/minor/micro versions for API version checks. VERSION=$(./git-version-gen .tarball-version) case "$1" in -ma) echo $VERSION | cut -f1 -d. ;; -mi) echo $VERSION | cut -f2 -d. | cut -f1 -d~ ;; -mc) micro_version=$(echo $VERSION | cut -f3 -d. | cut -f1 -d-) if test -z "$micro_version"; then echo 0 else echo $micro_version fi ;; *) echo "Usage: $0 [-ma|-mi|-mc]" exit 1 ;; esac speech-dispatcher-0.8.3/src/0000775000175000017500000000000012536424375012722 500000000000000speech-dispatcher-0.8.3/src/server/0000775000175000017500000000000012536424374014227 500000000000000speech-dispatcher-0.8.3/src/server/speechd.h0000664000175000017500000002011212533727516015730 00000000000000 /* * speechd.h - Speech Dispatcher header * * Copyright (C) 2001, 2002, 2003, 2006, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: speechd.h,v 1.64 2008-06-27 12:29:07 hanke Exp $ */ #ifndef SPEECHDH #define SPEECHDH #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SPEECHD_DEBUG 0 /* Definition of semun needed for semaphore manipulation */ /* TODO: This fixes compilation for Mac OS X but might not be a correct solution for other platforms. A better check is needed, possibly including _POSIX_C_SOURCE and friends*/ #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) || defined(__APPLE__) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #endif #include #include "module.h" #include "compare.h" typedef struct { unsigned int uid; /* Unique ID of the client */ int fd; /* File descriptor the client is on. */ int active; /* Is this client still active on socket or gone? */ int paused; /* Internal flag, 1 for paused client or 0 for normal. */ int paused_while_speaking; SPDMessageType type; /* Type of the message (1=text, 2=icon, 3=char, 4=key) */ SPDDataMode ssml_mode; /* SSML mode on (1)/off (0) */ SPDPriority priority; /* Priority between 1 and 5 (1 - highest, 5 - lowest) */ SPDMsgSettings msg_settings; char *client_name; /* Name of the client. */ char *output_module; /* Output module name. (e.g. "festival", "flite", "apollo", ...) */ SPDNotification notification; /* Notification about start and stop of messages, about reached index marks and state (canceled, paused, resumed). */ int reparted; unsigned int min_delay_progress; int pause_context; /* Number of words that should be repeated after a pause */ char *index_mark; /* Current index mark for the message (only if paused) */ char *audio_output_method; char *audio_oss_device; char *audio_alsa_device; char *audio_nas_server; char *audio_pulse_server; int audio_pulse_min_length; int log_level; /* TODO: Should be moved out */ unsigned int hist_cur_uid; int hist_cur_pos; ESort hist_sorted; } TFDSetElement; typedef struct { char *pattern; TFDSetElement val; } TFDSetClientSpecific; /* Size of the buffer for socket communication */ #define BUF_SIZE 128 /* Mode of speechd execution */ typedef enum { SPD_MODE_DAEMON, /* Run as daemon (background, ...) */ SPD_MODE_SINGLE /* */ } TSpeechDMode; TSpeechDMode spd_mode; /* TSpeechDQueue is a queue for messages. */ typedef struct { GList *p1; /* important */ GList *p2; /* text */ GList *p3; /* message */ GList *p4; /* notification */ GList *p5; /* progress */ } TSpeechDQueue; /* TSpeechDMessage is an element of TSpeechDQueue, that is, some text with or without index marks inside and it's configuration. */ typedef struct { guint id; /* unique id */ time_t time; /* when was this message received */ char *buf; /* the actual text */ int bytes; /* number of bytes in buf */ TFDSetElement settings; /* settings of the client when queueing this message */ } TSpeechDMessage; #include "alloc.h" #include "speaking.h" struct { char *communication_method; int communication_method_set; char *socket_path; int socket_path_set; int port, port_set; int localhost_access_only, localhost_access_only_set; int log_level, log_level_set; char *pid_file; char *conf_file; char *conf_dir; char *runtime_speechd_dir; char *log_dir; int log_dir_set; int spawn; int debug; char *debug_destination; char *debug_logfile; int max_history_messages; /* Maximum of messages in history before they expire */ } SpeechdOptions; struct { int max_uid; /* The largest assigned uid + 1 */ int max_gid; /* The largest assigned gid + 1 */ int max_fd; } SpeechdStatus; /* speak() thread defined in speaking.c */ pthread_t speak_thread; pthread_mutex_t logging_mutex; pthread_mutex_t element_free_mutex; pthread_mutex_t output_layer_mutex; pthread_mutex_t socket_com_mutex; /* Activity requests for the speaking thread are handled with SYSV/IPC semaphore */ key_t speaking_sem_key; int speaking_sem_id; /* Table of all configured (and succesfully loaded) output modules */ extern GList *output_modules; /* Table of settings for each active client (=each active socket)*/ GHashTable *fd_settings; /* Table of default output modules for different languages */ GHashTable *language_default_modules; /* Table of relations between client file descriptors and their uids */ GHashTable *fd_uid; /* Speech Dispatcher main priority queue for messages */ TSpeechDQueue *MessageQueue; /* List of messages from paused clients waiting for resume */ GList *MessagePausedList; /* List of different entries of client-specific configuration */ GList *client_specific_settings; /* Saves the last received priority progress message */ GList *last_p5_block; /* Global default settings */ TFDSetElement GlobalFDSet; /* Variables for socket communication */ fd_set readfds; /* Inter thread comm pipe */ int speaking_pipe[2]; /* Managing sockets communication */ GHashTable *speechd_sockets_status; typedef struct { int awaiting_data; int inside_block; size_t o_bytes; GString *o_buf; } TSpeechDSock; int speechd_sockets_status_init(void); int speechd_socket_register(int fd); void speechd_socket_free(TSpeechDSock * speechd_socket); int speechd_socket_unregister(int fd); TSpeechDSock *speechd_socket_get_by_fd(int fd); #include "parse.h" /* Debugging */ void MSG(int level, char *format, ...); void MSG2(int level, char *kind, char *format, ...); #define FATAL(msg) { fatal_error(); MSG(-1,"Fatal error [%s:%d]:"msg, __FILE__, __LINE__); exit(EXIT_FAILURE); } #define DIE(msg) { MSG(0,"Error [%s:%d]:"msg, __FILE__, __LINE__); exit(EXIT_FAILURE); } FILE *logfile; FILE *custom_logfile; char *custom_log_kind; FILE *debug_logfile; /* For debugging purposes, does nothing */ void fatal_error(void); /* isanum() tests if the given string is a number, * returns 1 if yes, 0 otherwise. */ int isanum(const char *str); /* Construct a path given a filename and the directory where to refer relative paths. filename can be either absolute (starting with slash) or relative. */ char *spd_get_path(char *filename, char *startdir); /* Functions used in speechd.c only */ int speechd_connection_new(int server_socket); int speechd_connection_destroy(int fd); gboolean speechd_client_terminate(gpointer key, gpointer value, gpointer user); void speechd_modules_terminate(gpointer data, gpointer user_data); void speechd_modules_reload(gpointer data, gpointer user_data); void speechd_modules_debug(void); void speechd_modules_nodebug(void); void speechd_reload_dead_modules(int sig); void speechd_options_init(void); void speechd_init(void); void speechd_load_configuration(int sig); void speechd_quit(int sig); int create_pid_file(void); void destroy_pid_file(void); void logging_init(void); void check_locked(pthread_mutex_t * lock); #endif speech-dispatcher-0.8.3/src/server/speaking.c0000664000175000017500000006553112522771346016125 00000000000000 /* * speaking.c - Speech Dispatcher speech output functions * * Copyright (C) 2001,2002,2003, 2006, 2007 Brailcom, o.p.s * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: speaking.c,v 1.56 2008-10-15 18:06:48 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "speechd.h" #include "server.h" #include "index_marking.h" #include "module.h" #include "set.h" #include "alloc.h" #include "msg.h" #include "output.h" #include "speaking.h" #include "sem_functions.h" TSpeechDMessage *current_message = NULL; static SPDPriority highest_priority = 0; int SPEAKING = 0; int poll_count; /* Speak() is responsible for getting right text from right queue in right time and saying it loud through the corresponding synthetiser. This runs in a separate thread. */ void *speak(void *data) { TSpeechDMessage *message = NULL; int ret; struct pollfd *poll_fds; /* Descriptors to poll */ struct pollfd main_pfd; struct pollfd helper_pfd; int revents; /* Block all signals and set thread states */ set_speak_thread_attributes(); poll_fds = g_malloc(2 * sizeof(struct pollfd)); main_pfd.fd = speaking_pipe[0]; main_pfd.events = POLLIN; main_pfd.revents = 0; helper_pfd.fd = -1; helper_pfd.events = POLLIN; helper_pfd.revents = 0; poll_fds[0] = main_pfd; poll_fds[1] = helper_pfd; poll_count = 1; while (1) { ret = poll(poll_fds, poll_count, -1); MSG(5, "Poll in speak() returned socket activity, main_pfd revents=%d, poll_pfd revents=%d", poll_fds[0].revents, poll_fds[1].revents); if ((revents = poll_fds[0].revents)) { if (revents & POLLIN) { char buf[1]; MSG(5, "wait_for_poll: activity in Speech Dispatcher"); const ssize_t rd_bytes = safe_read(poll_fds[0].fd, buf, 1); if (rd_bytes != 1) FATAL ("read from polled fd: could not read 1 byte"); } } if (poll_count > 1) { if ((revents = poll_fds[1].revents)) { if (revents & POLLHUP) { // FIXME: We should handle this more gracefully FATAL ("wait_for_poll: output_module disconnected"); } else if ((revents & POLLIN) || (revents & POLLPRI)) { MSG(5, "wait_for_poll: activity on output_module"); /* Check if sb is speaking or they are all silent. * If some synthesizer is speaking, we must wait. */ is_sb_speaking(); } } } /* Handle pause requests */ if (pause_requested) { MSG(4, "Trying to pause..."); if (pause_requested == 1) speaking_pause_all(pause_requested_fd); if (pause_requested == 2) speaking_pause(pause_requested_fd, pause_requested_uid); MSG(4, "Paused..."); pause_requested = 0; continue; } if (SPEAKING) { MSG(5, "Continuing because already speaking in speak()"); continue; } /* Handle resume requests */ if (resume_requested) { GList *gl; MSG(5, "Resume requested"); /* Is there any message after resume? */ if (g_list_length(MessagePausedList) != 0) { while (1) { pthread_mutex_lock(&element_free_mutex); gl = g_list_find_custom (MessagePausedList, (void *)NULL, message_nto_speak); MSG(5, "Message insterted back to the queues!"); MessagePausedList = g_list_remove_link (MessagePausedList, gl); pthread_mutex_unlock (&element_free_mutex); if ((gl != NULL) && (gl->data != NULL)) { MSG(5, "Reloading message"); reload_message((TSpeechDMessage *) gl->data); /* If this resumed message is the same as current_message, then it gets * another trip through the queue. However, some code later in this * function will free current_message, even though it is now requeued! * Hence use-after-free. * current_message is pretty useless after the requeue, make it NULL. */ if (current_message == gl->data) current_message = NULL; } else break; } } MSG(5, "End of resume processing"); resume_requested = 0; } MSG(5, "Locking element_free_mutex in speak()"); pthread_mutex_lock(&element_free_mutex); /* Handle postponed priority progress message */ check_locked(&element_free_mutex); if ((g_list_length(last_p5_block) != 0) && (g_list_length(MessageQueue->p5) == 0)) { /* Transfer messages from last_p5_block to priority 2 (message) queue */ while (g_list_length(last_p5_block) != 0) { GList *item; item = g_list_first(last_p5_block); message = item->data; check_locked(&element_free_mutex); MessageQueue->p2 = g_list_insert_sorted(MessageQueue->p2, message, sortbyuid); last_p5_block = g_list_remove_link(last_p5_block, item); g_list_free1(item); } assert(message != NULL); highest_priority = SPD_MESSAGE; stop_priority_older_than(SPD_TEXT, message->id); stop_priority(SPD_NOTIFICATION); stop_priority(SPD_PROGRESS); check_locked(&element_free_mutex); pthread_mutex_unlock(&element_free_mutex); speaking_semaphore_post(); continue; } else { /* Extract the right message from priority queue */ message = get_message_from_queues(); if (message == NULL) { pthread_mutex_unlock(&element_free_mutex); MSG(5, "No message in the queue"); continue; } } /* Isn't the parent client of this message paused? * If it is, insert the message to the MessagePausedList. */ if (message_nto_speak(message, NULL)) { MSG(4, "Inserting message to paused list..."); MessagePausedList = g_list_append(MessagePausedList, message); pthread_mutex_unlock(&element_free_mutex); continue; } /* Insert index marks into textual messages */ if (message->settings.type == SPD_MSGTYPE_TEXT) { insert_index_marks(message, message->settings.ssml_mode); } /* Write the message to the output layer. */ ret = output_speak(message); MSG(4, "Message sent to output module"); if (ret == -1) { MSG(2, "Error: Output module failed"); output_check_module(get_output_module(message)); pthread_mutex_unlock(&element_free_mutex); continue; } if (ret != 0) { MSG(2, "ERROR: Can't say message. Module reported error in speaking: %d", ret); pthread_mutex_unlock(&element_free_mutex); continue; } SPEAKING = 1; if (speaking_module != NULL) { poll_count = 2; helper_pfd.fd = speaking_module->pipe_out[0]; poll_fds[1] = helper_pfd; } /* Set the id of the client who is speaking. */ speaking_uid = message->settings.uid; if (current_message != NULL) { if (!current_message->settings.paused_while_speaking) { /* Check if the client who emited this message is disconnected by now and this was his last message. If so, delete it's settings from fdset */ if (get_client_settings_by_uid (current_message->settings.uid)->active == 0) { if (!client_has_messages (current_message->settings.uid) && (current_message->settings.uid != message->settings.uid)) { /* client_has_messages does not account for message, which was just retrieved from the queue. We also have to compare the uids of message and current_message to be sure that there are no outstanding messages. */ MSG(4, "Removing client settings for uid %d", current_message-> settings.uid); remove_client_settings_by_uid (current_message-> settings.uid); } } mem_free_message(current_message); } } current_message = message; /* Check if the last priority 5 message wasn't said yet */ if (last_p5_block != NULL) { GList *elem; TSpeechDMessage *p5_message; elem = g_list_last(last_p5_block); if (elem != NULL) { p5_message = (TSpeechDMessage *) elem->data; if (p5_message->settings.reparted == message->settings.reparted) { g_list_foreach(last_p5_block, (GFunc) mem_free_message, NULL); g_list_free(last_p5_block); last_p5_block = NULL; } } } pthread_mutex_unlock(&element_free_mutex); } } int reload_message(TSpeechDMessage * msg) { TFDSetElement *client_settings; int im; char *pos; char *newtext; char *tptr; if (msg == NULL) { MSG(4, "Warning: msg == NULL in reload_message()"); return -1; } if (msg->settings.index_mark != NULL) { MSG(5, "Recovering index mark %s", msg->settings.index_mark); client_settings = get_client_settings_by_uid(msg->settings.uid); /* Scroll back to provide context, if required */ /* WARNING: This relies on ordered SD_MARK_BODY index marks! */ MSG(5, "Recovering index mark (number)"); im = strtol(msg->settings.index_mark + SD_MARK_BODY_LEN, &tptr, 10); MSG(5, "Recovering index mark (comparing tptr)"); if (msg->settings.index_mark + SD_MARK_BODY_LEN == tptr) { MSG2(2, "index_marking", "ERROR: Invalid index_mark '%s'. Message not reloaded.", msg->settings.index_mark); return -1; } MSG(5, "Recovered index mark number: %d", im); im += client_settings->pause_context; MSG2(5, "index_marking", "Requested index mark (with context) is %d (%d+%d)", im, msg->settings.index_mark, client_settings->pause_context); if (im < 0) { im = 0; pos = msg->buf; } else { pos = find_index_mark(msg, im); if (pos == NULL) return -1; } newtext = strip_index_marks(pos, client_settings->ssml_mode); g_free(msg->buf); if (newtext == NULL) return -1; msg->buf = newtext; msg->bytes = strlen(msg->buf); if (queue_message (msg, -msg->settings.uid, 0, SPD_MSGTYPE_TEXT, 0) == 0) { if (SPEECHD_DEBUG) FATAL("Can't queue message\n"); g_free(msg->buf); g_free(msg); return -1; } return 0; } else { MSG(5, "Index mark unknown, inserting the whole message."); if (queue_message (msg, -msg->settings.uid, 0, SPD_MSGTYPE_TEXT, 0) == 0) { if (SPEECHD_DEBUG) FATAL("Can't queue message\n"); g_free(msg->buf); g_free(msg); return -1; } return 0; } return 0; } void speaking_stop(int uid) { TSpeechDMessage *msg; GList *gl; GList *queue; signed int gid = -1; /* Only act if the currently speaking client is the specified one */ if (get_speaking_client_uid() == uid) { output_stop(); /* Get the queue where the message being spoken came from */ queue = speaking_get_queue(highest_priority); if (queue == NULL) return; /* Get group ID of the current message */ gl = g_list_last(queue); if (gl == NULL) return; if (gl->data == NULL) return; msg = (TSpeechDMessage *) gl->data; if ((msg->settings.reparted != 0) && (msg->settings.uid == uid)) { gid = msg->settings.reparted; } else { return; } while (1) { gl = g_list_last(queue); if (gl == NULL) { speaking_set_queue(highest_priority, queue); return; } if (gl->data == NULL) return; msg = (TSpeechDMessage *) gl->data; if ((msg->settings.reparted == gid) && (msg->settings.uid == uid)) { queue = g_list_remove_link(queue, gl); assert(gl->data != NULL); mem_free_message(gl->data); } else { speaking_set_queue(highest_priority, queue); return; } } } } void speaking_stop_all() { TSpeechDMessage *msg; GList *gl; GList *queue; int gid = -1; output_stop(); queue = speaking_get_queue(highest_priority); if (queue == NULL) return; gl = g_list_last(queue); if (gl == NULL) return; assert(gl->data != NULL); msg = (TSpeechDMessage *) gl->data; if (msg->settings.reparted != 0) { gid = msg->settings.reparted; } else { return; } while (1) { gl = g_list_last(queue); if (gl == NULL) { speaking_set_queue(highest_priority, queue); return; } if (SPEECHD_DEBUG) assert(gl->data != NULL); msg = (TSpeechDMessage *) gl->data; if (msg->settings.reparted == 1) { queue = g_list_remove_link(queue, gl); assert(gl->data != NULL); mem_free_message(gl->data); } else { speaking_set_queue(highest_priority, queue); return; } } } void speaking_cancel(int uid) { pthread_mutex_lock(&element_free_mutex); speaking_stop(uid); stop_from_uid(uid); pthread_mutex_unlock(&element_free_mutex); } void speaking_cancel_all() { output_stop(); pthread_mutex_lock(&element_free_mutex); stop_priority(SPD_IMPORTANT); stop_priority(SPD_MESSAGE); stop_priority(SPD_TEXT); stop_priority(SPD_NOTIFICATION); stop_priority(SPD_PROGRESS); pthread_mutex_unlock(&element_free_mutex); } int speaking_pause_all(int fd) { int err = 0; int i; int uid; for (i = 1; i <= SpeechdStatus.max_fd; i++) { uid = get_client_uid_by_fd(i); if (uid == 0) continue; err += speaking_pause(i, uid); } if (err > 0) return 1; else return 0; } int speaking_pause(int fd, int uid) { TFDSetElement *settings; int ret; MSG(4, "Pause"); /* Find settings for this particular client */ settings = get_client_settings_by_uid(uid); if (settings == NULL) { MSG(4, "ERROR: Can't get settings of active client in speaking_pause()!"); return 1; } settings->paused = 1; if (speaking_uid != uid) { MSG(5, "given uid %d not speaking_uid", speaking_uid, uid); return 0; } if (SPEAKING) { if (current_message == NULL) { MSG(5, "current_message is null"); return 0; } ret = output_pause(); if (ret < 0) { MSG(5, "output_pause returned %d", ret); return 0; } MSG(5, "Including current message into the message paused list"); current_message->settings.paused = 2; current_message->settings.paused_while_speaking = 1; if (g_list_find(MessagePausedList, current_message) == NULL) MessagePausedList = g_list_append(MessagePausedList, current_message); } return 0; } int speaking_resume_all() { int err = 0; int i; int uid; for (i = 1; i <= SpeechdStatus.max_fd; i++) { uid = get_client_uid_by_fd(i); if (uid == 0) continue; err += speaking_resume(uid); } if (err > 0) return 1; else return 0; } int speaking_resume(int uid) { TFDSetElement *settings; /* Find settings for this particular client */ settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; /* Set it to speak again. */ settings->paused = 0; resume_requested = 1; speaking_semaphore_post(); return 0; } int socket_send_msg(int fd, char *msg) { int ret; assert(msg != NULL); pthread_mutex_lock(&socket_com_mutex); MSG2(5, "protocol", "%d:REPLY:|%s|", fd, msg); ret = write(fd, msg, strlen(msg)); pthread_mutex_unlock(&socket_com_mutex); if (ret < 0) { MSG(1, "write() error: %s", strerror(errno)); return -1; } return 0; } int report_index_mark(TSpeechDMessage * msg, char *index_mark) { char *cmd; int ret; cmd = g_strdup_printf(EVENT_INDEX_MARK_C "-%d\r\n" EVENT_INDEX_MARK_C "-%d\r\n" EVENT_INDEX_MARK_C "-%s\r\n" EVENT_INDEX_MARK, msg->id, msg->settings.uid, index_mark); ret = socket_send_msg(msg->settings.fd, cmd); if (ret) { MSG(1, "ERROR: Can't report index mark!"); return -1; } g_free(cmd); return 0; } #define REPORT_STATE(state, ssip_code, ssip_msg) \ int \ report_ ## state (TSpeechDMessage *msg) \ { \ char *cmd; \ int ret; \ cmd = g_strdup_printf(ssip_code"-%d\r\n"ssip_code"-%d\r\n"ssip_msg, \ msg->id, msg->settings.uid); \ ret = socket_send_msg(msg->settings.fd, cmd); \ if (ret){ \ MSG(2, "ERROR: Can't report index mark!"); \ return -1; \ } \ g_free(cmd); \ return 0; \ } REPORT_STATE(begin, EVENT_BEGIN_C, EVENT_BEGIN) REPORT_STATE(end, EVENT_END_C, EVENT_END) REPORT_STATE(pause, EVENT_PAUSED_C, EVENT_PAUSED) REPORT_STATE(resume, EVENT_RESUMED_C, EVENT_RESUMED) REPORT_STATE(cancel, EVENT_CANCELED_C, EVENT_CANCELED) int is_sb_speaking(void) { int ret; char *index_mark; TFDSetElement *settings; MSG(5, "is_sb_speaking(), SPEAKING=%d", SPEAKING); /* Determine if the current module is still speaking */ if (speaking_module != NULL) { if (current_message == NULL) { MSG(1, "Error: Current message is NULL in is_sb_speaking()"); return -1; } settings = &(current_message->settings); ret = output_is_speaking(&index_mark); if (index_mark == NULL) return SPEAKING = 0; if (!strcmp(index_mark, "no")) { g_free(index_mark); return SPEAKING; } MSG(5, "INDEX MARK: %s", index_mark); if (!strcmp(index_mark, SD_MARK_BODY "begin")) { SPEAKING = 1; if (!settings->paused_while_speaking) { if (settings->notification & SPD_BEGIN) report_begin(current_message); } else { if (settings->notification & SPD_RESUME) report_resume(current_message); settings->paused_while_speaking = 0; } } else if (!strcmp(index_mark, SD_MARK_BODY "end")) { SPEAKING = 0; poll_count = 1; if (settings->notification & SPD_END) report_end(current_message); speaking_semaphore_post(); } else if (!strcmp(index_mark, SD_MARK_BODY "paused")) { SPEAKING = 0; poll_count = 1; if (settings->notification & SPD_PAUSE) report_pause(current_message); /* We don't want to free this message in speak() since we will later copy it in resume() */ current_message = NULL; } else if (!strcmp(index_mark, SD_MARK_BODY "stopped")) { SPEAKING = 0; poll_count = 1; if (settings->notification & SPD_CANCEL) report_cancel(current_message); speaking_semaphore_post(); } else if (index_mark != NULL) { if (strncmp(index_mark, SD_MARK_BODY, SD_MARK_BODY_LEN)) { if (settings->notification & SPD_INDEX_MARKS) report_index_mark(current_message, index_mark); } else { MSG(5, "Setting current index_mark for the message to %s", index_mark); if (current_message->settings.index_mark != NULL) g_free(current_message-> settings.index_mark); current_message->settings.index_mark = g_strdup(index_mark); } } g_free(index_mark); } else { MSG(5, "Speaking module is NULL, SPEAKING==%d", SPEAKING); SPEAKING = 0; } if (SPEAKING == 0) speaking_module = NULL; return SPEAKING; } int get_speaking_client_uid(void) { int speaking = 0; if (SPEAKING == 0) { speaking_uid = 0; return 0; } if (speaking_uid != 0) { speaking = speaking_uid; } return speaking; } GList *queue_remove_message(GList * queue, GList * gl) { TSpeechDMessage *msg; assert(gl != NULL); assert(gl->data != NULL); msg = (TSpeechDMessage *) gl->data; if (msg->settings.notification & SPD_CANCEL) report_cancel(msg); mem_free_message(gl->data); queue = g_list_delete_link(queue, gl); return queue; } GList *empty_queue(GList * queue) { int num, i; GList *gl; num = g_list_length(queue); for (i = 0; i <= num - 1; i++) { gl = g_list_first(queue); queue = queue_remove_message(queue, gl); } return queue; } GList *empty_queue_by_time(GList * queue, unsigned int uid) { int num, i; GList *gl, *gln; TSpeechDMessage *msg; num = g_list_length(queue); gl = g_list_first(queue); for (i = 0; i <= num - 1; i++) { gln = g_list_next(gl); if (gl == NULL) break; assert(gl->data != NULL); msg = gl->data; if (msg->id < uid) { queue = queue_remove_message(queue, gl); } gl = gln; } return queue; } int stop_priority(SPDPriority priority) { GList *queue; queue = speaking_get_queue(priority); if (highest_priority == priority) { output_stop(); } queue = empty_queue(queue); speaking_set_queue(priority, queue); return 0; } int stop_priority_older_than(SPDPriority priority, unsigned int uid) { GList *queue; queue = speaking_get_queue(priority); if (highest_priority == priority) { output_stop(); } queue = empty_queue_by_time(queue, uid); speaking_set_queue(priority, queue); return 0; } GList *stop_priority_from_uid(GList * queue, const int uid) { GList *ret = queue; GList *gl; while ((gl = g_list_find_custom(ret, &uid, p_msg_uid_lc))) ret = queue_remove_message(ret, gl); return ret; } void stop_from_uid(const int uid) { check_locked(&element_free_mutex); MessageQueue->p1 = stop_priority_from_uid(MessageQueue->p1, uid); MessageQueue->p2 = stop_priority_from_uid(MessageQueue->p2, uid); MessageQueue->p3 = stop_priority_from_uid(MessageQueue->p3, uid); MessageQueue->p4 = stop_priority_from_uid(MessageQueue->p4, uid); MessageQueue->p5 = stop_priority_from_uid(MessageQueue->p5, uid); } /* Determines if this messages is to be spoken * (returns 1) or its parent client is paused (returns 0). * Note: If you are wondering why it's reversed (not to speak instead * of to speak), it's because we also use this function for * searching through the list. */ gint message_nto_speak(gconstpointer data, gconstpointer nothing) { TFDSetElement *global_settings; TSpeechDMessage *message = (TSpeechDMessage *) data; /* Is there something in the body of the message? */ if (message == NULL) return 0; /* Find global settings for this connection. */ global_settings = get_client_settings_by_fd(message->settings.fd); if (global_settings == NULL) return 0; if (!global_settings->paused) return 0; else return 1; } void set_speak_thread_attributes() { int ret; sigset_t all_signals; ret = sigfillset(&all_signals); if (ret == 0) { ret = pthread_sigmask(SIG_BLOCK, &all_signals, NULL); if (ret != 0) MSG(1, "Can't set signal set, expect problems when terminating!"); } else { MSG(1, "Can't fill signal set, expect problems when terminating!"); } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); } void stop_priority_except_first(SPDPriority priority) { GList *queue; GList *gl; TSpeechDMessage *msg; GList *gl_next; int gid; queue = speaking_get_queue(priority); gl = g_list_last(queue); if (gl == NULL) return; if (gl->data == NULL) return; msg = (TSpeechDMessage *) gl->data; if (msg->settings.reparted <= 0) { queue = g_list_remove_link(queue, gl); speaking_set_queue(priority, queue); stop_priority(priority); /* Fill the queue with the list containing only the first message */ speaking_set_queue(priority, gl); } else { gid = msg->settings.reparted; if (highest_priority == priority && speaking_gid != gid) { output_stop(); } gl = g_list_first(queue); while (gl) { gl_next = g_list_next(gl); if (gl->data != NULL) { TSpeechDMessage *msgg = gl->data; if (msgg->settings.reparted != gid) { queue = g_list_remove_link(queue, gl); mem_free_message(msgg); } } gl = gl_next; } speaking_set_queue(priority, queue); } return; } void resolve_priorities(SPDPriority priority) { if (priority == SPD_IMPORTANT) { if (SPEAKING && highest_priority != SPD_IMPORTANT) output_stop(); stop_priority(SPD_NOTIFICATION); stop_priority(SPD_PROGRESS); } if (priority == SPD_MESSAGE) { if (SPEAKING && highest_priority != SPD_IMPORTANT && highest_priority != SPD_MESSAGE) output_stop(); stop_priority(SPD_TEXT); stop_priority(SPD_NOTIFICATION); stop_priority(SPD_PROGRESS); } if (priority == SPD_TEXT) { stop_priority_except_first(SPD_TEXT); stop_priority(SPD_NOTIFICATION); stop_priority(SPD_PROGRESS); } if (priority == SPD_NOTIFICATION) { stop_priority_except_first(SPD_NOTIFICATION); if (SPEAKING && highest_priority != SPD_NOTIFICATION) stop_priority(SPD_NOTIFICATION); } if (priority == SPD_PROGRESS) { stop_priority(SPD_NOTIFICATION); if (SPEAKING) { GList *gl; check_locked(&element_free_mutex); gl = g_list_last(MessageQueue->p5); check_locked(&element_free_mutex); MessageQueue->p5 = g_list_remove_link(MessageQueue->p5, gl); if (gl != NULL) { check_locked(&element_free_mutex); MessageQueue->p5 = empty_queue(MessageQueue->p5); if (gl->data != NULL) { MessageQueue->p5 = gl; } } } } } TSpeechDMessage *get_message_from_queues() { GList *gl; SPDPriority prio; TSpeechDMessage *message; /* We will descend through priorities to say more important messages first. */ for (prio = SPD_IMPORTANT; prio <= SPD_PROGRESS; prio++) { GList *current_queue = speaking_get_queue(prio); check_locked(&element_free_mutex); gl = g_list_first(current_queue); while (gl != NULL) { if (message_nto_speak ((TSpeechDMessage *) gl->data, NULL)) { gl = g_list_next(gl); continue; } speaking_set_queue(prio, g_list_remove_link(current_queue, gl)); highest_priority = prio; message = gl->data; g_list_free(gl); return (TSpeechDMessage *) message; } } return NULL; } gint message_has_uid(gconstpointer msg, gconstpointer uid) { if (((TSpeechDMessage *) msg)->settings.uid == *(int *)uid) return 0; else return 1; } /* Return 1 if any message from this client is found in any of the queues, otherwise return 0 */ int client_has_messages(int uid) { if (g_list_find_custom (MessageQueue->p5, (gconstpointer) & uid, message_has_uid) || g_list_find_custom(MessageQueue->p4, (gconstpointer) & uid, message_has_uid) || g_list_find_custom(MessageQueue->p3, (gconstpointer) & uid, message_has_uid) || g_list_find_custom(MessageQueue->p2, (gconstpointer) & uid, message_has_uid) || g_list_find_custom(MessageQueue->p1, (gconstpointer) & uid, message_has_uid)) return 1; else return 0; } GList *speaking_get_queue(SPDPriority priority) { GList *queue = NULL; assert(priority >= SPD_IMPORTANT && priority <= SPD_PROGRESS); check_locked(&element_free_mutex); switch (priority) { case SPD_IMPORTANT: queue = MessageQueue->p1; break; case SPD_MESSAGE: queue = MessageQueue->p2; break; case SPD_TEXT: queue = MessageQueue->p3; break; case SPD_NOTIFICATION: queue = MessageQueue->p4; break; case SPD_PROGRESS: queue = MessageQueue->p5; break; } return queue; } void speaking_set_queue(SPDPriority priority, GList * queue) { assert(priority >= SPD_IMPORTANT && priority <= SPD_PROGRESS); check_locked(&element_free_mutex); switch (priority) { case SPD_IMPORTANT: MessageQueue->p1 = queue; break; case SPD_MESSAGE: MessageQueue->p2 = queue; break; case SPD_TEXT: MessageQueue->p3 = queue; break; case SPD_NOTIFICATION: MessageQueue->p4 = queue; break; case SPD_PROGRESS: MessageQueue->p5 = queue; break; } } gint sortbyuid(gconstpointer a, gconstpointer b) { const TSpeechDMessage *msg1 = a; const TSpeechDMessage *msg2 = b; if ((msg1 == NULL) && (msg2 != NULL)) return -1; if ((msg1 != NULL) && (msg2 == NULL)) return +1; if ((msg1 == NULL) && (msg2 == NULL)) return 0; return msg1->id - msg2->id; } speech-dispatcher-0.8.3/src/server/sem_functions.h0000664000175000017500000000170212522771346017173 00000000000000/* * sem_functions.h - Functions for manipulating System V / IPC semaphores * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: sem_functions.h,v 1.6 2006-07-11 16:12:27 hanke Exp $ */ void speaking_semaphore_post(void); speech-dispatcher-0.8.3/src/server/configuration.h0000644000175000017500000000266012233560613017160 00000000000000 /* * config.h - Configuration for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: config.h,v 1.4 2007-02-17 18:58:27 hanke Exp $ */ #ifndef CONFIG_H #define CONFIG_H #include #include #define SPEECHD_DEFAULT_PORT 6560 /* Loading options from DotConf */ configoption_t *spd_options; int spd_num_options; configoption_t *load_config_options(int *num_options); void free_config_options(configoption_t * opts, int *num); configoption_t *add_config_option(configoption_t * options, int *num_config_options, char *name, int type, dotconf_callback_t callback, info_t * info, unsigned long context); void load_default_global_set_options(); #endif speech-dispatcher-0.8.3/src/server/module.c0000664000175000017500000003477412522771346015616 00000000000000 /* * module.c - Output modules for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003, 2006, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: module.c,v 1.40 2008-07-07 14:30:51 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "speechd.h" #include #include "output.h" #include "module.h" void destroy_module(OutputModule * module) { g_free(module->name); g_free(module->filename); g_free(module->configfilename); g_free(module); } /* * detect_output_modules: automatically discover all available modules. * Parameters: * dirname: name of the directory containing module binaries. * Returns: a list of detected modules. * For each file in the directory containing module binaries, * add an entry to a list of discovered modules. */ GList *detect_output_modules(char *dirname) { static const int FNAME_PREFIX_LENGTH = 3; DIR *module_dir = opendir(dirname); struct dirent *entry; char **module_parameters; GList *modules = NULL; char *full_path; struct stat fileinfo; int sys_ret; if (module_dir == NULL) { MSG(3, "couldn't open directory %s because of error %s\n", dirname, strerror(errno)); return NULL; } while (NULL != (entry = readdir(module_dir))) { if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; full_path = spd_get_path(entry->d_name, dirname); sys_ret = stat(full_path, &fileinfo); g_free(full_path); if (sys_ret != 0) { MSG(4, "stat failed on file %s in %s", entry->d_name, dirname); continue; } /* Note: stat(2) dereferences symlinks. */ if (!S_ISREG(fileinfo.st_mode)) { MSG(4, "Ignoring %s in %s; not a regular file.", entry->d_name, dirname); continue; } if (strncmp(entry->d_name, "sd_", FNAME_PREFIX_LENGTH) || (entry->d_name[FNAME_PREFIX_LENGTH] == '\0')) { MSG(1, "Module discovery ignoring %s: malformed filename.", entry->d_name); continue; } module_parameters = g_malloc(4 * sizeof(char *)); module_parameters[0] = g_strdup(entry->d_name + FNAME_PREFIX_LENGTH); module_parameters[1] = g_strdup(entry->d_name); module_parameters[2] = g_strdup_printf("%s.conf", module_parameters[0]); module_parameters[3] = g_strdup_printf("%s/%s.log", SpeechdOptions.log_dir, module_parameters[0]); modules = g_list_append(modules, module_parameters); MSG(5, "Module name=%s being inserted into detected_modules list", module_parameters[0]); } closedir(module_dir); return modules; } OutputModule *load_output_module(char *mod_name, char *mod_prog, char *mod_cfgfile, char *mod_dbgfile) { OutputModule *module; int fr; char *argv[3] = { 0, 0, 0 }; int ret; char *module_conf_dir; char *rep_line = NULL; FILE *f; size_t n = 0; char s; GString *reply; if (mod_name == NULL) return NULL; module = (OutputModule *) g_malloc(sizeof(OutputModule)); module->name = (char *)g_strdup(mod_name); module->filename = (char *)spd_get_path(mod_prog, MODULEBINDIR); module_conf_dir = g_strdup_printf("%s/modules", SpeechdOptions.conf_dir); module->configfilename = (char *)spd_get_path(mod_cfgfile, module_conf_dir); g_free(module_conf_dir); if (mod_dbgfile != NULL) module->debugfilename = g_strdup(mod_dbgfile); else module->debugfilename = NULL; if (!strcmp(mod_name, "testing")) { module->pipe_in[1] = 1; /* redirect to stdin */ module->pipe_out[0] = 0; /* redirect to stdout */ return module; } if ((pipe(module->pipe_in) != 0) || (pipe(module->pipe_out) != 0)) { MSG(3, "Can't open pipe! Module not loaded."); return NULL; } argv[0] = module->filename; if (mod_cfgfile) { argv[1] = module->configfilename; } /* Open the file for child stderr (logging) redirection */ if (module->debugfilename != NULL) { module->stderr_redirect = open(module->debugfilename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (module->stderr_redirect == -1) MSG(1, "ERROR: Openning debug file for %s failed: (error=%d) %s", module->name, module->stderr_redirect, strerror(errno)); } else { module->stderr_redirect = -1; } MSG(2, "Initializing output module %s with binary %s and configuration %s", module->name, module->filename, module->configfilename); if (module->stderr_redirect >= 0) MSG(3, "Output module is logging to file %s", module->debugfilename); else MSG(3, "Output module is logging to standard error output (stderr)"); fr = fork(); if (fr == -1) { printf("Can't fork, error! Module not loaded."); return NULL; } if (fr == 0) { ret = dup2(module->pipe_in[0], 0); close(module->pipe_in[0]); close(module->pipe_in[1]); ret = dup2(module->pipe_out[1], 1); close(module->pipe_out[1]); close(module->pipe_out[0]); /* Redirrect stderr to the appropriate logfile */ if (module->stderr_redirect >= 0) { ret = dup2(module->stderr_redirect, 2); } execvp(argv[0], argv); MSG(1, "Exec of module \"%s\" with config \"%s\" failed with error %d: %s", argv[0], argv[1] ? argv[1] : "", errno, strerror(errno)); exit(1); } module->pid = fr; close(module->pipe_in[0]); close(module->pipe_out[1]); usleep(100); /* So that the other child has at least time to fail with the execlp */ ret = waitpid(module->pid, NULL, WNOHANG); if (ret != 0) { MSG(2, "ERROR: Can't load output module %s with binary %s. Bad filename in configuration?", module->name, module->filename); destroy_module(module); return NULL; } module->working = 1; MSG(2, "Module %s loaded.", module->name); /* Create a stream from the socket */ module->stream_out = fdopen(module->pipe_out[0], "r"); if (!module->stream_out) FATAL("Can't create a stream for socket, fdopen() failed."); /* Switch to line buffering mode */ ret = setvbuf(module->stream_out, NULL, _IONBF, 4096); if (ret) FATAL("Can't set line buffering, setvbuf failed."); MSG(4, "Trying to initialize %s.", module->name); if (output_send_data("INIT\n", module, 0) != 0) { MSG(1, "ERROR: Something wrong with %s, can't initialize", module->name); output_close(module); return NULL; } reply = g_string_new("\n---------------\n"); f = fdopen(dup(module->pipe_out[0]), "r"); while (1) { ret = spd_getline(&rep_line, &n, f); if (ret <= 0) { MSG(1, "ERROR: Bad syntax from output module %s 1", module->name); if (rep_line != NULL) g_free(rep_line); return NULL; } assert(rep_line != NULL); MSG(5, "Reply from output module: %d %s", n, rep_line); if (ret <= 4) { MSG(1, "ERROR: Bad syntax from output module %s 2", module->name); g_free(rep_line); return NULL; } if (rep_line[3] != '-') { s = rep_line[0]; g_free(rep_line); break; } g_string_append(reply, rep_line + 4); } fclose(f); g_string_append_printf(reply, "---------------\n"); if (s == '3') { MSG(1, "ERROR: Module %s failed to initialize. Reason: %s", module->name, reply->str); module->working = 0; kill(module->pid, 9); waitpid(module->pid, NULL, WNOHANG); destroy_module(module); g_string_free(reply, TRUE); return NULL; } if (s == '2') MSG(2, "Module %s started successfully with message: %s", module->name, reply->str); g_string_free(reply, 1); if (SpeechdOptions.debug) { MSG(4, "Switching debugging on for output module %s", module->name); output_module_debug(module); } /* Initialize audio settings */ ret = output_send_audio_settings(module); if (ret != 0) { MSG(1, "ERROR: Can't initialize audio in output module, see reason above."); module->working = 0; kill(module->pid, 9); waitpid(module->pid, NULL, WNOHANG); destroy_module(module); return NULL; } /* Send log level configuration setting */ ret = output_send_loglevel_setting(module); if (ret != 0) { MSG(1, "ERROR: Can't set the log level inin the output module."); module->working = 0; kill(module->pid, 9); waitpid(module->pid, NULL, WNOHANG); destroy_module(module); return NULL; } return module; } int unload_output_module(OutputModule * module) { assert(module != NULL); MSG(3, "Unloading module name=%s", module->name); output_close(module); close(module->pipe_in[1]); close(module->pipe_out[0]); destroy_module(module); return 0; } int reload_output_module(OutputModule * old_module) { OutputModule *new_module; int pos; assert(old_module != NULL); assert(old_module->name != NULL); if (old_module->working) return 0; MSG(3, "Reloading output module %s", old_module->name); output_close(old_module); close(old_module->pipe_in[1]); close(old_module->pipe_out[0]); new_module = load_output_module(old_module->name, old_module->filename, old_module->configfilename, old_module->debugfilename); if (new_module == NULL) { MSG(3, "Can't load module %s while reloading modules.", old_module->name); return -1; } pos = g_list_index(output_modules, old_module); output_modules = g_list_remove(output_modules, old_module); output_modules = g_list_insert(output_modules, new_module, pos); destroy_module(old_module); return 0; } int output_module_debug(OutputModule * module) { char *new_log_path; assert(module != NULL); assert(module->name != NULL); if (!module->working) return -1; MSG(4, "Output module debug logging for %s into %s", module->name, SpeechdOptions.debug_destination); new_log_path = g_strdup_printf("%s/%s.log", SpeechdOptions.debug_destination, module->name); output_send_debug(module, 1, new_log_path); return 0; } int output_module_nodebug(OutputModule * module) { assert(module != NULL); assert(module->name != NULL); if (!module->working) return -1; MSG(4, "Output module debug logging off for", module->name); output_send_debug(module, 0, NULL); return 0; } static GList *requested_modules = NULL; /* * module_already_requested: determine whether we have already received * a load request for a given module. * Parameters: * module_name: the name of the module. * module_cmd: name of the binary associated with this module. * module_cfgfile: the name of the module's configuration file. * * Returns: * TRUE if the module was previously requested, FALSE otherwise. * * A module is previously requested if: * 1. module_name is the same as some other module in the list of load * requests. We select a given output module using its name, so names * must be unique. * 2. The name of the executable and the name of the configuration file * are exactly the same as those of another module. * It is acceptable to load the same module binary multiple times, where * each instance uses a different configuration file. In fact, this is * how sd_generic works. The instances are differentiated by module_name. * However, it is not reasonable to load multiple instances, all of which * use the same (binary, config file) pair. * These two rules should cover all cases adequately. * */ gboolean module_already_requested(char *module_name, char *module_cmd, char *module_cfgfile) { GList *lp; for (lp = requested_modules; lp != NULL; lp = lp->next) { char **params = lp->data; if (strcmp(module_name, params[0]) == 0 || (strcmp(module_cmd, params[1]) == 0 && strcmp(module_cfgfile, params[2]) == 0)) return TRUE; } return FALSE; } /* * module_add_load_request - request that a module be loaded. * In other words, add it to the list of modules which will be loaded * by module_load_requested_modules. * Returns: nothing. * Parameters: * module_name: the name of the module. * module_cmd: name of the binary associated with this module. * module_cfgfile: the name of the module's configuration file. * module_dbgfile: name of the file to which the module writes logging * and debugging information. * Note that all parameters are dynamically-allocated strings (char *), * and the caller relinquishes ownership of them when calling this function. */ void module_add_load_request(char *module_name, char *module_cmd, char *module_cfgfile, char *module_dbgfile) { char **module_params = NULL; if (module_already_requested(module_name, module_cmd, module_cfgfile)) { MSG(1, "Load request for module %s with command %s and configuration file %s was previously received; ignoring the second one.", module_name, module_cmd, module_cfgfile); g_free(module_name); g_free(module_cmd); g_free(module_cfgfile); g_free(module_dbgfile); return; } module_params = g_malloc(4 * sizeof(char *)); module_params[0] = module_name; module_params[1] = module_cmd; module_params[2] = module_cfgfile; module_params[3] = module_dbgfile; requested_modules = g_list_append(requested_modules, module_params); MSG(5, "Module name=%s being inserted into requested_modules list", module_params[0]); } /* * module_load_requested_modules: load all modules requested by calls * to module_add_load_request. * Returns: nothing. * Parameters: none. */ void module_load_requested_modules(void) { while (NULL != requested_modules) { OutputModule *new_module; char **module_params = requested_modules->data; new_module = load_output_module(module_params[0], module_params[1], module_params[2], module_params[3]); if (new_module != NULL) output_modules = g_list_append(output_modules, new_module); g_free(module_params[0]); g_free(module_params[1]); g_free(module_params[2]); g_free(module_params[3]); g_free(module_params); requested_modules = g_list_delete_link(requested_modules, requested_modules); } } /* * module_number_of_requested_modules: return the current number of requested modules. * Returns: number of modules. * Parameters: none. */ guint module_number_of_requested_modules(void) { if (requested_modules == NULL) { return 0; } return g_list_length(requested_modules); } speech-dispatcher-0.8.3/src/server/set.c0000664000175000017500000003304412536417045015107 00000000000000 /* * set.c - Settings related functions for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: set.c,v 1.46 2008-07-01 09:00:32 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "set.h" #include "alloc.h" #include "msg.h" gint spd_str_compare(gconstpointer a, gconstpointer b) { return strcmp((char *)a, (char *)b); } int set_priority_self(int fd, SPDPriority priority) { int uid; int ret; uid = get_client_uid_by_fd(fd); if (uid == 0) return 1; ret = set_priority_uid(uid, priority); return ret; } int set_priority_uid(int uid, SPDPriority priority) { TFDSetElement *settings; if ((priority < SPD_IMPORTANT) || (priority > SPD_PROGRESS)) return 1; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->priority = priority; return 0; } #define SET_SELF_ALL(type, param) \ int \ set_ ## param ## _self(int fd, type param) \ { \ int uid; \ uid = get_client_uid_by_fd(fd); \ if (uid == 0) return 1; \ return set_ ## param ## _uid(uid, param); \ } \ int \ set_ ## param ## _all(type param) \ { \ int i; \ int uid; \ int err = 0; \ for(i=1;i<=SpeechdStatus.max_fd;i++){ \ uid = get_client_uid_by_fd(i); \ if (uid == 0) continue; \ err += set_ ## param ## _uid(uid, param); \ } \ if (err > 0) return 1; \ return 0; \ } SET_SELF_ALL(int, rate) int set_rate_uid(int uid, int rate) { TFDSetElement *settings; if ((rate > 100) || (rate < -100)) return 1; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.rate = rate; return 0; } SET_SELF_ALL(int, pitch) int set_pitch_uid(int uid, int pitch) { TFDSetElement *settings; if ((pitch > 100) || (pitch < -100)) return 1; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.pitch = pitch; return 0; } SET_SELF_ALL(int, volume) int set_volume_uid(int uid, int volume) { TFDSetElement *settings; if ((volume > 100) || (volume < -100)) return 1; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.volume = volume; return 0; } SET_SELF_ALL(char *, voice) int set_voice_uid(int uid, char *voice) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; if (!strcmp(voice, "male1")) settings->msg_settings.voice_type = SPD_MALE1; else if (!strcmp(voice, "male2")) settings->msg_settings.voice_type = SPD_MALE2; else if (!strcmp(voice, "male3")) settings->msg_settings.voice_type = SPD_MALE3; else if (!strcmp(voice, "female1")) settings->msg_settings.voice_type = SPD_FEMALE1; else if (!strcmp(voice, "female2")) settings->msg_settings.voice_type = SPD_FEMALE2; else if (!strcmp(voice, "female3")) settings->msg_settings.voice_type = SPD_FEMALE3; else if (!strcmp(voice, "child_male")) settings->msg_settings.voice_type = SPD_CHILD_MALE; else if (!strcmp(voice, "child_female")) settings->msg_settings.voice_type = SPD_CHILD_FEMALE; else return 1; if (settings->msg_settings.voice.name != NULL) { g_free(settings->msg_settings.voice.name); settings->msg_settings.voice.name = NULL; } return 0; } SET_SELF_ALL(SPDPunctuation, punctuation_mode) int set_punctuation_mode_uid(int uid, SPDPunctuation punctuation) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.punctuation_mode = punctuation; return 0; } #define SET_PARAM_STR(name) \ settings->name = set_param_str(settings->name, name); SET_SELF_ALL(SPDCapitalLetters, capital_letter_recognition) int set_capital_letter_recognition_uid(int uid, SPDCapitalLetters recogn) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.cap_let_recogn = recogn; return 0; } SET_SELF_ALL(SPDSpelling, spelling) int set_spelling_uid(int uid, SPDSpelling spelling) { TFDSetElement *settings; assert((spelling == 0) || (spelling == 1)); settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.spelling_mode = spelling; return 0; } SET_SELF_ALL(char *, language) int set_language_uid(int uid, char *language) { TFDSetElement *settings; char *output_module; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.voice.language = set_param_str(settings->msg_settings.voice.language, language); /* Check if it is not desired to change output module */ output_module = g_hash_table_lookup(language_default_modules, language); if (output_module != NULL) set_output_module_uid(uid, output_module); return 0; } SET_SELF_ALL(char *, synthesis_voice) int set_synthesis_voice_uid(int uid, char *synthesis_voice) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->msg_settings.voice.name = set_param_str(settings->msg_settings.voice.name, synthesis_voice); /* Delete ordinary voice settings so that we don't mix */ settings->msg_settings.voice_type = -1; return 0; } #define CHECK_SET_PAR(name, ival) \ if (cl_set->val.name != ival){ set->name = cl_set->val.name; \ MSG(4,"parameter " #name " set to %d", cl_set->val.name); } #define CHECK_SET_PAR_STR(name) \ if (cl_set->val.name != NULL){ \ g_free(set->name); \ set->name = g_strdup(cl_set->val.name); \ MSG(4,"parameter " #name " set to %s", cl_set->val.name); \ } void update_cl_settings(gpointer data, gpointer user_data) { TFDSetClientSpecific *cl_set = data; TFDSetElement *set = user_data; MSG(4, "Updating client specific settings %s against %s", set->client_name, cl_set->pattern); if (fnmatch(cl_set->pattern, set->client_name, 0)) return; /* Warning: If you modify this, you must also modify cb_BeginClient in config.c ! */ CHECK_SET_PAR(msg_settings.rate, -101) CHECK_SET_PAR(msg_settings.pitch, -101) CHECK_SET_PAR(msg_settings.volume, -101) CHECK_SET_PAR(msg_settings.punctuation_mode, -1) CHECK_SET_PAR(msg_settings.spelling_mode, -1) CHECK_SET_PAR(msg_settings.voice_type, -1) CHECK_SET_PAR(msg_settings.cap_let_recogn, -1) CHECK_SET_PAR(pause_context, -1) CHECK_SET_PAR(ssml_mode, -1) CHECK_SET_PAR_STR(msg_settings.voice.language) CHECK_SET_PAR_STR(output_module) return; } #undef CHECK_SET_PAR #undef CHECK_SET_PAR_STR int set_client_name_self(int fd, char *client_name) { TFDSetElement *settings; int dividers = 0; int i; assert(client_name != NULL); settings = get_client_settings_by_fd(fd); if (settings == NULL) return 1; /* Is the parameter a valid client name? */ for (i = 0; i <= strlen(client_name) - 1; i++) if (client_name[i] == ':') dividers++; if (dividers != 2) return 1; SET_PARAM_STR(client_name); /* Update fd_set for this cilent with client-specific options */ g_list_foreach(client_specific_settings, update_cl_settings, settings); return 0; } SET_SELF_ALL(char *, output_module) int set_output_module_uid(int uid, char *output_module) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; if (output_module == NULL) return 1; MSG(5, "Setting output module to %s", output_module); MSG(5, "In set_output_module the desired output module is x%s", output_module); SET_PARAM_STR(output_module); /* Delete synth_voice since it is module specific */ if (settings->msg_settings.voice.name != NULL) { g_free(settings->msg_settings.voice.name); settings->msg_settings.voice.name = NULL; } return 0; } SET_SELF_ALL(int, pause_context) int set_pause_context_uid(int uid, int pause_context) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->pause_context = pause_context; return 0; } SET_SELF_ALL(SPDDataMode, ssml_mode) int set_ssml_mode_uid(int uid, SPDDataMode ssml_mode) { TFDSetElement *settings; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; settings->ssml_mode = ssml_mode; return 0; } SET_SELF_ALL(int, debug) int set_debug_uid(int uid, int debug) { char *debug_logfile_path; /* Do not switch debugging on when already on and vice-versa */ if (SpeechdOptions.debug && debug) return 1; if (!SpeechdOptions.debug && !debug) return 1; if (debug) { debug_logfile_path = g_strdup_printf("%s/speech-dispatcher.log", SpeechdOptions.debug_destination); debug_logfile = fopen(debug_logfile_path, "w"); if (debug_logfile == NULL) { MSG(3, "Error: can't open additional debug logging file %s!\n", debug_logfile_path); return 1; } SpeechdOptions.debug = debug; g_free(debug_logfile_path); /* Redirecting debugging for all output modules */ speechd_modules_debug(); } else { SpeechdOptions.debug = 0; speechd_modules_nodebug(); fclose(debug_logfile); } return 0; } #define SET_NOTIFICATION_STATE(state) \ if (val) \ settings->notification = settings->notification | SPD_ ## state; \ else \ settings->notification = settings->notification & (! SPD_ ## state); int set_notification_self(int fd, char *type, int val) { TFDSetElement *settings; int uid; uid = get_client_uid_by_fd(fd); if (uid == 0) return 1; settings = get_client_settings_by_uid(uid); if (settings == NULL) return 1; if (!strcmp(type, "begin")) { SET_NOTIFICATION_STATE(BEGIN); } else if (!strcmp(type, "end")) { SET_NOTIFICATION_STATE(END); } else if (!strcmp(type, "index_marks")) { SET_NOTIFICATION_STATE(INDEX_MARKS); } else if (!strcmp(type, "pause")) { SET_NOTIFICATION_STATE(PAUSE); } else if (!strcmp(type, "resume")) { SET_NOTIFICATION_STATE(RESUME); } else if (!strcmp(type, "cancel")) { SET_NOTIFICATION_STATE(CANCEL); } else if (!strcmp(type, "all")) { SET_NOTIFICATION_STATE(END); SET_NOTIFICATION_STATE(BEGIN); SET_NOTIFICATION_STATE(INDEX_MARKS); SET_NOTIFICATION_STATE(CANCEL); SET_NOTIFICATION_STATE(PAUSE); SET_NOTIFICATION_STATE(RESUME); } else return 1; return 0; } TFDSetElement *default_fd_set(void) { TFDSetElement *new; new = (TFDSetElement *) g_malloc(sizeof(TFDSetElement)); new->paused = 0; /* Fill with the global settings values */ /* We can't use global_fdset copy as this returns static structure and we need dynamic */ new->priority = GlobalFDSet.priority; new->msg_settings.punctuation_mode = GlobalFDSet.msg_settings.punctuation_mode; new->msg_settings.rate = GlobalFDSet.msg_settings.rate; new->msg_settings.pitch = GlobalFDSet.msg_settings.pitch; new->msg_settings.volume = GlobalFDSet.msg_settings.volume; new->msg_settings.voice.language = g_strdup(GlobalFDSet.msg_settings.voice.language); new->output_module = g_strdup(GlobalFDSet.output_module); new->client_name = g_strdup(GlobalFDSet.client_name); new->index_mark = g_strdup(GlobalFDSet.index_mark); new->audio_output_method = g_strdup(GlobalFDSet.audio_output_method); new->audio_oss_device = g_strdup(GlobalFDSet.audio_oss_device); new->audio_alsa_device = g_strdup(GlobalFDSet.audio_alsa_device); new->audio_nas_server = g_strdup(GlobalFDSet.audio_nas_server); new->audio_pulse_server = g_strdup(GlobalFDSet.audio_pulse_server); new->msg_settings.voice_type = GlobalFDSet.msg_settings.voice_type; new->msg_settings.voice.name = NULL; new->msg_settings.spelling_mode = GlobalFDSet.msg_settings.spelling_mode; new->msg_settings.cap_let_recogn = GlobalFDSet.msg_settings.cap_let_recogn; new->pause_context = GlobalFDSet.pause_context; new->ssml_mode = GlobalFDSet.ssml_mode; new->notification = GlobalFDSet.notification; new->active = 1; new->hist_cur_uid = -1; new->hist_cur_pos = -1; new->hist_sorted = 0; new->index_mark = NULL; new->paused_while_speaking = 0; return (new); } int get_client_uid_by_fd(int fd) { int *uid; if (fd <= 0) return 0; uid = g_hash_table_lookup(fd_uid, &fd); if (uid == NULL) return 0; return *uid; } TFDSetElement *get_client_settings_by_fd(int fd) { TFDSetElement *settings; int uid; uid = get_client_uid_by_fd(fd); if (uid == 0) return NULL; settings = g_hash_table_lookup(fd_settings, &uid); return settings; } TFDSetElement *get_client_settings_by_uid(int uid) { TFDSetElement *element; if (uid < 0) return NULL; element = g_hash_table_lookup(fd_settings, &uid); return element; } void remove_client_settings_by_uid(int uid) { TFDSetElement *element; assert(uid > 0); element = (TFDSetElement *) g_hash_table_lookup(fd_settings, &uid); if (element) { mem_free_fdset(element); g_hash_table_remove(fd_settings, &uid); g_free(element); } else { MSG(5, "Warning: FDSet element to be removed not found"); } } char *set_param_str(char *parameter, char *value) { char *new; if (value == NULL) { new = NULL; return new; } new = g_realloc(parameter, (strlen(value) + 1) * sizeof(char)); strcpy(new, value); return new; } speech-dispatcher-0.8.3/src/server/sem_functions.c0000664000175000017500000000234512522771346017172 00000000000000 /* * sem_functions.c - Functions for manipulating System V / IPC semaphores * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: sem_functions.c,v 1.9 2006-07-11 16:12:27 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "speechd.h" #include "sem_functions.h" void speaking_semaphore_post(void) { char buf[1]; buf[0] = 42; const ssize_t wr_bytes = safe_write(speaking_pipe[1], buf, 1); if (wr_bytes != 1) FATAL("write to polled fd: could not write 1 byte"); } speech-dispatcher-0.8.3/src/server/history.h0000644000175000017500000000336212233560613016012 00000000000000 /* * history.h - History functions for Speech Dispatcher header * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: history.h,v 1.11 2006-07-11 16:12:27 hanke Exp $ */ #ifndef HISTORY_H #define HISTORY_H #include "speechd.h" char *history_get_client_list(); char *history_get_message_list(guint client_id, int from, int num); char *history_get_last(int fd); char *history_cursor_set_last(int fd, guint client_id); char *history_cursor_set_first(int fd, guint client_id); char *history_cursor_set_pos(int fd, guint client_id, int pos); char *history_cursor_next(int fd); char *history_cursor_prev(int fd); char *history_cursor_get(int fd); char *history_cursor_forward(int fd); char *history_cursor_backward(int fd); char *history_say_id(int fd, int id); char *history_get_client_id(int fd); char *history_get_message(int uid); int history_add_message(TSpeechDMessage * msg); /* Internal functions */ GList *get_messages_by_client(int uid); gint message_compare_id(gconstpointer element, gconstpointer value); #endif /* HISTORY_H */ speech-dispatcher-0.8.3/src/server/index_marking.c0000664000175000017500000001167512522771346017143 00000000000000 /* * index_marking.c -- Implements functions handling index marking * for Speech Dispatcher * * Copyright (C) 2001,2002,2003, 2007 Brailcom, o.p.s * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: index_marking.c,v 1.17 2008-06-11 12:11:25 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include "index_marking.h" void insert_index_marks(TSpeechDMessage * msg, SPDDataMode ssml_mode) { GString *marked_text; char *pos; char character[6]; char character2[6]; gunichar u_char; int n = 0; int ret; int inside_tag = 0; marked_text = g_string_new(""); assert(msg != NULL); assert(msg->buf != NULL); MSG2(5, "index_marking", "MSG before index marking: |%s|, ssml_mode=%d", msg->buf, ssml_mode); if (ssml_mode == SPD_DATA_TEXT) g_string_printf(marked_text, ""); pos = msg->buf; while (pos) { ret = spd_utf8_read_char(pos, character); if (ret == 0 || (strlen(character) == 0)) break; u_char = g_utf8_get_char(character); if (u_char == '<') { if (ssml_mode == SPD_DATA_SSML) { inside_tag = 1; g_string_append_printf(marked_text, "%s", character); } else g_string_append_printf(marked_text, "<"); } else if (u_char == '>') { if (ssml_mode == SPD_DATA_SSML) { inside_tag = 0; g_string_append_printf(marked_text, "%s", character); } else g_string_append_printf(marked_text, ">"); } else if (u_char == '&') { if (ssml_mode == SPD_DATA_SSML) { g_string_append_printf(marked_text, "%s", character); } else { if (!inside_tag) g_string_append_printf(marked_text, "&"); } } else if (((u_char == '.') || (u_char == '?') || (u_char == '!')) && !inside_tag) { pos = g_utf8_find_next_char(pos, NULL); ret = spd_utf8_read_char(pos, character2); if ((ret == 0) || (strlen(character2) == 0)) { g_string_append_printf(marked_text, "%s", character); MSG2(6, "index_marking", "MSG altering 1: |%s|", marked_text->str); break; } u_char = g_utf8_get_char(character2); if ((g_unichar_isspace(u_char)) || (u_char == '<') || (u_char == '&')) { g_string_append_printf(marked_text, "%s" SD_MARK_HEAD "%d" SD_MARK_TAIL, character, n); n++; MSG2(6, "index_marking", "MSG altering 2: |%s|", marked_text->str); continue; } else { g_string_append_printf(marked_text, "%s", character); MSG2(6, "index_marking", "MSG altering 3: |%s|", marked_text->str); continue; } } else { g_string_append_printf(marked_text, "%s", character); } pos = g_utf8_find_next_char(pos, NULL); } if (ssml_mode == SPD_DATA_TEXT) g_string_append_printf(marked_text, ""); g_free(msg->buf); msg->buf = marked_text->str; g_string_free(marked_text, 0); MSG2(5, "index_marking", "MSG after index marking: |%s|", msg->buf); } /* Finds the index mark specified in _mark_ . */ char *find_index_mark(TSpeechDMessage * msg, int mark) { char str_mark[64]; char *pos; char *p; MSG(5, "Trying to find index mark %d", mark); /* Fix this for variable space number */ sprintf(str_mark, SD_MARK_HEAD "%d" SD_MARK_TAIL, mark); p = strstr(msg->buf, str_mark); if (p == 0) return NULL; pos = p + strlen(str_mark); MSG(5, "Search for index mark sucessfull"); return pos; } /* Deletes all index marks from the given text */ char *strip_index_marks(char *buf, SPDDataMode ssml_mode) { GString *str; char *strret; char str_mark[] = SD_MARK_HEAD; char *p; char *p_old; if (ssml_mode == SPD_DATA_SSML) str = g_string_new(""); else str = g_string_new(""); MSG2(5, "index_marking", "Message before stripping index marks: |%s|", buf); p = buf; while (1) { if (*p == '\0') break; p_old = p; p = strstr(p, str_mark); if (p != NULL) { g_string_append_len(str, p_old, (int)(p - p_old)); } else { g_string_append(str, p_old); break; } do { p++; } while (*p != '>' && *p != '\0'); if (*p == '>') p++; } if (ssml_mode == SPD_DATA_TEXT) { p = strstr(str->str, ""); if (p != NULL) *p = 0; } strret = str->str; g_string_free(str, 0); MSG2(5, "index_marking", "Message after stripping index marks: |%s|", strret); return strret; } speech-dispatcher-0.8.3/src/server/compare.h0000664000175000017500000000235212522771346015747 00000000000000 /* * compare.h - Auxiliary functions for comparing elements in lists * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: compare.h,v 1.3 2006-07-11 16:12:27 hanke Exp $ */ #ifndef COMPARE_H #define COMPARE_H gint compare_message_fd(gconstpointer element, gconstpointer value, gpointer x); gint compare_message_uid(gconstpointer element, gconstpointer value, gpointer x); /* Pointers to functions compare_message_fd and compare_message_uid */ gint(*p_msg_lc) (); gint(*p_msg_uid_lc) (); #endif /* COMPARE_H */ speech-dispatcher-0.8.3/src/server/server.c0000664000175000017500000002040212522771346015616 00000000000000 /* * server.c - Speech Dispatcher server core * * Copyright (C) 2001,2002,2003, 2004, 2006, 2007 Brailcom, o.p.s * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: server.c,v 1.85 2008-06-27 12:28:58 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include "speechd.h" #include "server.h" #include "set.h" #include "speaking.h" #include "sem_functions.h" #include "history.h" int last_message_id = 0; /* Put a message into its queue. * * Parameters: * new -- the (allocated) message structure to queue, it must contain * the text to be queued in new->buf * fd -- file descriptor of the calling client (positive) * unique id if the client is gone (negative) -- in this * case it means we are reloading the message and the * behavior is slightly different * history_flag -- should this message be included in history? * type -- type of the message (see ../../include/speechd_types.h) * reparted -- if this is a preprocessed message reparted * in more pieces * It returns 0 on success, -1 otherwise. */ #define COPY_SET_STR(name) \ new->settings.name = (char*) g_strdup(settings->name); /* Queue a message _new_. When fd is a positive number, it means we have a new message from the client on connection fd and we should fill in the proper settings. When fd is negative, it's absolute value is the client uid and the message _new_ already contains a fully filled in settings structure which should not be overwritten (on must be cautius that the original client might not be still connected to speechd). _history_flag_ indicates if inclusion into history is desired and _reparted_ flag indicates whether this message is a part of a reparted message (one of a block of messages). */ int queue_message(TSpeechDMessage * new, int fd, int history_flag, SPDMessageType type, int reparted) { TFDSetElement *settings; TSpeechDMessage *message_copy; int id; GList *element; /* Check function parameters */ if (new == NULL) return -1; if (new->buf == NULL) return -1; if (strlen(new->buf) < 1) return -1; /* Find settings for this particular client */ if (fd > 0) { settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL ("Couldn't find settings for active client, internal error."); } else if (fd < 0) { settings = get_client_settings_by_uid(-fd); } else { if (SPEECHD_DEBUG) FATAL("fd == 0, this shouldn't happen..."); return -1; } MSG(5, "In queue_message desired output module is %s", settings->output_module); if (fd > 0) { /* Copy the settings to the new to-be-queued element */ new->settings = *settings; new->settings.type = type; new->settings.index_mark = NULL; COPY_SET_STR(client_name); COPY_SET_STR(output_module); COPY_SET_STR(msg_settings.voice.language); COPY_SET_STR(msg_settings.voice.name); COPY_SET_STR(index_mark); COPY_SET_STR(audio_output_method); COPY_SET_STR(audio_oss_device); COPY_SET_STR(audio_alsa_device); COPY_SET_STR(audio_nas_server); COPY_SET_STR(audio_pulse_server); /* And we set the global id (note that this is really global, not * depending on the particular client, but unique) */ last_message_id++; new->id = last_message_id; new->time = time(NULL); new->settings.paused_while_speaking = 0; } id = new->id; new->settings.reparted = reparted; MSG(5, "Queueing message |%s| with priority %d", new->buf, settings->priority); /* If desired, put the message also into history */ /* NOTE: This should be before we put it into queues() to avoid conflicts with the other thread (it could delete the message before we woud copy it) */ // if (history_flag){ if (0) { pthread_mutex_lock(&element_free_mutex); history_add_message(new); pthread_mutex_unlock(&element_free_mutex); } pthread_mutex_lock(&element_free_mutex); /* Put the element new to queue according to it's priority. */ check_locked(&element_free_mutex); switch (settings->priority) { case SPD_IMPORTANT: MessageQueue->p1 = g_list_append(MessageQueue->p1, new); break; case SPD_MESSAGE: MessageQueue->p2 = g_list_append(MessageQueue->p2, new); break; case SPD_TEXT: MessageQueue->p3 = g_list_append(MessageQueue->p3, new); break; case SPD_NOTIFICATION: MessageQueue->p4 = g_list_append(MessageQueue->p4, new); break; case SPD_PROGRESS: MessageQueue->p5 = g_list_append(MessageQueue->p5, new); //clear last_p5_block if we get new block or no block message element = g_list_last(last_p5_block); if (!element || !element->data || ((TSpeechDMessage *) (element->data))-> settings.reparted != new->settings.reparted) { g_list_foreach(last_p5_block, (GFunc) mem_free_message, NULL); g_list_free(last_p5_block); last_p5_block = NULL; } // insert message message_copy = spd_message_copy(new); if (message_copy != NULL) last_p5_block = g_list_append(last_p5_block, message_copy); break; default: FATAL("Nonexistent priority given"); } /* Look what is the highest priority of waiting * messages and take the desired actions on other * messages */ /* TODO: Do the entire resolve_priorities() here is certainly not the best approach possible. Especially the part that calls output_stop() should be moved to speaking.c speak() function in future */ resolve_priorities(settings->priority); pthread_mutex_unlock(&element_free_mutex); speaking_semaphore_post(); MSG(5, "Message inserted into queue."); return id; } #undef COPY_SET_STR /* Switch data mode on for the particular client. */ int server_data_on(int fd) { TSpeechDSock *speechd_socket = speechd_socket_get_by_fd(fd); assert(speechd_socket); /* Mark this client as ,,sending data'' */ speechd_socket->awaiting_data = 1; /* Create new output buffer */ speechd_socket->o_buf = g_string_new(""); MSG(4, "Switching to data mode..."); return 0; } /* Switch data mode off for the particular client. */ void server_data_off(int fd) { TSpeechDSock *speechd_socket = speechd_socket_get_by_fd(fd); assert(speechd_socket); assert(speechd_socket->o_buf); speechd_socket->o_bytes = 0; g_string_free(speechd_socket->o_buf, 1); speechd_socket->o_buf = NULL; } /* Serve the client on _fd_ if we got some activity. */ int serve(int fd) { char *reply; /* Reply to the client */ int ret; { size_t bytes = 0; /* Number of bytes we got */ int buflen = BUF_SIZE; char *buf = (char *)g_malloc(buflen + 1); /* Read data from socket */ /* Read exactly one complete line, the `parse' routine relies on it */ { while (1) { int n = read(fd, buf + bytes, 1); if (n <= 0) { g_free(buf); return -1; } /* Note, bytes is a 0-based index into buf. */ if ((buf[bytes] == '\n') && (bytes >= 1) && (buf[bytes - 1] == '\r')) { buf[++bytes] = '\0'; break; } if (buf[bytes] == '\0') buf[bytes] = '?'; if ((++bytes) == buflen) { buflen *= 2; buf = g_realloc(buf, buflen + 1); } } } /* Parse the data and read the reply */ MSG2(5, "protocol", "%d:DATA:|%s| (%d)", fd, buf, bytes); reply = parse(buf, bytes, fd); g_free(buf); } if (reply == NULL) FATAL("Internal error, reply from parse() is NULL!"); /* Send the reply to the socket */ if (strlen(reply) == 0) { g_free(reply); return 0; } if (reply[0] != '9') { /* Don't reply to data etc. */ pthread_mutex_lock(&socket_com_mutex); MSG2(5, "protocol", "%d:REPLY:|%s|", fd, reply); ret = write(fd, reply, strlen(reply)); g_free(reply); pthread_mutex_unlock(&socket_com_mutex); if (ret == -1) { MSG(5, "write() error: %s", strerror(errno)); return -1; } } else { g_free(reply); } return 0; } speech-dispatcher-0.8.3/src/server/set.h0000664000175000017500000000767112536417045015123 00000000000000 /* * set.h - Settings related functions for Speech Dispatcher header * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: set.h,v 1.17 2008-06-27 12:29:02 hanke Exp $ */ #ifndef SET_H #define SET_H #include "speechd.h" #include "history.h" TFDSetElement *get_client_settings_by_uid(int uid); TFDSetElement *get_client_settings_by_fd(int fd); void remove_client_settings_by_uid(int uid); int get_client_uid_by_fd(int fd); int set_priority_uid(int uid, SPDPriority priority); int set_language_uid(int uid, char *language); int set_rate_uid(int uid, int rate); int set_pitch_uid(int uid, int pitch); int set_volume_uid(int uid, int volume); int set_punct_mode_uid(int uid, int punct); int set_cap_let_recog_uid(int uid, int recog); int set_spelling_uid(int uid, SPDSpelling spelling); int set_output_module_self(int uid, char *output_module); int set_voice_uid(int uid, char *voice); int set_synthesis_voice_uid(int uid, char *synthesis_voice); int set_punctuation_mode_uid(int uid, SPDPunctuation punctuation); int set_capital_letter_recognition_uid(int uid, SPDCapitalLetters recogn); int set_output_module_uid(int uid, char *output_module); int set_ssml_mode_uid(int uid, SPDDataMode ssml_mode); int set_pause_context_uid(int uid, int pause_context); int set_debug_uid(int uid, int debug); int set_debug_destination_uid(int uid, char *debug_destination); int set_priority_self(int fd, SPDPriority priority); int set_language_self(int fd, char *language); int set_rate_self(int fd, int rate); int set_pitch_self(int fd, int pitch); int set_volume_self(int fd, int volume); int set_punct_mode_self(int fd, int punct); int set_cap_let_recog_self(int fd, int recog); int set_spelling_self(int fd, SPDSpelling spelling); int set_output_module_self(int fd, char *output_module); int set_client_name_self(int fd, char *client_name); int set_voice_self(int fd, char *voice); int set_synthesis_voice_self(int fd, char *synthesis_voice); int set_punctuation_mode_self(int fd, SPDPunctuation punctuation); int set_capital_letter_recognition_self(int fd, SPDCapitalLetters recogn); int set_ssml_mode_self(int fd, SPDDataMode ssml_mode); int set_notification_self(int fd, char *type, int val); int set_pause_context_self(int fd, int pause_context); int set_debug_self(int fd, int debug); int set_debug_destination_self(int fd, char *debug_destination); int set_priority_all(SPDPriority priority); int set_language_all(char *language); int set_rate_all(int rate); int set_pitch_all(int pitch); int set_volume_all(int volume); int set_punct_mode_all(int punct); int set_cap_let_recog_all(int recog); int set_spelling_all(SPDSpelling spelling); int set_output_module_all(char *output_module); int set_voice_all(char *voice); int set_synthesis_voice_all(char *synthesis_voice); int set_punctuation_mode_all(SPDPunctuation punctuation); int set_capital_letter_recognition_all(SPDCapitalLetters recogn); int set_ssml_mode_all(SPDDataMode ssml_mode); int set_pause_context_all(int pause_context); int set_debug_all(int debug); int set_debug_destination_all(char *debug_destination); TFDSetElement *default_fd_set(void); char *set_param_str(char *parameter, char *value); void update_cl_settings(gpointer data, gpointer user_data); gint spd_str_compare(gconstpointer a, gconstpointer b); #endif speech-dispatcher-0.8.3/src/server/speaking.h0000664000175000017500000000657012522771346016130 00000000000000 /* * speaking.h - Speech Dispatcher speech output functions header * * Copyright (C) 2001,2002,2003 Brailcom, o.p.s, Prague 2, * Vysehradska 3/255, 128 00, * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: speaking.h,v 1.11 2006-07-11 16:12:27 hanke Exp $ */ #ifndef SPEAKING_H #define SPEAKING_H #include OutputModule *speaking_module; int speaking_uid; int speaking_gid; /* Pause and resume handling */ int pause_requested; int pause_requested_fd; int pause_requested_uid; int resume_requested; /* Speak() is responsible for getting right text from right * queue in right time and saying it loud through corresponding * synthetiser. (Note that there can be a big problem with synchronization). * This runs in a separate thread. */ void *speak(void *data); /* Put this message into queue again, stripping index marks etc. */ int reload_message(TSpeechDMessage * msg); /* Speech flow control functions */ void speaking_stop(int uid); void speaking_stop_all(); void speaking_cancel(int uid); void speaking_cancel_all(); int speaking_pause(int fd, int uid); int speaking_pause_all(int fd); int speaking_resume(int uid); int speaking_resume_all(); /* Internal speech flow control functions */ /* If there is someone speaking on some output * module, return 1, otherwise 0. */ int is_sb_speaking(); /* Stops speaking and cancels currently spoken message.*/ void stop_speaking_active_module(); int stop_priority(SPDPriority priority); void stop_from_uid(int uid); /* Decides if the message should (not) be spoken now */ gint message_nto_speak(gconstpointer, gconstpointer); void set_speak_thread_attributes(); /* Do priority interaction */ void resolve_priorities(SPDPriority priority); /* Queue interaction helper functions */ TSpeechDMessage *get_message_from_queues(); GList *speaking_get_queue(SPDPriority priority); void speaking_set_queue(SPDPriority priority, GList * queue); gint sortbyuid(gconstpointer a, gconstpointer b); int client_has_messages(int uid); /* Get the unique id of the client who is speaking * on some output module */ int get_speaking_client_uid(); int socket_send_msg(int fd, char *msg); int report_index_mark(TSpeechDMessage * msg, char *index_mark); int report_begin(TSpeechDMessage * msg); int report_end(TSpeechDMessage * msg); int report_pause(TSpeechDMessage * msg); int report_resume(TSpeechDMessage * msg); int report_cancel(TSpeechDMessage * msg); GList *empty_queue(GList * queue); GList *empty_queue_by_time(GList * queue, unsigned int uid); int stop_priority_older_than(SPDPriority priority, unsigned int uid); GList *stop_priority_from_uid(GList * queue, const int uid); void stop_priority_except_first(SPDPriority priority); #endif /* SPEAKING_H */ speech-dispatcher-0.8.3/src/server/options.c0000664000175000017500000001473212533727516016016 00000000000000/* * options.c - Parse and process possible command line options * * Copyright (C) 2003, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: options.c,v 1.13 2008-07-10 15:35:56 hanke Exp $ */ /* NOTE: Be careful not to include options.h, we would get repetitive initializations warnings */ #ifdef HAVE_CONFIG_H #include #endif #include #include "speechd.h" #include "options.h" #include static const struct option spd_long_options[] = { {"run-daemon", 0, 0, 'd'}, {"run-single", 0, 0, 's'}, {"spawn", 0, 0, 'a'}, {"log-level", 1, 0, 'l'}, {"log-dir", required_argument, 0, 'L'}, {"communication-method", 1, 0, 'c'}, {"socket-path", 1, 0, 'S'}, {"port", 1, 0, 'p'}, {"pid-file", 1, 0, 'P'}, {"config-dir", required_argument, 0, 'C'}, {"version", 0, 0, 'v'}, {"debug", 0, 0, 'D'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; static const char *const spd_short_options = "dsal:L:c:S:p:P:C:vDh"; void options_print_help(char *argv[]) { assert(argv); assert(argv[0]); printf(_("Usage: ")); printf ("%s [-{d|s}] [-l {1|2|3|4|5}] [-c com_method] [-S socket_path] [-p port] | [-v] | [-h]\n", argv[0]); printf(_("%s -- Common interface for Speech Synthesis %s\n\n"), "Speech Dispatcher", "(GNU GPL)"); printf("-d, --run-daemon\t"); printf(_("Run as a daemon\n")); printf("-s, --run-single\t"); printf(_("Run as single application\n")); printf("-a, --spawn\t\t"); printf(_("Start only if autospawn is not disabled\n")); printf("-l, --log-level\t\t"); printf(_("Set log level (between %d and %d)\n"), 1, 5); printf("-L, --log-dir\t\t"); printf(_("Set path to logging\n")); printf("-c, --communication-method\t"); printf(_("Communication method to use ('%s' or '%s')\n"), "unix_socket", "inet_socket"); printf("-S, --socket-path\t"); printf(_ ("Socket path to use for '%s' method (filesystem path or '%s')\n"), "unix_socket", "default"); printf("-p, --port\t\t"); printf(_("Specify a port number for '%s' method\n"), "inet_socket"); printf("-P, --pid-file\t\t"); printf(_("Set path to pid file\n")); printf("-C, --config-dir\t"); printf(_("Set path to configuration\n")); printf("-v, --version\t\t"); printf(_("Report version of this program\n")); printf("-D, --debug\t\t"); printf(_("Output debugging information into %s\n"), "/tmp/.speech-dispatcher"); printf("-h, --help\t\t"); printf(_("Print this info\n")); printf("\n"); printf(_ ("Copyright (C) %d-%d Brailcom, o.p.s.\n" "This is free software; you can redistribute it and/or modify it\n" "under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2, or (at your option)\n" "any later version. Please see COPYING for more details.\n\n" "Please report bugs to %s\n\n"), 2002, 2012, PACKAGE_BUGREPORT); } void options_print_version(void) { printf("%s %s\n", PACKAGE, VERSION); printf(_ ("Copyright (C) %d-%d Brailcom, o.p.s.\n" "%s comes with ABSOLUTELY NO WARRANTY.\n" "You may redistribute copies of this program\n" "under the terms of the GNU General Public License.\n" "For more information about these matters, see the file named COPYING.\n"), 2002, 2012, "Speech Dispatcher"); } #define SPD_OPTION_SET_INT(param) \ val = strtol(optarg, &tail_ptr, 10); \ if(tail_ptr != optarg){ \ SpeechdOptions.param ## _set = 1; \ SpeechdOptions.param = val; \ } #define SPD_OPTION_SET_STR(param) \ SpeechdOptions.param = g_strdup(optarg) void options_parse(int argc, char *argv[]) { char *tail_ptr; int c_opt; int option_index; int val; int ret; char *tmpdir; char *debug_logfile_path; assert(argc > 0); assert(argv); while (1) { option_index = 0; c_opt = getopt_long(argc, argv, spd_short_options, spd_long_options, &option_index); if (c_opt == -1) break; switch (c_opt) { case 'd': spd_mode = SPD_MODE_DAEMON; break; case 's': spd_mode = SPD_MODE_SINGLE; break; case 'l': SPD_OPTION_SET_INT(log_level); break; case 'L': SPD_OPTION_SET_STR(log_dir); SpeechdOptions.log_dir_set = 1; break; case 'c': SPD_OPTION_SET_STR(communication_method); SpeechdOptions.communication_method_set = 1; break; case 'S': SPD_OPTION_SET_STR(socket_path); SpeechdOptions.socket_path_set = 1; break; case 'p': SPD_OPTION_SET_INT(port); break; case 'a': SpeechdOptions.spawn = TRUE; break; case 'P': SPD_OPTION_SET_STR(pid_file); break; case 'C': SPD_OPTION_SET_STR(conf_dir); break; case 'v': options_print_version(); exit(0); break; case 'D': tmpdir = g_strdup(getenv("TMPDIR")); if (!tmpdir) tmpdir = g_strdup("/tmp"); SpeechdOptions.debug_destination = g_strdup_printf("%s/speechd-debug", tmpdir); g_free(tmpdir); ret = mkdir(SpeechdOptions.debug_destination, S_IRWXU); if (ret) { MSG(1, "Can't create additional debug destination in %s, reason %d-%s", SpeechdOptions.debug_destination, errno, strerror(errno)); if (errno == EEXIST) { MSG(1, "Debugging directory %s already exists, please delete it first", SpeechdOptions.debug_destination); } exit(1); } debug_logfile_path = g_strdup_printf("%s/speech-dispatcher.log", SpeechdOptions.debug_destination); /* Open logfile for writing */ debug_logfile = fopen(debug_logfile_path, "wx"); g_free(debug_logfile_path); if (debug_logfile == NULL) { MSG(1, "Error: can't open additional debug logging file %s [%d-%s]!\n", debug_logfile_path, errno, strerror(errno)); exit(1); } SpeechdOptions.debug = 1; break; case 'h': options_print_help(argv); exit(0); break; default: MSG(2, "Unrecognized option\n"); options_print_help(argv); exit(1); } } } #undef SPD_OPTION_SET_INT speech-dispatcher-0.8.3/src/server/parse.c0000664000175000017500000010025612536417045015426 00000000000000/* * parse.c - Parses commands Speech Dispatcher got from client * * Copyright (C) 2001, 2002, 2003, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: parse.c,v 1.73 2008-07-01 08:52:31 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "speechd.h" #include "set.h" #include "history.h" #include "msg.h" #include "server.h" #include "sem_functions.h" #include "output.h" /* Parse() receives input data and parses them. It can be either command or data to speak. If it's command, it is immadetaily executed (eg. parameters are set). If it's data to speak, they are queued in corresponding queues with corresponding parameters for synthesis. */ /* SSIP command allowed inside block? */ #define BLOCK_NO 0 #define BLOCK_OK 1 #define CHECK_SSIP_COMMAND(cmd_name, parse_function, allowed_in_block)\ if(!strcmp(command, cmd_name)){ \ g_free(command); \ if ((allowed_in_block == BLOCK_NO) && speechd_socket->inside_block) \ return g_strdup(ERR_NOT_ALLOWED_INSIDE_BLOCK); \ return (char*) (parse_function) (buf, bytes, fd, speechd_socket); \ } #define NOT_ALLOWED_INSIDE_BLOCK() \ if(speechd_socket->inside_block > 0) \ return g_strdup(ERR_NOT_ALLOWED_INSIDE_BLOCK); #define ALLOWED_INSIDE_BLOCK() ; char *parse(const char *buf, const int bytes, const int fd) { TSpeechDMessage *new; char *command; int r; int end_data; char *pos; int reparted; int msg_uid; GString *ok_queued_reply; char *reply; TSpeechDSock *speechd_socket = speechd_socket_get_by_fd(fd); assert(speechd_socket); end_data = 0; if ((buf == NULL) || (bytes == 0)) { if (SPEECHD_DEBUG) FATAL("invalid buffer for parse()\n"); return g_strdup(ERR_INTERNAL); } /* First the condition that we are not in data mode and we * are awaiting commands */ if (speechd_socket->awaiting_data == 0) { /* Read the command */ command = get_param(buf, 0, bytes, 1); MSG(5, "Command caught: \"%s\"", command); /* Here we will check which command we got and process * it with its parameters. */ if (command == NULL) { if (SPEECHD_DEBUG) FATAL("Invalid buffer for parse()\n"); return g_strdup(ERR_INTERNAL); } CHECK_SSIP_COMMAND("set", parse_set, BLOCK_OK); CHECK_SSIP_COMMAND("history", parse_history, BLOCK_NO); CHECK_SSIP_COMMAND("stop", parse_stop, BLOCK_NO); CHECK_SSIP_COMMAND("cancel", parse_cancel, BLOCK_NO); CHECK_SSIP_COMMAND("pause", parse_pause, BLOCK_NO); CHECK_SSIP_COMMAND("resume", parse_resume, BLOCK_NO); CHECK_SSIP_COMMAND("sound_icon", parse_snd_icon, BLOCK_OK); CHECK_SSIP_COMMAND("char", parse_char, BLOCK_OK); CHECK_SSIP_COMMAND("key", parse_key, BLOCK_OK) CHECK_SSIP_COMMAND("list", parse_list, BLOCK_NO); CHECK_SSIP_COMMAND("get", parse_get, BLOCK_NO); CHECK_SSIP_COMMAND("help", parse_help, BLOCK_NO); CHECK_SSIP_COMMAND("block", parse_block, BLOCK_OK); if (!strcmp(command, "bye") || !strcmp(command, "quit")) { MSG(4, "Bye received."); /* Send a reply to the socket */ if (write(fd, OK_BYE, strlen(OK_BYE))) { MSG(2, "ERROR: Can't write OK_BYE message to client socket: %s", strerror(errno)); } speechd_connection_destroy(fd); /* This is internal Speech Dispatcher message, see serve() */ g_free(command); return g_strdup("999 CLIENT GONE"); /* This is an internal message, not part of SSIP */ } if (!strcmp(command, "speak")) { g_free(command); /* Ckeck if we have enough space in awaiting_data table for * this client, that can have higher file descriptor that * everything we got before */ r = server_data_on(fd); if (r != 0) { if (SPEECHD_DEBUG) FATAL("Can't switch to data on mode\n"); return g_strdup(ERR_INTERNAL); } return g_strdup(OK_RECEIVE_DATA); } g_free(command); return g_strdup(ERR_INVALID_COMMAND); /* The other case is that we are in awaiting_data mode and * we are waiting for text that is comming through the chanel */ } else { enddata: /* In the end of the data flow we got a "\r\n." NEWLINE command. */ MSG(5, "Buffer: |%s| bytes:", buf, bytes); if (((bytes >= 5) && ((!strncmp(buf, "\r\n." NEWLINE, bytes)))) || (end_data == 1) || ((bytes == 3) && (!strncmp(buf, "." NEWLINE, bytes)))) { MSG(5, "Finishing data"); end_data = 0; /* Set the flag to command mode */ MSG(5, "Switching back to command mode..."); speechd_socket->awaiting_data = 0; /* Prepare element (text+settings commands) to be queued. */ /* TODO: Remove? */ if ((bytes == 3) && (speechd_socket->o_bytes > 2)) speechd_socket->o_bytes -= 2; /* Check if message contains any data */ if (speechd_socket->o_bytes == 0) return g_strdup(OK_MSG_CANCELED); /* Check buffer for proper UTF-8 encoding */ if (!g_utf8_validate (speechd_socket->o_buf->str, speechd_socket->o_bytes, NULL)) { MSG(4, "ERROR: Invalid character encoding on input (failed UTF-8 validation)"); MSG(4, "Rejecting this message."); return g_strdup(ERR_INVALID_ENCODING); } new = (TSpeechDMessage *) g_malloc(sizeof(TSpeechDMessage)); new->bytes = speechd_socket->o_bytes; assert(speechd_socket->o_buf != NULL); new->buf = deescape_dot(speechd_socket->o_buf->str, new->bytes); reparted = speechd_socket->inside_block; MSG(5, "New buf is now: |%s|", new->buf); if ((msg_uid = queue_message(new, fd, 1, SPD_MSGTYPE_TEXT, reparted)) == 0) { if (SPEECHD_DEBUG) FATAL("Can't queue message\n"); g_free(new->buf); g_free(new); return g_strdup(ERR_INTERNAL); } /* Clear the counter of bytes in the output buffer. */ server_data_off(fd); ok_queued_reply = g_string_new(""); g_string_printf(ok_queued_reply, C_OK_MESSAGE_QUEUED "-%d" NEWLINE OK_MESSAGE_QUEUED, msg_uid); reply = ok_queued_reply->str; g_string_free(ok_queued_reply, 0); return reply; } { int real_bytes; if (bytes >= 5) { if ((pos = strstr(buf, "\r\n." NEWLINE))) { real_bytes = pos - buf; end_data = 1; MSG(5, "Command in data caught"); } else { real_bytes = bytes; } } else { real_bytes = bytes; } /* Get the number of bytes read before, sum it with the number of bytes read * now and store again in the counter */ speechd_socket->o_bytes += real_bytes; g_string_insert_len(speechd_socket->o_buf, -1, buf, real_bytes); } } if (end_data == 1) goto enddata; /* Don't reply on data */ return g_strdup("999 DATA"); } #undef CHECK_SSIP_COMMAND #define CHECK_PARAM(param) \ if (param == NULL){ \ MSG(4, "Missing parameter from client"); \ return g_strdup(ERR_MISSING_PARAMETER); \ } #define GET_PARAM_INT(name, pos) \ { \ char *helper; \ helper = get_param(buf, pos, bytes, 0); \ CHECK_PARAM(helper); \ if (!isanum(helper)){ \ g_free(helper); \ return g_strdup(ERR_NOT_A_NUMBER); \ } \ name = atoi(helper); \ g_free(helper); \ } #define CONV_DOWN 1 #define NO_CONV 0 #define GET_PARAM_STR(name, pos, up_lo_case) \ name = get_param(buf, pos, bytes, up_lo_case); \ CHECK_PARAM(name); /* Tests if cmd is the same as str AND deallocates cmd if the test is succesful */ #define TEST_CMD(cmd, str) \ (!strcmp(cmd, str) ? g_free(cmd), 1 : 0 ) /* Parses @history commands and calls the appropriate history_ functions. */ char *parse_history(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { char *cmd_main; GET_PARAM_STR(cmd_main, 1, CONV_DOWN); if (TEST_CMD(cmd_main, "get")) { char *hist_get_sub; GET_PARAM_STR(hist_get_sub, 2, CONV_DOWN); if (TEST_CMD(hist_get_sub, "client_list")) { return (char *)history_get_client_list(); } else if (TEST_CMD(hist_get_sub, "client_id")) { return (char *)history_get_client_id(fd); } else if (TEST_CMD(hist_get_sub, "client_messages")) { int start, num; char *who; int who_id; /* TODO: This needs to be (sim || am)-plified */ who = get_param(buf, 3, bytes, 1); CHECK_PARAM(who); if (!strcmp(who, "self")) return g_strdup(ERR_NOT_IMPLEMENTED); if (!strcmp(who, "all")) return g_strdup(ERR_NOT_IMPLEMENTED); if (!isanum(who)) return g_strdup(ERR_NOT_A_NUMBER); who_id = atoi(who); g_free(who); GET_PARAM_INT(start, 4); GET_PARAM_INT(num, 5); return (char *)history_get_message_list(who_id, start, num); } else if (TEST_CMD(hist_get_sub, "last")) { return (char *)history_get_last(fd); } else if (TEST_CMD(hist_get_sub, "message")) { int msg_id; GET_PARAM_INT(msg_id, 3); return (char *)history_get_message(msg_id); } else { return g_strdup(ERR_MISSING_PARAMETER); } } else if (TEST_CMD(cmd_main, "cursor")) { char *hist_cur_sub; GET_PARAM_STR(hist_cur_sub, 2, CONV_DOWN); if (TEST_CMD(hist_cur_sub, "set")) { int who; char *location; GET_PARAM_INT(who, 3); GET_PARAM_STR(location, 4, CONV_DOWN); if (TEST_CMD(location, "last")) { return (char *)history_cursor_set_last(fd, who); } else if (TEST_CMD(location, "first")) { return (char *)history_cursor_set_first(fd, who); } else if (TEST_CMD(location, "pos")) { int pos; GET_PARAM_INT(pos, 5); return (char *)history_cursor_set_pos(fd, who, pos); } else { g_free(location); return g_strdup(ERR_MISSING_PARAMETER); } } else if (TEST_CMD(hist_cur_sub, "forward")) { return (char *)history_cursor_forward(fd); } else if (TEST_CMD(hist_cur_sub, "backward")) { return (char *)history_cursor_backward(fd); } else if (TEST_CMD(hist_cur_sub, "get")) { return (char *)history_cursor_get(fd); } else { g_free(hist_cur_sub); return g_strdup(ERR_MISSING_PARAMETER); } } else if (TEST_CMD(cmd_main, "say")) { int msg_id; GET_PARAM_INT(msg_id, 2); return (char *)history_say_id(fd, msg_id); } else if (TEST_CMD(cmd_main, "sort")) { // TODO: everything :) return g_strdup(ERR_NOT_IMPLEMENTED); } else { g_free(cmd_main); return g_strdup(ERR_MISSING_PARAMETER); } return g_strdup(ERR_INVALID_COMMAND); } #define SSIP_SET_COMMAND(param) \ if (who == 0) ret = set_ ## param ## _self(fd, param); \ else if (who == 1) ret = set_ ## param ## _uid(uid, param); \ else if (who == 2) ret = set_ ## param ## _all(param); \ #define SSIP_ON_OFF_PARAM(param, ok_message, err_message, inside_block) \ if (!strcmp(set_sub, #param)){ \ char *helper_s; \ int param; \ \ inside_block \ \ GET_PARAM_STR(helper_s, 3, CONV_DOWN); \ \ if(TEST_CMD(helper_s, "on")) param = 1; \ else if(TEST_CMD(helper_s, "off")) param = 0; \ else{ \ g_free(helper_s); \ return g_strdup(ERR_PARAMETER_NOT_ON_OFF); \ } \ SSIP_SET_COMMAND(param); \ if (ret) return g_strdup(err_message); \ return g_strdup(ok_message); \ } char *parse_set(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { int who; /* 0 - self, 1 - uid specified, 2 - all */ int uid = -1; /* uid of the client (only if who == 1) */ /* uid = -1 avoids gcc warning */ int ret = -1; // =-1 has no effect but avoids gcc warning char *set_sub; char *who_s; GET_PARAM_STR(who_s, 1, CONV_DOWN); if (TEST_CMD(who_s, "self")) who = 0; else if (TEST_CMD(who_s, "all")) who = 2; else if (isanum(who_s)) { who = 1; uid = atoi(who_s); g_free(who_s); } else { g_free(who_s); return g_strdup(ERR_PARAMETER_INVALID); } GET_PARAM_STR(set_sub, 2, CONV_DOWN); if (TEST_CMD(set_sub, "priority")) { char *priority_s; SPDPriority priority; NOT_ALLOWED_INSIDE_BLOCK(); /* Setting priority only allowed for "self" */ if (who != 0) return g_strdup(ERR_COULDNT_SET_PRIORITY); GET_PARAM_STR(priority_s, 3, CONV_DOWN); if (TEST_CMD(priority_s, "important")) priority = SPD_IMPORTANT; else if (TEST_CMD(priority_s, "message")) priority = SPD_MESSAGE; else if (TEST_CMD(priority_s, "text")) priority = SPD_TEXT; else if (TEST_CMD(priority_s, "notification")) priority = SPD_NOTIFICATION; else if (TEST_CMD(priority_s, "progress")) priority = SPD_PROGRESS; else { g_free(priority_s); return g_strdup(ERR_UNKNOWN_PRIORITY); } ret = set_priority_self(fd, priority); if (ret) return g_strdup(ERR_COULDNT_SET_PRIORITY); return g_strdup(OK_PRIORITY_SET); } else if (TEST_CMD(set_sub, "language")) { char *language; GET_PARAM_STR(language, 3, CONV_DOWN); SSIP_SET_COMMAND(language); g_free(language); if (ret) return g_strdup(ERR_COULDNT_SET_LANGUAGE); return g_strdup(OK_LANGUAGE_SET); } else if (TEST_CMD(set_sub, "synthesis_voice")) { char *synthesis_voice; GET_PARAM_STR(synthesis_voice, 3, CONV_DOWN); SSIP_SET_COMMAND(synthesis_voice); g_free(synthesis_voice); if (ret) return g_strdup(ERR_COULDNT_SET_VOICE); return g_strdup(OK_VOICE_SET); } else if (TEST_CMD(set_sub, "client_name")) { char *client_name; NOT_ALLOWED_INSIDE_BLOCK(); /* Setting client name only allowed for "self" */ if (who != 0) return g_strdup(ERR_PARAMETER_INVALID); GET_PARAM_STR(client_name, 3, CONV_DOWN); ret = set_client_name_self(fd, client_name); g_free(client_name); if (ret) return g_strdup(ERR_COULDNT_SET_CLIENT_NAME); return g_strdup(OK_CLIENT_NAME_SET); } else if (TEST_CMD(set_sub, "rate")) { signed int rate; GET_PARAM_INT(rate, 3); if (rate < -100) return g_strdup(ERR_RATE_TOO_LOW); if (rate > +100) return g_strdup(ERR_RATE_TOO_HIGH); SSIP_SET_COMMAND(rate); if (ret) return g_strdup(ERR_COULDNT_SET_RATE); return g_strdup(OK_RATE_SET); } else if (TEST_CMD(set_sub, "pitch")) { signed int pitch; GET_PARAM_INT(pitch, 3); if (pitch < -100) return g_strdup(ERR_PITCH_TOO_LOW); if (pitch > +100) return g_strdup(ERR_PITCH_TOO_HIGH); SSIP_SET_COMMAND(pitch); if (ret) return g_strdup(ERR_COULDNT_SET_PITCH); return g_strdup(OK_PITCH_SET); } else if (TEST_CMD(set_sub, "volume")) { signed int volume; GET_PARAM_INT(volume, 3); if (volume < -100) return g_strdup(ERR_VOLUME_TOO_LOW); if (volume > +100) return g_strdup(ERR_VOLUME_TOO_HIGH); SSIP_SET_COMMAND(volume); if (ret) return g_strdup(ERR_COULDNT_SET_VOLUME); return g_strdup(OK_VOLUME_SET); } else if (TEST_CMD(set_sub, "voice") || TEST_CMD(set_sub, "voice_type")) { char *voice; GET_PARAM_STR(voice, 3, CONV_DOWN); SSIP_SET_COMMAND(voice); g_free(voice); if (TEST_CMD(set_sub, "voice")) MSG(1, "The SET VOICE command is deprecated since Speech Dispatcher 0.8.3."); if (ret) return g_strdup(ERR_COULDNT_SET_VOICE); return g_strdup(OK_VOICE_SET); } else if (TEST_CMD(set_sub, "punctuation")) { char *punct_s; SPDPunctuation punctuation_mode; GET_PARAM_STR(punct_s, 3, CONV_DOWN); if (TEST_CMD(punct_s, "all")) punctuation_mode = SPD_PUNCT_ALL; else if (TEST_CMD(punct_s, "some")) punctuation_mode = SPD_PUNCT_SOME; else if (TEST_CMD(punct_s, "none")) punctuation_mode = SPD_PUNCT_NONE; else { g_free(punct_s); return g_strdup(ERR_PARAMETER_INVALID); } SSIP_SET_COMMAND(punctuation_mode); if (ret) return g_strdup(ERR_COULDNT_SET_PUNCT_MODE); return g_strdup(OK_PUNCT_MODE_SET); } else if (TEST_CMD(set_sub, "output_module")) { char *output_module; NOT_ALLOWED_INSIDE_BLOCK(); GET_PARAM_STR(output_module, 3, CONV_DOWN); SSIP_SET_COMMAND(output_module); g_free(output_module); if (ret) return g_strdup(ERR_COULDNT_SET_OUTPUT_MODULE); return g_strdup(OK_OUTPUT_MODULE_SET); } else if (TEST_CMD(set_sub, "cap_let_recogn")) { int capital_letter_recognition; char *recognition; GET_PARAM_STR(recognition, 3, CONV_DOWN); if (TEST_CMD(recognition, "none")) capital_letter_recognition = SPD_CAP_NONE; else if (TEST_CMD(recognition, "spell")) capital_letter_recognition = SPD_CAP_SPELL; else if (TEST_CMD(recognition, "icon")) capital_letter_recognition = SPD_CAP_ICON; else { g_free(recognition); return g_strdup(ERR_PARAMETER_INVALID); } SSIP_SET_COMMAND(capital_letter_recognition); if (ret) return g_strdup(ERR_COULDNT_SET_CAP_LET_RECOG); return g_strdup(OK_CAP_LET_RECOGN_SET); } else if (TEST_CMD(set_sub, "pause_context")) { int pause_context; GET_PARAM_INT(pause_context, 3); SSIP_SET_COMMAND(pause_context); if (ret) return g_strdup(ERR_COULDNT_SET_PAUSE_CONTEXT); return g_strdup(OK_PAUSE_CONTEXT_SET); } else SSIP_ON_OFF_PARAM(spelling, OK_SPELLING_SET, ERR_COULDNT_SET_SPELLING, NOT_ALLOWED_INSIDE_BLOCK()) else SSIP_ON_OFF_PARAM(ssml_mode, OK_SSML_MODE_SET, ERR_COULDNT_SET_SSML_MODE, ALLOWED_INSIDE_BLOCK()) else SSIP_ON_OFF_PARAM(debug, g_strdup_printf("262-%s" NEWLINE OK_DEBUGGING, SpeechdOptions. debug_destination), ERR_COULDNT_SET_DEBUGGING,; ) else if (TEST_CMD(set_sub, "notification")) { char *scope; char *par_s; int par; if (who != 0) return g_strdup(ERR_PARAMETER_INVALID); GET_PARAM_STR(scope, 3, CONV_DOWN); GET_PARAM_STR(par_s, 4, CONV_DOWN); if (TEST_CMD(par_s, "on")) par = 1; else if (TEST_CMD(par_s, "off")) par = 0; else { g_free(par_s); return g_strdup(ERR_PARAMETER_INVALID); } ret = set_notification_self(fd, scope, par); g_free(scope); if (ret) return g_strdup(ERR_COULDNT_SET_NOTIFICATION); return g_strdup(OK_NOTIFICATION_SET); } else { g_free(set_sub); return g_strdup(ERR_PARAMETER_INVALID); } return g_strdup(ERR_INVALID_COMMAND); } #undef SSIP_SET_COMMAND char *parse_stop(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { int uid = 0; char *who_s; MSG(5, "Stop received from fd %d.", fd); GET_PARAM_STR(who_s, 1, CONV_DOWN); if (TEST_CMD(who_s, "all")) { pthread_mutex_lock(&element_free_mutex); speaking_stop_all(); pthread_mutex_unlock(&element_free_mutex); } else if (TEST_CMD(who_s, "self")) { uid = get_client_uid_by_fd(fd); if (uid == 0) return g_strdup(ERR_INTERNAL); pthread_mutex_lock(&element_free_mutex); speaking_stop(uid); pthread_mutex_unlock(&element_free_mutex); } else if (isanum(who_s)) { uid = atoi(who_s); g_free(who_s); if (uid <= 0) return g_strdup(ERR_ID_NOT_EXIST); pthread_mutex_lock(&element_free_mutex); speaking_stop(uid); pthread_mutex_unlock(&element_free_mutex); } else { g_free(who_s); return g_strdup(ERR_PARAMETER_INVALID); } return g_strdup(OK_STOPPED); } char *parse_cancel(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { int uid = 0; char *who_s; MSG(4, "Cancel received from fd %d.", fd); GET_PARAM_STR(who_s, 1, CONV_DOWN); if (TEST_CMD(who_s, "all")) { speaking_cancel_all(); } else if (TEST_CMD(who_s, "self")) { uid = get_client_uid_by_fd(fd); if (uid == 0) return g_strdup(ERR_INTERNAL); speaking_cancel(uid); } else if (isanum(who_s)) { uid = atoi(who_s); g_free(who_s); if (uid <= 0) return g_strdup(ERR_ID_NOT_EXIST); speaking_cancel(uid); } else { g_free(who_s); return g_strdup(ERR_PARAMETER_INVALID); } return g_strdup(OK_CANCELED); } char *parse_pause(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { int uid = 0; char *who_s; MSG(4, "Pause received from fd %d.", fd); GET_PARAM_STR(who_s, 1, CONV_DOWN); /* Note: In this case, the semaphore has a special meaning to allow the speaking loop detect the request for pause */ if (TEST_CMD(who_s, "all")) { pause_requested = 1; pause_requested_fd = fd; speaking_semaphore_post(); } else if (TEST_CMD(who_s, "self")) { uid = get_client_uid_by_fd(fd); if (uid == 0) return g_strdup(ERR_INTERNAL); pause_requested = 2; pause_requested_fd = fd; pause_requested_uid = uid; speaking_semaphore_post(); } else if (isanum(who_s)) { uid = atoi(who_s); g_free(who_s); if (uid <= 0) return g_strdup(ERR_ID_NOT_EXIST); pause_requested = 2; pause_requested_fd = fd; pause_requested_uid = uid; speaking_semaphore_post(); } else { g_free(who_s); return g_strdup(ERR_PARAMETER_INVALID); } return g_strdup(OK_PAUSED); } char *parse_resume(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { int uid = 0; char *who_s; MSG(4, "Resume received from fd %d.", fd); GET_PARAM_STR(who_s, 1, CONV_DOWN); if (TEST_CMD(who_s, "all")) { speaking_resume_all(); } else if (TEST_CMD(who_s, "self")) { uid = get_client_uid_by_fd(fd); if (uid == 0) return g_strdup(ERR_INTERNAL); speaking_resume(uid); } else if (isanum(who_s)) { uid = atoi(who_s); g_free(who_s); if (uid <= 0) return g_strdup(ERR_ID_NOT_EXIST); speaking_resume(uid); } else { g_free(who_s); return g_strdup(ERR_PARAMETER_INVALID); } return g_strdup(OK_RESUMED); } char *parse_general_event(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket, SPDMessageType type) { char *param; TSpeechDMessage *msg; GET_PARAM_STR(param, 1, NO_CONV); if (param == NULL) return g_strdup(ERR_MISSING_PARAMETER); if (param[0] == 0) { g_free(param); return g_strdup(ERR_MISSING_PARAMETER); } /* Check for proper UTF-8 */ /* Check buffer for proper UTF-8 encoding */ if (!g_utf8_validate(buf, bytes, NULL)) { MSG(4, "ERROR: Invalid character encoding on event input (failed UTF-8 validation)"); MSG(4, "Rejecting this event (char/key/sound_icon)."); return g_strdup(ERR_INVALID_ENCODING); } msg = (TSpeechDMessage *) g_malloc(sizeof(TSpeechDMessage)); msg->bytes = strlen(param); msg->buf = g_strdup(param); if (queue_message(msg, fd, 1, type, speechd_socket->inside_block) == 0) { if (SPEECHD_DEBUG) FATAL("Couldn't queue message\n"); MSG(2, "Error: Couldn't queue message!\n"); } g_free(param); return g_strdup(OK_MESSAGE_QUEUED); } char *parse_snd_icon(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { return parse_general_event(buf, bytes, fd, speechd_socket, SPD_MSGTYPE_SOUND_ICON); } char *parse_char(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { return parse_general_event(buf, bytes, fd, speechd_socket, SPD_MSGTYPE_CHAR); } char *parse_key(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { return parse_general_event(buf, bytes, fd, speechd_socket, SPD_MSGTYPE_KEY); } char *parse_list(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { char *list_type; char *voice_list; GET_PARAM_STR(list_type, 1, CONV_DOWN); if (TEST_CMD(list_type, "voices")) { voice_list = (char *)g_malloc(1024); sprintf(voice_list, C_OK_VOICES "-MALE1" NEWLINE C_OK_VOICES "-MALE2" NEWLINE C_OK_VOICES "-MALE3" NEWLINE C_OK_VOICES "-FEMALE1" NEWLINE C_OK_VOICES "-FEMALE2" NEWLINE C_OK_VOICES "-FEMALE3" NEWLINE C_OK_VOICES "-CHILD_MALE" NEWLINE C_OK_VOICES "-CHILD_FEMALE" NEWLINE OK_VOICE_LIST_SENT); return voice_list; } else if (TEST_CMD(list_type, "output_modules")) { GString *result = g_string_new(""); char *helper; OutputModule *mod; int i, len; len = g_list_length(output_modules); for (i = 0; i < len; i++) { mod = g_list_nth_data(output_modules, i); g_string_append_printf(result, C_OK_MODULES "-%s" NEWLINE, mod->name); } g_string_append(result, OK_MODULES_LIST_SENT); helper = result->str; g_string_free(result, 0); return helper; } else if (TEST_CMD(list_type, "synthesis_voices")) { char *module_name; int uid; TFDSetElement *settings; SPDVoice **voices; GString *result; int i; char *helper; uid = get_client_uid_by_fd(fd); settings = get_client_settings_by_uid(uid); if (settings == NULL) return g_strdup(ERR_INTERNAL); module_name = settings->output_module; if (module_name == NULL) return g_strdup(ERR_NO_OUTPUT_MODULE); voices = output_list_voices(module_name); if (voices == NULL) return g_strdup(ERR_CANT_REPORT_VOICES); result = g_string_new(""); for (i = 0;; i++) { if (voices[i] == NULL) break; g_string_append_printf(result, C_OK_VOICES "-%s %s %s" NEWLINE, voices[i]->name, voices[i]->language, voices[i]->variant); g_free(voices[i]->name); g_free(voices[i]->language); g_free(voices[i]->variant); g_free(voices[i]); } g_string_append(result, OK_VOICE_LIST_SENT); helper = result->str; g_string_free(result, 0); g_free(voices); return helper; } else { g_free(list_type); return g_strdup(ERR_PARAMETER_INVALID); } } char *parse_get(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { char *get_type; GString *result; char *helper; TFDSetElement *settings; settings = get_client_settings_by_fd(fd); if (settings == NULL) return g_strdup(ERR_INTERNAL); result = g_string_new(""); GET_PARAM_STR(get_type, 1, CONV_DOWN); if (TEST_CMD(get_type, "voice_type")) { switch (settings->msg_settings.voice_type) { case SPD_MALE1: g_string_append(result, C_OK_GET "-MALE1" NEWLINE OK_GET); break; case SPD_MALE2: g_string_append(result, C_OK_GET "-MALE2" NEWLINE OK_GET); break; case SPD_MALE3: g_string_append(result, C_OK_GET "-MALE3" NEWLINE OK_GET); break; case SPD_FEMALE1: g_string_append(result, C_OK_GET "-FEMALE1" NEWLINE OK_GET); break; case SPD_FEMALE2: g_string_append(result, C_OK_GET "-FEMALE2" NEWLINE OK_GET); break; case SPD_FEMALE3: g_string_append(result, C_OK_GET "-FEMALE3" NEWLINE OK_GET); break; case SPD_CHILD_MALE: g_string_append(result, C_OK_GET "-CHILD_MALE" NEWLINE OK_GET); break; case SPD_CHILD_FEMALE: g_string_append(result, C_OK_GET "-CHILD_FEMALE" NEWLINE OK_GET); break; default: g_string_append(result, C_OK_GET "-NO_VOICE" NEWLINE OK_GET); break; } } else if (TEST_CMD(get_type, "output_module")) { g_string_append_printf(result, C_OK_GET "-%s" NEWLINE OK_GET, settings->output_module); } else if (TEST_CMD(get_type, "language")) { g_string_append_printf(result, C_OK_GET "-%s" NEWLINE OK_GET, settings->msg_settings.voice.language); } else if (TEST_CMD(get_type, "rate")) { g_string_append_printf(result, C_OK_GET "-%d" NEWLINE OK_GET, settings->msg_settings.rate); } else if (TEST_CMD(get_type, "pitch")) { g_string_append_printf(result, C_OK_GET "-%d" NEWLINE OK_GET, settings->msg_settings.pitch); } else if (TEST_CMD(get_type, "volume")) { g_string_append_printf(result, C_OK_GET "-%d" NEWLINE OK_GET, settings->msg_settings.volume); } else { g_free(get_type); g_string_append(result, ERR_PARAMETER_INVALID); } helper = result->str; g_string_free(result, 0); return helper; } char *parse_help(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket) { char *help; help = (char *)g_malloc(1024 * sizeof(char)); sprintf(help, C_OK_HELP "- SPEAK -- say text " NEWLINE C_OK_HELP "- KEY -- say a combination of keys " NEWLINE C_OK_HELP "- CHAR -- say a character " NEWLINE C_OK_HELP "- SOUND_ICON -- execute a sound icon " NEWLINE C_OK_HELP "- SET -- set a parameter " NEWLINE C_OK_HELP "- GET -- get a current parameter " NEWLINE C_OK_HELP "- LIST -- list available arguments " NEWLINE C_OK_HELP "- HISTORY -- commands related to history " NEWLINE C_OK_HELP "- QUIT -- close the connection " NEWLINE OK_HELP_SENT); return help; } char *parse_block(const char *buf, const int bytes, const int fd, TSpeechDSock * speechd_socket) { char *cmd_main; GET_PARAM_STR(cmd_main, 1, CONV_DOWN); if (TEST_CMD(cmd_main, "begin")) { assert(speechd_socket->inside_block >= 0); if (speechd_socket->inside_block == 0) { speechd_socket->inside_block = ++SpeechdStatus.max_gid; return g_strdup(OK_INSIDE_BLOCK); } else { return g_strdup(ERR_ALREADY_INSIDE_BLOCK); } } else if (TEST_CMD(cmd_main, "end")) { assert(speechd_socket->inside_block >= 0); if (speechd_socket->inside_block > 0) { speechd_socket->inside_block = 0; return g_strdup(OK_OUTSIDE_BLOCK); } else { return g_strdup(ERR_ALREADY_OUTSIDE_BLOCK); } } else { g_free(cmd_main); return g_strdup(ERR_PARAMETER_INVALID); } } /* * deescape_dot: Replace .. with . at the start of lines or at the * start of the string. * @orig_text: text to be unescaped. * @orig_len: length of the text. * Returns: a freshly allocated string, containing the unescaped data. * * In SSIP, the message terminator is \r\n.\r\n, just as it is in SMTP * and similar protocols. Thus, period needs to be escaped when it * is the only character on a line. deescape_dot reverts that * transformation, after the message is received. * This function deserves further examination. */ char *deescape_dot(const char *orig_text, size_t orig_len) { /* Constants. DOTLINE is CRLF followed by a period. * DOTLINELEN is the length of DOTLINE. * ESCAPED_DOTLINELEN is the length of the sequence \r\n.., * which is used in the original (unescaped) text. */ static const char *DOTLINE = "\r\n."; static const size_t DOTLINELEN = 3; static const size_t ESCAPED_DOTLINELEN = 4; /* \r\n.. */ char *out_text = NULL; char *out_ptr; const char *orig_end = orig_text + orig_len; if (orig_text == NULL) return NULL; out_text = g_malloc(orig_len + 1); /* We may have allocated more than we need. In any case, out_text * can be no longer than orig_text. * Note: g_malloc aborts the program on failure to allocate. */ out_ptr = out_text; if (orig_len >= 2) { /* De-escape .. at start of text. */ if ((orig_text[0] == '.') && (orig_text[1] == '.')) { *(out_ptr++) = '.'; orig_text = orig_text + 2; } } while (orig_text < orig_end) { if ((orig_text[0] == '\r') && (orig_text[1] == '\n') && (orig_text[2] == '.') && (orig_text[3] == '.')) { /* We just found \r\n.., the sequence we want to unescape. */ memcpy(out_ptr, DOTLINE, DOTLINELEN); out_ptr += DOTLINELEN; orig_text += ESCAPED_DOTLINELEN; } else { /* Just copy the character from source to destination... */ *(out_ptr++) = *(orig_text++); } } *out_ptr = '\0'; /* NUL-terminate. */ return out_text; } /* isanum() tests if the given string is a number, * returns 1 if yes, 0 otherwise. */ int isanum(const char *str) { int i; if (!isdigit(str[0]) && !((str[0] == '+') || (str[0] == '-'))) return 0; for (i = 1; i <= strlen(str) - 1; i++) { if (!isdigit(str[i])) return 0; } return 1; } /* Gets command parameter _n_ from the text buffer _buf_ * which has _bytes_ bytes. Note that the parameter with * index 0 is the command itself. */ char *get_param(const char *buf, const int n, const int bytes, const int lower_case) { char *param; char *par; int i, y, z = 0; assert(bytes != 0); param = (char *)g_malloc(bytes); assert(param != NULL); strcpy(param, ""); i = 0; /* Read all the parameters one by one, * but stop after the one with index n, * while maintaining it's value in _param_ */ for (y = 0; y <= n; y++) { z = 0; for (; i < bytes; i++) { if (buf[i] == ' ') break; param[z] = buf[i]; z++; } i++; } if (z <= 0) { g_free(param); return NULL; } /* Write the trailing zero */ if (i >= bytes) { param[z > 1 ? z - 2 : 0] = 0; } else { param[z] = 0; } if (lower_case) { par = g_ascii_strdown(param, strlen(param)); g_free(param); } else { par = param; } return par; } /* Read one char (which _pointer_ is pointing to) from an UTF-8 string * and store it into _character_. _character_ must have space for * at least 7 bytes (6 bytes character + 1 byte trailing 0). This * function doesn't validate if the string is valid UTF-8. */ int spd_utf8_read_char(char *pointer, char *character) { int bytes; gunichar u_char; u_char = g_utf8_get_char(pointer); bytes = g_unichar_to_utf8(u_char, character); character[bytes] = 0; return bytes; } speech-dispatcher-0.8.3/src/server/history.c0000644000175000017500000002114512233560613016004 00000000000000 /* * history.c - History functions for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: history.c,v 1.24 2008-02-08 10:01:09 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include "speechd.h" #include "msg.h" #include "set.h" #include "server.h" #include "history.h" /* List of messages in history */ static GList *message_history; /* Compares TSpeechDMessage data structure elements with given ID */ gint message_compare_id(gconstpointer element, gconstpointer value) { gint ret; ret = ((TSpeechDMessage *) element)->id - *((int *)value); return ret; } gint(*p_msg_comp_id) () = message_compare_id; char *history_get_client_list() { TFDSetElement *client; GString *clist; int i; clist = g_string_new(""); for (i = 1; i <= SpeechdStatus.max_uid; i++) { MSG(4, "Getting settings for client %d of %d", i, SpeechdStatus.max_uid - 1); client = get_client_settings_by_uid(i); assert(client != NULL); g_string_append_printf(clist, C_OK_CLIENTS "-"); g_string_append_printf(clist, "%d ", client->uid); g_string_append(clist, client->client_name); g_string_append_printf(clist, " %d", client->active); g_string_append(clist, "\r\n"); } g_string_append_printf(clist, OK_CLIENT_LIST_SENT); return clist->str; } char *history_get_client_id(int fd) { GString *cid; int uid; cid = g_string_new(""); uid = get_client_uid_by_fd(fd); if (uid == 0) return g_strdup(ERR_INTERNAL); g_string_append_printf(cid, C_OK_CLIENT_ID "-%d\r\n", uid); g_string_append_printf(cid, OK_CLIENT_ID_SENT); return cid->str; } char *history_get_message(int uid) { /* TODO: Rework. */ #if 0 GString *mtext; GList *gl; TSpeechDMessage *msg; int i, pos; char c; char helper[1024]; mtext = g_string_new(""); gl = g_list_find_custom(message_history, &uid, compare_message_uid); if (gl == NULL) return g_strdup(ERR_ID_NOT_EXIST); if (gl->data == NULL) return g_strdup(ERR_INTERNAL); msg = (TSpeechDMessage *) gl->data; i = 0; pos = 0; while (c = msg->buf[i]) { helper[pos] = msg->buf[i]; pos++; i++; if (c == '\n') { helper[pos - 2] = 0; g_string_append_printf(mtext, C_OK_MSG_TEXT "-%s\r\n", helper); pos = 0; } } helper[pos] = 0; g_string_append_printf(mtext, C_OK_MSG_TEXT "-%s\r\n", helper); g_string_append_printf(mtext, OK_MSG_TEXT_SENT); #endif return g_strdup(ERR_NOT_IMPLEMENTED); } char *history_get_message_list(guint client_id, int from, int num) { TSpeechDMessage *message; GString *mlist; GList *gl; TFDSetElement *client_settings; GList *client_msgs; int i; MSG(4, "message_list: from %d num %d, client %d\n", from, num, client_id); mlist = g_string_new(""); client_settings = get_client_settings_by_uid(client_id); if (client_settings == NULL) return g_strdup(ERR_NO_SUCH_CLIENT); client_msgs = get_messages_by_client(client_id); for (i = from; i <= from + num - 1; i++) { gl = g_list_nth(client_msgs, i); if (gl == NULL) { g_string_append_printf(mlist, OK_MSGS_LIST_SENT); return mlist->str; } message = gl->data; if (message == NULL) { if (SPEECHD_DEBUG) FATAL("Internal error.\n"); return g_strdup(ERR_INTERNAL); } g_string_append_printf(mlist, C_OK_MSGS "-"); g_string_append_printf(mlist, "%d %s\r\n", message->id, client_settings->client_name); } g_string_append_printf(mlist, OK_MSGS_LIST_SENT); return mlist->str; } char *history_get_last(int fd) { TSpeechDMessage *message; GString *lastm; GList *gl; lastm = g_string_new(""); gl = g_list_last(message_history); if (gl == NULL) return g_strdup(ERR_NO_MESSAGE); message = gl->data; g_string_append_printf(lastm, C_OK_LAST_MSG "-%d\r\n", message->id); g_string_append_printf(lastm, OK_LAST_MSG); return lastm->str; } char *history_cursor_set_last(int fd, guint client_id) { GList *client_msgs; TFDSetElement *settings; settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); client_msgs = get_messages_by_client(client_id); settings->hist_cur_pos = g_list_length(client_msgs) - 1; settings->hist_cur_uid = client_id; return g_strdup(OK_CUR_SET_LAST); } char *history_cursor_set_first(int fd, guint client_id) { TFDSetElement *settings; settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); settings->hist_cur_pos = 0; settings->hist_cur_uid = client_id; return g_strdup(OK_CUR_SET_FIRST); } char *history_cursor_set_pos(int fd, guint client_id, int pos) { TFDSetElement *settings; GList *client_msgs; if (pos < 0) return g_strdup(ERR_POS_LOW); client_msgs = get_messages_by_client(client_id); if (pos > g_list_length(client_msgs) - 1) return g_strdup(ERR_POS_HIGH); settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); settings->hist_cur_pos = pos; settings->hist_cur_uid = client_id; MSG(4, "cursor pos:%d\n", settings->hist_cur_pos); return g_strdup(OK_CUR_SET_POS); } char *history_cursor_forward(int fd) { TFDSetElement *settings; GList *client_msgs; settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); client_msgs = get_messages_by_client(settings->hist_cur_uid); if ((settings->hist_cur_pos + 1) > g_list_length(client_msgs) - 1) return g_strdup(ERR_POS_HIGH); settings->hist_cur_pos++; return g_strdup(OK_CUR_MOV_FOR); } char *history_cursor_backward(int fd) { TFDSetElement *settings; settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); if ((settings->hist_cur_pos - 1) < 0) return g_strdup(ERR_POS_LOW); settings->hist_cur_pos--; return g_strdup(OK_CUR_MOV_BACK); } char *history_cursor_get(int fd) { TFDSetElement *settings; TSpeechDMessage *new; GString *reply; GList *gl, *client_msgs; reply = g_string_new(""); settings = get_client_settings_by_fd(fd); if (settings == NULL) FATAL("Couldn't find settings for active client"); client_msgs = get_messages_by_client(settings->hist_cur_uid); gl = g_list_nth(client_msgs, (int)settings->hist_cur_pos); if (gl == NULL) return g_strdup(ERR_NO_MESSAGE); new = gl->data; g_string_printf(reply, C_OK_CUR_POS "-%d\r\n" OK_CUR_POS_RET, new->id); return reply->str; } char *history_say_id(int fd, int id) { TSpeechDMessage *msg, *new; GList *gl; gl = g_list_find_custom(message_history, &id, p_msg_comp_id); if (gl == NULL) return g_strdup(ERR_ID_NOT_EXIST); msg = gl->data; if (msg == NULL) return g_strdup(ERR_INTERNAL); MSG(4, "putting history message into queue\n"); new = (TSpeechDMessage *) spd_message_copy(msg); // queue_message(new, fd, 0, 0); return g_strdup(OK_MESSAGE_QUEUED); } int history_add_message(TSpeechDMessage * msg) { TSpeechDMessage *hist_msg; /* We will make an exact copy of the message for inclusion into history. */ hist_msg = (TSpeechDMessage *) spd_message_copy(msg); if (hist_msg == NULL) { if (SPEECHD_DEBUG) FATAL("Can't include message into history\n"); return -1; } /* Do the necessary expiration of old messages */ if (g_list_length(message_history) >= SpeechdOptions.max_history_messages) { GList *gl; MSG(5, "Discarding older history message, limit reached"); gl = g_list_first(message_history); if (gl != NULL) { message_history = g_list_remove_link(message_history, gl); if (gl->data != NULL) mem_free_message(gl->data); } } /* Save the message into history */ message_history = g_list_append(message_history, hist_msg); return 0; } GList *get_messages_by_client(int uid) { GList *list = NULL; GList *gl; TSpeechDMessage *msg; guint i; guint history_length = g_list_length(message_history); for (i = 0; i < history_length; i++) { gl = g_list_nth(message_history, i); assert(gl != NULL); msg = gl->data; if (msg->settings.uid == uid) { list = g_list_append(list, msg); } } return list; } speech-dispatcher-0.8.3/src/server/module.h0000664000175000017500000000341612522771346015610 00000000000000 /* * module.h - Definition of a module for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: module.h,v 1.6 2008-06-27 12:28:43 hanke Exp $ */ #ifndef MODULE_H #define MODULE_H #include #include typedef struct { char *name; char *filename; char *configfilename; char *debugfilename; int pipe_in[2]; int pipe_out[2]; FILE *stream_out; int stderr_redirect; pid_t pid; int working; } OutputModule; GList *detect_output_modules(char *dirname); OutputModule *load_output_module(char *mod_name, char *mod_prog, char *mod_cfgfile, char *mod_dbgfile); int unload_output_module(OutputModule * module); int reload_output_module(OutputModule * old_module); int output_module_debug(OutputModule * module); int output_module_nodebug(OutputModule * module); void destroy_module(OutputModule * module); void module_add_load_request(char *module_name, char *module_cmd, char *module_cfgfile, char *module_dbgfile); void module_load_requested_modules(void); guint module_number_of_requested_modules(void); #endif speech-dispatcher-0.8.3/src/server/compare.c0000664000175000017500000000336512522771346015747 00000000000000 /* * compare.c - Auxiliary functions for comparing elements in lists * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: compare.c,v 1.5 2007-02-17 18:58:53 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "speechd.h" #include "compare.h" /* Pointers to compare_message_fd and compare_message_uid */ gint(*p_msg_lc) () = compare_message_fd; gint(*p_msg_uid_lc) () = compare_message_uid; gint compare_message_fd(gconstpointer element, gconstpointer value, gpointer x) { int *fd_val; TSpeechDMessage *message; fd_val = (int *)value; message = ((TSpeechDMessage *) element); assert(message != NULL); assert(message->settings.fd != 0); return (message->settings.fd - *fd_val); } gint compare_message_uid(gconstpointer element, gconstpointer value, gpointer x) { int *uid_val; TSpeechDMessage *message; uid_val = (int *)value; message = ((TSpeechDMessage *) element); assert(message != NULL); //assert(message->settings.fd!=0); return (message->settings.uid - *uid_val); } speech-dispatcher-0.8.3/src/server/Makefile.in0000664000175000017500000015005712536424264016222 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = speech-dispatcher$(EXEEXT) subdir = src/server DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_speech_dispatcher_OBJECTS = speech_dispatcher-speechd.$(OBJEXT) \ speech_dispatcher-server.$(OBJEXT) \ speech_dispatcher-history.$(OBJEXT) \ speech_dispatcher-module.$(OBJEXT) \ speech_dispatcher-configuration.$(OBJEXT) \ speech_dispatcher-parse.$(OBJEXT) \ speech_dispatcher-set.$(OBJEXT) \ speech_dispatcher-alloc.$(OBJEXT) \ speech_dispatcher-compare.$(OBJEXT) \ speech_dispatcher-speaking.$(OBJEXT) \ speech_dispatcher-options.$(OBJEXT) \ speech_dispatcher-output.$(OBJEXT) \ speech_dispatcher-sem_functions.$(OBJEXT) \ speech_dispatcher-index_marking.$(OBJEXT) speech_dispatcher_OBJECTS = $(am_speech_dispatcher_OBJECTS) am__DEPENDENCIES_1 = speech_dispatcher_DEPENDENCIES = $(lib_common) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = speech_dispatcher_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(speech_dispatcher_CFLAGS) $(CFLAGS) \ $(speech_dispatcher_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(speech_dispatcher_SOURCES) DIST_SOURCES = $(speech_dispatcher_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ inc_local = -I$(top_srcdir)/include/ lib_common = $(top_builddir)/src/common/libcommon.la speech_dispatcher_SOURCES = speechd.c speechd.h server.c server.h \ history.c history.h module.c module.h configuration.c configuration.h \ parse.c parse.h set.c set.h msg.h alloc.c alloc.h \ compare.c compare.h speaking.c speaking.h options.c options.h \ output.c output.h sem_functions.c sem_functions.h \ index_marking.c index_marking.h speech_dispatcher_CFLAGS = $(ERROR_CFLAGS) speech_dispatcher_CPPFLAGS = $(inc_local) $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) $(GTHREAD_CFLAGS) -DSYS_CONF=\"$(spdconfdir)\" \ -DSND_DATA=\"$(snddatadir)\" -DMODULEBINDIR=\"$(modulebindir)\" \ -D_GNU_SOURCE -DDEFAULT_AUDIO_METHOD=\"$(default_audio_method)\" speech_dispatcher_LDFLAGS = $(RDYNAMIC) speech_dispatcher_LDADD = $(lib_common) $(DOTCONF_LIBS) $(GLIB_LIBS) \ $(GMODULE_LIBS) $(GTHREAD_LIBS) $(EXTRA_SOCKET_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/server/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/server/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list speech-dispatcher$(EXEEXT): $(speech_dispatcher_OBJECTS) $(speech_dispatcher_DEPENDENCIES) $(EXTRA_speech_dispatcher_DEPENDENCIES) @rm -f speech-dispatcher$(EXEEXT) $(AM_V_CCLD)$(speech_dispatcher_LINK) $(speech_dispatcher_OBJECTS) $(speech_dispatcher_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-alloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-compare.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-history.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-index_marking.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-module.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-output.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-sem_functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-set.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-speaking.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speech_dispatcher-speechd.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< speech_dispatcher-speechd.o: speechd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-speechd.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-speechd.Tpo -c -o speech_dispatcher-speechd.o `test -f 'speechd.c' || echo '$(srcdir)/'`speechd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-speechd.Tpo $(DEPDIR)/speech_dispatcher-speechd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speechd.c' object='speech_dispatcher-speechd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-speechd.o `test -f 'speechd.c' || echo '$(srcdir)/'`speechd.c speech_dispatcher-speechd.obj: speechd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-speechd.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-speechd.Tpo -c -o speech_dispatcher-speechd.obj `if test -f 'speechd.c'; then $(CYGPATH_W) 'speechd.c'; else $(CYGPATH_W) '$(srcdir)/speechd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-speechd.Tpo $(DEPDIR)/speech_dispatcher-speechd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speechd.c' object='speech_dispatcher-speechd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-speechd.obj `if test -f 'speechd.c'; then $(CYGPATH_W) 'speechd.c'; else $(CYGPATH_W) '$(srcdir)/speechd.c'; fi` speech_dispatcher-server.o: server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-server.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-server.Tpo -c -o speech_dispatcher-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-server.Tpo $(DEPDIR)/speech_dispatcher-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='speech_dispatcher-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c speech_dispatcher-server.obj: server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-server.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-server.Tpo -c -o speech_dispatcher-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-server.Tpo $(DEPDIR)/speech_dispatcher-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='speech_dispatcher-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` speech_dispatcher-history.o: history.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-history.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-history.Tpo -c -o speech_dispatcher-history.o `test -f 'history.c' || echo '$(srcdir)/'`history.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-history.Tpo $(DEPDIR)/speech_dispatcher-history.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='history.c' object='speech_dispatcher-history.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-history.o `test -f 'history.c' || echo '$(srcdir)/'`history.c speech_dispatcher-history.obj: history.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-history.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-history.Tpo -c -o speech_dispatcher-history.obj `if test -f 'history.c'; then $(CYGPATH_W) 'history.c'; else $(CYGPATH_W) '$(srcdir)/history.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-history.Tpo $(DEPDIR)/speech_dispatcher-history.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='history.c' object='speech_dispatcher-history.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-history.obj `if test -f 'history.c'; then $(CYGPATH_W) 'history.c'; else $(CYGPATH_W) '$(srcdir)/history.c'; fi` speech_dispatcher-module.o: module.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-module.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-module.Tpo -c -o speech_dispatcher-module.o `test -f 'module.c' || echo '$(srcdir)/'`module.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-module.Tpo $(DEPDIR)/speech_dispatcher-module.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='module.c' object='speech_dispatcher-module.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-module.o `test -f 'module.c' || echo '$(srcdir)/'`module.c speech_dispatcher-module.obj: module.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-module.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-module.Tpo -c -o speech_dispatcher-module.obj `if test -f 'module.c'; then $(CYGPATH_W) 'module.c'; else $(CYGPATH_W) '$(srcdir)/module.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-module.Tpo $(DEPDIR)/speech_dispatcher-module.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='module.c' object='speech_dispatcher-module.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-module.obj `if test -f 'module.c'; then $(CYGPATH_W) 'module.c'; else $(CYGPATH_W) '$(srcdir)/module.c'; fi` speech_dispatcher-configuration.o: configuration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-configuration.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-configuration.Tpo -c -o speech_dispatcher-configuration.o `test -f 'configuration.c' || echo '$(srcdir)/'`configuration.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-configuration.Tpo $(DEPDIR)/speech_dispatcher-configuration.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='configuration.c' object='speech_dispatcher-configuration.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-configuration.o `test -f 'configuration.c' || echo '$(srcdir)/'`configuration.c speech_dispatcher-configuration.obj: configuration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-configuration.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-configuration.Tpo -c -o speech_dispatcher-configuration.obj `if test -f 'configuration.c'; then $(CYGPATH_W) 'configuration.c'; else $(CYGPATH_W) '$(srcdir)/configuration.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-configuration.Tpo $(DEPDIR)/speech_dispatcher-configuration.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='configuration.c' object='speech_dispatcher-configuration.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-configuration.obj `if test -f 'configuration.c'; then $(CYGPATH_W) 'configuration.c'; else $(CYGPATH_W) '$(srcdir)/configuration.c'; fi` speech_dispatcher-parse.o: parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-parse.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-parse.Tpo -c -o speech_dispatcher-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-parse.Tpo $(DEPDIR)/speech_dispatcher-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse.c' object='speech_dispatcher-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c speech_dispatcher-parse.obj: parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-parse.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-parse.Tpo -c -o speech_dispatcher-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-parse.Tpo $(DEPDIR)/speech_dispatcher-parse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse.c' object='speech_dispatcher-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi` speech_dispatcher-set.o: set.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-set.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-set.Tpo -c -o speech_dispatcher-set.o `test -f 'set.c' || echo '$(srcdir)/'`set.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-set.Tpo $(DEPDIR)/speech_dispatcher-set.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set.c' object='speech_dispatcher-set.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-set.o `test -f 'set.c' || echo '$(srcdir)/'`set.c speech_dispatcher-set.obj: set.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-set.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-set.Tpo -c -o speech_dispatcher-set.obj `if test -f 'set.c'; then $(CYGPATH_W) 'set.c'; else $(CYGPATH_W) '$(srcdir)/set.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-set.Tpo $(DEPDIR)/speech_dispatcher-set.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='set.c' object='speech_dispatcher-set.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-set.obj `if test -f 'set.c'; then $(CYGPATH_W) 'set.c'; else $(CYGPATH_W) '$(srcdir)/set.c'; fi` speech_dispatcher-alloc.o: alloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-alloc.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-alloc.Tpo -c -o speech_dispatcher-alloc.o `test -f 'alloc.c' || echo '$(srcdir)/'`alloc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-alloc.Tpo $(DEPDIR)/speech_dispatcher-alloc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='alloc.c' object='speech_dispatcher-alloc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-alloc.o `test -f 'alloc.c' || echo '$(srcdir)/'`alloc.c speech_dispatcher-alloc.obj: alloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-alloc.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-alloc.Tpo -c -o speech_dispatcher-alloc.obj `if test -f 'alloc.c'; then $(CYGPATH_W) 'alloc.c'; else $(CYGPATH_W) '$(srcdir)/alloc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-alloc.Tpo $(DEPDIR)/speech_dispatcher-alloc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='alloc.c' object='speech_dispatcher-alloc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-alloc.obj `if test -f 'alloc.c'; then $(CYGPATH_W) 'alloc.c'; else $(CYGPATH_W) '$(srcdir)/alloc.c'; fi` speech_dispatcher-compare.o: compare.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-compare.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-compare.Tpo -c -o speech_dispatcher-compare.o `test -f 'compare.c' || echo '$(srcdir)/'`compare.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-compare.Tpo $(DEPDIR)/speech_dispatcher-compare.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compare.c' object='speech_dispatcher-compare.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-compare.o `test -f 'compare.c' || echo '$(srcdir)/'`compare.c speech_dispatcher-compare.obj: compare.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-compare.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-compare.Tpo -c -o speech_dispatcher-compare.obj `if test -f 'compare.c'; then $(CYGPATH_W) 'compare.c'; else $(CYGPATH_W) '$(srcdir)/compare.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-compare.Tpo $(DEPDIR)/speech_dispatcher-compare.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compare.c' object='speech_dispatcher-compare.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-compare.obj `if test -f 'compare.c'; then $(CYGPATH_W) 'compare.c'; else $(CYGPATH_W) '$(srcdir)/compare.c'; fi` speech_dispatcher-speaking.o: speaking.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-speaking.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-speaking.Tpo -c -o speech_dispatcher-speaking.o `test -f 'speaking.c' || echo '$(srcdir)/'`speaking.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-speaking.Tpo $(DEPDIR)/speech_dispatcher-speaking.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speaking.c' object='speech_dispatcher-speaking.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-speaking.o `test -f 'speaking.c' || echo '$(srcdir)/'`speaking.c speech_dispatcher-speaking.obj: speaking.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-speaking.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-speaking.Tpo -c -o speech_dispatcher-speaking.obj `if test -f 'speaking.c'; then $(CYGPATH_W) 'speaking.c'; else $(CYGPATH_W) '$(srcdir)/speaking.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-speaking.Tpo $(DEPDIR)/speech_dispatcher-speaking.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='speaking.c' object='speech_dispatcher-speaking.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-speaking.obj `if test -f 'speaking.c'; then $(CYGPATH_W) 'speaking.c'; else $(CYGPATH_W) '$(srcdir)/speaking.c'; fi` speech_dispatcher-options.o: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-options.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-options.Tpo -c -o speech_dispatcher-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-options.Tpo $(DEPDIR)/speech_dispatcher-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='speech_dispatcher-options.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c speech_dispatcher-options.obj: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-options.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-options.Tpo -c -o speech_dispatcher-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-options.Tpo $(DEPDIR)/speech_dispatcher-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='speech_dispatcher-options.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` speech_dispatcher-output.o: output.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-output.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-output.Tpo -c -o speech_dispatcher-output.o `test -f 'output.c' || echo '$(srcdir)/'`output.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-output.Tpo $(DEPDIR)/speech_dispatcher-output.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='output.c' object='speech_dispatcher-output.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-output.o `test -f 'output.c' || echo '$(srcdir)/'`output.c speech_dispatcher-output.obj: output.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-output.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-output.Tpo -c -o speech_dispatcher-output.obj `if test -f 'output.c'; then $(CYGPATH_W) 'output.c'; else $(CYGPATH_W) '$(srcdir)/output.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-output.Tpo $(DEPDIR)/speech_dispatcher-output.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='output.c' object='speech_dispatcher-output.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-output.obj `if test -f 'output.c'; then $(CYGPATH_W) 'output.c'; else $(CYGPATH_W) '$(srcdir)/output.c'; fi` speech_dispatcher-sem_functions.o: sem_functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-sem_functions.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-sem_functions.Tpo -c -o speech_dispatcher-sem_functions.o `test -f 'sem_functions.c' || echo '$(srcdir)/'`sem_functions.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-sem_functions.Tpo $(DEPDIR)/speech_dispatcher-sem_functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sem_functions.c' object='speech_dispatcher-sem_functions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-sem_functions.o `test -f 'sem_functions.c' || echo '$(srcdir)/'`sem_functions.c speech_dispatcher-sem_functions.obj: sem_functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-sem_functions.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-sem_functions.Tpo -c -o speech_dispatcher-sem_functions.obj `if test -f 'sem_functions.c'; then $(CYGPATH_W) 'sem_functions.c'; else $(CYGPATH_W) '$(srcdir)/sem_functions.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-sem_functions.Tpo $(DEPDIR)/speech_dispatcher-sem_functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sem_functions.c' object='speech_dispatcher-sem_functions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-sem_functions.obj `if test -f 'sem_functions.c'; then $(CYGPATH_W) 'sem_functions.c'; else $(CYGPATH_W) '$(srcdir)/sem_functions.c'; fi` speech_dispatcher-index_marking.o: index_marking.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-index_marking.o -MD -MP -MF $(DEPDIR)/speech_dispatcher-index_marking.Tpo -c -o speech_dispatcher-index_marking.o `test -f 'index_marking.c' || echo '$(srcdir)/'`index_marking.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-index_marking.Tpo $(DEPDIR)/speech_dispatcher-index_marking.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='index_marking.c' object='speech_dispatcher-index_marking.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-index_marking.o `test -f 'index_marking.c' || echo '$(srcdir)/'`index_marking.c speech_dispatcher-index_marking.obj: index_marking.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -MT speech_dispatcher-index_marking.obj -MD -MP -MF $(DEPDIR)/speech_dispatcher-index_marking.Tpo -c -o speech_dispatcher-index_marking.obj `if test -f 'index_marking.c'; then $(CYGPATH_W) 'index_marking.c'; else $(CYGPATH_W) '$(srcdir)/index_marking.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/speech_dispatcher-index_marking.Tpo $(DEPDIR)/speech_dispatcher-index_marking.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='index_marking.c' object='speech_dispatcher-index_marking.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(speech_dispatcher_CPPFLAGS) $(CPPFLAGS) $(speech_dispatcher_CFLAGS) $(CFLAGS) -c -o speech_dispatcher-index_marking.obj `if test -f 'index_marking.c'; then $(CYGPATH_W) 'index_marking.c'; else $(CYGPATH_W) '$(srcdir)/index_marking.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/server/alloc.c0000644000175000017500000000335112233560613015374 00000000000000 #ifdef HAVE_CONFIG_H #include #endif #include "alloc.h" TFDSetElement spd_fdset_copy(TFDSetElement old) { TFDSetElement new; new = old; new.msg_settings.voice.language = g_strdup(old.msg_settings.voice.language); new.msg_settings.voice.name = g_strdup(old.msg_settings.voice.name); new.client_name = g_strdup(old.client_name); new.output_module = g_strdup(old.output_module); new.index_mark = g_strdup(old.index_mark); new.audio_output_method = g_strdup(old.audio_output_method); new.audio_oss_device = g_strdup(old.audio_oss_device); new.audio_alsa_device = g_strdup(old.audio_alsa_device); new.audio_nas_server = g_strdup(old.audio_nas_server); new.audio_pulse_server = g_strdup(old.audio_pulse_server); return new; } TSpeechDMessage *spd_message_copy(TSpeechDMessage * old) { TSpeechDMessage *new = NULL; if (old == NULL) return NULL; new = (TSpeechDMessage *) g_malloc(sizeof(TSpeechDMessage)); *new = *old; new->buf = g_malloc((old->bytes + 1) * sizeof(char)); memcpy(new->buf, old->buf, old->bytes); new->buf[new->bytes] = 0; new->settings = spd_fdset_copy(old->settings); return new; } void mem_free_fdset(TFDSetElement * fdset) { /* Don't forget that only these items are filled in in a TSpeechDMessage */ g_free(fdset->client_name); g_free(fdset->msg_settings.voice.language); g_free(fdset->msg_settings.voice.name); g_free(fdset->output_module); g_free(fdset->index_mark); g_free(fdset->audio_output_method); g_free(fdset->audio_oss_device); g_free(fdset->audio_alsa_device); g_free(fdset->audio_nas_server); g_free(fdset->audio_pulse_server); } void mem_free_message(TSpeechDMessage * msg) { if (msg == NULL) return; g_free(msg->buf); mem_free_fdset(&(msg->settings)); g_free(msg); } speech-dispatcher-0.8.3/src/server/index_marking.h0000664000175000017500000000311612522771346017137 00000000000000/* * index_marking.h -- Implements functions handling index marking * for Speech Dispatcher (header) * * Copyright (C) 2001,2002,2003 Brailcom, o.p.s * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: index_marking.h,v 1.5 2006-07-11 16:12:27 hanke Exp $ */ #include "speechd.h" #ifndef INDEX_MARKING_H #define INDEX_MARKING_H #define SD_MARK_BODY_LEN 6 #define SD_MARK_BODY "__spd_" #define SD_MARK_HEAD "" /* Insert index marks into a message. */ void insert_index_marks(TSpeechDMessage * msg, SPDDataMode ssml_mode); /* Find the index mark specified as _mark_ and return the rest of the text after that index mark. */ char *find_index_mark(TSpeechDMessage * msg, int mark); /* Delete all index marks from _buf_ and return a newly allocated string. */ char *strip_index_marks(char *buf, SPDDataMode ssml_mode); #endif /* INDEX_MARKING_H */ speech-dispatcher-0.8.3/src/server/Makefile.am0000644000175000017500000000176612233560613016202 00000000000000## Process this file with automake to produce Makefile.in inc_local = -I$(top_srcdir)/include/ lib_common = $(top_builddir)/src/common/libcommon.la bin_PROGRAMS = speech-dispatcher speech_dispatcher_SOURCES = speechd.c speechd.h server.c server.h \ history.c history.h module.c module.h configuration.c configuration.h \ parse.c parse.h set.c set.h msg.h alloc.c alloc.h \ compare.c compare.h speaking.c speaking.h options.c options.h \ output.c output.h sem_functions.c sem_functions.h \ index_marking.c index_marking.h speech_dispatcher_CFLAGS = $(ERROR_CFLAGS) speech_dispatcher_CPPFLAGS = $(inc_local) $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) \ $(GMODULE_CFLAGS) $(GTHREAD_CFLAGS) -DSYS_CONF=\"$(spdconfdir)\" \ -DSND_DATA=\"$(snddatadir)\" -DMODULEBINDIR=\"$(modulebindir)\" \ -D_GNU_SOURCE -DDEFAULT_AUDIO_METHOD=\"$(default_audio_method)\" speech_dispatcher_LDFLAGS = $(RDYNAMIC) speech_dispatcher_LDADD = $(lib_common) $(DOTCONF_LIBS) $(GLIB_LIBS) \ $(GMODULE_LIBS) $(GTHREAD_LIBS) $(EXTRA_SOCKET_LIBS) speech-dispatcher-0.8.3/src/server/options.h0000644000175000017500000000200712233560613015777 00000000000000/* * options.h - Defines possible command line options * * Copyright (C) 2003, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: options.h,v 1.7 2008-07-07 14:31:08 hanke Exp $ */ #include void options_print_help(char *argv[]); void options_print_version(void); void options_parse(int argc, char *argv[]); speech-dispatcher-0.8.3/src/server/output.c0000664000175000017500000005176012536417045015661 00000000000000/* * output.c - Output layer for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: output.c,v 1.38 2008-06-27 12:28:48 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "output.h" #include "parse.h" #if !(defined(__GLIBC__) && defined(_GNU_SOURCE)) /* Added by Willie Walker - strndup is a gcc-ism */ char *strndup(const char *s, size_t n) { size_t nAvail; char *p; if (!s) return 0; if (strlen(s) > n) nAvail = n + 1; else nAvail = strlen(s) + 1; p = g_malloc(nAvail); memcpy(p, s, nAvail); p[nAvail - 1] = '\0'; return p; } #endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */ void output_set_speaking_monitor(TSpeechDMessage * msg, OutputModule * output) { /* Set the speaking-monitor so that we know who is speaking */ speaking_module = output; speaking_uid = msg->settings.uid; speaking_gid = msg->settings.reparted; } OutputModule *get_output_module_by_name(char *name) { OutputModule *output; int i; for (i = 0; i < g_list_length(output_modules); i++) { output = g_list_nth_data(output_modules, i); if (!strcmp(output->name, name)) { if (output->working) return output; else return NULL; } } return NULL; } /* get_output_module tries to return a pointer to the appropriate output module according to message context. If it is not possible to find the required module, it will subsequently try to get the default module, any of the other remaining modules except dummy and at last, the dummy output module. Only if not even dummy output module is working (serious issues), it will log an error message and return a NULL pointer. */ OutputModule *get_output_module(const TSpeechDMessage * message) { OutputModule *output = NULL; int i, len; if (message->settings.output_module != NULL) { MSG(5, "Desired output module is %s", message->settings.output_module); output = get_output_module_by_name(message->settings.output_module); if ((output != NULL) && output->working) return output; } MSG(3, "Warning: Didn't find preferred output module, using default"); // If the requested module was not found or is not working, // first try to use the default output module if (GlobalFDSet.output_module != NULL) output = get_output_module_by_name(GlobalFDSet.output_module); if (output != NULL && output->working) return output; MSG(3, "Couldn't load default output module, trying other modules"); /* Try all other output modules other than dummy */ len = g_list_length(output_modules); for (i = 0; i < len; i++) { output = g_list_nth_data(output_modules, i); if (0 == strcmp(output->name, "dummy")) continue; if (output->working) { MSG(3, "Output module %s seems to be working, using it", output->name); return output; } } // if we get here there are no good modules use the dummy // a pre-synthesized error message with some hints over and over). if (output == NULL || !output->working) output = get_output_module_by_name("dummy"); // Give up.... if (output == NULL) MSG(1, "Error: No output module working, not even dummy, no sound produced!\n"); return output; } void static output_lock(void) { pthread_mutex_lock(&output_layer_mutex); } void static output_unlock(void) { pthread_mutex_unlock(&output_layer_mutex); } #define OL_RET(value) \ { output_unlock(); \ return (value); } GString *output_read_reply(OutputModule * output) { GString *rstr; int bytes; char *line = NULL; size_t N = 0; gboolean errors = FALSE; rstr = g_string_new(""); /* Wait for activity on the socket, when there is some, read all the message line by line */ do { bytes = spd_getline(&line, &N, output->stream_out); if (bytes == -1) { MSG(2, "Error: Broken pipe to module."); output->working = 0; speaking_module = NULL; output_check_module(output); errors = TRUE; /* Broken pipe */ } else { MSG(5, "Got %d bytes from output module over socket", bytes); g_string_append(rstr, line); } /* terminate if we reached the last line (without '-' after numcode) */ } while (!errors && !((strlen(line) < 4) || (line[3] == ' '))); if (line != NULL) g_free(line); if (errors) { g_string_free(rstr, TRUE); rstr = NULL; } return rstr; } char *output_read_reply2(OutputModule * output) { int bytes; char *reply; reply = g_malloc(1024 * sizeof(char)); bytes = read(output->pipe_out[0], reply, 1024); reply[bytes] = 0; MSG2(1, "output_module", "2Read: %d bytes: <%s>", bytes, reply); return reply; } int output_send_data(char *cmd, OutputModule * output, int wfr) { int ret; GString *response; if (output == NULL) return -1; if (cmd == NULL) return -1; ret = safe_write(output->pipe_in[1], cmd, strlen(cmd)); fflush(NULL); if (ret == -1) { MSG(2, "Error: Broken pipe to module."); output->working = 0; speaking_module = NULL; output_check_module(output); return -1; /* Broken pipe */ } MSG2(5, "output_module", "Command sent to output module: |%s| (%d)", cmd, wfr); if (wfr) { /* wait for reply? */ int ret = 0; response = output_read_reply(output); if (response == NULL) return -1; MSG2(5, "output_module", "Reply from output module: |%s|", response->str); switch (response->str[0]) { case '3': MSG(2, "Error: Module reported error in request from speechd (code 3xx): %s.", response->str); ret = -2; /* User (speechd) side error */ break; case '4': MSG(2, "Error: Module reported error in itself (code 4xx): %s", response->str); ret = -3; /* Module side error */ break; case '2': ret = 0; break; default: /* unknown response */ MSG(3, "Unknown response from output module!"); ret = -3; break; } g_string_free(response, TRUE); return ret; } return 0; } static void free_voice(gpointer data) { SPDVoice *voice = (SPDVoice *)data; if (voice != NULL) { if (voice->name != NULL) g_free(voice->name); if (voice->language != NULL) g_free(voice->language); if (voice->variant != NULL) g_free(voice->variant); g_free(voice); } } static SPDVoice **output_get_voices(OutputModule * module) { SPDVoice **voice_dscr; SPDVoice *voice; GString *reply; gchar **lines; gchar **atoms; GQueue *voices; int i; int ret = 0; int numvoices = 0; gboolean errors = FALSE; output_lock(); if (module == NULL) { MSG(1, "ERROR: Can't list voices for broken output module"); OL_RET(NULL); } output_send_data("LIST VOICES\n", module, 0); reply = output_read_reply(module); if (reply == NULL) { output_unlock(); return NULL; } lines = g_strsplit(reply->str, "\n", -1); g_string_free(reply, TRUE); voices = g_queue_new(); for (i = 0; !errors && (lines[i] != NULL); i++) { MSG(1, "LINE here:|%s|", lines[i]); if (strlen(lines[i]) <= 4) { MSG(1, "ERROR: Bad communication from driver in synth_voices"); ret = -1; errors = TRUE; } else if (lines[i][3] == ' ') break; else if (lines[i][3] == '-') { atoms = g_strsplit(&lines[i][4], " ", 0); // Name, language, dialect if ((atoms[0] == NULL) || (atoms[1] == NULL) || (atoms[2] == NULL)) { ret = -1; errors = TRUE; } else { //Fill in VoiceDescription voice = g_malloc(sizeof(SPDVoice)); voice->name = g_strdup(atoms[0]); voice->language = g_strdup(atoms[1]); voice->variant = g_strdup(atoms[2]); g_queue_push_tail(voices, voice); } if (atoms != NULL) g_strfreev(atoms); } /* Should we do something in a final "else" branch? */ } numvoices = g_queue_get_length(voices); if (errors == TRUE) { g_queue_free_full(voices, (GDestroyNotify)free_voice); g_strfreev(lines); output_unlock(); return NULL; } voice_dscr = g_malloc((numvoices + 1) * sizeof(SPDVoice *)); for (i = 0; i < numvoices; i++) { voice_dscr[i] = g_queue_pop_head(voices); } voice_dscr[i] = NULL; g_queue_free(voices); g_strfreev(lines); output_unlock(); return voice_dscr; } SPDVoice **output_list_voices(char *module_name) { OutputModule *module; if (module_name == NULL) return NULL; module = get_output_module_by_name(module_name); if (module == NULL) { MSG(1, "ERROR: Can't list voices for module %s", module_name); return NULL; } return output_get_voices(module); } #define SEND_CMD_N(cmd) \ { err = output_send_data(cmd"\n", output, 1); \ if (err < 0) return (err); } #define SEND_CMD(cmd) \ { err = output_send_data(cmd"\n", output, 1); \ if (err < 0) OL_RET(err)} #define SEND_DATA_N(data) \ { err = output_send_data(data, output, 0); \ if (err < 0) return (err); } #define SEND_DATA(data) \ { err = output_send_data(data, output, 0); \ if (err < 0) OL_RET(err); } #define SEND_CMD_GET_VALUE(data) \ { err = output_send_data(data"\n", output, 1); \ OL_RET(err); } #define ADD_SET_INT(name) \ g_string_append_printf(set_str, #name"=%d\n", msg->settings.name); #define ADD_SET_STR(name) \ if (msg->settings.name != NULL){ \ g_string_append_printf(set_str, #name"=%s\n", msg->settings.name); \ }else{ \ g_string_append_printf(set_str, #name"=NULL\n"); \ } #define ADD_SET_STR_C(name, fconv) \ val = fconv(msg->settings.msg_settings.name); \ if (val != NULL){ \ g_string_append_printf(set_str, #name"=%s\n", val); \ } \ g_free(val); int output_send_settings(TSpeechDMessage * msg, OutputModule * output) { GString *set_str; char *val; int err; MSG(4, "Module set parameters."); set_str = g_string_new(""); g_string_append_printf(set_str, "pitch=%d\n", msg->settings.msg_settings.pitch); g_string_append_printf(set_str, "rate=%d\n", msg->settings.msg_settings.rate); g_string_append_printf(set_str, "volume=%d\n", msg->settings.msg_settings.volume); ADD_SET_STR_C(punctuation_mode, EPunctMode2str); ADD_SET_STR_C(spelling_mode, ESpellMode2str); ADD_SET_STR_C(cap_let_recogn, ECapLetRecogn2str); val = EVoice2str(msg->settings.msg_settings.voice_type); if (val != NULL) { g_string_append_printf(set_str, "voice=%s\n", val); } g_free(val); if (msg->settings.msg_settings.voice.language != NULL) { g_string_append_printf(set_str, "language=%s\n", msg->settings.msg_settings.voice. language); } else { g_string_append_printf(set_str, "language=NULL\n"); } if (msg->settings.msg_settings.voice.name != NULL) { g_string_append_printf(set_str, "synthesis_voice=%s\n", msg->settings.msg_settings.voice.name); } else { g_string_append_printf(set_str, "synthesis_voice=NULL\n"); } SEND_CMD_N("SET"); SEND_DATA_N(set_str->str); SEND_CMD_N("."); g_string_free(set_str, 1); return 0; } #undef ADD_SET_INT #undef ADD_SET_STR #define ADD_SET_INT(name) \ g_string_append_printf(set_str, #name"=%d\n", GlobalFDSet.name); #define ADD_SET_STR(name) \ if (GlobalFDSet.name != NULL){ \ g_string_append_printf(set_str, #name"=%s\n", GlobalFDSet.name); \ }else{ \ g_string_append_printf(set_str, #name"=NULL\n"); \ } int output_send_audio_settings(OutputModule * output) { GString *set_str; int err; MSG(4, "Module set parameters."); set_str = g_string_new(""); ADD_SET_STR(audio_output_method); ADD_SET_STR(audio_oss_device); ADD_SET_STR(audio_alsa_device); ADD_SET_STR(audio_nas_server); ADD_SET_STR(audio_pulse_server); ADD_SET_INT(audio_pulse_min_length); SEND_CMD_N("AUDIO"); SEND_DATA_N(set_str->str); SEND_CMD_N("."); g_string_free(set_str, 1); return 0; } int output_send_loglevel_setting(OutputModule * output) { GString *set_str; int err; MSG(4, "Module set parameters."); set_str = g_string_new(""); ADD_SET_INT(log_level); SEND_CMD_N("LOGLEVEL"); SEND_DATA_N(set_str->str); SEND_CMD_N("."); g_string_free(set_str, 1); return 0; } #undef ADD_SET_INT #undef ADD_SET_STR int output_send_debug(OutputModule * output, int flag, char *log_path) { char *cmd_str; int err; MSG(4, "Module sending debug flag %d with file %s", flag, log_path); output_lock(); if (flag) { cmd_str = g_strdup_printf("DEBUG ON %s \n", log_path); err = output_send_data(cmd_str, output, 1); g_free(cmd_str); if (err) { MSG(3, "ERROR: Can't set debugging on for output module %s", output->name); OL_RET(-1); } } else { err = output_send_data("DEBUG OFF \n", output, 1); if (err) { MSG(3, "ERROR: Can't switch debugging off for output module %s", output->name); OL_RET(-1); } } OL_RET(0); } int output_speak(TSpeechDMessage * msg) { OutputModule *output; int err; int ret; if (msg == NULL) return -1; output_lock(); /* Determine which output module should be used */ output = get_output_module(msg); if (output == NULL) { MSG(3, "Output module doesn't work..."); OL_RET(-1) } msg->buf = escape_dot(msg->buf); msg->bytes = -1; output_set_speaking_monitor(msg, output); ret = output_send_settings(msg, output); if (ret != 0) OL_RET(ret); MSG(4, "Module speak!"); switch (msg->settings.type) { case SPD_MSGTYPE_TEXT: SEND_CMD("SPEAK") break; case SPD_MSGTYPE_SOUND_ICON: SEND_CMD("SOUND_ICON"); break; case SPD_MSGTYPE_CHAR: SEND_CMD("CHAR"); break; case SPD_MSGTYPE_KEY: SEND_CMD("KEY"); break; default: MSG(2, "Invalid message type in output_speak()!"); } SEND_DATA(msg->buf) SEND_CMD("\n.") OL_RET(0) } int output_stop() { int err; OutputModule *output; output_lock(); if (speaking_module == NULL) OL_RET(0) else output = speaking_module; MSG(4, "Module stop!"); SEND_DATA("STOP\n"); OL_RET(0) } size_t output_pause() { static int err; static OutputModule *output; output_lock(); if (speaking_module == NULL) OL_RET(0) else output = speaking_module; MSG(4, "Module pause!"); SEND_DATA("PAUSE\n"); OL_RET(0) } int output_module_is_speaking(OutputModule * output, char **index_mark) { GString *response; int retcode = -1; output_lock(); MSG(5, "output_module_is_speaking()"); if (output == NULL) { MSG(5, "output==NULL in output_module_is_speaking()"); OL_RET(-1); } response = output_read_reply(output); if (response == NULL) { *index_mark = NULL; OL_RET(-1); } MSG2(5, "output_module", "Reply from output module: |%s|", response->str); if (response->len < 4) { MSG2(2, "output_module", "Error: Wrong communication from output module! Reply less than four bytes."); g_string_free(response, TRUE); OL_RET(-1); } switch (response->str[0]) { case '3': MSG(2, "Error: Module reported error in request from speechd (code 3xx)."); retcode = -2; /* User (speechd) side error */ break; case '4': MSG(2, "Error: Module reported error in itself (code 4xx)."); retcode = -3; /* Module side error */ break; case '2': retcode = 0; if (response->len > 4) { if (response->str[3] == '-') { char *p; p = strchr(response->str, '\n'); *index_mark = (char *)strndup(response->str + 4, p - response->str - 4); MSG2(5, "output_module", "Detected INDEX MARK: %s", *index_mark); } else { MSG2(2, "output_module", "Error: Wrong communication from output module!" "Reply on SPEAKING not multi-line."); retcode = -1; } } break; case '7': retcode = 0; MSG2(5, "output_module", "Received event:\n %s", response->str); if (!strncmp(response->str, "701", 3)) *index_mark = (char *)g_strdup("__spd_begin"); else if (!strncmp(response->str, "702", 3)) *index_mark = (char *)g_strdup("__spd_end"); else if (!strncmp(response->str, "703", 3)) *index_mark = (char *)g_strdup("__spd_stopped"); else if (!strncmp(response->str, "704", 3)) *index_mark = (char *)g_strdup("__spd_paused"); else if (!strncmp(response->str, "700", 3)) { char *p; p = strchr(response->str, '\n'); MSG2(5, "output_module", "response:|%s|\n p:|%s|", response->str, p); *index_mark = (char *)strndup(response->str + 4, p - response->str - 4); MSG2(5, "output_module", "Detected INDEX MARK: %s", *index_mark); } else { MSG2(2, "output_module", "ERROR: Unknown event received from output module"); retcode = -5; } break; default: /* unknown response */ MSG(3, "Unknown response from output module!"); retcode = -3; break; } g_string_free(response, TRUE); OL_RET(retcode) } int output_is_speaking(char **index_mark) { int err; OutputModule *output; output = speaking_module; err = output_module_is_speaking(output, index_mark); if (err < 0) { *index_mark = NULL; } return err; } /* Wait until the child _pid_ returns with timeout. Calls waitpid() each 100ms until timeout is exceeded. This is not exact and you should not rely on the exact time waited. */ int waitpid_with_timeout(pid_t pid, int *status_ptr, int options, size_t timeout) { size_t i; int ret; for (i = 0; i <= timeout; i += 100) { ret = waitpid(pid, status_ptr, options | WNOHANG); if (ret > 0) return ret; if (ret < 0) return ret; usleep(100 * 1000); /* Sleep 100 ms */ } return 0; } int output_close(OutputModule * module) { int err; int ret; OutputModule *output; output = module; if (output == NULL) return -1; output_lock(); assert(output->name != NULL); MSG(3, "Closing module \"%s\"...", output->name); if (output->working) { SEND_DATA("STOP\n"); SEND_CMD("QUIT"); usleep(100); /* So that the module has some time to exit() correctly */ } MSG(4, "Waiting for module pid %d", module->pid); ret = waitpid_with_timeout(module->pid, NULL, 0, 1000); if (ret > 0) { MSG(4, "Ok, module closed successfully."); } else if (ret == 0) { int ret2; MSG(1, "ERROR: Timed out when waiting for child cancellation"); MSG(3, "Killing the module"); kill(module->pid, SIGKILL); MSG(4, "Waiting until the child terminates."); ret2 = waitpid_with_timeout(module->pid, NULL, 0, 1000); if (ret2 > 0) { MSG(3, "Module terminated"); } else { MSG(1, "ERROR: Module is not able to terminate, giving up."); } } else { MSG(1, "ERROR: waitpid() failed when waiting for child (module)."); } OL_RET(0) } #undef SEND_CMD #undef SEND_DATA int output_check_module(OutputModule * output) { int ret; int err; int status; if (output == NULL) return -1; MSG(4, "Output module working status: %d (pid:%d)", output->working, output->pid); if (output->working == 0) { /* Investigate on why it crashed */ ret = waitpid(output->pid, &status, WNOHANG); if (ret == 0) { MSG(2, "Output module not running."); return 0; } ret = WIFEXITED(status); /* TODO: Linux kernel implementation of threads is not very good :( */ // if (ret == 0){ if (1) { /* Module terminated abnormally */ MSG(2, "Output module terminated abnormally, probably crashed."); } else { /* Module terminated normally, check status */ err = WEXITSTATUS(status); if (err == 0) MSG(2, "Module exited normally"); if (err == 1) MSG(2, "Internal error in output module!"); if (err == 2) { MSG(2, "Output device not working. For software devices, this can mean" "that they are not running or they are not accessible due to wrong" "acces permissions."); } if (err > 2) MSG(2, "Unknown error happened in output module, exit status: %d !", err); } } return 0; } char *escape_dot(char *otext) { char *seq; GString *ntext; char *ootext; char *ret = NULL; int len; if (otext == NULL) return NULL; MSG2(5, "escaping", "Incoming text: |%s|", otext); ootext = otext; ntext = g_string_new(""); if (strlen(otext) == 1) { if (!strcmp(otext, ".")) { g_string_append(ntext, ".."); otext += 1; } } if (strlen(otext) >= 2) { if ((otext[0] == '.') && (otext[1] == '\n')) { g_string_append(ntext, "..\n"); otext = otext + 2; } } MSG2(6, "escaping", "Altering text (I): |%s|", ntext->str); while ((seq = strstr(otext, "\n.\n"))) { *seq = 0; g_string_append(ntext, otext); g_string_append(ntext, "\n..\n"); otext = seq + 3; } MSG2(6, "escaping", "Altering text (II): |%s|", ntext->str); len = strlen(otext); if (len >= 2) { if ((otext[len - 2] == '\n') && (otext[len - 1] == '.')) { g_string_append(ntext, otext); g_string_append(ntext, "."); otext = otext + len; MSG2(6, "escaping", "Altering text (II-b): |%s|", ntext->str); } } if (otext == ootext) { g_string_free(ntext, 1); ret = otext; } else { g_string_append(ntext, otext); g_free(ootext); ret = ntext->str; g_string_free(ntext, 0); } MSG2(6, "escaping", "Altered text: |%s|", ret); return ret; } speech-dispatcher-0.8.3/src/server/output.h0000644000175000017500000000367012233560613015653 00000000000000/* * output.h - Output layer for Speech Dispatcher header * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: output.h,v 1.9 2008-06-27 12:28:50 hanke Exp $ */ #include "speechd.h" #include "speaking.h" OutputModule *get_output_module(const TSpeechDMessage * message); int output_speak(TSpeechDMessage * msg); int output_stop(); size_t output_pause(); int output_is_speaking(char **index_mark); int output_send_debug(OutputModule * output, int flag, char *logfile_path); int output_check_module(OutputModule * output); char *escape_dot(char *otext); void output_set_speaking_monitor(TSpeechDMessage * msg, OutputModule * output); GString *output_read_reply(OutputModule * output); char *output_read_reply2(OutputModule * output); int output_send_data(char *cmd, OutputModule * output, int wfr); int output_send_settings(TSpeechDMessage * msg, OutputModule * output); int output_send_audio_settings(OutputModule * output); int output_send_loglevel_setting(OutputModule * output); int output_module_is_speaking(OutputModule * output, char **index_mark); int waitpid_with_timeout(pid_t pid, int *status_ptr, int options, size_t timeout); int output_close(OutputModule * module); SPDVoice **output_list_voices(char *module_name); speech-dispatcher-0.8.3/src/server/alloc.h0000644000175000017500000000043412233560613015400 00000000000000 #include "speechd.h" #ifndef ALLOC_H #define ALLOC_H /* Copy a message */ TSpeechDMessage *spd_message_copy(TSpeechDMessage * old); /* Free a message */ void mem_free_message(TSpeechDMessage * msg); /* Free a settings element */ void mem_free_fdset(TFDSetElement * set); #endif speech-dispatcher-0.8.3/src/server/msg.h0000664000175000017500000001672312536417045015114 00000000000000/* * msg.h - Client/server messages for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: msg.h,v 1.31 2008-07-01 08:50:46 hanke Exp $ */ #ifndef MSG_H #define MSG_H #define NEWLINE "\r\n" #define OK_LANGUAGE_SET "201 OK LANGUAGE SET" NEWLINE #define OK_PRIORITY_SET "202 OK PRIORITY SET" NEWLINE #define OK_RATE_SET "203 OK RATE SET" NEWLINE #define OK_PITCH_SET "204 OK PITCH SET" NEWLINE #define OK_PUNCT_MODE_SET "205 OK PUNCTUATION SET" NEWLINE #define OK_CAP_LET_RECOGN_SET "206 OK CAP LET RECOGNITION SET" NEWLINE #define OK_SPELLING_SET "207 OK SPELLING SET" NEWLINE #define OK_CLIENT_NAME_SET "208 OK CLIENT NAME SET" NEWLINE #define OK_VOICE_SET "209 OK VOICE SET" NEWLINE #define OK_STOPPED "210 OK STOPPED" NEWLINE #define OK_PAUSED "211 OK PAUSED" NEWLINE #define OK_RESUMED "212 OK RESUMED" NEWLINE #define OK_CANCELED "213 OK CANCELED" NEWLINE #define OK_TABLE_SET "215 OK TABLE SET" NEWLINE #define OK_OUTPUT_MODULE_SET "216 OK OUTPUT MODULE SET" NEWLINE #define OK_PAUSE_CONTEXT_SET "217 OK PAUSE CONTEXT SET" NEWLINE #define OK_VOLUME_SET "218 OK VOLUME SET" NEWLINE #define OK_SSML_MODE_SET "219 OK SSML MODE SET" NEWLINE #define OK_NOTIFICATION_SET "220 OK NOTIFICATION SET" NEWLINE #define OK_CUR_SET_FIRST "220 OK CURSOR SET FIRST" NEWLINE #define OK_CUR_SET_LAST "221 OK CURSOR SET LAST" NEWLINE #define OK_CUR_SET_POS "222 OK CURSOR SET TO POSITION" NEWLINE #define OK_CUR_MOV_FOR "223 OK CURSOR MOVED FORWARD" NEWLINE #define OK_CUR_MOV_BACK "224 OK CURSOR MOVED BACKWARD" NEWLINE #define C_OK_MESSAGE_QUEUED "225" #define OK_MESSAGE_QUEUED "225 OK MESSAGE QUEUED" NEWLINE #define OK_SND_ICON_QUEUED "226 OK SOUND ICON QUEUED" NEWLINE #define OK_MSG_CANCELED "227 OK MESSAGE CANCELED" NEWLINE #define OK_RECEIVE_DATA "230 OK RECEIVING DATA" NEWLINE #define OK_BYE "231 HAPPY HACKING" NEWLINE #define OK_CLIENT_LIST_SENT "240 OK CLIENTS LIST SENT" NEWLINE #define C_OK_CLIENTS "240" #define OK_MSGS_LIST_SENT "241 OK MSGS LIST SENT" NEWLINE #define C_OK_MSGS "241" #define OK_LAST_MSG "242 OK LAST MSG SAID" NEWLINE #define C_OK_LAST_MSG "242" #define OK_CUR_POS_RET "243 OK CURSOR POSITION RETURNED" NEWLINE #define C_OK_CUR_POS "243" #define OK_TABLE_LIST_SENT "244 OK TABLE LIST SEND" NEWLINE #define C_OK_TABLES "244" #define OK_CLIENT_ID_SENT "245 OK CLIENT ID SENT" NEWLINE #define C_OK_CLIENT_ID "245" #define OK_MSG_TEXT_SENT "246 OK MESSAGE TEXT SENT" NEWLINE #define C_OK_MSG_TEXT "246" #define OK_HELP_SENT "248 OK HELP SENT" NEWLINE #define C_OK_HELP "248" #define OK_VOICE_LIST_SENT "249 OK VOICE LIST SENT" NEWLINE #define C_OK_VOICES "249" #define OK_MODULES_LIST_SENT "250 OK VOICE LIST SENT" NEWLINE #define C_OK_MODULES "250" #define OK_GET "251 OK GET RETURNED" NEWLINE #define C_OK_GET "251" #define OK_INSIDE_BLOCK "260 OK INSIDE BLOCK" NEWLINE #define OK_OUTSIDE_BLOCK "261 OK OUTSIDE BLOCK" NEWLINE #define OK_DEBUGGING "262 OK DEBUGGING SET" NEWLINE #define OK_NOT_IMPLEMENTED "299 OK BUT NOT IMPLEMENTED -- DOES NOTHING" NEWLINE #define ERR_NO_CLIENT "401 ERR NO CLIENT" NEWLINE #define ERR_NO_SUCH_CLIENT "402 ERR NO SUCH CLIENT" NEWLINE #define ERR_NO_MESSAGE "403 ERR NO MESSAGE" NEWLINE #define ERR_POS_LOW "404 ERR POSITION TOO LOW" NEWLINE #define ERR_POS_HIGH "405 ERR POSITION TOO HIGH" NEWLINE #define ERR_ID_NOT_EXIST "406 ERR ID DOESNT EXIST" NEWLINE #define ERR_UNKNOWN_ICON "407 ERR UNKNOWN ICON" NEWLINE #define ERR_UNKNOWN_PRIORITY "408 ERR UNKNOWN PRIORITY" NEWLINE #define ERR_RATE_TOO_HIGH "409 ERR RATE TOO HIGH" NEWLINE #define ERR_RATE_TOO_LOW "410 ERR RATE TOO LOW" NEWLINE #define ERR_PITCH_TOO_HIGH "411 ERR PITCH TOO HIGH" NEWLINE #define ERR_PITCH_TOO_LOW "412 ERR PITCH TOO LOW" NEWLINE #define ERR_VOLUME_TOO_HIGH "413 ERR PITCH TOO HIGH" NEWLINE #define ERR_VOLUME_TOO_LOW "414 ERR PITCH TOO LOW" NEWLINE #define ERR_INTERNAL "300 ERR INTERNAL" NEWLINE #define ERR_COULDNT_SET_PRIORITY "301 ERR COULDNT SET PRIORITY" NEWLINE #define ERR_COULDNT_SET_LANGUAGE "302 ERR COULDNT SET LANGUAGE" NEWLINE #define ERR_COULDNT_SET_RATE "303 ERR COULDNT SET RATE" NEWLINE #define ERR_COULDNT_SET_PITCH "304 ERR COULDNT SET PITCH" NEWLINE #define ERR_COULDNT_SET_PUNCT_MODE "305 ERR COULDNT SET PUNCT MODE" NEWLINE #define ERR_COULDNT_SET_CAP_LET_RECOG "306 ERR COULDNT SET CAP LET RECOGNITION" NEWLINE #define ERR_COULDNT_SET_SPELLING "308 ERR COULDNT SET SPELLING" NEWLINE #define ERR_COULDNT_SET_VOICE "309 ERR COULDNT SET VOICE" NEWLINE #define ERR_COULDNT_SET_TABLE "310 ERR COULDNT SET TABLE" NEWLINE #define ERR_COULDNT_SET_CLIENT_NAME "311 ERR COULDNT SET CLIENT_NAME" NEWLINE #define ERR_COULDNT_SET_OUTPUT_MODULE "312 ERR COULDNT SET OUTPUT MODULE" NEWLINE #define ERR_COULDNT_SET_PAUSE_CONTEXT "313 ERR COULDNT SET PAUSE CONTEXT" NEWLINE #define ERR_COULDNT_SET_VOLUME "314 ERR COULDNT SET VOLUME" NEWLINE #define ERR_COULDNT_SET_SSML_MODE "315 ERR COULDNT SET SSML MODE" NEWLINE #define ERR_COULDNT_SET_NOTIFICATION "316 ERR COULDNT SET NOTIFICATION" NEWLINE #define ERR_COULDNT_SET_DEBUGGING "317 ERR COULDNT SET DEBUGGING" NEWLINE #define ERR_NO_SND_ICONS "320 ERR NO SOUND ICONS" NEWLINE #define ERR_CANT_REPORT_VOICES "321 ERR MODULE CANT REPORT VOICES" NEWLINE #define ERR_NO_OUTPUT_MODULE "321 ERR NO OUTPUT MODULE LOADED" NEWLINE #define ERR_ALREADY_INSIDE_BLOCK "330 ERR ALREADY INSIDE BLOCK" NEWLINE #define ERR_ALREADY_OUTSIDE_BLOCK "331 ERR ALREADY OUTSIDE BLOCK" NEWLINE #define ERR_NOT_ALLOWED_INSIDE_BLOCK "332 ERR NOT ALLOWED INSIDE BLOCK" NEWLINE #define ERR_NOT_IMPLEMENTED "380 ERR NOT YET IMPLEMENTED" NEWLINE #define ERR_INVALID_COMMAND "500 ERR INVALID COMMAND" NEWLINE #define ERR_INVALID_ENCODING "501 ERR INVALID ENCODING" NEWLINE #define ERR_MISSING_PARAMETER "510 ERR MISSING PARAMETER" NEWLINE #define ERR_NOT_A_NUMBER "511 ERR PARAMETER NOT A NUMBER" NEWLINE #define ERR_NOT_A_STRING "512 ERR PARAMETER NOT A STRING" NEWLINE #define ERR_PARAMETER_NOT_ON_OFF "513 ERR PARAMETER NOT ON OR OFF" NEWLINE #define ERR_PARAMETER_INVALID "514 ERR PARAMETER INVALID" NEWLINE #define EVENT_INDEX_MARK_C "700" #define EVENT_INDEX_MARK EVENT_INDEX_MARK_C" INDEX MARK" NEWLINE #define EVENT_BEGIN_C "701" #define EVENT_BEGIN EVENT_BEGIN_C" BEGIN" NEWLINE #define EVENT_END_C "702" #define EVENT_END EVENT_END_C" END" NEWLINE #define EVENT_CANCELED_C "703" #define EVENT_CANCELED EVENT_CANCELED_C" CANCELED" NEWLINE #define EVENT_PAUSED_C "704" #define EVENT_PAUSED EVENT_PAUSED_C" PAUSED" NEWLINE #define EVENT_RESUMED_C "705" #define EVENT_RESUMED EVENT_RESUMED_C" RESUMED" NEWLINE #endif /* MSG_H */ speech-dispatcher-0.8.3/src/server/server.h0000644000175000017500000000240012233560613015607 00000000000000 /* * server.h - The server body * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: server.h,v 1.3 2006-07-11 16:12:27 hanke Exp $ */ #ifndef SERVER_H #define SERVER_H /* serve() reads data from clients and sends it to parse() */ int serve(int fd); /* Switches `receiving data' mode on and off for specified client */ int server_data_on(int fd); void server_data_off(int fd); /* Put a message into Dispatcher's queue */ int queue_message(TSpeechDMessage * new, int fd, int history_flag, SPDMessageType type, int reparted); #endif speech-dispatcher-0.8.3/src/server/configuration.c0000664000175000017500000003454412536417045017171 00000000000000 /* * dc_decl.h - Dotconf functions and types for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: config.c,v 1.18 2009-05-14 08:11:33 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "speechd.h" #include "configuration.h" #include static TFDSetClientSpecific *cl_spec_section; /* So that gcc doesn't comply about casts to char* */ /* == CONFIGURATION MANAGEMENT FUNCTIONS */ /* Add dotconf configuration option */ configoption_t *add_config_option(configoption_t * options, int *num_config_options, char *name, int type, dotconf_callback_t callback, info_t * info, unsigned long context) { configoption_t *opts; (*num_config_options)++; opts = (configoption_t *) g_realloc(options, (*num_config_options) * sizeof(configoption_t)); opts[*num_config_options - 1].name = g_strdup(name); opts[*num_config_options - 1].type = type; opts[*num_config_options - 1].callback = callback; opts[*num_config_options - 1].info = info; opts[*num_config_options - 1].context = context; return opts; } /* Free all configuration options. */ void free_config_options(configoption_t * opts, int *num) { int i = 0; if (opts == NULL) return; for (i = 0; i <= (*num) - 1; i++) { g_free((char *)opts[i].name); } g_free(opts); *num = 0; opts = NULL; } /* == CALLBACK DEFINITION MACROS == */ #define GLOBAL_FDSET_OPTION_CB_STR(name, arg) \ DOTCONF_CB(cb_ ## name) \ { \ assert(cmd->data.str != NULL); \ if (!cl_spec_section) \ GlobalFDSet.arg = g_strdup(cmd->data.str); \ else \ cl_spec_section->val.arg = g_strdup(cmd->data.str); \ return NULL; \ } #define GLOBAL_FDSET_OPTION_CB_INT(name, arg, cond, str) \ DOTCONF_CB(cb_ ## name) \ { \ int val = cmd->data.value; \ if (!(cond)) FATAL(str); \ if (!cl_spec_section) \ GlobalFDSet.arg = val; \ else \ cl_spec_section->val.arg = val; \ return NULL; \ } #define GLOBAL_FDSET_OPTION_CB_SPECIAL(name, arg, type, fconv) \ DOTCONF_CB(cb_ ## name) \ { \ char *val_str; \ type val; \ val_str = g_ascii_strdown(cmd->data.str, strlen(cmd->data.str)); \ if (val_str == NULL) FATAL("Invalid parameter in configuration"); \ val = fconv(val_str); \ g_free(val_str); \ if (val == -1) FATAL("Invalid parameter in configuration."); \ if (!cl_spec_section) \ GlobalFDSet.arg = val; \ else \ cl_spec_section->val.arg = val; \ return NULL; \ } #define SPEECHD_OPTION_CB_STR_M(name, arg) \ DOTCONF_CB(cb_ ## name) \ { \ if (cl_spec_section) \ FATAL("This command isn't allowed in a client specific section!"); \ if (!SpeechdOptions.arg ## _set) SpeechdOptions.arg = g_strdup(cmd->data.str); \ return NULL; \ } #define SPEECHD_OPTION_CB_INT_M(name, arg, cond, str) \ DOTCONF_CB(cb_ ## name) \ { \ int val = cmd->data.value; \ if (cl_spec_section) \ FATAL("This command isn't allowed in a client specific section!"); \ if (!(cond)) FATAL(str); \ if (!SpeechdOptions.arg ## _set) SpeechdOptions.arg = val; \ return NULL; \ } #define SPEECHD_OPTION_CB_STR(name, arg) \ DOTCONF_CB(cb_ ## name) \ { \ if (cl_spec_section) \ FATAL("This command isn't allowed in a client specific section!"); \ SpeechdOptions.arg = g_strdup(cmd->data.str); \ return NULL; \ } #define SPEECHD_OPTION_CB_INT(name, arg, cond, str) \ DOTCONF_CB(cb_ ## name) \ { \ int val = cmd->data.value; \ if (cl_spec_section) \ FATAL("This command isn't allowed in a client specific section!"); \ if (!(cond)) FATAL(str); \ SpeechdOptions.arg = val; \ return NULL; \ } #define GLOBAL_SET_LOGLEVEL(name, arg, cond, str) \ DOTCONF_CB(cb_ ## name) \ { \ int val = cmd->data.value; \ if (cl_spec_section) \ FATAL("This command isn't allowed in a client specific section!"); \ if (!(cond)) FATAL(str); \ if (!SpeechdOptions.arg ## _set){ \ SpeechdOptions.arg = val; \ GlobalFDSet.arg = val; \ } \ return NULL; \ } /* == CALLBACK DEFINITIONS == */ GLOBAL_FDSET_OPTION_CB_STR(DefaultModule, output_module) GLOBAL_FDSET_OPTION_CB_STR(DefaultLanguage, msg_settings.voice.language) GLOBAL_FDSET_OPTION_CB_STR(DefaultClientName, client_name) GLOBAL_FDSET_OPTION_CB_STR(AudioOutputMethod, audio_output_method) GLOBAL_FDSET_OPTION_CB_STR(AudioOSSDevice, audio_oss_device) GLOBAL_FDSET_OPTION_CB_STR(AudioALSADevice, audio_alsa_device) GLOBAL_FDSET_OPTION_CB_STR(AudioNASServer, audio_nas_server) GLOBAL_FDSET_OPTION_CB_STR(AudioPulseServer, audio_pulse_server) GLOBAL_FDSET_OPTION_CB_INT(AudioPulseMinLength, audio_pulse_min_length, 1, "") GLOBAL_FDSET_OPTION_CB_INT(DefaultRate, msg_settings.rate, (val >= -100) && (val <= +100), "Rate out of range.") GLOBAL_FDSET_OPTION_CB_INT(DefaultPitch, msg_settings.pitch, (val >= -100) && (val <= +100), "Pitch out of range.") GLOBAL_FDSET_OPTION_CB_INT(DefaultVolume, msg_settings.volume, (val >= -100) && (val <= +100), "Volume out of range.") GLOBAL_FDSET_OPTION_CB_INT(DefaultSpelling, msg_settings.spelling_mode, 1, "Invalid spelling mode") GLOBAL_FDSET_OPTION_CB_INT(DefaultPauseContext, pause_context, 1, "") GLOBAL_FDSET_OPTION_CB_SPECIAL(DefaultPriority, priority, SPDPriority, str2intpriority) GLOBAL_FDSET_OPTION_CB_SPECIAL(DefaultVoiceType, msg_settings.voice_type, SPDVoiceType, str2EVoice) GLOBAL_FDSET_OPTION_CB_SPECIAL(DefaultPunctuationMode, msg_settings.punctuation_mode, SPDPunctuation, str2EPunctMode) GLOBAL_FDSET_OPTION_CB_SPECIAL(DefaultCapLetRecognition, msg_settings.cap_let_recogn, SPDCapitalLetters, str2ECapLetRecogn) SPEECHD_OPTION_CB_STR_M(CommunicationMethod, communication_method) SPEECHD_OPTION_CB_STR_M(SocketPath, socket_path) SPEECHD_OPTION_CB_INT_M(Port, port, val >= 0, "Invalid port number!") SPEECHD_OPTION_CB_INT_M(LocalhostAccessOnly, localhost_access_only, val >= 0, "Invalid access controll mode!") GLOBAL_SET_LOGLEVEL(LogLevel, log_level, (val >= 0) && (val <= 5), "Invalid log (verbosity) level!") SPEECHD_OPTION_CB_INT(MaxHistoryMessages, max_history_messages, val >= 0, "Invalid parameter!") DOTCONF_CB(cb_LanguageDefaultModule) { char *key; char *value; if (cmd->data.list[0] == NULL) FATAL("No language specified for LanguageDefaultModule"); if (cmd->data.list[0] == NULL) FATAL("No module specified for LanguageDefaultModule"); key = g_strdup(cmd->data.list[0]); value = g_strdup(cmd->data.list[1]); g_hash_table_insert(language_default_modules, key, value); return NULL; } DOTCONF_CB(cb_LogFile) { /* This option is DEPRECATED. If it is specified, get the directory. */ assert(cmd->data.str != NULL); SpeechdOptions.log_dir = g_path_get_dirname(cmd->data.str); logging_init(); MSG(1, "WARNING: The LogFile option is deprecated. Directory accepted but filename ignored"); return NULL; } DOTCONF_CB(cb_LogDir) { assert(cmd->data.str != NULL); if (strcmp(cmd->data.str, "default") && !SpeechdOptions.log_dir_set) { // cmd->data.str different from "default" SpeechdOptions.log_dir = g_strdup(cmd->data.str); } logging_init(); return NULL; } DOTCONF_CB(cb_CustomLogFile) { char *kind; char *file; if (cmd->data.list[0] == NULL) FATAL("No log kind specified in CustomLogFile"); if (cmd->data.list[1] == NULL) FATAL("No log file specified in CustomLogFile"); kind = g_strdup(cmd->data.list[0]); assert(kind != NULL); file = g_strdup(cmd->data.list[1]); assert(file != NULL); custom_log_kind = kind; if (!strncmp(file, "stdout", 6)) { custom_logfile = stdout; return NULL; } if (!strncmp(file, "stderr", 6)) { custom_logfile = stderr; return NULL; } custom_logfile = fopen(file, "a"); if (custom_logfile == NULL) { fprintf(stderr, "Error: can't open custom log file, using stdout\n"); custom_logfile = stdout; } MSG(2, "Speech Dispatcher custom logging to file %s", file); return NULL; } DOTCONF_CB(cb_AddModule) { if (cmd->data.list[0] == NULL) { MSG(3, "No output module name specified in configuration under AddModule"); return NULL; } module_add_load_request(g_strdup(cmd->data.list[0]), g_strdup(cmd->data.list[1]), g_strdup(cmd->data.list[2]), g_strdup_printf("%s/%s.log", SpeechdOptions.log_dir, cmd->data.list[0])); return NULL; } /* == CLIENT SPECIFIC CONFIGURATION == */ #define SET_PAR(name, value) cl_spec->val.name = value; #define SET_PAR_STR(name) cl_spec->val.name = NULL; DOTCONF_CB(cb_BeginClient) { TFDSetClientSpecific *cl_spec; if (cl_spec_section != NULL) FATAL ("Configuration: Already in client specific section, can't open a new one!"); if (cmd->data.str == NULL) FATAL ("Configuration: You must specify some client's name for BeginClient"); cl_spec = (TFDSetClientSpecific *) g_malloc(sizeof(TFDSetClientSpecific)); cl_spec->pattern = g_strdup(cmd->data.str); cl_spec_section = cl_spec; MSG(4, "Reading configuration for pattern %s", cl_spec->pattern); /* Warning: If you modify this, you must also modify update_cl_settings() in set.c ! */ SET_PAR(msg_settings.rate, -101) SET_PAR(msg_settings.pitch, -101) SET_PAR(msg_settings.volume, -101) SET_PAR(msg_settings.punctuation_mode, -1) SET_PAR(msg_settings.spelling_mode, -1) SET_PAR(msg_settings.voice_type, -1) SET_PAR(msg_settings.cap_let_recogn, -1) SET_PAR(pause_context, -1); SET_PAR(ssml_mode, -1); SET_PAR_STR(msg_settings.voice.language) SET_PAR_STR(output_module) return NULL; } #undef SET_PAR #undef SET_PAR_STR DOTCONF_CB(cb_EndClient) { if (cl_spec_section == NULL) FATAL ("Configuration: Already outside the client specific section!"); client_specific_settings = g_list_append(client_specific_settings, cl_spec_section); cl_spec_section = NULL; return NULL; } /* == CALLBACK FOR UNKNOWN OPTIONS == */ DOTCONF_CB(cb_unknown) { MSG(2, "Unknown option in configuration!"); return NULL; } /* == Auto-spawn no-action callback == */ DOTCONF_CB(cb_DisableAutoSpawn) { /* DisableAutoSpawn option is handled earlier during startup, not via the DotConf mechanism. This callback here is a hack to ensure DotConf doesn't complain about an unknown option */ return NULL; } /* == LOAD CALLBACKS == */ #define ADD_CONFIG_OPTION(name, arg_type) \ options = add_config_option(options, num_options, #name, arg_type, cb_ ## name, 0, 0); #define ADD_LAST_OPTION() \ options = add_config_option(options, num_options, "", 0, NULL, NULL, 0); configoption_t *load_config_options(int *num_options) { configoption_t *options = NULL; cl_spec_section = NULL; ADD_CONFIG_OPTION(CommunicationMethod, ARG_STR); ADD_CONFIG_OPTION(SocketPath, ARG_STR); ADD_CONFIG_OPTION(Port, ARG_INT); ADD_CONFIG_OPTION(DisableAutoSpawn, ARG_NONE); ADD_CONFIG_OPTION(LocalhostAccessOnly, ARG_INT); ADD_CONFIG_OPTION(LogFile, ARG_STR); ADD_CONFIG_OPTION(LogDir, ARG_STR); ADD_CONFIG_OPTION(CustomLogFile, ARG_LIST); ADD_CONFIG_OPTION(LogLevel, ARG_INT); ADD_CONFIG_OPTION(DefaultModule, ARG_STR); ADD_CONFIG_OPTION(LanguageDefaultModule, ARG_LIST); ADD_CONFIG_OPTION(DefaultRate, ARG_INT); ADD_CONFIG_OPTION(DefaultPitch, ARG_INT); ADD_CONFIG_OPTION(DefaultVolume, ARG_INT); ADD_CONFIG_OPTION(DefaultLanguage, ARG_STR); ADD_CONFIG_OPTION(DefaultPriority, ARG_STR); ADD_CONFIG_OPTION(MaxHistoryMessages, ARG_INT); ADD_CONFIG_OPTION(DefaultPunctuationMode, ARG_STR); ADD_CONFIG_OPTION(DefaultClientName, ARG_STR); ADD_CONFIG_OPTION(DefaultVoiceType, ARG_STR); ADD_CONFIG_OPTION(DefaultSpelling, ARG_TOGGLE); ADD_CONFIG_OPTION(DefaultCapLetRecognition, ARG_STR); ADD_CONFIG_OPTION(DefaultPauseContext, ARG_INT); ADD_CONFIG_OPTION(AddModule, ARG_LIST); ADD_CONFIG_OPTION(AudioOutputMethod, ARG_STR); ADD_CONFIG_OPTION(AudioOSSDevice, ARG_STR); ADD_CONFIG_OPTION(AudioALSADevice, ARG_STR); ADD_CONFIG_OPTION(AudioNASServer, ARG_STR); ADD_CONFIG_OPTION(AudioPulseServer, ARG_STR); ADD_CONFIG_OPTION(AudioPulseMinLength, ARG_INT); ADD_CONFIG_OPTION(BeginClient, ARG_STR); ADD_CONFIG_OPTION(EndClient, ARG_NONE); return options; } /* == DEFAULT OPTIONS == */ void load_default_global_set_options() { GlobalFDSet.priority = SPD_MESSAGE; GlobalFDSet.msg_settings.punctuation_mode = SPD_PUNCT_NONE; GlobalFDSet.msg_settings.spelling_mode = 0; GlobalFDSet.msg_settings.rate = 0; GlobalFDSet.msg_settings.pitch = 0; GlobalFDSet.msg_settings.volume = 0; GlobalFDSet.client_name = g_strdup("unknown:unknown:unknown"); GlobalFDSet.msg_settings.voice.language = g_strdup("en"); GlobalFDSet.output_module = NULL; GlobalFDSet.msg_settings.voice_type = SPD_MALE1; GlobalFDSet.msg_settings.cap_let_recogn = SPD_CAP_NONE; GlobalFDSet.min_delay_progress = 2000; GlobalFDSet.pause_context = 0; GlobalFDSet.ssml_mode = SPD_DATA_TEXT; GlobalFDSet.notification = 0; GlobalFDSet.audio_output_method = g_strdup(DEFAULT_AUDIO_METHOD); GlobalFDSet.audio_oss_device = g_strdup("/dev/dsp"); GlobalFDSet.audio_alsa_device = g_strdup("default"); GlobalFDSet.audio_nas_server = g_strdup("tcp/localhost:5450"); GlobalFDSet.audio_pulse_server = g_strdup("default"); GlobalFDSet.audio_pulse_min_length = 100; SpeechdOptions.max_history_messages = 10000; /* Options which are accessible from command line must be handled specially to make sure we don't overwrite them */ if (!SpeechdOptions.log_level_set) SpeechdOptions.log_level = 3; if (!SpeechdOptions.communication_method_set) SpeechdOptions.communication_method = g_strdup("unix_socket"); if (!SpeechdOptions.socket_path_set) SpeechdOptions.socket_path = g_strdup("default"); if (!SpeechdOptions.port_set) SpeechdOptions.port = SPEECHD_DEFAULT_PORT; if (!SpeechdOptions.localhost_access_only_set) SpeechdOptions.localhost_access_only = 1; logfile = stderr; custom_logfile = NULL; } speech-dispatcher-0.8.3/src/server/speechd.c0000664000175000017500000010123412536417045015724 00000000000000/* * speechd.c - Speech Dispatcher server program * * Copyright (C) 2001, 2002, 2003, 2006, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: speechd.c,v 1.81 2008-07-10 15:36:49 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "speechd.h" /* Declare dotconf functions and data structures*/ #include "configuration.h" /* Declare functions to allocate and create important data * structures */ #include "alloc.h" #include "sem_functions.h" #include "speaking.h" #include "set.h" #include "options.h" #include "server.h" #include /* list of output modules */ GList *output_modules; /* Manipulating pid files */ int create_pid_file(); void destroy_pid_file(); /* Server socket file descriptor */ int server_socket; void speechd_load_configuration(int sig); #ifdef __SUNPRO_C /* Added by Willie Walker - daemon is a gcc-ism */ #include static int daemon(int nochdir, int noclose) { int fd, i; switch (fork()) { case 0: break; case -1: return -1; default: _exit(0); } if (!nochdir) { chdir("/"); } if (setsid() < 0) { return -1; } if (!noclose) { if (fd = open("/dev/null", O_RDWR) >= 0) { for (i = 0; i < 3; i++) { dup2(fd, i); } if (fd > 2) { close(fd); } } } return 0; } #endif /* __SUNPRO_C */ char *spd_get_path(char *filename, char *startdir) { char *ret; if (filename == NULL) return NULL; if (filename[0] != '/') { if (startdir == NULL) ret = g_strdup(filename); else ret = g_strdup_printf("%s/%s", startdir, filename); } else { ret = g_strdup(filename); } return ret; } /* --- DEBUGGING --- */ /* Just to be able to set breakpoints */ void fatal_error(void) { int i = 0; i++; } /* Logging messages, level of verbosity is defined between 1 and 5, * see documentation */ void MSG2(int level, char *kind, char *format, ...) { int std_log = level <= SpeechdOptions.log_level; int custom_log = (kind != NULL && custom_log_kind != NULL && !strcmp(kind, custom_log_kind) && custom_logfile != NULL); if (std_log || custom_log) { va_list args; int i; pthread_mutex_lock(&logging_mutex); { { /* Print timestamp */ time_t t; char *tstr; struct timeval tv; t = time(NULL); tstr = g_strdup(ctime(&t)); gettimeofday(&tv, NULL); assert(tstr); /* Remove the trailing \n */ assert(strlen(tstr) > 1); tstr[strlen(tstr) - 1] = 0; if (std_log) { fprintf(logfile, "[%s : %d] speechd: ", tstr, (int)tv.tv_usec); // fprintf(logfile, "[test : %d] speechd: ", // (int) tv.tv_usec); } if (custom_log) { fprintf(custom_logfile, "[%s : %d] speechd: ", tstr, (int)tv.tv_usec); } if (SpeechdOptions.debug) { fprintf(debug_logfile, "[%s : %d] speechd: ", tstr, (int)tv.tv_usec); } g_free(tstr); } for (i = 1; i < level; i++) { if (std_log) { fprintf(logfile, " "); } if (custom_log) { fprintf(custom_logfile, " "); } } if (std_log) { va_start(args, format); vfprintf(logfile, format, args); va_end(args); fprintf(logfile, "\n"); fflush(logfile); } if (custom_log) { va_start(args, format); vfprintf(custom_logfile, format, args); va_end(args); fprintf(custom_logfile, "\n"); fflush(custom_logfile); } if (SpeechdOptions.debug) { va_start(args, format); vfprintf(debug_logfile, format, args); va_end(args); fprintf(debug_logfile, "\n"); fflush(debug_logfile); } } pthread_mutex_unlock(&logging_mutex); } } /* The main logging function for Speech Dispatcher, level is between -1 and 5. 1 means the most important, 5 less important. Loglevels after 4 can contain private data. -1 logs also to stderr. See Speech Dispatcher documentation */ /* TODO: Define this in terms of MSG somehow. I don't know how to pass '...' arguments to another C function */ void MSG(int level, char *format, ...) { if ((level <= SpeechdOptions.log_level) || (SpeechdOptions.debug)) { va_list args; int i; pthread_mutex_lock(&logging_mutex); { /* Print timestamp */ { time_t t; char *tstr; struct timeval tv; t = time(NULL); tstr = g_strdup(ctime(&t)); gettimeofday(&tv, NULL); /* Remove the trailing \n */ assert(tstr); assert(strlen(tstr) > 1); assert((level >= -1) && (level <= 5)); tstr[strlen(tstr) - 1] = 0; /* Write timestamps */ if (level <= SpeechdOptions.log_level) fprintf(logfile, "[%s : %d] speechd: ", tstr, (int)tv.tv_usec); if (SpeechdOptions.debug) fprintf(debug_logfile, "[%s : %d] speechd: ", tstr, (int)tv.tv_usec); /* fprintf(logfile, "[%s : %d] speechd: ", tstr, (int) tv.tv_usec); */ g_free(tstr); } for (i = 1; i < level; i++) { fprintf(logfile, " "); } /* Log to ordinary logfile */ if (level <= SpeechdOptions.log_level) { va_start(args, format); vfprintf(logfile, format, args); va_end(args); fprintf(logfile, "\n"); fflush(logfile); } /* Log into debug logfile */ if (SpeechdOptions.debug) { va_start(args, format); vfprintf(debug_logfile, format, args); va_end(args); fprintf(debug_logfile, "\n"); fflush(debug_logfile); } /* Log also into stderr for loglevel -1 */ if (level == -1) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); fflush(stderr); } } pthread_mutex_unlock(&logging_mutex); } } /* --- CLIENTS / CONNECTIONS MANAGING --- */ /* Initialize sockets status table */ int speechd_sockets_status_init(void) { speechd_sockets_status = g_hash_table_new_full(g_int_hash, g_int_equal, (GDestroyNotify) g_free, (GDestroyNotify) speechd_socket_free); if (speechd_sockets_status) return 0; else return 1; } /* Register a new socket for SSIP connection */ int speechd_socket_register(int fd) { int *fd_key; TSpeechDSock *speechd_socket; speechd_socket = g_malloc(sizeof(TSpeechDSock)); speechd_socket->o_buf = NULL; speechd_socket->o_bytes = 0; speechd_socket->awaiting_data = 0; speechd_socket->inside_block = 0; fd_key = g_malloc(sizeof(int)); *fd_key = fd; g_hash_table_insert(speechd_sockets_status, fd_key, speechd_socket); return 0; } /* Free a TSpeechDSock structure including it's data */ void speechd_socket_free(TSpeechDSock * speechd_socket) { if (speechd_socket->o_buf) g_string_free(speechd_socket->o_buf, 1); g_free(speechd_socket); } /* Unregister a socket for SSIP communication */ int speechd_socket_unregister(int fd) { return (!g_hash_table_remove(speechd_sockets_status, &fd)); } /* Get a pointer to the TSpeechDSock structure for a given file descriptor */ TSpeechDSock *speechd_socket_get_by_fd(int fd) { return g_hash_table_lookup(speechd_sockets_status, &fd); } /* activity is on server_socket (request for a new connection) */ int speechd_connection_new(int server_socket) { TFDSetElement *new_fd_set; struct sockaddr_in client_address; unsigned int client_len = sizeof(client_address); int client_socket; int *p_client_socket, *p_client_uid, *p_client_uid2; client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_len); if (client_socket == -1) { MSG(2, "Error: Can't handle connection request of a new client"); return -1; } /* We add the associated client_socket to the descriptor set. */ FD_SET(client_socket, &readfds); if (client_socket > SpeechdStatus.max_fd) SpeechdStatus.max_fd = client_socket; MSG(4, "Adding client on fd %d", client_socket); speechd_socket_register(client_socket); /* Create a record in fd_settings */ new_fd_set = (TFDSetElement *) default_fd_set(); if (new_fd_set == NULL) { MSG(2, "Error: Failed to create a record in fd_settings for the new client"); if (SpeechdStatus.max_fd == client_socket) SpeechdStatus.max_fd--; FD_CLR(client_socket, &readfds); return -1; } new_fd_set->fd = client_socket; new_fd_set->uid = ++SpeechdStatus.max_uid; p_client_socket = (int *)g_malloc(sizeof(int)); p_client_uid = (int *)g_malloc(sizeof(int)); p_client_uid2 = (int *)g_malloc(sizeof(int)); *p_client_socket = client_socket; *p_client_uid = SpeechdStatus.max_uid; *p_client_uid2 = SpeechdStatus.max_uid; g_hash_table_insert(fd_settings, p_client_uid, new_fd_set); g_hash_table_insert(fd_uid, p_client_socket, p_client_uid2); MSG(4, "Data structures for client on fd %d created", client_socket); return 0; } int speechd_connection_destroy(int fd) { TFDSetElement *fdset_element; /* Client has gone away and we remove it from the descriptor set. */ MSG(4, "Removing client on fd %d", fd); MSG(4, "Tagging client as inactive in settings"); fdset_element = get_client_settings_by_fd(fd); if (fdset_element != NULL) { fdset_element->fd = -1; fdset_element->active = 0; /* The fdset_element will be freed and removed from the hash table as soon as the client no longer has any message in the queues, check out the speak() function */ } else if (SPEECHD_DEBUG) { DIE("Can't find settings for this client\n"); } MSG(4, "Removing client from the fd->uid table."); g_hash_table_remove(fd_uid, &fd); speechd_socket_unregister(fd); MSG(4, "Closing clients file descriptor %d", fd); if (close(fd) != 0) if (SPEECHD_DEBUG) DIE("Can't close file descriptor associated to this client"); FD_CLR(fd, &readfds); if (fd == SpeechdStatus.max_fd) SpeechdStatus.max_fd--; MSG(4, "Connection closed"); return 0; } gboolean speechd_client_terminate(gpointer key, gpointer value, gpointer user) { TFDSetElement *set; set = (TFDSetElement *) value; if (set == NULL) { MSG(2, "Error: Empty connection, internal error"); if (SPEECHD_DEBUG) FATAL("Internal error"); return TRUE; } if (set->fd > 0) { MSG(4, "Closing connection on fd %d\n", set->fd); speechd_connection_destroy(set->fd); } mem_free_fdset(set); g_free(set); return TRUE; } /* --- OUTPUT MODULES MANAGING --- */ void speechd_modules_terminate(gpointer data, gpointer user_data) { OutputModule *module; module = (OutputModule *) data; if (module == NULL) { MSG(2, "Error: Empty module, internal error"); return; } unload_output_module(module); return; } void speechd_modules_reload(gpointer data, gpointer user_data) { OutputModule *module; module = (OutputModule *) data; if (module == NULL) { MSG(2, "Empty module, internal error"); return; } reload_output_module(module); return; } void speechd_module_debug(gpointer data, gpointer user_data) { OutputModule *module; module = (OutputModule *) data; if (module == NULL) { MSG(2, "Empty module, internal error"); return; } output_module_debug(module); return; } void speechd_module_nodebug(gpointer data, gpointer user_data) { OutputModule *module; module = (OutputModule *) data; if (module == NULL) { MSG(2, "Empty module, internal error"); return; } output_module_nodebug(module); return; } void speechd_reload_dead_modules(int sig) { /* Reload dead modules */ g_list_foreach(output_modules, speechd_modules_reload, NULL); /* Make sure there aren't any more child processes left */ while (waitpid(-1, NULL, WNOHANG) > 0) ; } void speechd_modules_debug(void) { /* Redirect output to debug for all modules */ g_list_foreach(output_modules, speechd_module_debug, NULL); } void speechd_modules_nodebug(void) { /* Redirect output to normal for all modules */ g_list_foreach(output_modules, speechd_module_nodebug, NULL); } /* --- SPEECHD START/EXIT FUNCTIONS --- */ void speechd_options_init(void) { SpeechdOptions.spawn = FALSE; SpeechdOptions.log_level_set = 0; SpeechdOptions.communication_method = NULL; SpeechdOptions.socket_path = NULL; SpeechdOptions.port_set = 0; SpeechdOptions.localhost_access_only_set = 0; SpeechdOptions.pid_file = NULL; SpeechdOptions.conf_file = NULL; SpeechdOptions.runtime_speechd_dir = NULL; SpeechdOptions.log_dir = NULL; SpeechdOptions.log_dir_set = 0; SpeechdOptions.debug = 0; SpeechdOptions.debug_destination = NULL; debug_logfile = NULL; spd_mode = SPD_MODE_DAEMON; } void speechd_init() { int ret; SpeechdStatus.max_uid = 0; SpeechdStatus.max_gid = 0; /* Initialize inter-thread comm pipe */ if (pipe(speaking_pipe)) { MSG(1, "Speaking pipe creation failed (%s)", strerror(errno)); FATAL("Can't create pipe"); } /* Initialize Speech Dispatcher priority queue */ MessageQueue = g_malloc0(sizeof(TSpeechDQueue)); if (MessageQueue == NULL) FATAL("Couldn't alocate memmory for MessageQueue."); /* Initialize lists */ MessagePausedList = NULL; /* Initialize hash tables */ fd_settings = g_hash_table_new_full(g_int_hash, g_int_equal, (GDestroyNotify) g_free, NULL); assert(fd_settings != NULL); fd_uid = g_hash_table_new_full(g_int_hash, g_int_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free); assert(fd_uid != NULL); language_default_modules = g_hash_table_new(g_str_hash, g_str_equal); assert(language_default_modules != NULL); speechd_sockets_status_init(); pause_requested = 0; resume_requested = 0; /* Perform some functionality tests */ if (g_module_supported() == FALSE) DIE("Loadable modules not supported by current platform.\n"); if (_POSIX_VERSION < 199506L) DIE("This system doesn't support POSIX.1c threads\n"); /* Fill GlobalFDSet with default values */ GlobalFDSet.min_delay_progress = 2000; /* Initialize list of different client specific settings entries */ client_specific_settings = NULL; /* Initialize mutexes, semaphores and synchronization */ ret = pthread_mutex_init(&element_free_mutex, NULL); if (ret != 0) DIE("Mutex initialization failed"); ret = pthread_mutex_init(&output_layer_mutex, NULL); if (ret != 0) DIE("Mutex initialization failed"); ret = pthread_mutex_init(&socket_com_mutex, NULL); if (ret != 0) DIE("Mutex initialization failed"); if (SpeechdOptions.log_dir == NULL) { SpeechdOptions.log_dir = g_strdup_printf("%s/log/", SpeechdOptions.runtime_speechd_dir); mkdir(SpeechdOptions.log_dir, S_IRWXU); if (!SpeechdOptions.debug_destination) { SpeechdOptions.debug_destination = g_strdup_printf("%s/log/debug", SpeechdOptions.runtime_speechd_dir); mkdir(SpeechdOptions.debug_destination, S_IRWXU); } } /* Load configuration from the config file */ MSG(4, "Reading Speech Dispatcher configuration from %s", SpeechdOptions.conf_file); speechd_load_configuration(0); logging_init(); /* Check for output modules */ if (g_list_length(output_modules) == 0) { DIE("No speech output modules were loaded - aborting..."); } else { MSG(3, "Speech Dispatcher started with %d output module%s", g_list_length(output_modules), g_list_length(output_modules) > 1 ? "s" : ""); } last_p5_block = NULL; } void speechd_load_configuration(int sig) { configfile_t *configfile = NULL; GList *detected_modules = NULL; /* Clean previous configuration */ if (output_modules != NULL) { g_list_foreach(output_modules, speechd_modules_terminate, NULL); g_list_free(output_modules); output_modules = NULL; } /* Make sure there aren't any more child processes left */ while (waitpid(-1, NULL, WNOHANG) > 0) ; /* Load new configuration */ load_default_global_set_options(); spd_num_options = 0; spd_options = load_config_options(&spd_num_options); /* Add the LAST option */ spd_options = add_config_option(spd_options, &spd_num_options, "", 0, NULL, NULL, 0); configfile = dotconf_create(SpeechdOptions.conf_file, spd_options, 0, CASE_INSENSITIVE); if (configfile) { configfile->includepath = g_strdup(SpeechdOptions.conf_dir); MSG(5, "Config file include path is: %s", configfile->includepath); if (dotconf_command_loop(configfile) == 0) DIE("Error reading config file\n"); dotconf_cleanup(configfile); MSG(2, "Configuration has been read from \"%s\"", SpeechdOptions.conf_file); /* We need to load modules here, since this is called both by speechd_init * and to handle SIGHUP. */ if (module_number_of_requested_modules() < 2) { detected_modules = detect_output_modules(MODULEBINDIR); while (detected_modules != NULL) { char **parameters = detected_modules->data; module_add_load_request(parameters[0], parameters[1], parameters[2], parameters[3]); g_free(detected_modules->data); detected_modules->data = NULL; detected_modules = g_list_delete_link(detected_modules, detected_modules); } } module_load_requested_modules(); } else { MSG(1, "Can't open %s", SpeechdOptions.conf_file); } free_config_options(spd_options, &spd_num_options); } void speechd_quit(int sig) { int ret; MSG(1, "Terminating..."); MSG(2, "Closing open connections..."); /* We will browse through all the connections and close them. */ g_hash_table_foreach_remove(fd_settings, speechd_client_terminate, NULL); g_hash_table_destroy(fd_settings); MSG(4, "Closing speak() thread..."); ret = pthread_cancel(speak_thread); if (ret != 0) FATAL("Speak thread failed to cancel!\n"); ret = pthread_join(speak_thread, NULL); if (ret != 0) FATAL("Speak thread failed to join!\n"); MSG(2, "Closing open output modules..."); /* Call the close() function of each registered output module. */ g_list_foreach(output_modules, speechd_modules_terminate, NULL); g_list_free(output_modules); MSG(2, "Closing server connection..."); if (close(server_socket) == -1) MSG(2, "close() failed: %s", strerror(errno)); FD_CLR(server_socket, &readfds); MSG(4, "Removing pid file"); destroy_pid_file(); fflush(NULL); MSG(2, "Speech Dispatcher terminated correctly"); exit(0); } /* --- PID FILES --- */ int create_pid_file() { FILE *pid_file; int pid_fd; struct flock lock; int ret; /* If the file exists, examine it's lock */ pid_file = fopen(SpeechdOptions.pid_file, "r"); if (pid_file != NULL) { pid_fd = fileno(pid_file); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 1; lock.l_len = 3; /* If there is a lock, exit, otherwise remove the old file */ ret = fcntl(pid_fd, F_GETLK, &lock); if (ret == -1) { MSG(-1, "Can't check lock status of an existing pid file.\n"); return -1; } fclose(pid_file); if (lock.l_type != F_UNLCK) { MSG(-1, "Speech Dispatcher already running.\n"); return -1; } unlink(SpeechdOptions.pid_file); } /* Create a new pid file and lock it */ pid_file = fopen(SpeechdOptions.pid_file, "w"); if (pid_file == NULL) { MSG(-1, "Can't create pid file in %s, wrong permissions?\n", SpeechdOptions.pid_file); return -1; } fprintf(pid_file, "%d\n", getpid()); fflush(pid_file); pid_fd = fileno(pid_file); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 1; lock.l_len = 3; ret = fcntl(pid_fd, F_SETLK, &lock); if (ret == -1) { MSG(-1, "Can't set lock on pid file.\n"); return -1; } return 0; } void destroy_pid_file(void) { unlink(SpeechdOptions.pid_file); } void logging_init(void) { char *file_name = g_strdup_printf("%s/speech-dispatcher.log", SpeechdOptions.log_dir); assert(file_name != NULL); if (!strncmp(file_name, "stdout", 6)) { logfile = stdout; } else if (!strncmp(file_name, "stderr", 6)) { logfile = stderr; } else { logfile = fopen(file_name, "a"); if (logfile == NULL) { fprintf(stderr, "Error: can't open logging file %s! Using stdout.\n", file_name); logfile = stdout; } else { MSG(3, "Speech Dispatcher Logging to file %s", file_name); } } if (!debug_logfile) debug_logfile = stdout; g_free(file_name); return; } /* --- Sockets --- */ int make_local_socket(const char *filename) { struct sockaddr_un name; int sock; size_t size; /* Create the socket. */ sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { FATAL("Can't create local socket"); } /* Bind a name to the socket. */ name.sun_family = AF_UNIX; strncpy(name.sun_path, filename, sizeof(name.sun_path)); name.sun_path[sizeof(name.sun_path) - 1] = '\0'; size = SUN_LEN(&name); if (bind(sock, (struct sockaddr *)&name, size) < 0) { FATAL("Can't bind local socket"); } if (listen(sock, 50) == -1) { MSG(2, "listen failed: ERRNO:%s", strerror(errno)); FATAL("listen() failed for local socket"); } return sock; } int make_inet_socket(const int port) { struct sockaddr_in server_address; int server_socket; /* Create an inet socket */ server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket < 0) { FATAL("Can't create inet socket"); } /* Set REUSEADDR flag */ const int flag = 1; if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int))) MSG(2, "Error: Setting socket option failed!"); server_address.sin_family = AF_INET; /* Enable access only to localhost or for any address based on LocalhostAccessOnly configuration option. */ if (SpeechdOptions.localhost_access_only) server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(port); MSG(4, "Openning inet socket connection"); if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) { MSG(-1, "bind() failed: %s", strerror(errno)); FATAL("Couldn't open inet socket, try a few minutes later."); } if (listen(server_socket, 50) == -1) { MSG(2, "ERRNO:%s", strerror(errno)); FATAL ("listen() failed for inet socket, another Speech Dispatcher running?"); } return server_socket; } /* --- MAIN --- */ int main(int argc, char *argv[]) { fd_set testfds; int fd; int ret; /* Autospawn helper variables */ char *spawn_communication_method = NULL; int spawn_port = 0; char *spawn_socket_path = NULL; /* Initialize threading and thread safety in Glib */ g_thread_init(NULL); /* Strip all permisions for 'others' from the files created */ umask(007); /* Initialize logging */ logfile = stdout; SpeechdOptions.log_level = 1; custom_logfile = NULL; custom_log_kind = NULL; /* initialize i18n support */ i18n_init(); speechd_options_init(); options_parse(argc, argv); if (SpeechdOptions.spawn) { /* In case of --spawn, copy the host port and socket_path parameters into temporary spawn_ variables for later comparison with the config file and unset them */ if (SpeechdOptions.communication_method_set) { spawn_communication_method = g_strdup(SpeechdOptions.communication_method); g_free(SpeechdOptions.communication_method); SpeechdOptions.communication_method_set = 0; } if (SpeechdOptions.port_set) { spawn_port = SpeechdOptions.port; SpeechdOptions.port_set = 0; } if (SpeechdOptions.socket_path_set) { spawn_socket_path = g_strdup(SpeechdOptions.socket_path); g_free(SpeechdOptions.socket_path); SpeechdOptions.socket_path_set = 0; } } MSG(1, "Speech Dispatcher " VERSION " starting"); /* By default, search for configuration options in $XDG_CONFIG_HOME/speech-dispatcher and sockets and pid files in $XDG_RUNTIME_DIR/speech-dispatcher */ { const char *user_runtime_dir; const char *user_config_dir; char *test_speechd_conf_file = NULL; user_runtime_dir = g_get_user_runtime_dir(); user_config_dir = g_get_user_config_dir(); /* Setup a speechd-dispatcher directory or create a new one */ SpeechdOptions.runtime_speechd_dir = g_strdup_printf("%s/speech-dispatcher", user_runtime_dir); MSG(4, "Trying to find %s", SpeechdOptions.runtime_speechd_dir); g_mkdir_with_parents(SpeechdOptions.runtime_speechd_dir, S_IRWXU); MSG(4, "Using directory: %s for pidfile and logging", SpeechdOptions.runtime_speechd_dir); /* Pidfile */ if (SpeechdOptions.pid_file == NULL) { /* If no pidfile path specified on command line, use default local dir */ SpeechdOptions.pid_file = g_strdup_printf("%s/pid/speech-dispatcher.pid", SpeechdOptions.runtime_speechd_dir); g_mkdir(g_path_get_dirname(SpeechdOptions.pid_file), S_IRWXU); } /* Config file */ if (SpeechdOptions.conf_dir == NULL) { /* If no conf_dir was specified on command line, try default local config dir */ SpeechdOptions.conf_dir = g_build_filename(user_config_dir, "speech-dispatcher", NULL); test_speechd_conf_file = g_build_filename(SpeechdOptions.conf_dir, "speechd.conf", NULL); if (!g_file_test (test_speechd_conf_file, G_FILE_TEST_IS_REGULAR)) { /* If the local configuration file doesn't exist, read the global configuration */ if (strcmp(SYS_CONF, "")) SpeechdOptions.conf_dir = g_strdup(SYS_CONF); else SpeechdOptions.conf_dir = g_strdup("/etc/speech-dispatcher/"); } g_free(test_speechd_conf_file); } SpeechdOptions.conf_file = g_strdup_printf("%s/speechd.conf", SpeechdOptions.conf_dir); } /* Check for PID file or create a new one or exit if Speech Dispatcher is already running */ if (create_pid_file() != 0) exit(1); /* Handle --spawn request */ if (SpeechdOptions.spawn) { /* Check whether spawning is not disabled */ gchar *config_contents; int err; GRegex *regexp; int result; err = g_file_get_contents(SpeechdOptions.conf_file, &config_contents, NULL, NULL); if (err == FALSE) { MSG(-1, "Error openning %s", SpeechdOptions.conf_file); FATAL("Can't open conf file"); } regexp = g_regex_new("^[ ]*DisableAutoSpawn", G_REGEX_MULTILINE, 0, NULL); result = g_regex_match(regexp, config_contents, 0, NULL); if (result) { MSG(-1, "Autospawn requested but disabled in configuration"); exit(1); } g_free(config_contents); g_regex_unref(regexp); MSG(2, "Starting Speech Dispatcher due to auto-spawn"); } /* Initialize logging mutex to workaround ctime threading bug */ /* Must be done no later than here */ ret = pthread_mutex_init(&logging_mutex, NULL); if (ret != 0) { fprintf(stderr, "Mutex initialization failed"); exit(1); } /* Register signals */ (void)signal(SIGINT, speechd_quit); (void)signal(SIGHUP, speechd_load_configuration); (void)signal(SIGPIPE, SIG_IGN); (void)signal(SIGUSR1, speechd_reload_dead_modules); speechd_init(); /* Handle socket_path 'default' */ // TODO: This is a hack, we should do that at appropriate places... if (!strcmp(SpeechdOptions.socket_path, "default")) { /* This code cannot be moved above next to conf_dir and pidpath resolution because we need to also consider the DotConf configuration, which is read in speechd_init() */ GString *socket_filename; socket_filename = g_string_new(""); if (SpeechdOptions.runtime_speechd_dir) { g_string_printf(socket_filename, "%s/speechd.sock", SpeechdOptions.runtime_speechd_dir); } else { FATAL ("Socket name file not set and user has no runtime directory"); } g_free(SpeechdOptions.socket_path); SpeechdOptions.socket_path = g_strdup(socket_filename->str); g_string_free(socket_filename, 1); } /* Check if the communication method corresponds to the spawn request */ /* TODO: This should preferably be done much sooner, but the current configuration mechanism doesn't allow it */ if (SpeechdOptions.spawn) { if (spawn_communication_method) { if (strcmp (spawn_communication_method, SpeechdOptions.communication_method)) { MSG(-1, "Autospawn failed: Mismatch in communication methods. Client " "requests %s, most probably due to its configuration or the value of " "the SPEECHD_ADDRESS environment variable, but the server is configured " "to provide the %s method.", spawn_communication_method, SpeechdOptions.communication_method); exit(1); } else { if (!strcmp (SpeechdOptions.communication_method, "inet_socket")) { /* Check port */ if (spawn_port != 0) if (spawn_port != SpeechdOptions.port) { MSG(-1, "Autospawn failed: Mismatch in port numbers. Server " "is configured to use the inet_socket method on the port %d " "while the client requests port %d, most probably due to its " "configuration or the value of the SPEECHD_ADDRESS environment " "variable.", SpeechdOptions.port, spawn_port); exit(1); } } else if (!strcmp (SpeechdOptions.communication_method, "unix_socket")) { /* Check socket name */ if (spawn_socket_path) if (strcmp (spawn_socket_path, SpeechdOptions.socket_path)) { MSG(-1, "Autospawn failed: Mismatch in socket names. The server " "is configured to provide a socket interface in %s, but the " "client requests a different path: %s. This is most probably " "due to the client application configuration or the value of " "the SPEECHD_ADDRESS environment variable.", SpeechdOptions.socket_path, spawn_socket_path); exit(1); } } else assert(0); } } g_free(spawn_communication_method); g_free(spawn_socket_path); } if (!strcmp(SpeechdOptions.communication_method, "inet_socket")) { MSG(4, "Speech Dispatcher will use inet port %d", SpeechdOptions.port); /* Connect and start listening on inet socket */ server_socket = make_inet_socket(SpeechdOptions.port); } else if (!strcmp(SpeechdOptions.communication_method, "unix_socket")) { /* Determine appropariate socket file name */ MSG(4, "Speech Dispatcher will use local unix socket: %s", SpeechdOptions.socket_path); /* Delete an old socket file if it exists */ if (g_file_test(SpeechdOptions.socket_path, G_FILE_TEST_EXISTS)) if (g_unlink(SpeechdOptions.socket_path) == -1) FATAL ("Local socket file exists but impossible to delete. Wrong permissions?"); /* Connect and start listening on local unix socket */ server_socket = make_local_socket(SpeechdOptions.socket_path); } else { FATAL("Unknown communication method"); } /* Fork, set uid, chdir, etc. */ if (spd_mode == SPD_MODE_DAEMON) { if (daemon(0, 0)) { FATAL("Can't fork child process"); } /* Re-create the pid file under this process */ unlink(SpeechdOptions.pid_file); if (create_pid_file() == -1) return -1; } MSG(4, "Creating new thread for speak()"); ret = pthread_create(&speak_thread, NULL, speak, NULL); if (ret != 0) FATAL("Speak thread failed!\n"); FD_ZERO(&readfds); FD_SET(server_socket, &readfds); SpeechdStatus.max_fd = server_socket; /* Now wait for clients and requests. */ MSG(1, "Speech Dispatcher started and waiting for clients ..."); while (1) { testfds = readfds; if (select (FD_SETSIZE, &testfds, (fd_set *) 0, (fd_set *) 0, NULL) >= 1) { /* Once we know we've got activity, * we find which descriptor it's on by checking each in turn using FD_ISSET. TODO: This is a hack. We should not be browsing all possible socket numbers but only those which are connected. */ for (fd = 0; fd <= SpeechdStatus.max_fd && fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd, &testfds)) { MSG(4, "Activity on fd %d ...", fd); if (fd == server_socket) { /* server activity (new client) */ ret = speechd_connection_new (server_socket); if (ret != 0) { MSG(2, "Error: Failed to add new client!"); if (SPEECHD_DEBUG) FATAL ("Failed to add new client"); } } else { /* client activity */ int nread; ioctl(fd, FIONREAD, &nread); if (nread == 0) { /* client has gone */ speechd_connection_destroy (fd); if (ret != 0) MSG(2, "Error: Failed to close the client!"); } else { /* client sends some commands or data */ if (serve(fd) == -1) MSG(2, "Error: Failed to serve client on fd %d!", fd); } } } } } } } void check_locked(pthread_mutex_t * lock) { if (pthread_mutex_trylock(lock) == 0) { MSG(1, "CRITICAL ERROR: Not locked but accessing structure data!"); fprintf(stderr, "WARNING! WARNING! MUTEX CHECK FAILED!\n"); fflush(stderr); exit(0); } } speech-dispatcher-0.8.3/src/server/parse.h0000644000175000017500000000360712233560613015425 00000000000000 #ifndef PARSE_H #define PARSE_H char *parse(const char *buf, const int bytes, const int fd); char *parse_history(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_set(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_stop(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_cancel(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_pause(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_resume(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_snd_icon(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_char(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_key(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_list(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_get(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_help(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket); char *parse_block(const char *buf, const int bytes, const int fd, TSpeechDSock * speechd_socket); char *deescape_dot(const char *orig_text, size_t orig_len); /* Function for parsing the input from clients */ char *get_param(const char *buf, const int n, const int bytes, const int lower_case); /* Other internal functions */ char *parse_general_event(const char *buf, const int bytes, const int fd, const TSpeechDSock * speechd_socket, SPDMessageType type); int spd_utf8_read_char(char *pointer, char *character); #endif speech-dispatcher-0.8.3/src/api/0000775000175000017500000000000012536424374013472 500000000000000speech-dispatcher-0.8.3/src/api/cl/0000755000175000017500000000000012536417045014063 500000000000000speech-dispatcher-0.8.3/src/api/cl/sysdep.lisp0000664000175000017500000000311512522771346016207 00000000000000;;; System dependent functions ;; Author: Milan Zamazal ;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation; either version 2.1 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ;; for more details. ;; You should have received a copy of the GNU Lesser General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (in-package :ssip) (defun getenv (var) #+SBCL (sb-ext:posix-getenv var) #+CLISP (ext:getenv var)) #+CLISP (defparameter +encoding+ (ext:make-encoding :charset 'charset:utf-8 :line-terminator :unix)) (defun open-network-stream (host port) #+CLISP (socket:socket-connect port host :external-format +encoding+) #+SBCL (let ((s (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))) (sb-bsd-sockets:socket-connect s (sb-bsd-sockets:host-ent-address (sb-bsd-sockets:get-host-by-name host)) port) (sb-bsd-sockets:socket-make-stream s :input t :output t :buffering :none)) ) (defun close-network-stream (stream) #+(or SBCL CLISP) (close stream)) speech-dispatcher-0.8.3/src/api/cl/configuration.lisp0000664000175000017500000000456612536417045017560 00000000000000;;; Configuration variables ;; Author: Milan Zamazal ;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation; either version 2.1 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ;; for more details. ;; You should have received a copy of the GNU Lesser General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (in-package :ssip) (defvar *host* "localhost" "Name of the default host running speechd to connect to.") (defvar *port* (or (ignore-errors (car (read-from-string (getenv "SPEECHD_PORT")))) 6560) "Default port of speechd.") (defvar *default-text-priority* :text "Default Speech Dispatcher priority of sent texts.") (defvar *default-sound-priority* :message "Default Speech Dispatcher priority of sent sound icons.") (defvar *default-char-priority* :notification "Default Speech Dispatcher priority of sent single letters.") (defvar *connection-parameters* '() "Alist of connection names and their parameters. Each element of the list is of the form (CONNECTION-NAME . PARAMETERS), where CONNECTION-NAME is a connection name as expected to be in `speechd-client-name' and PARAMETERS is a property list with the pairs of parameter identifiers and parameter values. Valid parameter names are the following symbols: language, message-priority, punctuation-mode, capital-character-mode, voice, rate, pitch, output-module. See the corresponding speechd-set-* functions for valid parameter values. If the symbol t is specified as the connection name, the element defines default connection parameters if no connection specification applies. Only one such an element is allowed in the whole alist. The message-priority parameter has a special meaning: It overrides priority of all messages sent through the connection. You must reopen the connections to apply the changes to this variable.") speech-dispatcher-0.8.3/src/api/cl/README0000644000175000017500000000112212233560613014651 00000000000000This is a simple Common Lisp interface to Speech Dispatcher through the Speech Synthesis Interface Protocol (SSIP). Currently, there is no documentation, read the sources. The simplest use can be as follows: (asdf:operate-on-system 'asdf:load-op :ssip) (ssip:say-text "Hello, world!") It works with CLisp and SBCL, but it should be easy to port to other systems, just add the support to sysdep.lisp. Feel free to contact us with any questions regarding the Common Lisp interface at the Speech Dispatcher mailing list . -- Milan Zamazal speech-dispatcher-0.8.3/src/api/cl/ssip.asd0000644000175000017500000000173512233560613015452 00000000000000;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (in-package :asdf) (defsystem :ssip :depends-on (:regex #+SBCL :sb-bsd-sockets) :components ((:file "package") (:file "sysdep") (:file "elisp") (:file "configuration") (:file "ssip")) :serial t) speech-dispatcher-0.8.3/src/api/cl/ssip.lisp0000664000175000017500000005247512536417045015671 00000000000000;;; Speech Synthesis Interface Protocol (SSIP) interface ;; Author: Milan Zamazal ;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation; either version 2.1 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ;; for more details. ;; You should have received a copy of the GNU Lesser General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ;;; Note: This library was ported from the Elisp library, so don't wonder much ;;; about elispisms found here... (in-package :ssip) ;;; Exported variables (defvar *application-name* "lisp" "String defining current application name.") (defvar *client-name* "default" "String defining current client name. This variable's value defines which connection is used when communicating via SSIP, each connection has its own client name. Usually, you select the proper client (connection) by assigning a value to this variable locally through `let'.") (defvar *language* nil "If non-nil, it is an RFC 1766 language code, as a string. If text is read and this variable is non-nil, the text is read in the given language.") (defvar *spell* nil "If non-nil, any spoken text is spelled.") ;;; Internal constants and configuration variables (defparameter +version+ "$Id: ssip.lisp,v 1.3 2006-02-17 13:18:55 pdm Exp $" "Version stamp of the source file. Useful only for diagnosing problems.") (defvar *language-codes* '(("czech" . "cs") ("english" . "en") ("french" . "fr") ("german" . "de")) "Mapping of LANG values to language ISO codes.") (defvar *default-voice* "male1") (defvar *default-language* (or (cdr (assoc (getenv "LANG") *language-codes* :test #'string=)) "en")) (defparameter +parameter-names+ '((client-name . "CLIENT_NAME") (language . "LANGUAGE") (message-priority . "PRIORITY") (punctuation-mode . "PUNCTUATION") (pause-context . "PAUSE_CONTEXT") (capital-character-mode . "CAP_LET_RECOGN") (voice . "VOICE") (rate . "RATE") (pitch . "PITCH") (spelling-mode . "SPELLING") (output-module . "OUTPUT_MODULE") )) (defparameter +list-parameter-names+ '((voices . "VOICES"))) (defparameter +parameter-value-mappings+ '((message-priority (:important . "IMPORTANT") (:message . "MESSAGE") (:text . "TEXT") (:notification . "NOTIFICATION") (:progress . "PROGRESS") ) (punctuation-mode (:none . "none") (:some . "some") (:all . "all")) (capital-character-mode (:none . "none") (:spell . "spell") (:icon . "icon")) (spelling-mode (t . "on") (nil . "off")))) (defparameter +volatile-parameters+ '(output-module)) (defparameter +punctuation-modes+ '(("none" . none) ("some" . some) ("all" . all))) (defparameter +capital-character-modes+ '(("none" . none) ("spell" . spell) ("icon" . icon))) ;;; Internal variables (defstruct connection name host port (failure-p nil) stream (paused-p nil) (in-block nil) (transaction-state nil) (parameters ()) (forced-priority nil) (last-command nil)) (defstruct request string (transaction-state '(nil nil))) (defvar *connections* (make-hash-table :test #'equal) "Hash table mapping client names to `connection' instances.") (defvar *connection* nil "Current connection.") ;;; Utilities (defmacro iterate-clients (&rest body) `(maphash #'(lambda (*client-name* _) (declare (ignore _)) ,@body) *connections*)) (defmacro iterate-connections (&rest body) `(maphash #'(lambda (_ *connection*) (declare (ignore _)) ,@body) *connections*)) (defun connection-names () "Return the list of all present connection names." (let ((names '())) (iterate-clients (push *client-name* names)) names)) (defmacro with-current-connection (&rest body) `(let ((*connection* (get-connection))) ,@body)) (defmacro with-connection-setting (var value &rest body) (let ((accessor (intern (concat "CONNECTION-" (symbol-name var)))) (orig-value (gensym))) `(let ((,orig-value (,accessor *connection*))) (setf (,accessor *connection*) ,value) (unwind-protect (progn ,@body) (setf (,accessor *connection*) ,orig-value))))) (defmacro with-connection-parameters (parameters &rest body) (let (($parameters (gensym)) ($orig-parameters (gensym)) ($cparameters (gensym)) ($p (gensym)) ($v (gensym)) ($orig-v (gensym)) ($pv (gensym))) `(let* ((,$parameters ,parameters) (,$orig-parameters ())) (unwind-protect (progn (while ,$parameters (let* ((,$p (first ,$parameters)) (,$v (second ,$parameters)) (,$cparameters (connection-parameters *connection*)) (,$orig-v (plist-get ,$cparameters ,$p))) (when (and (not (equal ,$v ,$orig-v)) (or ,$v (not (member ,$p '(language))))) (when (plist-member ,$cparameters ,$p) (push (cons ,$p ,$orig-v) ,$orig-parameters)) (set-parameter ,$p ,$v))) (setq ,$parameters (nthcdr 2 ,$parameters))) ,@body) (dolist (,$pv ,$orig-parameters) (set-parameter (car ,$pv) (cdr ,$pv))))))) ;;; Process management functions (defun get-connection (&optional (name *client-name*) (create-if-needed t)) (or (gethash name *connections*) (and create-if-needed (let ((*client-name* name)) (open-connection))))) (defun close-connection-stream (connection) (let ((stream (connection-stream connection))) (when stream (ignore-errors (close-network-stream stream))) (setf (connection-stream connection) nil))) (defun open-connection (&optional host port &key quiet force-reopen) "Open SSIP connection to given HOST and PORT. If the connection corresponding to the current `*client-name*' value already exists, close it and reopen again, with the same connection parameters. The optional arguments HOST and PORT identify the speechd server location differing from the values of `speechd-host' and `speechd-port'. If the key argument QUIET is non-nil, don't report failures and quit silently. If the key argument FORCE-REOPEN is non-nil, try to reopen an existent connection even if it previously failed. Return the opened connection on success, nil otherwise." (let ((connection (gethash *client-name* *connections*))) (let ((host (or host *host*)) (port (or port *port*))) (when connection (close-connection connection) (setq host (connection-host connection) port (connection-port connection))) (let* ((name *client-name*) (default-parameters (append (cdr (assoc *client-name* *connection-parameters* :test #'string=)) (cdr (assoc t *connection-parameters*)))) (parameters (if connection (append (connection-parameters connection) default-parameters) default-parameters)) (stream (when (or (not connection) (not (connection-failure-p connection)) force-reopen) (ignore-errors (open-network-stream host port))))) (when (and (not stream) (not quiet)) (error "Connection to SSIP failed")) (setq connection (make-connection :name name :host host :port port :stream stream :failure-p (not stream))) (setf (gethash name *connections*) connection) (when stream (set-connection-name name) (setq parameters (append parameters (list 'language *default-language* 'voice *default-voice*))) (let ((already-set '(client-name))) (while parameters (destructuring-bind (parameter value . next) parameters (unless (member parameter already-set) (push parameter already-set) (set-parameter parameter value)) (setq parameters next))))) (let ((priority (and connection (plist-get default-parameters 'message-priority)))) (when priority (set-parameter 'message-priority priority) (setf (connection-forced-priority connection) t))))) connection)) (defun close-connection (&optional (name *client-name*)) "Close speechd connection named NAME." (let ((connection (get-connection name nil))) (when connection (close-connection-stream connection) (remhash name *connections*)))) (defun reopen-connection () "Close and open again all the connections to speechd." (iterate-clients (open-connection :quiet t :force-reopen t))) (defun running-p () "Return non-nil, if the current speechd client name process is running." (let ((connection (get-connection))) (and connection (connection-stream connection)))) ;;; Process communication functions (defun permanent-connection-failure (connection) (close-connection-stream connection) (setf (connection-failure-p connection) t (connection-paused-p connection) nil (connection-transaction-state connection) nil (connection-parameters connection) ())) (defun send-string (string) (with-current-connection (let ((stream (connection-stream *connection*))) (when stream (unwind-protect (format stream "~A" string) (when (not (running-p)) (permanent-connection-failure *connection*))))))) (defun process-request (request) (with-current-connection ;; Ensure proper transaction state (let* ((state-spec (request-transaction-state request)) (required-state (first state-spec)) (new-state (second state-spec))) (labels ((check-state (reopen-if-needed) (let ((current-state (connection-transaction-state *connection*))) (when (and (not (eq current-state required-state)) (not (eq current-state new-state))) (cond ((and (eq required-state 'in-data) (not (eq new-state nil))) (send-data-begin)) ((eq required-state nil) (send-data-end)))) (setq current-state (connection-transaction-state *connection*)) (if (and reopen-if-needed (not (eq current-state required-state)) (not (eq current-state new-state)) (not (connection-failure-p *connection*))) (progn (open-connection) (setq *connection* (get-connection)) (check-state nil)) (eq current-state required-state))))) ;; Continue only if the state can be set properly after reopen, ;; otherwise give up and ignore the request completely. ;; This also works for the "." command when in non-data state. (when (check-state t) (send-string (request-string request)) ;; Read command answer (unless (equal state-spec '(in-data in-data)) (destructuring-bind (answer-line . data-lines) (loop with stream = (connection-stream *connection*) for line = (read-line stream) for lines = (list line) then (cons line lines) while (and (> (length line) 3) (char= (char line 3) #\-)) finally (return lines)) (let* ((code (subseq answer-line 0 3)) (answer (subseq answer-line 4)) (success (member (char code 0) '(#\1 #\2))) (data (and success (mapcar #'(lambda (line) (subseq line 4)) data-lines)))) (when success (setf (connection-transaction-state *connection*) new-state)) (list success data code answer))))))))) (defun send-request (request) (with-current-connection (process-request request))) (defparameter +block-commands+ '(("speak") ("sound_icon") ("char") ("key") ("quit") ("block" ("end")) ("set" ("self" ("rate" "pitch" "voice" "language"))))) (defun block-command-p (command &optional allowed) (unless allowed (setq allowed +block-commands+)) (let* ((match (assoc (first command) allowed :test #'string-equal)) (rest-allowed (cdr match))) (and match (or (not rest-allowed) (block-command-p (rest command) rest-allowed))))) (defun send-command (command &optional (transaction-state '(nil nil))) (unless (listp command) (setq command (list command))) (with-current-connection (setf (connection-last-command *connection*) command) (when (or (not (connection-in-block *connection*)) (block-command-p command)) (send-request (make-request :string (format nil "~{~A~^ ~}~A~A" command #\Return #\Linefeed) :transaction-state transaction-state))))) (defun send-data-begin () (send-command "SPEAK" '(nil in-data))) (defun send-data (text) (let ((text* text)) (flet ((send (string) (unless (string= string "") (send-request (make-request :string string :transaction-state '(in-data in-data)))))) (loop with eol = (format nil "~A~A" #\Return #\Linefeed) for length = (length text*) for nlpos = (or (position #\Linefeed text*) length) for dotted = (and (> (length text*) 0) (char= (char text* 0) #\.)) until (string= text* "") do (progn (when dotted (send ".")) (send (subseq text* 0 nlpos)) (send eol) (setq text* (subseq text* (min (1+ nlpos) length)))))))) (defun send-data-end () (send-command "." '(in-data nil))) ;;; Value retrieval functions (defun list-values (parameter) (second (send-command (list "LIST" (cdr (assoc parameter +list-parameter-names+)))))) ;;; Parameter setting functions (defun convert-numeric (number) (cond ((< number -100) -100) ((> number 100) 100) (t number))) (defun transform-parameter-value (parameter value) (cond ((stringp value) value) ((integerp value) (format nil "~D" (convert-numeric value))) ((symbolp value) (cdr (assoc value (cdr (assoc parameter +parameter-value-mappings+))))))) (defun set-parameter (parameter value) (with-current-connection (let* ((plist (connection-parameters *connection*)) (orig-value (if (plist-member plist parameter) (plist-get plist parameter) 'unknown))) (when (or (member parameter +volatile-parameters+) (and (not (equal orig-value value)) (or (not (eq parameter 'message-priority)) (not (connection-forced-priority *connection*))))) (let ((answer (send-command (let ((p (cdr (assoc parameter +parameter-names+))) (v (transform-parameter-value parameter value))) (unless p (error "Invalid parameter name: `~A'" parameter)) (unless v (error "Invalid parameter value: ~A=~A" parameter value)) (list "SET" "self" p v))))) (setq *connection* (get-connection)) (when (first answer) (setf (connection-parameters *connection*) (plist-put (connection-parameters *connection*) parameter value)))))))) (defun set-connection-name (name) (set-parameter 'client-name (format nil "~A:~A:~A" (user-login-name) *application-name* name))) (defun set-language (language) "Set language of the current client connection to LANGUAGE. Language must be an RFC 1766 language code, as a string." (set-parameter 'language language) (setq *language* language)) ;;; Blocks (defmacro with-block (parameters &rest body) "Set PARAMETERS and enclose BODY by an SSIP block. Before invoking BODY, the BLOCK BEGIN command is sent, and the BLOCK END command is sent afterwards. PARAMETERS is a property list defining parameters to be set before sending the BLOCK BEGIN command. The property-value pairs correspond to the arguments of the `set-parameter' function." `(with-current-connection (with-connection-parameters ,parameters (if (and *connection* (connection-in-block *connection*)) (progn ,@body) (let ((block-connection *connection*)) (send-command '("BLOCK BEGIN")) (unwind-protect (progn (with-current-connection (when *connection* (setf (connection-in-block *connection*) t))) ,@body) (let ((*connection* block-connection)) (when *connection* (setf (connection-in-block *connection*) nil) (let ((*client-name* (connection-name *connection*))) (send-command '("BLOCK END"))))))))))) ;;; Speaking functions (defun say-text (text &key (priority *default-text-priority*)) "Speak the given TEXT, represented by a string. The key argument `priority' defines the priority of the message and must be one of the symbols `important', `message', `text', `notification' or `progress'." (set-parameter 'message-priority priority) (unless (string= text "") (send-data-begin) (send-data text) (send-data-end))) (defun say-sound (name &key (priority *default-sound-priority*)) "Play an auditory icon. NAME is the name of the icon, any string acceptable by speechd. The key argument `priority' defines the priority of the message and must be one of the symbols `important', `message', `text', `notification' or `progress'." (set-parameter 'message-priority priority) (send-command (list "SOUND_ICON" name))) (defun say-char (char &key (priority *default-char-priority*)) "Speak the given CHAR, any UTF-8 character. The key argument `priority' defines the priority of the message and must be one of the symbols `important', `message', `text', `notification' or `progress'." (set-parameter 'message-priority priority) (with-current-connection (with-connection-parameters `(language ,*language*) (send-command (list "CHAR" (format nil "~A" (case char (? "space") (?\n "linefeed") (t (format nil "~A" char))))))))) ;;; Control functions (defun control-command (command all &optional repeatable) (cond ((not all) (when (or repeatable (not (equal (first (connection-last-command (get-connection))) command))) (send-command (list command "self")))) ((numberp all) (iterate-clients (control-command command nil))) (t (send-command (list command "all"))))) (defun cancel (&optional all) "Stop speaking all the messages sent through the current client so far. If the universal argument is given, stop speaking messages of all clients. If a numeric argument is given, stop speaking messages of all current Emacs session clients." (control-command "CANCEL" all)) (defun stop (&optional all) "Stop speaking the currently spoken message (if any) of this client. If the optional argument ALL is non-nil, stop speaking the currently spoken messages of all clients." (control-command "STOP" all t)) (defun pause (&optional all) "Pause speaking in the current client. If the optional argument ALL is non-nil, pause speaking in all clients." (if all (iterate-connections (setf (connection-paused-p *connection*) t)) (setf (connection-paused-p (get-connection)) t)) (control-command "PAUSE" (not (not all)))) (defun resume (&optional all) "Resume previously stopped speaking in the current client. If the optional argument ALL is non-nil, resume speaking messages of all clients." (when (or all (connection-paused-p (get-connection))) (control-command "RESUME" (not (not all))) (if all (setf (connection-paused-p (get-connection)) nil) (iterate-connections (setf (connection-paused-p *connection*) nil))))) speech-dispatcher-0.8.3/src/api/cl/ChangeLog0000644000175000017500000000030312233560613015543 000000000000002004-01-20 Milan Zamazal * sysdep.lisp (open-network-stream): Socket creation for SBCL fixed. * ssip.lisp: Exportable symbolic parameter values converted to keywords. speech-dispatcher-0.8.3/src/api/cl/elisp.lisp0000664000175000017500000000317512522771346016022 00000000000000;;; Elisp compatibility functions ;; Author: Milan Zamazal ;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation; either version 2.1 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ;; for more details. ;; You should have received a copy of the GNU Lesser General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (in-package :ssip) (defmacro while (condition &body body) `(loop while ,condition do (progn ,@body))) (defun plist-get-internal (plist prop) (cond ((null plist) nil) ((eq (car plist) prop) (cdr plist)) (t (plist-get-internal (nthcdr 2 plist) prop)))) (defun plist-get (plist prop) (first (plist-get-internal plist prop))) (defun plist-member (plist prop) (not (null (plist-get-internal plist prop)))) (defun plist-put (plist prop val) (let ((value (plist-get-internal plist prop))) (if value (progn (rplaca value val) plist) (list* prop val plist)))) (defun user-login-name () (or (getenv "LOGNAME") (getenv "USER"))) (defun concat (&rest args) (apply #'concatenate 'string args)) speech-dispatcher-0.8.3/src/api/cl/package.lisp0000664000175000017500000000233612522771346016277 00000000000000;;; Package definition ;; Author: Milan Zamazal ;; Copyright (C) 2004 Brailcom, o.p.s. ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation; either version 2.1 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License ;; for more details. ;; You should have received a copy of the GNU Lesser General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (in-package :cl-user) (defpackage :ssip (:use :cl) (:export ;; configuration.lisp #:*application-name* #:*client-name* #:*language* #:*spell* ;; ssip.lisp #:connection-names #:set-language #:open-connection #:close-connection #:reopen-connection #:say-text #:say-sound #:say-char #:cancel #:stop #:pause #:resume )) speech-dispatcher-0.8.3/src/api/guile/0000755000175000017500000000000012536417045014572 500000000000000speech-dispatcher-0.8.3/src/api/guile/README0000644000175000017500000000070012233560613015361 00000000000000This is a Guile interface to SSIP. It is in an experimental state now and is expected to be significantly reworked before first official release. To compile it, run `make'. libspeechd and guile libraries and headers files must be installed to get compiled the C part of the interface. If you have any questions, suggestions, etc., feel free to contact us at the mailing list . -- Milan Zamazal speech-dispatcher-0.8.3/src/api/guile/ChangeLog0000644000175000017500000000043512233560613016260 000000000000002004-06-14 Milan Zamazal * gssip.scm.in (ssip-say-sound): Renamed to ssip-say-icon; C function call fixed. 2004-06-14 Milan Zamazal * gssip.scm.in (ssip-block): New argument priority; missing argument in raw command invocations added. speech-dispatcher-0.8.3/src/api/guile/Makefile0000644000175000017500000000333312233560613016146 00000000000000# Makefile for speechd-guile # Copyright (C) 2004 Brailcom, o.p.s. # # Author: Milan Zamazal # # COPYRIGHT NOTICE # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. prefix = /usr/local INSTALL_PATH = $(prefix)/share/guile/site CC = gcc CFLAGS = -g -Wall INSTALL_PROGRAM = install -m 755 INSTALL_DATA = install -m 644 PROGRAM = gssip .PHONY: all install install-strip uninstall clean distclean mostlyclean \ maintainer-clean TAGS info dvi dist check all: $(PROGRAM).so $(PROGRAM).scm $(PROGRAM).so: $(PROGRAM).c $(PROGRAM).x $(PROGRAM).h $(CC) $(CFLAGS) -shared -fPIC -o $@ $(PROGRAM).c -lguile -lspeechd %.x: %.c guile-snarf -o $@ $< %.scm: %.scm.in sed 's/%%path%%/$(subst /,\/,$(INSTALL_PATH))/' $< > $@ install: all mkdir -p $(INSTALL_PATH) $(INSTALL_PROGRAM) $(PROGRAM).so $(INSTALL_PATH) $(INSTALL_DATA) $(PROGRAM).scm $(INSTALL_PATH) install-strip: $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install uninstall: mostlyclean: rm -f *.scm *.so *.x clean: mostlyclean distclean: clean maintainer-clean: distclean TAGS: info: dvi: dist: check: speech-dispatcher-0.8.3/src/api/guile/gssip.c0000664000175000017500000002351212536417045016010 00000000000000/* SSIP Guile interface */ /* Copyright (C) 2004 Brailcom, o.p.s. Author: Milan Zamazal COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #define _GNU_SOURCE #include #include #include #include #include "gssip.h" #define ASSIGN_VAR(var, pos, checker, setter) \ SCM_ASSERT (SCM_##checker##P (var), var, SCM_ARG##pos, FUNC_NAME); \ c_##var = SCM_##setter (var) #define ASSIGN_INT(var, pos) ASSIGN_VAR (var, pos, INUM, INUM) #define ASSIGN_STRING(var, pos) ASSIGN_VAR (var, pos, STRING, STRING_CHARS) #define ASSIGN_SYMBOL(var, pos) ASSIGN_VAR (var, pos, SYMBOL, SYMBOL_CHARS) #define ASSIGN_CONNECTION() ASSIGN_INT (connection, 1); #define ASSIGN_PRIORITY() c_priority = assign_priority (priority, FUNC_NAME) #define RETURN_SUCCESS(value) return ((value) ? SCM_BOOL_F : SCM_BOOL_T) static SPDPriority assign_priority(SCM priority, const char *func_name) { char *c_priority; SCM_ASSERT(SCM_SYMBOLP(priority), priority, SCM_ARG3, func_name); c_priority = SCM_SYMBOL_CHARS(priority); { const int invalid_priority = -1000; int int_priority = ((!strcmp(c_priority, "important")) ? SPD_IMPORTANT : (!strcmp(c_priority, "message")) ? SPD_MESSAGE : (!strcmp(c_priority, "text")) ? SPD_TEXT : (!strcmp(c_priority, "notification")) ? SPD_NOTIFICATION : (!strcmp(c_priority, "progress")) ? SPD_PROGRESS : invalid_priority); if (int_priority == invalid_priority) scm_wrong_type_arg(func_name, SCM_ARG3, priority); return int_priority; } } /* SSIP connection opening/closing functions */ SCM_DEFINE(ssip_open, "%ssip-open", 3, 0, 0, (SCM user, SCM client, SCM component), "Open new SSIP connection and return its identifier.") #define FUNC_NAME s_ssip_open { char *c_user, *c_client, *c_component; ASSIGN_STRING(user, 1); ASSIGN_STRING(client, 2); ASSIGN_STRING(component, 3); { int connection = spd_open(c_client, c_component, c_user); return (connection ? SCM_MAKINUM(connection) : SCM_EOL); } } #undef FUNC_NAME SCM_DEFINE(ssip_close, "%ssip-close", 1, 0, 0, (SCM connection), "Close the given SSIP connection.") #define FUNC_NAME s_ssip_close { int c_connection; ASSIGN_CONNECTION(); spd_close(c_connection); return SCM_UNSPECIFIED; } #undef FUNC_NAME /* Speech output functions */ #define SSIP_OUTPUT_DECL(name, sname) \ SCM_DEFINE (ssip_say_##name, "%ssip-say-" sname, 3, 0, 0, \ (SCM connection, SCM text, SCM priority), \ "Say " sname " on CONNECTION with PRIORITY and return whether it succeeded.") #define SSIP_OUTPUT_BODY(spd_func) \ { \ int c_connection; \ char *c_text; \ SPDPriority c_priority; \ ASSIGN_CONNECTION (); \ ASSIGN_STRING (text, 2); \ ASSIGN_PRIORITY (); \ RETURN_SUCCESS (spd_func (c_connection, c_priority, c_text)); \ } #define FUNC_NAME s_ssip_say_text SSIP_OUTPUT_DECL(text, "text") SSIP_OUTPUT_BODY(spd_say) #undef FUNC_NAME #define FUNC_NAME s_ssip_say_character SSIP_OUTPUT_DECL(character, "character") SSIP_OUTPUT_BODY(spd_char) #undef FUNC_NAME #define FUNC_NAME s_ssip_say_key SSIP_OUTPUT_DECL(key, "key") SSIP_OUTPUT_BODY(spd_key) #undef FUNC_NAME #define FUNC_NAME s_ssip_say_icon SSIP_OUTPUT_DECL(icon, "icon") SSIP_OUTPUT_BODY(spd_sound_icon) #undef FUNC_NAME /* Speech output management functions */ #define SSIP_CONTROL_DECL(name, sname) \ SCM_DEFINE (ssip_##name, "%ssip-" sname, 2, 0, 0, \ (SCM connection, SCM id), \ sname "speaking and return whether it succeeded.") #define SSIP_CONTROL_BODY(name) \ { \ int c_connection; \ int result_code; \ ASSIGN_CONNECTION (); \ if (SCM_INUMP (id)) \ result_code = spd_stop_uid (c_connection, SCM_INUM (id)); \ else if (id == SCM_EOL) \ result_code = spd_stop (c_connection); \ else if (SCM_SYMBOLP (id) \ && (! strcmp (SCM_SYMBOL_CHARS (id), "t"))) \ result_code = spd_stop_all (c_connection); \ else \ scm_wrong_type_arg (FUNC_NAME, SCM_ARG2, id); \ RETURN_SUCCESS (result_code); \ } #define FUNC_NAME s_ssip_stop SSIP_CONTROL_DECL(stop, "stop") SSIP_CONTROL_BODY(stop) #undef FUNC_NAME #define FUNC_NAME s_ssip_cancel SSIP_CONTROL_DECL(cancel, "cancel") SSIP_CONTROL_BODY(cancel) #undef FUNC_NAME #define FUNC_NAME s_ssip_pause SSIP_CONTROL_DECL(pause, "pause") SSIP_CONTROL_BODY(pause) #undef FUNC_NAME #define FUNC_NAME s_ssip_resume SSIP_CONTROL_DECL(resume, "resume") SSIP_CONTROL_BODY(resume) #undef FUNC_NAME /* Speech parameters functions */ #define SSIP_SET_DECL(name, sname) \ SCM_DEFINE (ssip_set_##name, "%ssip-set-" sname, 2, 0, 0, \ (SCM connection, SCM value), \ "Set " sname " for CONNECTION.") #define SSIP_PROCESS_SET_ARGS(type, type_f) \ int c_connection; \ type c_value; \ ASSIGN_CONNECTION (); \ ASSIGN_##type_f (value, 2); #define SSIP_SET_STRING_BODY(name) \ { \ SSIP_PROCESS_SET_ARGS (char *, STRING); \ RETURN_SUCCESS (spd_set_##name (c_connection, c_value)); \ } #define SSIP_SET_INT_BODY(name) \ { \ SSIP_PROCESS_SET_ARGS (int, INT); \ SCM_ASSERT ((-100 <= c_value && c_value <= 100), value, SCM_ARG2, \ FUNC_NAME); \ RETURN_SUCCESS (spd_set_##name (c_connection, c_value)); \ } #define FUNC_NAME s_ssip_set_language SSIP_SET_DECL(language, "language") SSIP_SET_STRING_BODY(language) #undef FUNC_NAME #define FUNC_NAME s_ssip_set_output_module SSIP_SET_DECL(output_module, "output-module") SSIP_SET_STRING_BODY(output_module) #undef FUNC_NAME #define FUNC_NAME s_ssip_set_rate SSIP_SET_DECL(rate, "rate") SSIP_SET_INT_BODY(voice_rate) #undef FUNC_NAME #define FUNC_NAME s_ssip_set_pitch SSIP_SET_DECL(pitch, "pitch") SSIP_SET_INT_BODY(voice_pitch) #undef FUNC_NAME #define FUNC_NAME s_ssip_set_volume SSIP_SET_DECL(volume, "volume") SSIP_SET_INT_BODY(volume) #undef FUNC_NAME #define FUNC_NAME s_ssip_set_voice SSIP_SET_DECL(voice, "voice") { SSIP_PROCESS_SET_ARGS(char *, STRING); { char *command; int result_code; if (asprintf(&command, "SET self VOICE %s", c_value) < 0) scm_memory_error(FUNC_NAME); result_code = spd_execute_command(c_connection, command); free(command); RETURN_SUCCESS(result_code); } } #undef FUNC_NAME #define FUNC_NAME s_ssip_set_punctuation_mode SSIP_SET_DECL(punctuation_mode, "punctuation-mode") { SSIP_PROCESS_SET_ARGS(char *, SYMBOL); { SPDPunctuation mode; if (!strcmp(c_value, "none")) mode = SPD_PUNCT_NONE; else if (!strcmp(c_value, "some")) mode = SPD_PUNCT_SOME; else if (!strcmp(c_value, "all")) mode = SPD_PUNCT_ALL; else scm_wrong_type_arg(FUNC_NAME, SCM_ARG2, value); RETURN_SUCCESS(spd_set_punctuation(c_connection, mode)); } } #undef FUNC_NAME #define FUNC_NAME s_ssip_set_spelling_mode SSIP_SET_DECL(spelling_mode, "spelling-mode") { SSIP_PROCESS_SET_ARGS(char *, SYMBOL); { SPDSpelling mode; if (!strcmp(c_value, "on")) mode = SPD_SPELL_ON; else if (!strcmp(c_value, "off")) mode = SPD_SPELL_OFF; else scm_wrong_type_arg(FUNC_NAME, SCM_ARG2, value); RETURN_SUCCESS(spd_set_spelling(c_connection, mode)); } } #undef FUNC_NAME /* Raw SSIP commands */ SCM_DEFINE(ssip_raw_command, "%ssip-raw-command", 2, 0, 0, (SCM connection, SCM command), "Send raw COMMAND to CONNECTION and return whether it succeeded.") #define FUNC_NAME s_ssip_raw_command { int c_connection; char *c_command; ASSIGN_CONNECTION(); ASSIGN_STRING(command, 2); RETURN_SUCCESS(spd_execute_command(c_connection, c_command)); } #undef FUNC_NAME /* Define the Scheme bindings */ void init_gssip() { #include "gssip.x" } speech-dispatcher-0.8.3/src/api/guile/gssip.scm.in0000664000175000017500000000517412536417045016761 00000000000000;;; SSIP interface ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (load-extension "%%path%%/gssip" "init_gssip") (define (ssip-open host port user client component) (%ssip-open user client component)) (define (ssip-close connection) (%ssip-close connection)) (define (ssip-say-text connection text priority) (%ssip-say-text connection text priority)) (define (ssip-say-character connection character priority) (%ssip-say-character connection character priority)) (define (ssip-say-key connection key priority) (%ssip-say-key connection key priority)) (define (ssip-say-icon connection sound priority) (%ssip-say-icon connection sound priority)) (define (ssip-stop connection id) (%ssip-stop connection id)) (define (ssip-cancel connection id) (%ssip-cancel connection id)) (define (ssip-pause connection id) (%ssip-pause connection id)) (define (ssip-resume connection id) (%ssip-resume connection id)) (define (ssip-set-language connection language) (%ssip-set-language connection language)) (define (ssip-set-output-module connection output-module) (%ssip-set-output-module connection output-module)) (define (ssip-set-rate connection rate) (%ssip-set-rate connection rate)) (define (ssip-set-pitch connection pitch) (%ssip-set-pitch connection pitch)) (define (ssip-set-volume connection volume) (%ssip-set-volume connection volume)) (define (ssip-set-voice connection voice) (%ssip-set-voice connection voice)) (define (ssip-set-punctuation-mode connection mode) (%ssip-set-punctuation-mode connection mode)) (define (ssip-set-spelling-mode connection mode) (%ssip-set-spelling-mode connection mode)) (define (ssip-block connection priority function) (%ssip-say-text connection "" priority) (%ssip-raw-command connection "BLOCK BEGIN") (catch #t (function) (lambda (key . args))) (%ssip-raw-command connection "BLOCK END")) (provide 'gssip) speech-dispatcher-0.8.3/src/api/guile/gssip.h0000664000175000017500000000156612522771346016024 00000000000000/* SSIP Guile support */ /* Copyright (C) 2004 Brailcom, o.p.s. Author: Milan Zamazal COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, version 2.1 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GSSIP_H #define __GSSIP_H void init_gssip(); #endif speech-dispatcher-0.8.3/src/api/python/0000775000175000017500000000000012536424374015013 500000000000000speech-dispatcher-0.8.3/src/api/python/README0000644000175000017500000000054412233560613015603 00000000000000This is a Python interface to SSIP. Full range of SSIP commands is implemented including callback handling. See the section "Python API" in Speech Dispatcher documentation for more information. If you have any questions, suggestions, etc., feel free to contact us at the mailing list . -- Tomas Cerha speech-dispatcher-0.8.3/src/api/python/speechd/0000775000175000017500000000000012536424374016426 500000000000000speech-dispatcher-0.8.3/src/api/python/speechd/client.py0000664000175000017500000013170512536420135020174 00000000000000# Copyright (C) 2003-2008 Brailcom, o.p.s. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """Python API to Speech Dispatcher Basic Python client API to Speech Dispatcher is provided by the 'SSIPClient' class. This interface maps directly to available SSIP commands and logic. A more convenient interface is provided by the 'Speaker' class. """ #TODO: Blocking variants for speak, char, key, sound_icon. import socket, sys, os, subprocess, time, tempfile try: import threading except: import dummy_threading as threading from . import paths class CallbackType(object): """Constants describing the available types of callbacks""" INDEX_MARK = 'index_marks' """Index mark events are reported when the place they were included into the text by the client application is reached when speaking them""" BEGIN = 'begin' """The begin event is reported when Speech Dispatcher starts actually speaking the message.""" END = 'end' """The end event is reported after the message has terminated and there is no longer any sound from it being produced""" CANCEL = 'cancel' """The cancel event is reported when a message is canceled either on request of the user, because of prioritization of messages or due to an error""" PAUSE = 'pause' """The pause event is reported after speaking of a message was paused. It no longer produces any audio.""" RESUME = 'resume' """The resume event is reported right after speaking of a message was resumed after previous pause.""" class SSIPError(Exception): """Common base class for exceptions during SSIP communication.""" class SSIPCommunicationError(SSIPError): """Exception raised when trying to operate on a closed connection.""" _additional_exception = None def __init__(self, description=None, original_exception=None, **kwargs): self._original_exception = original_exception self._description = description super(SSIPError, self).__init__(**kwargs) def original_exception(self): """Return the original exception if any If this exception is secondary, being caused by a lower level exception, return this original exception, otherwise None""" return self._original_exception def set_additional_exception(self, exception): """Set an additional exception See method additional_exception(). """ self._additional_exception = exception def additional_exception(self): """Return an additional exception Additional exceptions araise from failed attempts to resolve the former problem""" return self._additional_exception def description(self): """Return error description""" return self._description def __str__(self): msgs = [] if self.description(): msgs.append(self.description()) if self.original_exception: msgs.append("Original error: " + str(self.original_exception())) if self.additional_exception: msgs.append("Additional error: " + str(self.additional_exception())) return "\n".join(msgs) class SSIPResponseError(Exception): def __init__(self, code, msg, data): Exception.__init__(self, "%s: %s" % (code, msg)) self._code = code self._msg = msg self._data = data def code(self): """Return the server response error code as integer number.""" return self._code def msg(self): """Return server response error message as string.""" return self._msg class SSIPCommandError(SSIPResponseError): """Exception raised on error response after sending command.""" def command(self): """Return the command string which resulted in this error.""" return self._data class SSIPDataError(SSIPResponseError): """Exception raised on error response after sending data.""" def data(self): """Return the data which resulted in this error.""" return self._data class SpawnError(Exception): """Indicates failure in server autospawn.""" class CommunicationMethod(object): """Constants describing the possible methods of connection to server.""" UNIX_SOCKET = 'unix_socket' """Unix socket communication using a filesystem path""" INET_SOCKET = 'inet_socket' """Inet socket communication using a host and port""" class _SSIP_Connection(object): """Implemantation of low level SSIP communication.""" _NEWLINE = b"\r\n" _END_OF_DATA_MARKER = b'.' _END_OF_DATA_MARKER_ESCAPED = b'..' _END_OF_DATA = _NEWLINE + _END_OF_DATA_MARKER + _NEWLINE _END_OF_DATA_ESCAPED = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED + _NEWLINE # Constants representing \r\n. and \r\n.. _RAW_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER _ESCAPED_DOTLINE = _NEWLINE + _END_OF_DATA_MARKER_ESCAPED _CALLBACK_TYPE_MAP = {700: CallbackType.INDEX_MARK, 701: CallbackType.BEGIN, 702: CallbackType.END, 703: CallbackType.CANCEL, 704: CallbackType.PAUSE, 705: CallbackType.RESUME, } def __init__(self, communication_method, socket_path, host, port): """Init connection: open the socket to server, initialize buffers, launch a communication handling thread. """ if communication_method == CommunicationMethod.UNIX_SOCKET: socket_family = socket.AF_UNIX socket_connect_args = socket_path elif communication_method == CommunicationMethod.INET_SOCKET: assert host and port socket_family = socket.AF_INET socket_connect_args = (socket.gethostbyname(host), port) else: raise ValueError("Unsupported communication method") try: self._socket = socket.socket(socket_family, socket.SOCK_STREAM) self._socket.connect(socket_connect_args) except socket.error as ex: raise SSIPCommunicationError("Can't open socket using method " + communication_method, original_exception = ex) self._buffer = b"" self._com_buffer = [] self._callback = None self._ssip_reply_semaphore = threading.Semaphore(0) self._communication_thread = \ threading.Thread(target=self._communication, kwargs={}, name="SSIP client communication thread") self._communication_thread.start() def close(self): """Close the server connection, destroy the communication thread.""" # Read-write shutdown here is necessary, otherwise the socket.recv() # function in the other thread won't return at last on some platforms. try: self._socket.shutdown(socket.SHUT_RDWR) except socket.error: pass self._socket.close() # Wait for the other thread to terminate self._communication_thread.join() def _communication(self): """Handle incomming socket communication. Listens for all incomming communication on the socket, dispatches events and puts all other replies into self._com_buffer list in the already parsed form as (code, msg, data). Each time a new item is appended to the _com_buffer list, the corresponding semaphore 'self._ssip_reply_semaphore' is incremented. This method is designed to run in a separate thread. The thread can be interrupted by closing the socket on which it is listening for reading.""" while True: try: code, msg, data = self._recv_message() except IOError: # If the socket has been closed, exit the thread sys.exit() if code//100 != 7: # This is not an index mark nor an event self._com_buffer.append((code, msg, data)) self._ssip_reply_semaphore.release() continue # Ignore the event if no callback function has been registered. if self._callback is not None: type = self._CALLBACK_TYPE_MAP[code] if type == CallbackType.INDEX_MARK: kwargs = {'index_mark': data[2]} else: kwargs = {} # Get message and client ID of the event msg_id, client_id = map(int, data[:2]) self._callback(msg_id, client_id, type, **kwargs) def _readline(self): """Read one whole line from the socket. Blocks until the line delimiter ('_NEWLINE') is read. """ pointer = self._buffer.find(self._NEWLINE) while pointer == -1: try: d = self._socket.recv(1024) except: raise IOError if len(d) == 0: raise IOError self._buffer += d pointer = self._buffer.find(self._NEWLINE) line = self._buffer[:pointer] self._buffer = self._buffer[pointer+len(self._NEWLINE):] return line.decode('utf-8') def _recv_message(self): """Read server response or a callback and return the triplet (code, msg, data).""" data = [] c = None while True: line = self._readline() assert len(line) >= 4, "Malformed data received from server!" code, sep, text = line[:3], line[3], line[4:] assert code.isalnum() and (c is None or code == c) and \ sep in ('-', ' '), "Malformed data received from server!" if sep == ' ': msg = text return int(code), msg, tuple(data) data.append(text) def _recv_response(self): """Read server response from the communication thread and return the triplet (code, msg, data).""" # TODO: This check is dumb but seems to work. The main thread # hangs without it, when the Speech Dispatcher connection is lost. if not self._communication_thread.isAlive(): raise SSIPCommunicationError self._ssip_reply_semaphore.acquire() # The list is sorted, read the first item response = self._com_buffer[0] del self._com_buffer[0] return response def send_command(self, command, *args): """Send SSIP command with given arguments and read server response. Arguments can be of any data type -- they are all stringified before being sent to the server. Returns a triplet (code, msg, data), where 'code' is a numeric SSIP response code as an integer, 'msg' is an SSIP rsponse message as string and 'data' is a tuple of strings (all lines of response data) when a response contains some data. 'SSIPCommandError' is raised in case of non 2xx return code. See SSIP documentation for more information about server responses and codes. 'IOError' is raised when the socket was closed by the remote side. """ if __debug__: if command in ('SET', 'CANCEL', 'STOP',): assert args[0] in (Scope.SELF, Scope.ALL) \ or isinstance(args[0], int) cmd = ' '.join((command,) + tuple(map(str, args))) try: self._socket.send(cmd.encode('utf-8') + self._NEWLINE) except socket.error: raise SSIPCommunicationError("Speech Dispatcher connection lost.") code, msg, data = self._recv_response() if code//100 != 2: raise SSIPCommandError(code, msg, cmd) return code, msg, data def send_data(self, data): """Send multiline data and read server response. Returned value is the same as for 'send_command()' method. 'SSIPDataError' is raised in case of non 2xx return code. See SSIP documentation for more information about server responses and codes. 'IOError' is raised when the socket was closed by the remote side. """ data = data.encode('utf-8') # Escape the end-of-data marker even if present at the beginning # The start of the string is also the start of a line. if data.startswith(self._END_OF_DATA_MARKER): l = len(self._END_OF_DATA_MARKER) data = self._END_OF_DATA_MARKER_ESCAPED + data[l:] # Escape the end of data marker at the start of each subsequent # line. We can do that by simply replacing \r\n. with \r\n.., # since the start of a line is immediately preceded by \r\n, # when the line is not the beginning of the string. data = data.replace(self._RAW_DOTLINE, self._ESCAPED_DOTLINE) try: self._socket.send(data + self._END_OF_DATA) except socket.error: raise SSIPCommunicationError("Speech Dispatcher connection lost.") code, msg, response_data = self._recv_response() if code//100 != 2: raise SSIPDataError(code, msg, data) return code, msg, response_data def set_callback(self, callback): """Register a callback function for handling asynchronous events. Arguments: callback -- a callable object (function) which will be called to handle asynchronous events (arguments described below). Passing `None' results in removing the callback function and ignoring events. Just one callback may be registered. Attempts to register a second callback will result in the former callback being replaced. The callback function must accept three positional arguments ('message_id', 'client_id', 'event_type') and an optional keyword argument 'index_mark' (when INDEX_MARK events are turned on). Note, that setting the callback function doesn't turn the events on. The user is responsible to turn them on by sending the appropriate `SET NOTIFICATION' command. """ self._callback = callback class _CallbackHandler(object): """Internal object which handles callbacks.""" def __init__(self, client_id): self._client_id = client_id self._callbacks = {} self._lock = threading.Lock() def __call__(self, msg_id, client_id, type, **kwargs): if client_id != self._client_id: # TODO: does that ever happen? return self._lock.acquire() try: try: callback, event_types = self._callbacks[msg_id] except KeyError: pass else: if event_types is None or type in event_types: callback(type, **kwargs) if type in (CallbackType.END, CallbackType.CANCEL): del self._callbacks[msg_id] finally: self._lock.release() def add_callback(self, msg_id, callback, event_types): self._lock.acquire() try: self._callbacks[msg_id] = (callback, event_types) finally: self._lock.release() class Scope(object): """An enumeration of valid SSIP command scopes. The constants of this class should be used to specify the 'scope' argument for the 'Client' methods. """ SELF = 'self' """The command (mostly a setting) applies to current connection only.""" ALL = 'all' """The command applies to all current Speech Dispatcher connections.""" class Priority(object): """An enumeration of valid SSIP message priorities. The constants of this class should be used to specify the 'priority' argument for the 'Client' methods. For more information about message priorities and their interaction, see the SSIP documentation. """ IMPORTANT = 'important' TEXT = 'text' MESSAGE = 'message' NOTIFICATION = 'notification' PROGRESS = 'progress' class PunctuationMode(object): """Constants for selecting a punctuation mode. The mode determines which characters should be read. """ ALL = 'all' """Read all punctuation characters.""" NONE = 'none' """Don't read any punctuation character at all.""" SOME = 'some' """Only the user-defined punctuation characters are read. The set of characters is specified in Speech Dispatcher configuration. """ class DataMode(object): """Constants specifying the type of data contained within messages to be spoken. """ TEXT = 'text' """Data is plain text.""" SSML = 'ssml' """Data is SSML (Speech Synthesis Markup Language).""" class SSIPClient(object): """Basic Speech Dispatcher client interface. This class provides a Python interface to Speech Dispatcher functionality over an SSIP connection. The API maps directly to available SSIP commands. Each connection to Speech Dispatcher is represented by one instance of this class. Many commands take the 'scope' argument, thus it is shortly documented here. It is either one of 'Scope' constants or a number of connection. By specifying the connection number, you are applying the command to a particular connection. This feature is only meant to be used by Speech Dispatcher control application, however. More datails can be found in Speech Dispatcher documentation. """ DEFAULT_HOST = '127.0.0.1' """Default host for server connections.""" DEFAULT_PORT = 6560 """Default port number for server connections.""" DEFAULT_SOCKET_PATH = "speech-dispatcher/speechd.sock" """Default name of the communication unix socket""" def __init__(self, name, component='default', user='unknown', address=None, autospawn=None, # Deprecated -> host=None, port=None, method=None, socket_path=None): """Initialize the instance and connect to the server. Arguments: name -- client identification string component -- connection identification string. When one client opens multiple connections, this can be used to identify each of them. user -- user identification string (user name). When multi-user acces is expected, this can be used to identify their connections. address -- server address as specified in Speech Dispatcher documentation (e.g. "unix:/run/user/joe/speech-dispatcher/speechd.sock" or "inet:192.168.0.85:6561") autospawn -- a flag to specify whether the library should try to start the server if it determines its not already running or not Deprecated arguments: method -- communication method to use, one of the constants defined in class CommunicationMethod socket_path -- for CommunicationMethod.UNIX_SOCKET, socket path in filesystem. By default, this is $XDG_RUNTIME_DIR/speech-dispatcher/speechd.sock where $XDG_RUNTIME_DIR is determined using the XDG Base Directory Specification. host -- for CommunicationMethod.INET_SOCKET, server hostname or IP address as a string. If None, the default value is taken from SPEECHD_HOST environment variable (if it exists) or from the DEFAULT_HOST attribute of this class. port -- for CommunicationMethod.INET_SOCKET method, server port as number or None. If None, the default value is taken from SPEECHD_PORT environment variable (if it exists) or from the DEFAULT_PORT attribute of this class. For more information on client identification strings see Speech Dispatcher documentation. """ _home = os.path.expanduser("~") _runtime_dir = os.environ.get('XDG_RUNTIME_DIR', os.environ.get('XDG_CACHE_HOME', os.path.join(_home, '.cache'))) _sock_path = os.path.join(_runtime_dir, self.DEFAULT_SOCKET_PATH) # Resolve connection parameters: connection_args = {'communication_method': CommunicationMethod.UNIX_SOCKET, 'socket_path': _sock_path, 'host': self.DEFAULT_HOST, 'port': self.DEFAULT_PORT, } # Respect address method argument and SPEECHD_ADDRESS environemt variable _address = address or os.environ.get("SPEECHD_ADDRESS") if _address: connection_args.update(self._connection_arguments_from_address(_address)) # Respect the old (deprecated) key arguments and environment variables # TODO: Remove this section in 0.8 release else: # Read the environment variables env_speechd_host = os.environ.get("SPEECHD_HOST") try: env_speechd_port = int(os.environ.get("SPEECHD_PORT")) except: env_speechd_port = None env_speechd_socket_path = os.environ.get("SPEECHD_SOCKET") # Prefer old (deprecated) function arguments, but if # not specified and old (deprecated) environment variable # is set, use the value of the environment variable if method: connection_args['method'] = method if port: connection_args['port'] = port elif env_speechd_port: connection_args['port'] = env_speechd_port if socket_path: connection_args['socket_path'] = socket_path elif env_speechd_socket_path: connection_args['socket_path'] = env_speechd_socket_path self._connect_with_autospawn(connection_args, autospawn) self._initialize_connection(user, name, component) def _connect_with_autospawn(self, connection_args, autospawn): """Establish new connection (and/or autospawn server)""" try: self._conn = _SSIP_Connection(**connection_args) except SSIPCommunicationError as ce: # Suppose server might not be running, try the autospawn mechanism if autospawn != False: # Autospawn is however not guaranteed to start the server. The server # will decide, based on it's configuration, whether to honor the request. try: self._server_spawn(connection_args) except SpawnError as se: ce.set_additional_exception(se) raise ce self._conn = _SSIP_Connection(**connection_args) else: raise def _initialize_connection(self, user, name, component): """Initialize connection -- Set client name, get id, register callbacks etc.""" full_name = '%s:%s:%s' % (user, name, component) self._conn.send_command('SET', Scope.SELF, 'CLIENT_NAME', full_name) code, msg, data = self._conn.send_command('HISTORY', 'GET', 'CLIENT_ID') self._client_id = int(data[0]) self._callback_handler = _CallbackHandler(self._client_id) self._conn.set_callback(self._callback_handler) for event in (CallbackType.INDEX_MARK, CallbackType.BEGIN, CallbackType.END, CallbackType.CANCEL, CallbackType.PAUSE, CallbackType.RESUME): self._conn.send_command('SET', 'self', 'NOTIFICATION', event, 'on') def _connection_arguments_from_address(self, address): """Parse a Speech Dispatcher address line and return a dictionary of connection arguments""" connection_args = {} address_params = address.split(":") try: _method = address_params[0] except: raise SSIPCommunicationErrror("Wrong format of server address") connection_args['communication_method'] = _method if _method == CommunicationMethod.UNIX_SOCKET: try: connection_args['socket_path'] = address_params[1] except IndexError: pass # The additional parameters was not set, let's stay with defaults elif _method == CommunicationMethod.INET_SOCKET: try: connection_args['host'] = address_params[1] connection_args['port'] = int(address_params[2]) except ValueError: # Failed conversion to int raise SSIPCommunicationError("Third parameter of inet_socket address must be a port number") except IndexError: pass # The additional parameters was not set, let's stay with defaults else: raise SSIPCommunicationError("Unknown communication method in address."); return connection_args def __del__(self): """Close the connection""" self.close() def _server_spawn(self, connection_args): """Attempts to spawn the speech-dispatcher server.""" # Check whether we are not connecting to a remote host # TODO: This is a hack. inet sockets specific code should # belong to _SSIPConnection. We do not however have an _SSIPConnection # yet. if connection_args['communication_method'] == 'inet_socket': addrinfos = socket.getaddrinfo(connection_args['host'], connection_args['port']) # Check resolved addrinfos for presence of localhost ip_addresses = [addrinfo[4][0] for addrinfo in addrinfos] localhost=False for ip in ip_addresses: if ip.startswith("127.") or ip == "::1": connection_args['host'] = ip localhost=True if not localhost: # The hostname didn't resolve on localhost in neither case, # do not spawn server on localhost... raise SpawnError( "Can't start server automatically (autospawn), requested address %s " "resolves on %s which seems to be a remote host. You must start the " "server manually or choose another connection address." % (connection_args['host'], str(ip_addresses),)) if os.path.exists(paths.SPD_SPAWN_CMD): connection_params = [] for param, value in connection_args.items(): if param not in ["host",]: connection_params += ["--"+param.replace("_","-"), str(value)] server = subprocess.Popen([paths.SPD_SPAWN_CMD, "--spawn"]+connection_params, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_reply, stderr_reply = server.communicate() retcode = server.wait() if retcode != 0: raise SpawnError("Server refused to autospawn, stating this reason: %s" % (stderr_reply,)) return server.pid else: raise SpawnError("Can't find Speech Dispatcher spawn command %s" % (paths.SPD_SPAWN_CMD,)) def set_priority(self, priority): """Set the priority category for the following messages. Arguments: priority -- one of the 'Priority' constants. """ assert priority in (Priority.IMPORTANT, Priority.MESSAGE, Priority.TEXT, Priority.NOTIFICATION, Priority.PROGRESS), priority self._conn.send_command('SET', Scope.SELF, 'PRIORITY', priority) def set_data_mode(self, value): """Set the data mode for further speech commands. Arguments: value - one of the constants defined by the DataMode class. """ if value == DataMode.SSML: ssip_val = 'on' elif value == DataMode.TEXT: ssip_val = 'off' else: raise ValueError( 'Value "%s" is not one of the constants from the DataMode class.' % \ value) self._conn.send_command('SET', Scope.SELF, 'SSML_MODE', ssip_val) def speak(self, text, callback=None, event_types=None): """Say given message. Arguments: text -- message text to be spoken. This may be either a UTF-8 encoded byte string or a Python unicode string. callback -- a callback handler for asynchronous event notifications. A callable object (function) which accepts one positional argument `type' and one keyword argument `index_mark'. See below for more details. event_types -- a tuple of event types for which the callback should be called. Each item must be one of `CallbackType' constants. None (the default value) means to handle all event types. This argument is irrelevant when `callback' is not used. The callback function will be called whenever one of the events occurs. The event type will be passed as argument. Its value is one of the `CallbackType' constants. In case of an index mark event, additional keyword argument `index_mark' will be passed and will contain the index mark identifier as specified within the text. The callback function should not perform anything complicated and is not allowed to issue any further SSIP client commands. An attempt to do so would lead to a deadlock in SSIP communication. This method is non-blocking; it just sends the command, given message is queued on the server and the method returns immediately. """ self._conn.send_command('SPEAK') result = self._conn.send_data(text) if callback: msg_id = int(result[2][0]) # TODO: Here we risk, that the callback arrives earlier, than we # add the item to `self._callback_handler'. Such a situation will # lead to the callback being ignored. self._callback_handler.add_callback(msg_id, callback, event_types) return result def char(self, char): """Say given character. Arguments: char -- a character to be spoken. Either a Python unicode string or a UTF-8 encoded byte string. This method is non-blocking; it just sends the command, given message is queued on the server and the method returns immediately. """ self._conn.send_command('CHAR', char.replace(' ', 'space')) def key(self, key): """Say given key name. Arguments: key -- the key name (as defined in SSIP); string. This method is non-blocking; it just sends the command, given message is queued on the server and the method returns immediately. """ self._conn.send_command('KEY', key) def sound_icon(self, sound_icon): """Output given sound_icon. Arguments: sound_icon -- the name of the sound icon as defined by SSIP; string. This method is non-blocking; it just sends the command, given message is queued on the server and the method returns immediately. """ self._conn.send_command('SOUND_ICON', sound_icon) def cancel(self, scope=Scope.SELF): """Immediately stop speaking and discard messages in queues. Arguments: scope -- see the documentation of this class. """ self._conn.send_command('CANCEL', scope) def stop(self, scope=Scope.SELF): """Immediately stop speaking the currently spoken message. Arguments: scope -- see the documentation of this class. """ self._conn.send_command('STOP', scope) def pause(self, scope=Scope.SELF): """Pause speaking and postpone other messages until resume. This method is non-blocking. However, speaking can continue for a short while even after it's called (typically to the end of the sentence). Arguments: scope -- see the documentation of this class. """ self._conn.send_command('PAUSE', scope) def resume(self, scope=Scope.SELF): """Resume speaking of the currently paused messages. This method is non-blocking. However, speaking can continue for a short while even after it's called (typically to the end of the sentence). Arguments: scope -- see the documentation of this class. """ self._conn.send_command('RESUME', scope) def list_output_modules(self): """Return names of all active output modules as a tuple of strings.""" code, msg, data = self._conn.send_command('LIST', 'OUTPUT_MODULES') return data def list_synthesis_voices(self): """Return names of all available voices for the current output module. Returns a tuple of tripplets (name, language, dialect). 'name' is a string, 'language' is an ISO 639-1 Alpha-2 language code and 'dialect' is a string. Language and dialect may be None. """ try: code, msg, data = self._conn.send_command('LIST', 'SYNTHESIS_VOICES') except SSIPCommandError: return () def split(item): name, lang, dialect = tuple(item.rsplit(' ', 3)) return (name, lang or None, dialect or None) return tuple([split(item) for item in data]) def set_language(self, language, scope=Scope.SELF): """Switch to a particular language for further speech commands. Arguments: language -- two letter language code according to RFC 1776 as string. scope -- see the documentation of this class. """ assert isinstance(language, str) and len(language) == 2 self._conn.send_command('SET', scope, 'LANGUAGE', language) def get_language(self): """Get the current language.""" code, msg, data = self._conn.send_command('GET', 'LANGUAGE') if data: return data[0] return None def set_output_module(self, name, scope=Scope.SELF): """Switch to a particular output module. Arguments: name -- module (string) as returned by 'list_output_modules()'. scope -- see the documentation of this class. """ self._conn.send_command('SET', scope, 'OUTPUT_MODULE', name) def get_output_module(self): """Get the current output module.""" code, msg, data = self._conn.send_command('GET', 'OUTPUT_MODULE') if data: return data[0] return None def set_pitch(self, value, scope=Scope.SELF): """Set the pitch for further speech commands. Arguments: value -- integer value within the range from -100 to 100, with 0 corresponding to the default pitch of the current speech synthesis output module, lower values meaning lower pitch and higher values meaning higher pitch. scope -- see the documentation of this class. """ assert isinstance(value, int) and -100 <= value <= 100, value self._conn.send_command('SET', scope, 'PITCH', value) def get_pitch(self): """Get the current pitch.""" code, msg, data = self._conn.send_command('GET', 'PITCH') if data: return data[0] return None def set_rate(self, value, scope=Scope.SELF): """Set the speech rate (speed) for further speech commands. Arguments: value -- integer value within the range from -100 to 100, with 0 corresponding to the default speech rate of the current speech synthesis output module, lower values meaning slower speech and higher values meaning faster speech. scope -- see the documentation of this class. """ assert isinstance(value, int) and -100 <= value <= 100 self._conn.send_command('SET', scope, 'RATE', value) def get_rate(self): """Get the current speech rate (speed).""" code, msg, data = self._conn.send_command('GET', 'RATE') if data: return data[0] return None def set_volume(self, value, scope=Scope.SELF): """Set the speech volume for further speech commands. Arguments: value -- integer value within the range from -100 to 100, with 100 corresponding to the default speech volume of the current speech synthesis output module, lower values meaning softer speech. scope -- see the documentation of this class. """ assert isinstance(value, int) and -100 <= value <= 100 self._conn.send_command('SET', scope, 'VOLUME', value) def get_volume(self): """Get the speech volume.""" code, msg, data = self._conn.send_command('GET', 'VOLUME') if data: return data[0] return None def set_punctuation(self, value, scope=Scope.SELF): """Set the punctuation pronounciation level. Arguments: value -- one of the 'PunctuationMode' constants. scope -- see the documentation of this class. """ assert value in (PunctuationMode.ALL, PunctuationMode.SOME, PunctuationMode.NONE), value self._conn.send_command('SET', scope, 'PUNCTUATION', value) def set_spelling(self, value, scope=Scope.SELF): """Toogle the spelling mode or on off. Arguments: value -- if 'True', all incomming messages will be spelled instead of being read as normal words. 'False' switches this behavior off. scope -- see the documentation of this class. """ assert value in [True, False] if value == True: self._conn.send_command('SET', scope, 'SPELLING', "on") else: self._conn.send_command('SET', scope, 'SPELLING', "off") def set_cap_let_recogn(self, value, scope=Scope.SELF): """Set capital letter recognition mode. Arguments: value -- one of 'none', 'spell', 'icon'. None means no signalization of capital letters, 'spell' means capital letters will be spelled with a syntetic voice and 'icon' means that the capital-letter icon will be prepended before each capital letter. scope -- see the documentation of this class. """ assert value in ("none", "spell", "icon") self._conn.send_command('SET', scope, 'CAP_LET_RECOGN', value) def set_voice(self, value, scope=Scope.SELF): """Set voice by a symbolic name. Arguments: value -- one of the SSIP symbolic voice names: 'MALE1' .. 'MALE3', 'FEMALE1' ... 'FEMALE3', 'CHILD_MALE', 'CHILD_FEMALE' scope -- see the documentation of this class. Symbolic voice names are mapped to real synthesizer voices in the configuration of the output module. Use the method 'set_synthesis_voice()' if you want to work with real voices. """ assert isinstance(value, str) and \ value.lower() in ("male1", "male2", "male3", "female1", "female2", "female3", "child_male", "child_female") self._conn.send_command('SET', scope, 'VOICE_TYPE', value) def set_synthesis_voice(self, value, scope=Scope.SELF): """Set voice by its real name. Arguments: value -- voice name as returned by 'list_synthesis_voices()' scope -- see the documentation of this class. """ self._conn.send_command('SET', scope, 'SYNTHESIS_VOICE', value) def set_pause_context(self, value, scope=Scope.SELF): """Set the amount of context when resuming a paused message. Arguments: value -- a positive or negative value meaning how many chunks of data after or before the pause should be read when resume() is executed. scope -- see the documentation of this class. """ assert isinstance(value, int) self._conn.send_command('SET', scope, 'PAUSE_CONTEXT', value) def set_debug(self, val): """Switch debugging on and off. When switched on, debugging files will be created in the chosen destination (see set_debug_destination()) for Speech Dispatcher and all its running modules. All logging information will then be written into these files with maximal verbosity until switched off. You should always first call set_debug_destination. The intended use of this functionality is to switch debuging on for a period of time while the user will repeat the behavior and then send the logs to the appropriate bug-reporting place. Arguments: val -- a boolean value determining whether debugging is switched on or off scope -- see the documentation of this class. """ assert isinstance(val, bool) if val == True: ssip_val = "ON" else: ssip_val = "OFF" self._conn.send_command('SET', scope.ALL, 'DEBUG', ssip_val) def set_debug_destination(self, path): """Set debug destination. Arguments: path -- path (string) to the directory where debuging files will be created scope -- see the documentation of this class. """ assert isinstance(val, string) self._conn.send_command('SET', scope.ALL, 'DEBUG_DESTINATION', val) def block_begin(self): """Begin an SSIP block. See SSIP documentation for more details about blocks. """ self._conn.send_command('BLOCK', 'BEGIN') def block_end(self): """Close an SSIP block. See SSIP documentation for more details about blocks. """ self._conn.send_command('BLOCK', 'END') def close(self): """Close the connection to Speech Dispatcher.""" if hasattr(self, '_conn'): self._conn.close() del self._conn class Client(SSIPClient): """A DEPRECATED backwards-compatible API. This Class is provided only for backwards compatibility with the prevoius unofficial API. It will be removed in future versions. Please use either 'SSIPClient' or 'Speaker' interface instead. As deprecated, the API is no longer documented. """ def __init__(self, name=None, client=None, **kwargs): name = name or client or 'python' super(Client, self).__init__(name, **kwargs) def say(self, text, priority=Priority.MESSAGE): self.set_priority(priority) self.speak(text) def char(self, char, priority=Priority.TEXT): self.set_priority(priority) super(Client, self).char(char) def key(self, key, priority=Priority.TEXT): self.set_priority(priority) super(Client, self).key(key) def sound_icon(self, sound_icon, priority=Priority.TEXT): self.set_priority(priority) super(Client, self).sound_icon(sound_icon) class Speaker(SSIPClient): """Extended Speech Dispatcher Interface. This class provides an extended intercace to Speech Dispatcher functionality and tries to hide most of the lower level details of SSIP (such as a more sophisticated handling of blocks and priorities and advanced event notifications) under a more convenient API. Please note that the API is not yet stabilized and thus is subject to change! Please contact the authors if you plan using it and/or if you have any suggestions. Well, in fact this class is currently not implemented at all. It is just a draft. The intention is to hide the SSIP details and provide a generic interface practical for screen readers. """ # Deprecated but retained for backwards compatibility # This class was introduced in 0.7 but later renamed to CommunicationMethod class ConnectionMethod(object): """Constants describing the possible methods of connection to server. Retained for backwards compatibility but DEPRECATED. See CommunicationMethod.""" UNIX_SOCKET = 'unix_socket' """Unix socket communication using a filesystem path""" INET_SOCKET = 'inet_socket' """Inet socket communication using a host and port""" speech-dispatcher-0.8.3/src/api/python/speechd/_test.py0000664000175000017500000001203512522771346020036 00000000000000#!/usr/bin/env python # Copyright (C) 2003, 2006, 2007 Brailcom, o.p.s. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import unittest import time from .client import PunctuationMode, CallbackType, SSIPClient, Scope, Speaker class _SSIPClientTest(unittest.TestCase): def setUp(self): self._client = SSIPClient('test') self._client.set_language('en') self._client.set_rate(30) def tearDown(self): self._client.close() class AutomaticTest(_SSIPClientTest): """A set of tests which may be evaluated automatically. Please put all tests which require a user to listen to their output to the VoiceTest below. """ def test_callbacks(self): # TODO: This needs to be fixed. There is no guarantee that # the message will start in one second nor is there any # guarantee that it will start at all. It can be interrupted # by other applications etc. Also there is no guarantee that # the cancel will arrive on time and the end callback will be # received on time. Also the combination cancel/end does not have # to work as expected and SD and the interface can still be ok. # -- Hynek Hanke self._client.set_output_module('flite') called = {CallbackType.BEGIN: [], CallbackType.CANCEL: [], CallbackType.END: []} self._client.speak("This message should get interrupted. It is " "hopefully long enough to last more than 1 second.", callback=lambda type: called[type].append('msg1')) self._client.speak("This second message should not be spoken at all.", callback=lambda type: called[type].append('msg2')) time.sleep(1) self._client.cancel() self._client.speak("Hi.", callback=lambda type: called[type].append('msg3')) # Wait for pending events... time.sleep(3) started, canceled, ended = [called[t] for t in (CallbackType.BEGIN, CallbackType.CANCEL, CallbackType.END)] assert started == ['msg1', 'msg3'] and ended == ['msg3'] and \ 'msg1' in canceled and 'msg2' in canceled and \ 'msg3' not in canceled, \ (called, "This failure only indicates a possible error. The test " "depends on proper timing and results may warry depending " "on the used output module and other conditions. See the " "code of this test method if you want to investigate " "further.") class VoiceTest(_SSIPClientTest): """This set of tests requires a user to listen to it. The success or failure of the tests defined here can not be detected automatically. """ def test_escapes(self): c = self._client c.speak("Testing data escapes:") c.set_punctuation(PunctuationMode.ALL) c.speak(".") c.speak("Marker at the end.\r\n.\r\n") c.speak(".\r\nMarker at the beginning.") def test_voice_properties(self): c = self._client c.speak("Testing voice properties:") c.set_pitch(-100) c.speak("I am fat Billy") c.set_pitch(100) c.speak("I am slim Willy") c.set_pitch(0) c.set_rate(100) c.speak("I am quick Dick.") c.set_rate(-80) c.speak("I am slow Joe.") c.set_rate(0) c.set_pitch(100) c.set_volume(-50) c.speak("I am quiet Mariette.") c.set_volume(100) c.speak("I am noisy Daisy.") def test_other_commands(self): c = self._client c.speak("Testing other commands:") c.char("a") c.key("shift_b") c.sound_icon("empty") def test_lists(self): c = self._client for module in c.list_output_modules(): c.set_output_module(module) print("**", module) c.speak(module +"using default voice") for name, lang, dialect in c.list_synthesis_voices(): print(" -", module, name, lang, dialect) c.set_synthesis_voice(name) c.speak(module +" using voice "+ name) if __name__ == '__main__': unittest.main() speech-dispatcher-0.8.3/src/api/python/speechd/__init__.py0000664000175000017500000000143212522771346020456 00000000000000# Copyright (C) 2001, 2002 Brailcom, o.p.s. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from .client import * speech-dispatcher-0.8.3/src/api/python/speechd/Makefile.in0000664000175000017500000004726612536424263020427 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/api/python/speechd DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(speechd_python_PYTHON) $(top_srcdir)/py-compile ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__installdirs = "$(DESTDIR)$(speechd_pythondir)" \ "$(DESTDIR)$(speechd_pythondir)" am__pep3147_tweak = \ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' py_compile = $(top_srcdir)/py-compile am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ speechd_pythondir = $(pyexecdir)/speechd speechd_python_PYTHON = __init__.py _test.py client.py nodist_speechd_python_PYTHON = paths.py edit = sed \ -e 's:@bindir[@]:$(bindir):g' CLEANFILES = paths.py EXTRA_DIST = paths.py.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/api/python/speechd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/api/python/speechd/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nodist_speechd_pythonPYTHON: $(nodist_speechd_python_PYTHON) @$(NORMAL_INSTALL) @list='$(nodist_speechd_python_PYTHON)'; dlist=; list2=; test -n "$(speechd_pythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(speechd_pythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(speechd_pythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(speechd_pythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(speechd_pythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(speechd_pythondir)" $$dlist; \ else :; fi uninstall-nodist_speechd_pythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(nodist_speechd_python_PYTHON)'; test -n "$(speechd_pythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(speechd_pythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-speechd_pythonPYTHON: $(speechd_python_PYTHON) @$(NORMAL_INSTALL) @list='$(speechd_python_PYTHON)'; dlist=; list2=; test -n "$(speechd_pythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(speechd_pythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(speechd_pythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(speechd_pythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(speechd_pythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(speechd_pythondir)" $$dlist; \ else :; fi uninstall-speechd_pythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(speechd_python_PYTHON)'; test -n "$(speechd_pythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(speechd_pythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: for dir in "$(DESTDIR)$(speechd_pythondir)" "$(DESTDIR)$(speechd_pythondir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nodist_speechd_pythonPYTHON \ install-speechd_pythonPYTHON install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nodist_speechd_pythonPYTHON \ uninstall-speechd_pythonPYTHON .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-nodist_speechd_pythonPYTHON install-pdf install-pdf-am \ install-ps install-ps-am install-speechd_pythonPYTHON \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am \ uninstall-nodist_speechd_pythonPYTHON \ uninstall-speechd_pythonPYTHON paths.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(edit) $${srcdir}$@.in > $@ paths.py: $(srcdir)/paths.py.in # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/api/python/speechd/Makefile.am0000644000175000017500000000066512233560613020376 00000000000000## Process this file with automake to produce Makefile.in speechd_pythondir = $(pyexecdir)/speechd speechd_python_PYTHON = __init__.py _test.py client.py nodist_speechd_python_PYTHON = paths.py edit = sed \ -e 's:@bindir[@]:$(bindir):g' paths.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(edit) $${srcdir}$@.in > $@ paths.py: $(srcdir)/paths.py.in CLEANFILES = paths.py EXTRA_DIST = paths.py.in speech-dispatcher-0.8.3/src/api/python/speechd/paths.py.in0000644000175000017500000000005512233560613020431 00000000000000SPD_SPAWN_CMD = "@bindir@/speech-dispatcher" speech-dispatcher-0.8.3/src/api/python/ChangeLog0000644000175000017500000004137612233560613016505 000000000000002008-12-17 Hynek Hanke * Makefile.in: Create conf/desktop/ directory for installation. 2008-12-10 Hynek Hanke * speechd_config/config.py (Tests.diagnostics.decide_to_test): Set port in ~/.profile and place speechd.desktop in ~/.config/autostart * Makefile.in (all): Handle speechd.desktop. 2008-11-26 Hynek Hanke * Makefile.in (maintainer-clean): Maintainer-clean does clean. 2008-10-15 Hynek Hanke * Makefile.in: Respect ${DESTDIR}. 2008-08-11 Hynek Hanke * speechd_config/config.py (Tests.audio_try_play): Use proper os.path.join for constructing path to the testing wav file. 2008-07-31 Hynek Hanke * speechd_config/config.py (Tests.diagnostics): Only try hearing test if Speech Dispatcher was started successfuly. (Tests.diagnostics.decide_to_test): Do not ask whether to start/restart but first try to stop and then subsequently start via /etc/init.d/ (this covers both cases). 2008-07-14 Hynek Hanke * Makefile.in (clean): Delete speechd_config/paths.py (install): Include prefix correctly. (sysconfdir): Define sysconfdir. 2008-07-12 Hynek Hanke * speechd_config/config.py (Tests.diagnostics.decide_to_test): AudioOutput method is the proper parameter name, not DefaultAudioOutput. 2008-07-11 Hynek Hanke * speechd_config/config.py (Options.__init__): Added basic description into help message. * Makefile.in (all): Typo in directory paths. * speechd_config/config.py (Options.__init__): Include summary message into help. 2008-07-10 Hynek Hanke * speechd_config/config.py (Options): Restructured. test_spd_say: New test. Handle SPEECHD_PORT correctly. (Tests.write_diagnostics_results): New method. Use TMPDIR correctly. (Configuration. (Configure.speechd_start_system): Allow also restart. Bugfixes. 2008-07-09 Hynek Hanke * speechd_config/config.py (Tests.diagnostics.decide_to_test): Also include configuration into debugging archive. * speechd_config/spd-conf: Do not call main() since it will be called automatically on import. * speechd_config/config.py: Typo. * Makefile.in (all): speechd_config/paths.py generation moved from install. * setup.py (speechd_config) New module. * Makefile.in (speechd_config): New module. Write necessary paths into speech_config/conf_path.py 2008-06-27 Hynek Hanke * speechd/client.py (SSIPClient.set_debug): New method. (SSIPClient.set_debug_destination): New method. (SSIPClient.set_debug): New method. (SSIPClient.set_debug_destination): New method. 2008-02-19 Tomas Cerha * README: New file. * speechd/client.py (SSIPClient.__init__): Docstring improved. 2008-02-04 Hynek Hanke * Makefile.in: New file. Propagate $prefix correctly. 2008-01-29 Tomas Cerha * speechd/client.py (SSIPClient.__init__): Use the environment variable `SPEECHD_HOST' if defined. 2007-11-25 Tomas Cerha * speechd/client.py: Handle TypeError while SPEECHD_PORT value conversion. 2007-11-22 Tomas Cerha * speechd/client.py (SSIPClient.__init__): Use the environment variable `SPEECHD_PORT' if defined. 2007-07-11 Tomas Cerha * speechd/client.py (SSIPClient.list_synthesis_voices.split): Convert empty strings to `None'. Docstring improved. 2007-07-10 Tomas Cerha * speechd/_test.py (AutomaticTest.test_callbacks): Test also the `END' callback, which doesn't currently work with Flite. 2007-07-04 Tomas Cerha * speechd/client.py (SSIPClient.resume, SSIPClient.pause): Send the right SSIP commands. 2007-07-03 Tomas Cerha * speechd/client.py (_SSIP_Connection._recv_response): Raise exception if the communication thread is not alive. 2007-07-02 Tomas Cerha * speechd/client.py (SSIPCommunicationError): New class. (_SSIP_Connection._recv_response): Quit if the communication thread is not alive. (_SSIP_Connection.send_command, _SSIP_Connection.send_data): Raise `SSIPCommunicationError' on socket error. 2007-07-02 Hynek Hanke * speechd/_test.py: Voice list test uncommented. 2007-06-26 Tomas Cerha * speechd/_test.py (VoiceTest.test_lists): New test. * speechd/client.py (SSIPClient.list_output_modules) (SSIPClient.list_synthesis_voices, SSIPClient.set_output_module) (SSIPClient.set_synthesis_voice): New methods. 2007-05-03 Hynek Hanke * Makefile (clean): Remove build. 2007-02-21 Tomas Cerha * speechd/_test.py (AutomaticTest.test_callbacks): Added warning. 2007-02-17 Hynek Hanke * speechd/_test.py (AutomaticTest.test_callbacks): Removed comment about Scope.SELF not working. Added TODO comment about fixing this test. 2007-02-05 Tomas Cerha * speechd/client.py (_SSIP_Connection.__init__): Thread name changed. (SSIPClient.__init__): Allocate lock. (SSIPClient._callback_handler): Lock before accessing `self._callbacks'. (SSIPClient.speak): Added more doc. Lock before accessing `self._callbacks'. 2007-01-29 Tomas Cerha * speechd/client.py (SSIPClient._callback_handler) (SSIPClient.speak): Removed prints. * speechd/_test.py (SSIPClientTest.check_callbacks): Wait for callbacks after canceling messages. (TestSuite): Class removed. (tests): Instance removed. (SSIPClientTest): Class split into `AutomaticTest' and `VoiceTest'. (_SSIPClientTest, AutomaticTest, VoiceTest): New classes. (SpeakerTest): Class removed. (get_tests): Function removed. 2007-01-26 Tomas Cerha * speechd/_test.py (SSIPClientTest.check_callbacks): New test. (SSIPClientTest.check_notification): Temporarily commented out. * speechd/client.py (_SSIP_Connection._CALLBACK_TYPE_MAP): New constant. (_SSIP_Connection.__init__): Initialize `self._callback' instead of `self._callbacks'. (_SSIP_Connection._communication): Docstring reformatted. The whole event dispatching rewritten to use `_CALLBACK_TYPE_MAP' and use a single callback function. (_SSIP_Connection.send_command): Docstring typo fixed. (_SSIP_Connection.send_data): Docstring typo fixed. (_SSIP_Connection.send_data): Return also server response data. (_SSIP_Connection.set_callback): Argument `events' removed. Docstring updated and extended. (SSIPClient.__init__): Find out and store the client id. Register callback and turn on notifications for all supported event types. (SSIPClient._callback_handler): New method. (SSIPClient.speak): New keyword arguments `callback' and `event_types'. Docstring extended. Convert `text' to `utf-8' if it is a unicode instance. (SSIPClient.char): Convert `char' to `utf-8' if it is a unicode instance. (SSIPClient.set_notification): Method removed. (SSIPClient.close): Only operate on `self._conn' if it is defined. 2006-11-05 Hynek Hanke * speechd/client.py: IMPORTANT: On initialization of the connection, new lateral thread is started to handle the communication. This thread is terminated when the connection is closed. (_SSIP_Connection._com_buffer): New attribute. (_SSIP_Connection._callbacks): New attribute. (_SSIP_Connection._ssip_reply_semaphore): New attribute. (_SSIP_Connection._communication_thread): New attribute. (_SSIP_Connection.send_command): 'or isinstance(args[0], int)' added back again. This is valid SSIP. (SSIPClient.set_notification): New public API function. * speechd/_test.py (SSIPClientTest.check_notification.my_callback): New test. * speechd/client.py (_SSIP_Connection.__init__): Start the self._communication method in a new thread. (_SSIP_Connection._recv_response): 1->True (_SSIP_Connection._recv_message): Renamed from _recv_response. (SSIPClient.__del__): New destructor. 2006-08-09 Hynek Hanke * setup.py: Use /usr/bin/env instead of /usr/bin/python * Makefile (install): Install with correct prefix. 2006-07-13 Hynek Hanke * Makefile: Only attempt to use distutils if python is installed. 2006-07-11 Hynek Hanke * speechd/client.py: Typos in docstrings. (Speaker): Docstring clarification. Method say() removed. 2006-07-11 Tomas Cerha * speechd/_test.py: `Client' -> `SSIPClient'. (ClientTest): -> `SSIPClientTest'. (SSIPClientTest.check_escapes) (SSIPClientTest.check_voice_properties) (SSIPClientTest.check_other_commands): `say' -> `speak'. (SpeakerTest): New test class. * speechd/client.py (Module): Docstring updated. (Client): Class renamed to `SSIPClient'. (SSIPClient): Docstring improved. (SSIPClient.__init__): Don't initialize `self._current_priority'. (SSIPClient.set_priority): Added docstring. Always send the command. Don't check `self._current_priority'. (SSIPClient.say): Method renamed to `speak'. (SSIPClient.speak, SSIPClient.char, SSIPClient.key) (SSIPClient.sound_icon): The arguent `priority' removed. Don't set the priority here. (Speaker): New class. (Client): New class. 2006-07-10 Tomas Cerha * speechd/_test.py: Import `speechd' not `client'. (Client): Renamed to `ClientTest'. (ClientTest._client): New method. (ClientTest.check_escapes, ClientTest.check_voice_properties) (ClientTest.check_other_commands): New methods. (ClientTest.check_it): Method split into the above new methods. * speechd/client.py: Don't import `string'. (SSIPCommandError, SSIPDataError): Docstrings improved. (_SSIP_Connection.NEWLINE): Renamed to `_NEWLINE'. (_SSIP_Connection.END_OF_DATA_SINGLE): Renamed to `_END_OF_DATA_MARKER'. (_SSIP_Connection.END_OF_DATA_ESCAPED_SINGLE): Renamed to `_END_OF_DATA_MARKER_ESCAPED'. (_SSIP_Connection.END_OF_DATA_BEGIN) (_SSIP_Connection.END_OF_DATA_ESCAPED_BEGIN): Constants removed. (_SSIP_Connection.END_OF_DATA): Renamed to `_END_OF_DATA'. (_SSIP_Connection.END_OF_DATA_ESCAPED): Renamed to `_END_OF_DATA_ESCAPED'. (_SSIP_Connection._readline): Docstring improved. `self.NEWLINE' -> `self._NEWLINE'. (_SSIP_Connection.send_command): `self.NEWLINE' -> `self._NEWLINE'. (_SSIP_Connection.send_data): Use new constant names. (Client.__init__): Initialize the `_priority' attribute to None. (Client._set_priority): Only set the priority if it is different than the last priority stored in the `_priority' attribute. Set this attribute on change. (Client.char): Replace the space by `space' as required by SSIP. (Client.__init__): `self._priority' renamed to `self._current_priority'. (Client._set_priority): Renamed to `_set_priority'. (Client.set_priority): `self._priority' -> `self._current_priority'. (Client.char, Client.key, Client.sound_icon, Client.say): `self._set_priority' -> `self.set_priority'. (Client.pause): Improved docstring formatting. * speechd/util.py: File removed. 2006-06-28 Tomas Cerha * speechd/client.py (SSIPCommandError) (_CommunicationError): Renamed to `SSIPError'. (CommandError): Renamed to `SSIPCommandError'. (SendDataError): Renamed to `SSIPDataError'. (_SSIP_Connection.send_command): Added an assertion on the 'scope' argument for certain commands. (_SSIP_Connection.send_command): `CommandError' -> `SSIPCommandError'. (_SSIP_Connection.send_data): `SendDataError' -> `SSIPDataError'. (Scope, Priority): New classes. (Client): Derive from `object'. Some doc added. (Client.__init__): The `port' default value set to `None'. (Client.__set_priority): Renamed to `_set_priority()'. (Client._set_priority): Use the `Priority' constants for assertion. (__check_scope): Method removed. (Client.say, Client.char, Client.key, Client.sound_icon): Use `Priority' constants for default values. `__set_priority()' -> `_set_priority()'. Docstrings updated. (Client.char): Don't replace space by "space". (Client.cancel, Client.stop, Client.resume, Client.set_language) (Client.set_pitch, Client.set_rate, Client.set_volume) (Client.set_punctuation, Client.set_spelling) (Client.set_cap_let_recogn, Client.set_voice) (Client.set_pause_context): Use `Scope' constants for default values. Don't call `__check_scope()'. Docstrings updated. (Client.say): Only set the priority if it's not a 'MESSAGE'. (Client.set_rate, _SSIP_Connection.send_command): Use the `Scope' constants for assertions. (_SSIP_Connection.close): Unset the `_socket' attribute. (PunctuationMode): New class. (Client.__init__, Client._set_priority): Use the `Scope' constants. (Client.say): Don't set the priority if it is 'MESSAGE'. (Client.set_pitch, Client.set_rate, Client.set_volume) (Client.set_voice, Client.set_pause_context): Use `isinstance' instead of comparint types. (Client.set_punctuation): Use the 'PunctuationMode' constants for assertions. 2006-06-27 Tomas Cerha * speechd/client.py (_SSIP_Connection.__init__): Initialize the `_buffer' attribute. (_SSIP_Connection._readline): Read data from the socket using a buffer, not character by character... (Client.__init__): Require the `name' argument. Changed the default value of `user' to `unknown' and `component' to `default'. (Client.pause): Cosmetical change. 2003-11-20 Tomas Cerha * speechd/client.py (Client): Changed the port number. * speechd/_test.py (get_tests): Don't set the language. 2003-07-22 Tomas Cerha * speechd/_test.py (Client.check_it): Added tests for `set_rate()' and `set_pitch()' methods. (Client.check_it): Added test for Czech language. * speechd/client.py: `Speech Daemon' changed to `Speech Dispatcher'. (_SSIP_Connection): New Class. (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE) (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED): Constants removed. (_Socket): Class removed. (Client.__init__): Use `_SSIP_Conection' instead of plain socket. (Client._send_command, Client._send_data, Client._recv_response): Methods removed. (Client.close): Close `self._conn' instead of `self._socket'. (Client.say, Client.stop): Use `self._conn.send_command()' instead of `self._send_command()'. (Client.set_language): New method. (Client.set_pitch): New method. (Client.set_pitch): New method. (Client.get_client_list): Use `self._conn.send_command()' instead of `self._send_command()'. 2003-07-17 Tomas Cerha * speechd/_test.py (Client.check_it): Pass a new `user' argument to `Client' constructor. * speechd/client.py (Client.__init__._Socket): New class. (Client.__init__): Use `_Socket' instead of `socket.socket'. (Client._recv_response): Use `_Socket.readline()'. (module): The commented out C library code removed. (Client.say): Use new priority names. (Client.__init__): Arguments `client_name' and `connection_name' replaced by `user', `client' and `component'. Send `self' in the 'SET self CLIENT_NAME' command. 2003-03-30 Tomas Cerha * speechd/client.py (Client.SPEECH_PORT): Updated docstring. (Client.RECV_BUFFER_SIZE, Client.SSIP_NEWLINE) (Client._SSIP_END_OF_DATA, Client._SSIP_END_OF_DATA_ESCAPED): New constants. (Client._send_command, Client._send_data, Client._recv_response): Use them. (Client._send_data, Client._recv_response): Rewritten, to handle multiline responses. Return response data as third item of returned tuple. (Client.close): Don't send `BYE' command. (Client.say): Don't return server response (isolate client from those details). (Client.get_client_list): New method. 2003-03-29 Tomas Cerha * speechd/client.py (SPEECH_PORT, RECV_BUFFER_SIZE): Moved to class `Client'. (Client): Documentation added. (Client.SPEECH_PORT, Client.RECV_BUFFER_SIZE): New constants. (Client.__init__): `SPEECH_PORT' -> `self.SPEECH_PORT' (Client._send_command): Cosmetic changes. (Client._send_data): Cosmetic changes. (Client._recv_response): Commant added. `RECV_BUFFER_SIZE' -> `self.RECV_BUFFER_SIZE'. (Client.close): Documentation added. (Client.stop): New keyword argument `all'. (Client.say): Documentation added. Return the value of respose code and message. 2003-03-27 Tomas Cerha * speechd/client.py: Import `string' module. (SPEECH_PORT): Added docstring. (RECV_BUFFER_SIZE): New constant. (_CommunicationError): New class. (CommandError): New class. (SendDataError.data): New class. (Client.__init__): Make `client_name' and `conn_name' keyword args. (Client._send_command): Convert `args' to strings. Handle server response. Return resonse code and message. (Client._send_data): New method. (Client._recv_response): New method. (Client.close): Before closing socket send a `BYE' command. (Client.stop): New method. (Client.say): New method. * speechd/_test.py (Client.check_it): Test the `say()' method. speech-dispatcher-0.8.3/src/api/python/Makefile.in0000664000175000017500000005024212536424263017000 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/api/python DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ChangeLog \ README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = speechd speechd_config all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/api/python/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/api/python/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/api/python/Makefile.am0000644000175000017500000000013312233560613016751 00000000000000## Process this file with automake to produce Makefile.in SUBDIRS = speechd speechd_config speech-dispatcher-0.8.3/src/api/python/speechd_config/0000775000175000017500000000000012536424375017754 500000000000000speech-dispatcher-0.8.3/src/api/python/speechd_config/test.wav0000644000175000017500000004200212233560613021354 00000000000000RIFFúCWAVEfmt €>}dataÖC`ÿkGþ†_ÿÞýð'þDFcýE¤ýsÿ¯»üaŒœC‹ º¯úúmñ†ëÓø÷ýÛýd <*ìûa݆ÿ–ü*Ýü®ù< Çï l´‚öñò(ööL÷]þ“þ°ûœø0ýÍ 7äþÈåþ|îqï òœìü¬¥B"²ÎÖ*ýü’ÿ;ÿøöÿ÷6Ì) 'øBíÉçñë:ðØøJ]ÍuºýÑï«ò€ô£êécìpéìì¥F ˆ\)&f„ õ€µ–° w¡ÈÓ LŒ’ öý÷ôòçŒáýá×ç“öuÍ ˆý Éûaì^èÄä÷äqì ñrñÏûíjH®©w´såý„ ÿß÷¯úù®þ ç Ï "Qû‚ëCÜݯâ³í þ ÎS# qûlòÇî'í«ïÀó^õøCš ? zg#JÑ.ü©./+þÕú#ú}õtþ¿ µ Xg¾ùCäœ×_ÙÍàGï˜@N7ÂðÉé!å×åœí>ò«ñHús‰b”!„vÆÛ¢FQÿxrû€úÖ? ‰ŽþdôWãtá/ç©ï!ü¨ ÒdxØ àù;ïÆí‡ìaï‚ô«ó%óÌýÌí‰p"AqE*,ûØÿH؇ÿý³õyüOç íÿdûí®ápâ_ê¢ösØ?lJ¡¶ñ·ííˆë³ïÍó†ïöó(: £ ö!ê±Øý)P~ÿÿùùwù." qêaùÆêcâHâ[ìèøòÑ$zñ ûù‡ïLíöê¢ìÐñnðî4ù¥6‘(uRÅ[ýVþ[$TþýS÷ÑùâþÁËð©þ†õSéã[é²õ1ÿU Èóhõ,ïtì:éí9ò îžðÐý­Ù Z!C#Ž]s KþB½ýòü ø1õËúÛ¾ÿ.þCðeä'âvì"øc`¡æ½ÒLô!ðûê¡è+î|ð îh÷ÜVjô# í4 X÷ÿ Û‡ý°ýà÷þø#DË ÄÐ`ü÷ì¨ãæìñ€ûIÇK úòÕëæˆèDïÏíwð–üŽÅ•T šmüâÿ]TþÉý~ù±ôÛù«âö ¦öé äŽìc÷uUòÛîœø8ñ,é{æ íñƒð?ù­ºÑS"/íÌ ß ÿ@=jý¾ü#ö°õçû«–k{þOï:å_æˆñCúd °R )üNó·ë äÿä\ërëPîù¥þªU·jçAxÿ¦¾ÏobýFø­ûû” } …túní%çîiøÄ… ФO ƒùdòéEã©ç²ëëÈòžü1# š–biÿWüÃYÍñù}ùëþn¯Ì&£Qópè%èÛñðøh› ÒËM [ý‡õªï›ç4ç'íçìžï‚úòÿgà p=6Œÿý_Y§0Aù±û™ßÁ ¶üEîuæ¤ëYôÞû²Œ@æ2ø¡óŠìàåüè&ì8ê—ðÝù¡ý¢ XÀèè ªÂÿt3I»™ûñøDý¼Ã­ R>ö¬éêæ/ïö·. %êþ8øòDê)è™ízí°îaøÞý¼g t5Õ>ÎÿÙþÔýþl÷Eùùþ æHý¸ï]æ°éÏñIù'" ûÚ'où¸ó ì¾å é'íìëzòáû‰þ= GÜÇ+. ÷–Åž¾ÿnü-ù1ý‚\uÐ ½ÄùøìáèÛïeösÿ¨ V¯P/÷yñXéQæoë³ì'î7÷RüÕÿ '†Áá¶ÿú2¡°ýžùDúÿýIóî¬ÿ¯òè ëhòàø®& Ï! ùü“÷ ñêë®ïøî±ó™û®ýñùq(.þóYà»ýú˜ü•¨l "múíç*íŽó%ü, ð’ùeô›ìmé÷íìîáïû÷´üùÿ3ij³ " —€4þùx„úƒúøþ%¤ZV76óýçAéqððöŽ ðƽrü ÷­ðÞéhëbï¹îqó;û?ýw#ë( Ð t°ÿ|aß[SýÊùaüSC ³ úíbçdí³ó'üÝÒ „¨Œùqô×ìËéPîCï'ðøÃüþÿì,1J­á ‡îëc”ú«úÿ#”@2,kóèÏéäðH÷¨ Ðq‰…ü?÷ñbêêëÐï*ïßózûjýšÍ`ÐPš _ÎÿŸ]à[týúüp@ ûºúqíèàíôfüж Ì*•²ù´ô=íOêÐî¸ï’ðbøîü#Ю¿øe® u âêZ¸úÔú(ÿ" &¡óûè]êFñŒ÷¿ß ?‹üe÷SñÛêZìð„ï8ô©ûŠý¤mÑ_æB ,ÏÿŠ3Ò9ký(ú®ülæÒú«í„èHîRô–üЊ p³eÉùßô‹íÄê;ïðãð“øüü#’=™a U—îÊÔBÄúîú<ÿ \ûØ·ókéàê›ñË÷ȸGó”üz÷ŠñGë¿ìoðÞï|ôÆû¡ý 6í„ô Ñÿq·hý?úÄütû¸³…úõíé³îô±ü¾b RGØùõçí5ë¢ïjð4ñ¿ø ý0^ŠÀ/¤, <‘Ó³¾.ÝúûBÿí<ÑšêÿÜóÙégëûñø×‡ú"¦•üŸ÷ÈñÆë:í¨ð(ðÚôèû®ý¯¦œœ æàÿcã«ùbýZúåüÛŒbúAî–é#ïÖôÓü°> Äç êùDõ6î¢ëðÈðñõø$ý;%üCÊCï(޽Ÿèú2ûPÿ̨\âÿôIêÝëMòPøìn·´e¡üÍ÷ ò*ì¯íñ„ð)õ üÂýª1ÿ¾C ¿ÞÿGº•ÏVývúõüwÃs[4ú‰îê‰ïõý¨ c| øþùwõ‘îì_ð#ñòñ#ù0ýDàh»]ó³ ’±v„ôáú•ûõþ r.ÿ`ómë>ìkóø°œÓ w2ßü—ùÍò—í¿øyù´ìîxêî¶µ— sÑ ï `þ¨ºðþýT÷Þø• kÊý!òßxÞæ§ëÁøÒo W ð ôüƒ÷óýÞAß™ãqß’úVoä+5YÓñÞ7þr¥úém 1 6 % Ù]øÞðPñðí‰íNñ#óü±òú§ÿOñMæ)äÛŒå¤ùK€:ó ›³{¤8 ~öÜÞòTãŸÞ†åEóÓç {Æû#äxÛÄÜáÓîÍúJ7 'ò6 "!àôBû¹%üÓŒ¡Ÿ9x³2øðèçÞåVìÊ÷2 ëC¬£ ÜúòîÃáuÛ â²çöD ƒ$ 3lÙ­Võ*ïbôañdírïózÿ¥˜€ 8÷#ã Þ÷ãù™aô!]_ýÆì'ëìéhîù•ôò!õ¡ñø]4’Kª A³ýCö/îççñÂüû"û”ú~ï[ïvúéþV3'! [b =öòèí¶éIðCòLù ñ  ˜ûøûôÑôóZ  ýeùÂðûÊð¨í˜ä8Õ;Ø$èÏõ_ £*š0)'µ þ›ñŒì®ïOö‰ô>ôéúsüL 1$t#æ« "÷ïò‘ïsñÁó¿ö5Ò‘üñ©Þ°Ð¦Ô+åçó½±{X –jÒýŸú‚þŠ÷íîCýÂþ(E#d»T5~  ýÝüîlåèí{ùþy\!ûÙò¥î˜ñGù[¥  ïëóå`éÕæRõ Duß!ú#""'ÍÚ Å£þþUü‹þ™ü üç 9àó³êÇáÙQâcö>¼¶$ón =õïâÀܬÚFÞÊã(è™ô[,>223œ&â!c!å ]¸@û(óöú@†×½ ±û å~ÙÜÛéýP&Ãdò*ó‘â¤áUâVÛ¢å>òKöR Æ´Ýà6ü Œ [Sù6ùFÿ–C ½¾íö¼êÃéqô;I «Ø 9àø4î…íì¨ò¡ÿüú}÷@ûžúvĦ Yç£ü•ýçh]L 0ׯ â ° þ±íÙä¦è=ô5¤Ë êõ(äœÒ$ÓXßläfò™ ˜%?Ó ¥ñ ð;÷Dö›øüúÙö ­1$ß ò\ç{òýA¨Rœþäü÷<í„ê í›äìÞ¢ç ñ¡~}+Þ ÜüÀû¹øOò î|ìÈî^ø/ì döúNâÚ Øïô ¾ýÈó˜æ9â•ëðUôFc÷ ä ¦ê…0M ¾¼:ø€ô2øÐùýaÿ+ø¹ë­äéùøÌ >¢] ¡{ýô¦ï…è€ìýì“é§ò¸ù â%“à}ô!ö4ûý9ÛþQv ó Õ+þ¿êóÛßxèjólÏdS Õ*ù¬ï ð¨í¡îûmÿB 6ãY!z  B #û"ïCíÞ÷zô¢ ø Òÿ¤ëàå“ëþñlû“ Êrùkóûìéµó¿ö”ô&þ"›l> ÒsÕ ½ÿÐøÐHü¼‚…‰ ¸÷Öëôë+õ8B ˜ èk yúòî'êáéâöérë­õ3¥ ‡!Ç–‰ R\üW÷ýv<± I üFéKâCéóÚ †I Aûûò…è«æ‡éÈéÂñ(øÎý;ù%Dÿ¨_æç´úþ»tæÓcÿßï·èîsõñý@ %žRù]õíóìœðîeó¹ùjü tÓB•\BdûSýZä0 ³$·ï¿æJëóóËþn"ü^ø<ò~é"èžíYî¥ôòülðY!B ždÿGè$_Õú†þTƒS × !ñ9èùëÕóÍý¸Øûrû3ö‚íê™íìŠð ù¹ü ±©^b)†Ilÿ˜øÓù‡à`­ …‹ô+êÛìÑóÆü®fÒ~ pû[õéì¢éï"ïkó‰ûWý¡ ÐÜ­zÎqMM?ÐùZùjÿæ;ÙQ>ógèÐëõ‘þÛø¿’ .ü÷àî&ê¿îNîYñ(úŠýH v‰üüãBþrsä‰ü×üÒÄþfC§òXçÂèQð|ú»u D#2ÿ ùñð°ê@î8ïòuúyý&k‚|»Ê'  ‹ùþøê˜ 2÷YéKé®ï øYí 2 Qý'÷ñ¬ì‰ðMñóûú)ý¨eÅô,=V§B²#ý¡úwÿÄÈ’g÷Të€ëó,û¥ L Hüûõ6ï°èí)ïêðûqÿЏCz]¡ Ÿ›Ò‹™Düún¸[ 4T÷Ðè¸çïLøD ô*·÷ÔðÕè"ë²íØîõöXû›AÄ2¼. .<ŠÔýnú¹ÿVN$DÜúíÔêzð‚÷ÞÓ˜ [lùô!í»îãïxïØöRú’Uš’ ˾©{ÿÈúÕþ p½ÉRûŒìCéÁïRø,’ Ø@ñÿuö6ñúéQì…ðñHù1þlSן [m “hÿšüÏ g~ üÍîcêÔï~÷^qDY:Aúõbìúëî•íAõûµ*_ }+ §ƒ÷E.Xý–øýb€õ Ó Éÿ6ñŽëäï˜ö>ò;ï™;ùTô¶ì7íñðð!÷ëûƒþj ¯½O0 ïYà€”þøûJs>þðëJñ„øR‰ 3°íú öÔíÝìðxï…õQü B˜Õ8 „ÿ¥XÎkcü<þò:JFhý¹ï|èÇìÒôKþPŒÒîÂü²÷éîiìÞðÚð›õWü¾þa ÜÕkìÍlœþJù¾ûêÎ9 } .ò‡éHì®ò÷ûÒ dû¦÷ñÖîœò1òôõüUþ hÖ +ªÅCòï&û8ûöÿúoq<’ôCì´ïÓõýå ¡&ú[õî¡ë3ðÈð1ö(þþÿô ùA‹Òû¥£ˆüRûLüqYÞq•~ò5éíëOóÞüDQ g üžö¢îÿé€îïýñ!ú5ýiÃtã¯ØöC¬©_üÃûà‹¬•÷öÄì‚íÊòªù! Ú¡ ÷ýdù-óÍíCð&ðøñØø=û™6¨¨¯GÔüÏëü!û€ 0ˆ½öøë íÝóÛûÍÙ s iû>öŠðòë‰ðAò²ôAü¡ýw›ô  Ý ÿ+LÖŽ2ÿ]ýV¹û/ùœíDí9ó"ú¼N É oÿ«ùóìííïàðüøÞü~s‹†ŸÿÕ‚>¾ûDúŸÿ§H? Ë’û[ï{íò9úM9 o! Ûþªø‹óµí~ðòó`ù_û,éF™›ß Îg5p ü„ø}ým[«‹ú§ï ï‡ôeûÑh ëà âøù§ôäí<ïUñôñzùdýM¹&x %±ÿ0³Žÿÿäûæþ˜6Jú²í%ë5ñ‚øœ• ÆŒjû¼õ îÃï¼òxò.ù¶üAüÔï Q²“T1ýúéþ›ùQZüZïúêQïeö(ÿV„ • çMû;øòðMñô5ó~ø«üaàXï Ø (¶QUÿâù üêàñí‰þ¦ò®îpò°÷fÿ ä 7 XÛø½ôjîÑî¤òôKúªþ ¥‡Ð:Ð èâOc ŽÿzûeþÙt’=üxðòë²ð øz:¦ˆC:úõRîî¯ñIñ©ö]üSÿá †ûtp êR×1³iÔû'ý¿gMK_»õ²ïªñòõ¨üªÃ Š âeýŸúñósñìóó3öìúý­ú…  ïg_(e>üÜýYR£µÿ‚ö±ñ•ôcù‡ÿÝ äÝúšø?ô·ó2÷Í÷ úÀýkþ;H Y f)ÿM¤¦/?ÿžÿ p±žZZùKôØõùìýÏQ „þZûöóAõýõ øvýÿ›T ÂtUþþÿ²rJÿúüšý,­8öë üêö+÷˜úíþÎ[éfßý=ü†ùÛ÷ïùèùYúMüŽüÝ”]sLD b« ÿ üTüæþ\¹œÜHýìú?ûDý$ÛÄYQÿ…ýûÀøôù«ú"üÚþÓÿeµ8Œ3ÿ9¡—ôÿ`þvÿ-÷ÿ!dÿíû6ù?ú1üèþ©”«ß¹þsüxûŸüµüNý™þµþö•hDEÝÿ'ÿ þäþ=ÿ°þ^ÿ"«íBžýÿú›úìû`ýêþÒ\¯ÝmEôþJÿÿmþ;ÿ-"& ±dÖ `p¦¿þJýÁýûþÔÿôb›¿ÿØþ9þþ#ÿDÿÿÿ_þÕýèýaýSþ<åC† 5Ïs’´P*ŠVß<“~ÿUþfý‘ü ý¯þMð’Cÿuý%üýügü˜ÿôý þpÇ–. ÜÃú þ­>ýÐø•úsýîùüÍé &íýý{÷îkíTñÄù Û¬ ­ Ƶ¸e_y èó)ð3ú¹÷ñ©ô•ù%÷œôöCúÏü3ùqøaþþ}û°ý®ÔÇô  –·˜üà F ö÷î/ùù´ìÑå’éËìKïô¥ü?íüDûü ýÀ EÚ¸›âq ú?¡ö”ÃùÈê¼é+ì5ìyð×÷#]ºûXô!óLö ýâüþ[ OÿÌ Âöþó†¦ôhû "¾ï·èhêëøíó{þpõÿñ÷ãþM Y tCMþ„•ßÿÆöz +þÞùºU³ó²åVååéæ#íO÷¸s.ý1ù‰ûŽ&-|ù€ øþSp!  óV’o üO 'úÔâwÞõâçî—õVgþÓ÷WùˆÿˆØÿçŸîü‰„޼õHúe¼ óöùJëà™äêÜñ¯ø×¯ )ïûd÷F÷®ûù.òrù* ïÐïÛnú÷ú 7ùó[øôétêÈêFí¤ò~ú|`ñú¼ôèò¤õ/÷‘óøq ¥ À{âk1ô§0> í5 …jdê.éÌìãíØïžõ3 üõiôöø/õàõ?mÏÒ {"@FùãÿWŒÁ— _L!õøêë—è çôéö\þûõïjï„ñË÷eø‡õÕüÞ 1Mh5 Þ]TŠ Í ‹¬ù]çnærç'çØèlô€üÐñ+ð,ïÑñSô±ñö(ô »Dd&XùV`G˜ ô)2?ïzë»ë^éçöëÖø›ùŸð¶îPï4òÒö5õ*ôoÿdY {2 Þ!>ûÓ: C 1Z ôìtî‡ì²çˆéz÷Fý,ô¡ð6ñó<øùÕ÷íþè”m¦·w$kþ†{ ’õ­Cþ’îÃí‡íÙè¨æ ñéûö¿ï×î‡ðù¶ýÞú)ü aþÈ$!]&ÿ, Š¡ Yw ±,ìÉç|èUç„æÔï2þ-ýèõãóññÿõ#üšûÂú& Ê.$lãø­þÔæX ö‰ë±ê’è–ãµå¥ò÷oñlïðxô©úëüÑü«)Ç ãgfpg0SxkæøLìÆíâïÂíwìÊôÍúô ïîüï[÷îüþµ » yT¡ø Øû¸ >= ñ 2|4ðŠëÐëêNåê×õÂõÏñçñó ùŽ3ÿùRË ÔýH Ã,ú# moWö”JóŠê¦é0ê¥èJëG÷Tû´öôÚð°òwúyþ›üé_ɽý©RUEÑ}fô ¼úï–îXï/í€ë…ô†ûœöCóòòòhøëýþ¢ýi ª¥ øò Ç -i ;Ú•ý Ö ýï¾íãð“ò<ð‡ôIü¦ø—ó6òªñ…öýÿ¬üYúÇ–©ü~"« ÑÁƒÿ>ôÖëÂêÁëÉèdêáôsö*óûó¥ó~öüþÌÅÿÈ: =4á„ t’1'„ °!ø'îxìäî´î÷ìüô/úHöäóPñxðõõµüüéü¹ ›äàYkü hò Ù¸ -ªó@îFîWí¤êgñÇú(úò÷¯õò?ô·ùûÿøs" HÓ;á¥3ã `ÿ1î \önî ðKó`ðaòjû>û‰õ)òðóòžúµÿ&þˆÅÆ8SþåÿªÅ÷7Š þkñ¿íðQîì%õXùéõ£ô”ò1óAú%)ÿ~ý 7Q©u\õ so zŒ/þì (ºòëíOð ñîÿóÌûú¾÷“õMóöªûPý ûçÖä æ M—ÈmÙê Ùoõ%íí>ï^ì:ïù ûüù¿÷6ô^õþù'ýàû>0-˜Ì±]G{¯®_ýG1 ûÆññ²ô²ñSï¯öúIöÕó™ñòiø ÿîÿÔÿÏ B ±Ó½• Óþç%A ·}|óUì4í)î•ëÇñšú¸ù¯ö.óñ4õ›üuÿýùcy ê(\=ÙŠ ǹ ½´öòîfîNð îðzøùÔõ¾ôýòÜô&ûSýºþ3 Mv¤E@[Qr¿K£é Å âûÂñÙïÞñ)ð.îìõ¦û_ù/÷†ôìó÷–úòùÏú¡ üyg mþj°=|ü‰ xõò—ô†õ•ñ{õˆü¨ú"÷Ïôóòöõü[ÿ1ý7S 7} ðTÐÿÜ«Ü ¾R- Å–ö™îšíð…íï·ùþû(ø,öŸóøô7üäÑÿ¨ZÙ婯›3(… æ 7 ò ôý”óôî4ï¶íìôú“÷jö®ôFôöùB8ÿþóïãhß5 ¸T ä ®r¤ ÿQòþíBðñ^ï/õ-ýãúæö ôñ3ôºùbû@úÓH¥ A|û1ò— Èÿÿ Ž÷ ñPò]õÎñ}ñÝøúÜögõ=ôÛö+ýþÿ‹üÿƒ mÚæC‘Ø[»ÿ K } Ýýkóðrñmïœí·õíúø"övóCòôöYþrÿaÿ € i‰F# ¨þBîIÿO öG÷hñbñ ðîóuûûzøÏõ9ôK÷ýüÿˆü‚k Ô!þÔŠúž Uï ugŸ Ãöûï¨ðºòñÔóòûPý6ú÷Cô×õúÂýÈûjþÅ ý›WQ‡ÿ_ ¢ óžÿ² Ñ ˜üüñðïÃò£ñ?ðF÷®ûùröQõ-÷¤û|äÿKþJlýŸ #Ž ùþ Ÿÿôæ õIðãñ(ógðÄóÄùò÷yôLòºñQõ°üáÛþ<€lBL ÷ %Ûõ8 hÛô JùVòŠðMðûì«îË÷íúmùžøQ÷˜÷®úµýïú>üà0 ÄH»Á‰·D I ýÃóÍðÃòûñºðç÷óüRúÚö?óÕò"÷KüíüƒýÇT(•ƒžª'þ°Ýžþ Þ ºÂöåñó°õóÛöLýûj÷tõõ~ø3þ×ÿIü4à ¼ A … Îë¾ € þ ½€ùkòÀñïô§ò‡òú*ûN÷¿õ]ôöþû¹4ÿÏÿ ½/™¹ýyŸ ŠÎW / zü°òÓîèïïî÷õoûAúFúøø,øYûÿêýÓü]¥šÞÿ" ±X ={ êþFÿ[’ ÷®ó}õëõ¾ñ§ô¦ú_ùV÷¸õdôi÷ùû›ý½ý‰lR -P zlàÁ ü ÿfa $ú»ó¯ò[õmô}õ¤ülþüÝù+÷­÷?ûÍý8üðýt +¹Ab|ï? PZ¿äÏþj÷ýôJöºõ?ô¥øqûOø*öxõ§ö*ûá±~ <!ÿ^pݧÿµ} ´9\U {9ú¥öÂöröÏôs÷Óû`üëûhûûü¥ýOý ûþUÑ#±Uý À¦7 Ì€¯ƒ)ü-úÇúnû´ù}ù³üÂýäüóûêúûzü§ý ýÿä/zvx ? ª sýJÿkÌíûô÷Œ÷³ùû¶ú‰ýÀC,þâüîü›ý®ÿñÿÿ?Ê/¹û- *îÿ±:ÕÿGý3¤Bÿïü`ûBúsø€øãúSû@úMú!û‚üz3{ö£Ds;éCm‹¶<oýkúºùæùäùoûœþ1Eÿûý‚ýøüÜüýúüWý„ߟW©"øpÚÆÄ^þþ9þîýšþnþýØüýCý¹ýTþKÿ0}Üþƒýùþ8ÿJÿ¬†«’ÿYV‘ Â@ÿ¾þfþ&ÿ{½ÿ·ÿô2‹ÿ2ÿUþÖýMþ0þÿ„ËŠÈHþýSþ‘þÔý{ÿ–cï°ùÿwÿÿýÑüÏý‚þ%þÇýyýäýeÿž”—pkOÿšþTÀh€²óÿ&ÿ¤ÿ›þ‚ý°üÌü*üÝüÛÿ +›/úÿ—ÿÞþåþòÿÌÿEÿ•‘©ÔÿùJÏ+îäPfþÎý\ýÞû_üŒýþÚþçþªÿXe&MÿÁÿ  ,~âÎÿzÍ:ÿoÿoÿ‰ýzü›üqýÕÿI­ °ÿ’ý’üfýþÒþ*ÿ5ÿvê>µÖeÎwÿC£´ÿÿ§ÄA…‚ÿšþý1û2û[üý²ýŽþÌÿCQý}Ã¥ÿ!9ŤC®&1Ûÿàþ’ýGüôûhý ÿÀÿÿÿ+ÿ'þäý'þ£þ×þÇÿϯÿ$ÿ5cþEKÄû6öGÿðþlþCþ5ÿ»ÿUÿ¹þñþ²ÿõÿ­ÿþåý–þ+ÿÿMÜ2çd%&½ý‡üþZþý+ý€ýàþÁpC[Žÿ·þcÿõÿgôþ6×g‘6ýîýGÿ´ÿÁÿñia—ÿ4þwüüÍû©ûÎü‰ý¢ýïþ<l1ZCÖ@V$”^ÃÇß¡ÿ­þ˜ÿŽÿÎþÂþÊþÙþÿýîüný¿ý]ý“ý.þ‹þçþ*ÿôþ$"Oöpä‘$ËöœpNƒÿxþ6ýrüü_ýÿȼÄÿèþLþ­üÿûþý‰ÿ¶ÿ*‹Ô #{Rþ¹ÿ…dÿ0þVýàý×ÿªíŸfþ«üÓü:þ˜ÿ☶ÿÒÿ«Sªþeþ¯ÿÁÿÿ€ ²,áþ’þûý}ý ýmýiý­ýþÿâÿ†RÒÿ)3Q]Éíæ$2þ)þ¼ÿx¶ÿêþiÿ(ÞþÎýÙþÿ÷þÀÿûÿhgzÿìþóþóÿ"ÿxÿr\ÿÍþæ¨Ë‰ÿUýšüòü:ý÷ü–ýÂþ, =Äð-ÿAþ%ÿ)ýÿA?)y}ÿ‚üÏüÔþÿ©þÿ¨ÿõÿ¶ÿRÿ8ÿäþ‰þ²ý8ý‚þxÿç5Ó—&kñböoàÿ±ÿÿHÿÿz\éÿPýü{ü¶üÅýìþ˜ÿ¼þ2ý7ýwýàýyÿ<+Ü}ïUÜ! eìþÑþ¸þþýHý‰ýÐü7ýþ$ÿ—7K, ÿpÿÐþýþx|pÿÂ5ŽÛCÙê4ÿëþÿÿÕþÃý4þ)ÿ½ÿ÷ÿÔÿØÿûþŽýpüºüVÿSWt-4úþ ÿ`ÿ²ýîüÿ ÿãþÝÿ'›-äÿ{þÿòÿq4&»þ&;Z)ñåÕÝþUÿMÿSþþiýoýýý•ÿ~ÿ ÿ¡þ©þ”ÿîß{ aºyO9dvgÿLþ;ÿ¥Ib›þHýÊûÔú;ü!ýgý‡þÿ?$,ê£ýz…ÿ¡ÿ£‘hÿ”\Ù$Ò‡.þ›üýÒýÃþþþãÿŒ_ÿ­þ þXýíýXþký!ýÙþîŽ ËüÂÚÍgÀþÿ ÿÌþCþkþÄþ–ÿ¸ÿÜþÖþÿÿÿAÿ¨q‡gÿÿ—ÿžÿÿøÿ‡}–w«—x”W\–-­ÿ‡þFý%ýþoþþTþTýÈüýLþ ƪÁO{ØØ|ÿ–þZ‚Fÿ8ÿéäqåP•ÿ­ýü¸ý×þüþÿÎþuÿÉâA½ÿ¡ÿÿ¦ýSýrÿóË5asvP~AÿlýŠýAþžþšÿß´„¢ÿ-ÿðÿJÏÿRþþ*ÿ’y´‚þ«ÿÅÿ–þ9ÿU)Îþeýýùü¸ýÎþOÿÐÿêÿbÿºÿ ¸tg÷à1åáÿGöéÔÿÿPÿ]ÿ®þ¦þUÿ‹ÿUÿÿ‚þŒý÷üRüÓûrüPýpþëÿ9Ž—Q OjÞÅ¡ %ÿýÿµ?ÿÿ˜ÿÌþÿüû7ûý þ?ÿ`5ÿ­ý„ýÔþ“þÎý'ÿd}-išôF™ÄÙ²ÿ¦þAþSþµþÈþfÿÇÿQÿIþý{ý²þ^ÿ.ÿRÿX»ÿ´ÿ‚µ6ÿÛÿÃTÿÿœ"ÿ‚þFþHÿ\ '2xÿÿÿ à%ÿ­þÊÿ¼ÿßÿd~¿Y$ÏÿþáüDþ¾ÿ‰ÿ;ÿ[ÿìÿ„¾ÿEÿyÿ…þâýñýòý¼þ™ÿ¯ÿp:°#åìþkÿýÞqSÿ»ýþüìüürûý,þ ÿýUi#3‚ÿ‚ÿ§Â„ÿßþˆè憴"Ò¢ÿhÉ~ÿÙþœÿYæÿvþûýäý<ý©ý½ýÀý$ÿÀÿ¯ÿ'$=ÉÊ[w13×ÿ’þjÿ¹ãÿKþ9ý|ü¿üþÑÿ$¡¶²¬þZþÑþlþsþÝþáÿìÿsüügÍ® õþ¡ÿSÄÿ ÿŽÿcÿþWþ’þ“ý0üøû)ü@ý(ÿ€Òþ”ÎyÿÝTÔÿÁÿSS¾gÙ.Aÿÿ2ÿWþ&ýýÍýWþ.ÿÉÿ5÷cVþOýsþÓÿÁÿ·ÿÃ87Bÿìÿma'…¢šÿþÿós©ÿ;ÿ0ÿ~ÿ›ÿhÿmÿ˜ÿ¨ÿ ÿ#ÿÜ(†ÿ‘ÿjãÚåQ›ÿZÿÁþˆüü¦ü÷ü!þ±ÿèO“…uÎÿôÿ_y–arûÿ_ë³$ý§ÿ ý;ýDÿûóÊ ÌÿñýÊüaü~ü€üvüºüMý”þÕ¤€­UŒP‚£ömÜè þùüQýŠý,ý‹ý7ÿìÿÿŒþaþmþÿÿüýšþ+üÿÙHè6›q¶Zõz-]ÿ©þ!ÿÿTÿ£þÈý:ý_ý0þæþÄÿ(©Ôÿþ½þÿþÅþ3Åá[ƒ£²pÅþþ4þ¤þ§þ÷þY5ºÿÿÊþ%þVþ‹þÿ~üü¨wèUÿôþÿ8þý,ÿ§}¦9 TuþþÀþXþþ×ýýÒýrÿ=ø tí§ÿòÿàë!Ú|’µÿÿžÿGÿbþýÎýVþ›ý¹ý›ÿ1Úÿ"µÿ®ÿ<"•ÿÿÿRÿœÿ›_¯ÿŠÿej ŸFðšÿ2þ0þtýÖü{ýÜýâý‰þäþÈÿ§$B¨ÿŠ©CãV.¥ÿ_ÿ:ÿ‚ý&ü€ü´ýÊþáÿ½Š¥ÿ~þ2ý„ý“þ ÿvÿ-êr\Rꉚñþ²þôÿµGûÿXÑÿªý$üžüýIý&þˆþFÿìÿÿ<ÿëÿ:ǘs~a€¡Q§r¤wÿ#ÿ±þéýRý²ý¸þÿ÷þ`þ¢ýwþËÿ½ÿ¡ÿñ0ÃÍþ©ÿƒÿKþIÿ-=\:A&¾Ãÿ’ÿþþÈþ9ÿˆÿVÿ»þ˜þþþÂÿ¶Û¥ÿYþfþ¤þ@þþÿ=æY‘lþ.ý;þjþýÙüœý¦þ!xMNƒÿUÿåÿ•äÿ³ÿËéúããÿÈþÉÿ2JÿfÿVä"½þeþþaý¢üøüÐý˜ýýýOÿ–ÿâÿê³€ˆÔÅ‘ûƒa½¥Áíxÿ¢þLÿIÿ·þíþÈÿ1ÿnýTý]ýÇü(ýÏýþ }Ãÿ'ÈÕTž b]²Š]¯]¥%ÿOþýÖüSýkþ4ÿ¤ÿH_qÿdÿyÿþIýIþ%ÿÿþ‚ÿ<˜ûÐþ€PÿÙÿI*ÿ‘ý-ýþ§þiÿ3¬nëþÊý€ýHþà?1ÞKÿ÷ÿˆÈ^ÿ$óÐÿ¼ÿo‹ƒÿÏÿÞÿ¬þlþþ´ý‚ýþþ™þ¼ÿ·ÿ«þ—ÿÉiULŸô@k¦þ{þ‰ÿùÿmÿÔþïÿØþÊþ‰þpþðþIÿµÿpéÿÍÿúXãÿ ÿÇÿÅÿ¹þæþåüƒì™Òãÿ‘ý³ü‘ýŽý¡ýÅþ8ÿôÿå¯y̺6žÿªÿ—2 ÿâYÌë2Ø»ÿ€ý¥ýéþ)ÿ‡þþzÿÿþÿÄÿ$ÿ ÿ–þ?þ£þÿ0ö0ädqÆ*õ@àBóþLÿÓÕÿ7þ°ý+þÎýÖýÿ•ÿJÿ†þ]ýûüRý÷ý\þ'ÿ£ç·*±B¨ö"HÊÇÿÐþðþ†ÿ_ÿiþÄý<ý’üÁü¦ýÌþ[÷ƒÙÿ<™þýÞþXŽÿBÿEˆ<p%œÝ¡ÿ¸þÿþ_ÿÀþˆþÿ8ÿGÿvÿ­ÿ ÿSÿ¯þòýþŽÿ™f£€µ8=ñÿ}þÿýFÿuÿöþOÿ“ÿ¹ÿ—ÿ¦ÿÚWÙ€Àÿ»þëþ<ŠÃçÊ¡ÿmþyÛîûF—e`þÿKÿ=þåýõý¥þèþþØþ]ùÿRÿAÿ²þ¨þ±ÿ4žzœóÅ‚gVåÿÿ©ÿý¨êÿ&ÿ¾þµýæüGý’ý¶ý]þïþêÿÌY2íN~Tÿàÿf$£ÿ¨ÿ ïÇ#'óþ¥ý½ý³þ/ÿŸÿ™Sÿšþ^þþ³þWÿ ÿüþŒÿnü#•€²©zŒÿ}ÿ}ÿ ÿ|þnþÿþÿ|þâþ‘ÿÿ°ÿêÿúÿ`×K‡ÿÞÿ‚ÿàþþÿáX¡ ÅUâÿg ÆÿˆÿÓÿ­ÿ•þ‡þUÿ2ÿÃþ¢þòý;ýÃý½þ'ÿ«ùf(+ÿOÿs€çÿ®ÿ§ŸK^ ÿuþžþÄþÓþŸþ“þIÿ_EþACºÿ;þþ?œÉ¿²2“aœÂÿuþ,þÃþ0ÿàÿêÖMâÿMÿbÿðÿ†œÿPÿ *Øÿ#º¡éÿ ŽÿüÿÐvÈþ—ý˜ý‘ýnýlþÊÿƒÝßHÓ†pU9›¥xѲM´ÿåþÿÏþoþ™þTÿEOÅÿPÿ¯þÔý(ýýQýÐýòþuÿîÿ˜1ÂÒwnÖÚžÿ!ÐWÐÿ…ÿNÿ`þ/ý;ýÒýeþ ÿ«ÿA+J1âþàþåÿ#ÿWþÁÿ29œNM‘Š!v&ÿxþðþÿxÿ*àÿ ÿ<þÒýPþGÿ7N~.‘.ÿbÿ¹Ð%üéÉÿ Væâÿ ÿhþºþýþ)ÿÞÿÜÿÂÿïÿƒ>Eÿ¦ÿ7™ÿ¿ÿÊÿñ®Úþ™ý¦þFÿêþîþ ÿ?0;ìÿ%ÿTþzþ€þËþpÿ†ÿÿÃ"ß"jy$ÿöÿý·æî:ÿ•þiþÂþhþ=þ®þÄþLÿ2nîôR.Á©“ÿ\ÿŒÁúÿF%*wkŸÿšÿÕÿÿMÿÿnþˆþ”þÜþÿxÝñuãË ÎRû¨ÿ3¼ÿôþþãý%þUþuÿÓûòy”ÿ@ÿ0ÿ2ÿ;ÿ½ÿsJÀÿØ©4gvotÿ£ÿNJÿÿ“ÿÑÿ†ÿšÿçþéý¼ý þ‚þZÿ;‘Ä}|DÔ•ÿñÿç?T:0yÿqÿ¼ÿ’ÿ!ÿØþ¨þÛþ+ÿ\ÿÎÿ0=§ÿÿªÿ[úÿÏÿ(‰ùÿ[ÿåÿ +ýnÝÿ;2óÿøÿðÿ ÿ…ÿtÿ‰ÿ™ÿÖÿ6$<‘-Hÿkÿ}€3!ÚkiÌÿ±ÿÿ þ½ýîýPþ¦þ#ÿnvWÙ€!Öÿ*Ca"ÎÂÿ‡¿Ò¸Þýÿ²þƒþˆÿèÿæÿwÿ±þtþ˜þMþúýDþŸþÿ[â§¥f]çÔØõÿ…ÅZš½Ñÿ·þTþ¶þÿ#ÿbÿ·ÿšÿÿ±þ¿þãþqÿêÿ†ÿËÿ‡BÁ!Eñ î@Q£çÿŠÿdÿ«ÿšÿ5ÿÿ¾þ–þÓþGÿíÿ£F²ÿÈÿBÿ­þ$ÿ_ön¹âqãÿ+ÿäþÅþÿ ÿÊþ¿ÿ¾¤t6±ÿÿïþLÿ’ÿŸkðª"RZ|ÿûÿbuÿÊþmÿ?e7^x¢ÿVÿ²ÿqÿÿ©þxþÄþ|ÿþÿª¢óÅÿ|sÞ7ÂI¼þÿÖÿÏÿ}ÿ<ÿÿ:ÿˆÿ|ÿ¾ÿÞÿ¿ÿ²ÿ}ÿ»ÿ3k#:CÓÿÜÿ¨¶ÛÿÿÐÿˆ-¹õÿWÿ4ÿ ÿæþPÿsÿKÿcÿrÿôÿ–º›eL9ìÿØÿi6ß}  ÿéþ¤þ©þ ÿ‡ÿ±ÿ'Š<Úÿ{ÿBÿ^ÿpÿ³ÿâÿ*&‰Ëpï7‹ë‰·ÿpÿâÿòÿ´ÿ¹ÿâÿøÿyÿïþÿ7ÿ1ÿEÿxÿ¾ÿ¼ÿ§ÿÿ‚ÿ+º6;yÆK0¯DPUïÿ·ÿœÿ†ÿ‚ÿxÿ—ÿÿsÿaÿÿìþPÿ×ÿ7N£ýOƒÿìÿ,rÿ<ÿÉÿ2;[ ‰e¨ÿ”ÿžÿÈÿÒÿhÿRÿÿìÿ9a%Ûÿ©ÿXÿ:ÿñÿó ÉòîR~ÿOÿ“ÿDÿæþèþöþpÿôÿ‹Ùoûÿîÿòÿ—Ê=LîµÅÿ«ÿHv àÿf`–ÿAÿ,ÿ3ÿbÿ2ÿ3ÿzÿXÿQÿ²ÿÞÿâÿ!àÿ~Aÿ™ïŒ%¢ý‰íÿ¯ÿ²ÿ€ÿgÿžÿæÿ+íÿ|ÿDÿßþ§þÈþôþTÿéÿ?]Ð%¿'0œ^×ÿ"¤`"¨ÌKÙÿWÿùþîþÿ¤ÿðÿåÿùÿâÿ²ÿÁÿÆÿÿˆÿ×ÿ®ÿmÿºÿ®_ãi'ìÿ9…ÿÿäþ*ÿsÿ‚ÿ÷ÿx.“ÿRÿiÿ¨ÿúÿE‚ÕÊ–ÿòÿw´ÿP¬G%h†9Éÿ•ÿÁÿáÿÂÿ®ÿgÿBÿ;ÿSÿ‹ÿ·ÿ«ÿWÿÿbÅÁO, p›ÿÁÿãÿçÿÇÿÁÿ/ýÿôÿµÿÿ±ÿµÿØÿùÿ !,QVÕÿõÿïÿ¬ÿÀÿ1d[z„Mùÿ ÿ}ÿƒÿ†ÿ›ÿÎÿ÷ÿ27ãÿ»ÿ wV>~ýÿ›ÿÀÿäÿÄÿ±ÿÀÿËÿµÿ”ÿžÿÉÿæÿÛÿÁÿÊÿâÿöÿ4^hšv %‡q)1T7òÿèÿ ¾ÿ†ÿ|ÿ¢ÿÂÿÑÿôÿóÿ¬ÿwÿyÿtÿŒÿ«ÿ½ÿ xV€ûÞf=\b2;!Îÿ³ÿÊÿãÿïÿâÿÍÿŽÿNÿ\ÿ{ÿ¬ÿþÿGg=! ÌÿÿØÿàÿÃÿ t~l¦©IýÿâÿÒÿÓÿÇÿ¾ÿèÿôÿÞÿÖÿÜÿæÿÖÿÃÿÃÿèÿ$÷ÿA|Cüÿ9 ÄÿÉÿÚÿÃÿâÿÔÿØÿßÿÉÿïÿ0/þÿâÿéÿ*ecêÿºÿD-†.ÉÿÎÿÁÿ„ÿvÿ‡ÿ­ÿØÿ×ÿüÿ/âÿÃÿ®ÿ³ÿÚÿòÿûÿ+e]I“Âo íÿÚÿ;æÿÂÿ¶ÿ•ÿ…ÿ’ÿoÿhÿŠÿŸÿïÿYqcha+óÿP3ÍÿãÿDH*fˆ/Ãÿ•ÿ—ÿ­ÿÍÿóÿ+ Ïÿ¥ÿ‡ÿˆÿ¹ÿÔÿÚÿøÿ%5"2—E(z‰*úÿíÿ¸ÿ ÿ ÿ°ÿ´ÿ’ÿŠÿÂÿñÿûÿ9(ôÿéÿñÿÂÿ]3"‹¹lþÿèÿÅÿÆÿÝÿÛÿÒÿâÿôÿçÿÐÿ¨ÿvÿbÿxÿ¤ÿÌÿ|³x_ŽIÑÿÕÿõÿ ?P$þÿ÷ÿÖÿÒÿöÿöÿùÿ÷ÿúÿÿÿúÿùÿÿÿÿÿþÿúÿúÿúÿûÿÿÿûÿüÿÿÿÿÿþÿspeech-dispatcher-0.8.3/src/api/python/speechd_config/__init__.py0000644000175000017500000000137512233560613021777 00000000000000# Copyright (C) 2008 Brailcom, o.p.s. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from .config import * speech-dispatcher-0.8.3/src/api/python/speechd_config/Makefile.in0000664000175000017500000005766112536424263021754 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/api/python/speechd_config DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(dist_bin_SCRIPTS) $(speechd_python_PYTHON) \ $(top_srcdir)/py-compile $(dist_snddata_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(speechd_pythondir)" \ "$(DESTDIR)$(speechd_pythondir)" "$(DESTDIR)$(desktopdir)" \ "$(DESTDIR)$(snddatadir)" SCRIPTS = $(dist_bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile) am__pep3147_tweak = \ sed -e 's|\.py$$||' -e 's|[^/]*$$|__pycache__/&.*.py|' py_compile = $(top_srcdir)/py-compile DATA = $(desktop_DATA) $(dist_snddata_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ dist_snddata_DATA = test.wav DESKTOP_FILES = speechd.desktop.in desktop_DATA = $(DESKTOP_FILES:.desktop.in=.desktop) desktopdir = $(spddesktopconforigdir) dist_bin_SCRIPTS = spd-conf speechd_pythondir = $(pyexecdir)/speechd_config speechd_python_PYTHON = __init__.py nodist_speechd_python_PYTHON = config.py paths.py paths_edit = sed \ -e "s:[@]spdconforigdir[@]:$(spdconforigdir):" \ -e "s:[@]spdconfdir[@]:$(spdconfdir):" \ -e "s:[@]snddatadir[@]:$(snddatadir):" \ -e "s:[@]spddesktopconforigdir[@]:$(spddesktopconforigdir):" config_edit = sed \ -e "s:[@]GETTEXT_PACKAGE[@]:$(GETTEXT_PACKAGE):" \ -e "s:[@]localedir[@]:$(localedir):" CLEANFILES = paths.py config.py speechd.desktop EXTRA_DIST = paths.py.in speechd.desktop.in config.py.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/api/python/speechd_config/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/api/python/speechd_config/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nodist_speechd_pythonPYTHON: $(nodist_speechd_python_PYTHON) @$(NORMAL_INSTALL) @list='$(nodist_speechd_python_PYTHON)'; dlist=; list2=; test -n "$(speechd_pythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(speechd_pythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(speechd_pythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(speechd_pythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(speechd_pythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(speechd_pythondir)" $$dlist; \ else :; fi uninstall-nodist_speechd_pythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(nodist_speechd_python_PYTHON)'; test -n "$(speechd_pythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(speechd_pythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-speechd_pythonPYTHON: $(speechd_python_PYTHON) @$(NORMAL_INSTALL) @list='$(speechd_python_PYTHON)'; dlist=; list2=; test -n "$(speechd_pythondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(speechd_pythondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(speechd_pythondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ if test -f $$b$$p; then \ $(am__strip_dir) \ dlist="$$dlist $$f"; \ list2="$$list2 $$b$$p"; \ else :; fi; \ done; \ for file in $$list2; do echo $$file; done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(speechd_pythondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(speechd_pythondir)" || exit $$?; \ done || exit $$?; \ if test -n "$$dlist"; then \ $(am__py_compile) --destdir "$(DESTDIR)" \ --basedir "$(speechd_pythondir)" $$dlist; \ else :; fi uninstall-speechd_pythonPYTHON: @$(NORMAL_UNINSTALL) @list='$(speechd_python_PYTHON)'; test -n "$(speechd_pythondir)" || list=; \ py_files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$py_files" || exit 0; \ dir='$(DESTDIR)$(speechd_pythondir)'; \ pyc_files=`echo "$$py_files" | sed 's|$$|c|'`; \ pyo_files=`echo "$$py_files" | sed 's|$$|o|'`; \ py_files_pep3147=`echo "$$py_files" | $(am__pep3147_tweak)`; \ echo "$$py_files_pep3147";\ pyc_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|c|'`; \ pyo_files_pep3147=`echo "$$py_files_pep3147" | sed 's|$$|o|'`; \ st=0; \ for files in \ "$$py_files" \ "$$pyc_files" \ "$$pyo_files" \ "$$pyc_files_pep3147" \ "$$pyo_files_pep3147" \ ; do \ $(am__uninstall_files_from_dir) || st=$$?; \ done; \ exit $$st install-desktopDATA: $(desktop_DATA) @$(NORMAL_INSTALL) @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(desktopdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(desktopdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(desktopdir)" || exit $$?; \ done uninstall-desktopDATA: @$(NORMAL_UNINSTALL) @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(desktopdir)'; $(am__uninstall_files_from_dir) install-dist_snddataDATA: $(dist_snddata_DATA) @$(NORMAL_INSTALL) @list='$(dist_snddata_DATA)'; test -n "$(snddatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(snddatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(snddatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(snddatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(snddatadir)" || exit $$?; \ done uninstall-dist_snddataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_snddata_DATA)'; test -n "$(snddatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(snddatadir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(speechd_pythondir)" "$(DESTDIR)$(speechd_pythondir)" "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(snddatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-desktopDATA install-dist_snddataDATA \ install-nodist_speechd_pythonPYTHON \ install-speechd_pythonPYTHON install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-dist_binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-desktopDATA uninstall-dist_binSCRIPTS \ uninstall-dist_snddataDATA \ uninstall-nodist_speechd_pythonPYTHON \ uninstall-speechd_pythonPYTHON .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-desktopDATA install-dist_binSCRIPTS \ install-dist_snddataDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nodist_speechd_pythonPYTHON install-pdf install-pdf-am \ install-ps install-ps-am install-speechd_pythonPYTHON \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am uninstall-desktopDATA \ uninstall-dist_binSCRIPTS uninstall-dist_snddataDATA \ uninstall-nodist_speechd_pythonPYTHON \ uninstall-speechd_pythonPYTHON @INTLTOOL_DESKTOP_RULE@ paths.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(paths_edit) $${srcdir}$@.in > $@ config.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(config_edit) $${srcdir}$@.in > $@ paths.py: $(srcdir)/paths.py.in # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/api/python/speechd_config/Makefile.am0000664000175000017500000000212612522771346021727 00000000000000## Process this file with automake to produce Makefile.in dist_snddata_DATA = test.wav DESKTOP_FILES = speechd.desktop.in desktop_DATA = $(DESKTOP_FILES:.desktop.in=.desktop) desktopdir = $(spddesktopconforigdir) @INTLTOOL_DESKTOP_RULE@ dist_bin_SCRIPTS = spd-conf speechd_pythondir = $(pyexecdir)/speechd_config speechd_python_PYTHON = __init__.py nodist_speechd_python_PYTHON = config.py paths.py paths_edit = sed \ -e "s:[@]spdconforigdir[@]:$(spdconforigdir):" \ -e "s:[@]spdconfdir[@]:$(spdconfdir):" \ -e "s:[@]snddatadir[@]:$(snddatadir):" \ -e "s:[@]spddesktopconforigdir[@]:$(spddesktopconforigdir):" config_edit = sed \ -e "s:[@]GETTEXT_PACKAGE[@]:$(GETTEXT_PACKAGE):" \ -e "s:[@]localedir[@]:$(localedir):" paths.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(paths_edit) $${srcdir}$@.in > $@ config.py: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(config_edit) $${srcdir}$@.in > $@ paths.py: $(srcdir)/paths.py.in CLEANFILES = paths.py config.py speechd.desktop EXTRA_DIST = paths.py.in speechd.desktop.in config.py.in speech-dispatcher-0.8.3/src/api/python/speechd_config/paths.py.in0000644000175000017500000000022612233560613021756 00000000000000SPD_CONF_ORIG_PATH="@spdconforigdir@" SPD_CONF_PATH="@spdconfdir@" SPD_SOUND_DATA_PATH="@snddatadir@" SPD_DESKTOP_CONF_PATH="@spddesktopconforigdir@" speech-dispatcher-0.8.3/src/api/python/speechd_config/spd-conf0000644000175000017500000000033712233560613021317 00000000000000#!/usr/bin/env python3 # Helper script to be put in /usr/bin/ or a similar location # calling the appropriate python tool import speechd_config if __name__=='__main__': import sys sys.exit(speechd_config.main()) speech-dispatcher-0.8.3/src/api/python/speechd_config/speechd.desktop.in0000664000175000017500000000037112522771346023306 00000000000000[Desktop Entry] Type=Application Encoding=UTF-8 Version=1.0 _Name=Speech Dispatcher _Comment=Interface to Text to Speech services TryExec=speech-dispatcher Exec=speech-dispatcher X-GNOME-Autostart-enabled=true X-GNOME-Autostart-Phase=Initialization speech-dispatcher-0.8.3/src/api/python/speechd_config/config.py.in0000664000175000017500000010624312536417045022122 00000000000000# config.py - A simple dialog based tool for basic configuration of # Speech Dispatcher and problem diagnostics. # # Copyright (C) 2008, 2010 Brailcom, o.p.s. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import sys import os import shutil import fileinput import socket import time import datetime from optparse import OptionParser from xdg import BaseDirectory # Locale/gettext configuration import gettext import locale locale.setlocale(locale.LC_ALL, '') gettext.bindtextdomain ("@GETTEXT_PACKAGE@", "@localedir@") gettext.textdomain("@GETTEXT_PACKAGE@") _ = gettext.gettext # Configuration and sound data paths from . import paths def report(msg): """Output information messages for the user on stdout and if desired, by espeak synthesis""" print(msg) if options.use_espeak_synthesis: os.system("espeak \"" + msg + "\"") def input_audio_icon(): """Produce a sound for the event 'input requested' used in question()""" if options.use_espeak_synthesis: os.system("espeak \"Type in\"") def question(text, default): """Ask a simple question and suggest the default value""" while 1: if isinstance(default, bool): if default == True: default_str = "yes" else: default_str = "no" else: default_str = str(default) report(text + " ["+default_str+"] :") input_audio_icon() if not options.dont_ask: str_inp = input(">") # On plain enter, return default if options.dont_ask or (len(str_inp) == 0): return default # If a value was typed, check it and convert it elif isinstance(default, bool): if str_inp in ["yes","y", "Y", "true","t", "1"]: return True elif str_inp in ["no", "n", "N", "false", "f", "0"]: return False else: report ("Unknown answer (type 'yes' or 'no')") continue elif isinstance(default, int): return int(str_inp) elif isinstance(default, str): return str_inp else: raise TypeError("Invalid type for the default value") def question_with_suggested_answers(text, default, suggest): """Ask a question with suggested answers. If the answer typed is not in 'suggest', the user is notified and given an opportunity to correct his choice""" reply = question(text, default) while reply not in suggest: report(_("""The value you have chosen is not among the suggested values. You have chosen '%s'.""" % reply)) report(_("The suggested values are " + str(suggest))) correct = question(_("Do you want to correct your answer?", True)) if correct == True: reply = question(text, default) else: return reply return reply def question_with_required_answers(text, default, required): """Ask a question and repeat it until the answer typed in is in 'required'""" reply = question(text, default) while reply not in required: report(_("You have chosen '%s'. Please choose one of %s" % (reply, str(required)))) reply = question(text, default) return reply class Options(object): """Configuration for spdconf""" _conf_options = \ { 'create_user_configuration': { 'descr' : _("Create Speech Dispatcher configuration for the given user"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-u', '--create-user-conf'), }, 'config_basic_settings_user': { 'descr' : _("Configure basic settings in user configuration"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-c', '--config-basic-settings-user'), }, 'config_basic_settings_system': { 'descr' : _("Configure basic settings in system-wide configuration"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-C', '--config-basic-settings-system'), }, 'diagnostics': { 'descr' : _("Diagnose problems with the current setup"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-d', '--diagnostics'), }, 'test_spd_say': { 'descr' : _("Test connection to Speech Dispatcher using spd-say"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-s', '--test-spd-say'), }, 'test_festival': { 'descr' : _("Test whether Festival works as a server"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('', '--test-festival'), }, 'test_espeak': { 'descr' : _("Test whether Espeak works as a standalone binary"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('', '--test-espeak'), }, 'test_alsa': { 'descr' : _("Test ALSA audio"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('', '--test-alsa'), }, 'test_pulse': { 'descr' : _("Test Pulse Audio"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('', '--test-pulse'), }, 'use_espeak_synthesis': { 'descr' : _("Use espeak to synthesize messages"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-e', '--espeak'), }, 'dont_ask': { 'descr' : _("Do not ask any questions, always use default values"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-n', '--dont-ask'), }, 'debug': { 'descr' : _("Debug a problem and generate a report"), 'doc' : None, 'type' : bool, 'default' : False, 'command_line' : ('-D', '--debug'), }, } def __init__(self): usage = """%prog [options] A simple dialog based tool for basic configuration of Speech Dispatcher and problem diagnostics.""" self.cmdline_parser = OptionParser(usage) for option, definition in self._conf_options.items(): # Set object attributes to default values def_val = definition.get('default', None) setattr(self, option, def_val) # Fill in the cmdline_parser object if 'command_line' in definition: descr = definition.get('descr', None) type = definition.get('type', None) if 'arg_map' in definition: type, map = definition['arg_map'] if type == str: type_str = 'string' elif type == int: type_str = 'int' elif type == float: type_str = 'float' elif type == bool: type_str = None else: raise TypeError("Unknown type") if type != bool: self.cmdline_parser.add_option(type=type_str, dest=option, help=descr, *definition['command_line']) else: # type == bool self.cmdline_parser.add_option(action="store_true", dest=option, help=descr, *definition['command_line']) # Set options according to command line flags (cmdline_options, args) = self.cmdline_parser.parse_args() for option, definition in self._conf_options.items(): val = getattr(cmdline_options, option, None) if val != None: if 'arg_map' in definition: former_type, map = definition['arg_map'] try: val = map[val] except KeyError: raise ValueError("Invalid option value: " + str(val)) setattr(self, option, val) #if len(args) != 0: # raise ValueError("This command takes no positional arguments (without - or -- prefix)") class Tests: """Tests of functionality of Speech Dispatcher and its dependencies and methods for determination of proper paths""" def __init__(self): self.festival_socket = None def user_conf_dir(self): """Return user configuration directory""" return os.path.join(BaseDirectory.xdg_config_home, "speech-dispatcher") def system_conf_dir(self): """Determine system configuration directory""" return paths.SPD_CONF_PATH def user_conf_dir_exists(self): """Determine whether user configuration directory exists""" return os.path.exists(self.user_conf_dir()) def festival_connect(self, host="localhost", port=1314): """ Try to connect to festival and determine whether it is possible. On success self.festival_socket is initialized with the openned socket. """ self.festival_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.festival_socket.connect((socket.gethostbyname(host), port)) except socket.error as e: (num, reson) = e.args report(_("""ERROR: It was not possible to connect to Festival on the given host and port. Connection failed with error %d : %s .""" % (num, reson))) report(_("""Hint: Most likely, your Festival server is not running now or not at the default port %d. Try /etc/init.d/festival start or run 'festival --server' from the command line.""" % port)) return False return True def festival_with_freebsoft_utils(self): """Test whether festival works and contains working festival-freebsoft-utils. """ if not self.festival_socket: if not self.festival_connect(): return False self.festival_socket.send(bytes("(require 'speech-dispatcher)\n", "ascii")) reply = str(self.festival_socket.recv(1024)) if "LP" in reply: report(_("Festival contains freebsoft-utils.")) return True else: report(_("""ERROR: Your Festival server is working but it doesn't seem to load festival-freebsoft-utils. You need to install festival-freebsoft-utils to be able to use Festival with Speech Dispatcher.""")) return False def python_speechd_in_path(self): """Try whether python speechd library is importable""" try: import speechd except: report(_("""Python can't find the Speech Dispatcher library. Is it installed? This won't prevent Speech Dispatcher to work, but no Python applications like Orca will be able to use it. Search for package like python-speechd, download and install it""")) return False return True def audio_try_play(self, type): """Try to play a sound through the standard playback utility for the given audio method.""" wavfile = os.path.join(paths.SPD_SOUND_DATA_PATH,"test.wav") if type == 'alsa': cmd = "aplay" + " " + wavfile elif type == 'pulse': cmd = "paplay" + " " + wavfile else: raise NotImplementedError("Test for this audio system is not implemented") try: ret = os.system(cmd) except: report(_("""Can't execute the %s command, this audio output might not be available on your system, but it might also be a false warning. Please make sure your audio is working.""")) reply = question(_("Are you sure that %s audio is working?" % type), False) return reply if ret: report(_("Can't play audio via\n %s" % cmd)) report(_("""Your audio doesn't seem to work, please fix audio first or choose a different method.""")) return False reply = question(_("Did you hear the sound?"), True) if not reply: report(_("""Please examine the above output from the sound playback utility. If everything seems right, are you sure your audio is loud enough and not muted in the mixer? Please fix your audio system first or choose a different audio output method in configuration.""")) return False else: report(_("Audio output '%s' works" % type)) return True def test_spd_say(self): """Test Speech Dispatcher using spd_say""" report(_("Testing Speech Dispatcher using spd_say")) while True: try: ret = os.system("spd-say -P important \"Speech Dispatcher works\"") except: report(_("""Can't execute the spd-say binary, it is very likely that Speech Dispatcher is not installed.""")) return False hearing_test = question(_("Did you hear the message about Speech Dispatcher working?"), True) if hearing_test: report(_("Speech Dispatcher is installed and working!")) return True else: report(_("Speech Dispatcher is installed but there is some problem")) return False def test_festival(self): """Test whether Festival works as a server""" report(_("Testing whether Festival works as a server")) ret = self.festival_with_freebsoft_utils() if not ret: report(_("Festival server is not working.")) return False else: report(_("Festival server seems to work correctly")) return True def test_espeak(self): """Test the espeak utility""" report(_("Testing whether Espeak works")) while True: try: os.system("espeak \"Espeak seems to work\"") except: report(_("""Can't execute the espeak binary, it is likely that espeak is not installed.""")) return False report(_("Espeak is installed")) return True def test_alsa(self): """Test ALSA sound output""" report(_("Testing ALSA sound output")) return self.audio_try_play(type='alsa') def test_pulse(self): """Test Pulse Audio sound output""" report(_("Testing PULSE sound output")) return self.audio_try_play(type='pulse') def diagnostics(self, speechd_running = True, output_modules=[], audio_output=[]): """Perform a complete diagnostics""" working_modules = [] working_audio = [] if speechd_running: # Test whether Speech Dispatcher works if self.test_spd_say(): spd_say_working = True skip = question(_("Speech Dispatcher works. Do you want to skip other tests?"), True) if skip: return {'spd_say_working': True} else: spd_say_working = False else: spd_say_working = False if not spd_say_working: if not question(_(""" Speech Dispatcher isn't running or we can't connect to it (see above), do you want to proceed with other tests? (They can help to determine what is wrong)"""), True): return {'spd_say_working': False} def decide_to_test(identifier, name, listing): """"Ask the user whether to test a specific capability""" if ((identifier in listing) or (not len(listing) and question(_("Do you want to test the %s now?" % name), True))): return True else: return False if decide_to_test('festival', "Festival synthesizer", output_modules): if self.test_festival(): working_modules += ["festival"] if decide_to_test('espeak', "Espeak synthesizer", output_modules): if self.test_espeak(): working_modules += ["espeak"] if decide_to_test('alsa', "ALSA sound system", audio_output): if self.test_alsa(): working_audio += ["alsa"] if decide_to_test('pulse', "Pulse Audio sound system", audio_output): if self.test_pulse(): working_audio += ["pulse"] report(_("Testing whether Python Speech Dispatcher library is in path and importable")) python_speechd_working = test.python_speechd_in_path() return {'spd_say_working': spd_say_working, 'audio': working_audio, 'synthesizers': working_modules, 'python_speechd' : python_speechd_working} def write_diagnostics_results(self, results): """Write out diagnostics results using report()""" report(_(""" Diagnostics results:""")) if 'spd_say_working' in results: if results['spd_say_working']: report(_("Speech Dispatcher is working")) else: report(_("Speech Dispatcher not working through spd-say")) if 'synthesizers' in results: report(_("Synthesizers that were tested and seem to work: %s") % str(results['synthesizers'])) if 'audio' in results: report(_("Audio systems that were tested and seem to work: %s") % str(results['audio'])) if 'python_speechd' in results: if(results['python_speechd']): report(_("Python Speech Dispatcher module is importable")) else: report(_("""Python Speech Dispatcher module not importable. Either not installed or not in path.""")) report(_("End of diagnostics results")) def user_configuration_seems_complete(self): """Decide if the user configuration seems reasonably complete""" if not os.path.exists(os.path.join(self.user_conf_dir(), "speechd.conf")): return False if not len(os.listdir(self.user_conf_dir())) > 2: return False if not os.path.exists(os.path.join(self.user_conf_dir(), "modules")): return False if not os.path.exists(os.path.join(self.user_conf_dir(), "clients")): return False return True def debug_and_report(self, type = None): """Start Speech Dispatcher in debugging mode, collect the debugging output and offer to send it to the developers""" report(_("Starting collecting debugging output, configuration and logfiles")) if not type: type = question_with_required_answers(_(""" Do you want to debug 'system' or 'user' Speech Dispatcher?"""), 'user', ['user', 'system']) # Try to kill running Speech Dispatcher reply = question(_("""It is necessary to kill the currently running Speech Dispatcher processes. Do you want to do it now?"""), True) if reply: os.system("killall speech-dispatcher") # Attempt to workaround the psmisc 22.15 bug with 16 char max process names os.system("killall speech-dispatch") else: report(_(""" You decided not to kill running Speech Dispatcher processes. Please make sure your Speech Dispatcher is not running now.""")) reply = question(_("Is your Speech Dispatcher not running now?"), True) if not reply: report(_("Can't continue, please stop your Speech Dispatcher and try again")) time.sleep(2) # All debugging files are written to TMPDIR/speech-dispatcher/ if 'TMPDIR' in os.environ: tmpdir = os.environ['TMPDIR'] else: tmpdir = "/tmp/" debugdir_path = os.path.join(tmpdir, "speechd-debug") date = datetime.date.today() debugarchive_path = os.path.join(tmpdir, "speechd-debug-%d-%d-%d.tar.gz" % (date.day, date.month, date.year)) # Start Speech Dispatcher with debugging enabled if type == 'user': report(_("Speech Dispatcher will be started now in debugging mode")) speechd_started = not os.system("speech-dispatcher -D") configure_directory = test.user_conf_dir() else: report(_("Warning: You must be root or under sudo to do this.") ) report(_(""" Please start your system Speech Dispatcher now with parameter '-D'""")) reply = question(_("Is your Speech Dispatcher running now?"), True) if reply: speechd_started = True else: report(_("Can't continue")) configure_directory = test.system_conf_dir() time.sleep(2) if not speechd_started: reply = question("Speech Dispatcher failed to start, continuing anyway") report(_("Trying to speak some messages")) ret = os.system("spd-say \"Speech Dispatcher debugging 1\"") if not ret: os.system("spd-say \"Speech Dispatcher debugging 2\"") os.system("spd-say \"Speech Dispatcher debugging 3\"") else: report(_("Can't test Speech Dispatcher connection, can't connect")) report(_("Please wait (about 5 seconds)")) time.sleep(5) report(_("Collecting debugging output and your configuration information") ) os.system("umask 077") os.system("tar -cz %s %s > %s" % (debugdir_path, configure_directory, debugarchive_path)) os.system("killall speech-dispatcher") # Attempt to workaround the psmisc 22.15 bug with 16 char max process names os.system("killall speech-dispatch") os.system("rm -rf %s" % debugdir_path) report(_(""" Please send %s to speechd@bugs.freebsoft.org with a short description of what you did. We will get in touch with you soon and suggest a solution.""" % debugarchive_path)) test = Tests() class Configure: """Setup user configuration and/or set basic options in user/system configuration""" default_output_module = None default_language = None default_audio_method = None def remove_user_configuration(self): """Remove user configuration tree""" shutil.rmtree(test.user_conf_dir()) def options_substitute(self, configfile, options): """Substitute the given options with given values. Arguments: configfile -- the file path of the configuration file as a string options -- a list of tuples (option_name, value)""" # Parse config file in-place and replace the desired options+values for line in fileinput.input(configfile, inplace=True, backup=".bak"): # Check if the current line contains any of the desired options for opt, value in options.items(): if opt in line: # Now count unknown words and try to judge if this is # real configuration or just a comment unknown = 0 for word in line.split(): if word =='#' or word == '\t': continue elif word == opt: # If a foreign word went before our option identifier, # we are not in code but in comments if unknown != 0: unknown = 2 break else: unknown += 1 # Only consider the line as the actual code when the keyword # is followed by exactly one word value. Otherwise consider this # line as plain comment and leave intact if unknown == 1: # Convert value into string representation in spd_val if isinstance(value, bool): if value == True: spd_val = "1" elif value == False: spd_val = "2" elif isinstance(value, int): spd_val = str(value) else: spd_val = str(value) print(opt + " " + spd_val) break else: print(line, end=' ') def create_user_configuration(self): """Create user configuration in the standard location""" # Ask before touching things that we do not have to! if test.user_conf_dir_exists(): if test.user_configuration_seems_complete(): reply = question(_("""User configuration already exists. Do you want to rewrite it with a new one?"""), False) if reply == False: report(_("Keeping configuration intact and continuing with settings.")) return else: self.remove_user_configuration() else: reply = question(_("""User configuration already exists, but it seems to be incomplete. Do you want to keep it?"""), False) if reply == False: self.remove_user_configuration() else: report(_("Keeping configuration intact and aborting.")) return # Copy the original intact configuration files # creating a conf/ subdirectory shutil.copytree(paths.SPD_CONF_ORIG_PATH, test.user_conf_dir()) report(_("User configuration created in %s" % test.user_conf_dir())) def configure_basic_settings(self, type='user'): """Ask for basic settings and rewrite them in the configuration file""" if type == 'user': report(_("Configuring user settings for Speech Dispatcher")) elif type == 'system': report(_("Warning: You must be root or under sudo to do this.")) report(_("Configuring system settings for Speech Dispatcher")) else: raise ValueError("Invalid configuration type") # Now determine the most important config option self.default_output_module = question_with_suggested_answers( "Default output module", "espeak", ["espeak", "flite", "festival", "cicero", "ibmtts"]) self.default_language = question( "Default language (two-letter iso language code like \"en\" or \"cs\")", "en") self.default_audio_method = question_with_suggested_answers( "Default audio output method", "pulse", ["pulse", "libao", "alsa", "oss", "pulse,alsa"]) self.default_speech_rate = question( _("Default speech rate (on the scale of -100..100, 0 is default, 50 is faster, -50 is slower)"), "0") self.default_speech_pitch = question( _("Default speech pitch (on the scale of -100..100, 0 is default, 50 is higher, -50 is lower)"), "0") # Substitute given configuration options if type == 'user': configfile = os.path.join(test.user_conf_dir(), "speechd.conf") elif type == 'system': configfile = os.path.join(test.system_conf_dir(), "speechd.conf") self.options_substitute(configfile, {"DefaultModule": self.default_output_module, "DefaultLanguage": self.default_language, "AudioOutputMethod": self.default_audio_method, "DefaultRate": self.default_speech_rate, "DefaultPitch": self.default_speech_pitch, "DefaultLanguage": self.default_language, }) if type == 'user': self.setup_autostart = question( _("""Do you want to have Speech Dispatcher automatically started from ~/.config/autostart ? This is usually not necessary, most applications will start Speech Dispatcher automatically."""), False) if self.setup_autostart: os.system("""cp %s ~/.config/autostart/""" % os.path.join(paths.SPD_DESKTOP_CONF_PATH, "speechd.desktop")) report(_(""" Configuration written to %s Basic configuration now complete. You might still need to fine tune it by manually editing the configuration file above. Especially if you need to use special audio settings, non-standard synthesizer ports etc.""" % configfile)) def speechd_start_user(self): """Start Speech Dispatcher in user-mode""" report(_("Starting Speech Dispatcher in user-mode")) err = os.system("speech-dispatcher") if err: report(_("Can't start Speech Dispatcher. Exited with status %d" % err)) reply = question(_("""Perhaps this is because your Speech Dispatcher is already running. Do you want to kill all running Speech Dispatchers and try again?"""), True) if reply: os.system("killall speech-dispatcher") # Attempt to workaround the psmisc 22.15 bug with 16 char max process names os.system("killall speech-dispatch") err = os.system("speech-dispatcher") if err: report(_("Can't start Speech Dispatcher")) return False else: return False return True def speechd_start_system(self): """Start Speech Dispatcher in system-mode""" report(_("Warning: You must be root or under sudo to do this.") ) report(_("Starting Speech Dispatcher in system-mode")) reply = question(_("Is your system using an /etc/init.d/speech-dispatcher script?"), True) if reply: report(_("Stopping Speech Dispatcher in case any is running already")) os.system("/etc/init.d/speech-dispatcher stop") report(_("Starting Speech Dispatcher via /etc/init.d/speech-dispatcher")) ret = os.system("/etc/init.d/speech-dispatcher start") if ret: report(_("Can't start Speech Dispatcher. Exited with status %d" % ret)) return False else: report(_("""Do not know how to start system Speech Dispatcher, you have to start it manually to continue.""")) reply = question(_("Have you started Speech Dispatcher now?"), True) if not reply: report(_("Can't continue")) return False return True def complete_config(self): """Create a complete configuration, run diagnosis and if necessary, debugging""" speechd_type = question_with_required_answers( _("Do you want to create/setup a 'user' or 'system' configuration"), 'user', ['user', 'system']) if speechd_type == 'user': self.create_user_configuration() self.configure_basic_settings(type='user') elif speechd_type == 'system': self.configure_basic_settings(type='system') else: raise ValueError("Invalid configuration type") reply = question(_("Do you want to start/restart Speech Dispatcher now and run some tests?"), True) if not reply: report(_("Your configuration is now done but not tested")) return else: if speechd_type == 'user': started = self.speechd_start_user() elif speechd_type == 'system': started = self.speechd_start_system() if not started: report(_("Your Speech Dispatcher is not running")) result = test.diagnostics(speechd_running = started, audio_output=[self.default_audio_method], output_modules=[self.default_output_module]) test.write_diagnostics_results(result) if not started: reply = question(_("Do you want to run debugging now and send a request for help to the developers?"), False) if reply: test.debug_and_report(type=speechd_type) # Basic objects options = Options() configure = Configure() test = Tests() def main(): report(_("\nSpeech Dispatcher configuration tool\n")) if options.create_user_configuration: # Check for and/or create basic user configuration configure.create_user_configuration() reply = question(_("Do you want to continue with basic settings?"), True) if reply: configure.configure_basic_settings(type='user') elif options.config_basic_settings_user: configure.configure_basic_settings(type='user') elif options.config_basic_settings_system: configure.configure_basic_settings(type='system') elif options.test_festival: test.test_festival() elif options.test_spd_say: test.test_spd_say() elif options.test_espeak: test.test_espeak() elif options.test_alsa: test.audio_try_play(type='alsa') elif options.test_pulse: test.audio_try_play(type='pulse') elif options.diagnostics: ret = test.diagnostics() test.write_diagnostics_results(ret) elif options.debug: test.debug_and_report() else: reply = question(_("Do you want to setup a completely new configuration?"), True) if reply: configure.complete_config() else: reply = question(_("Do you want to run diagnosis of problems?"), True) if reply: ret=test.diagnostics() test.write_diagnostics_results(ret) else: report(_("""Please run this command again and select what you want to do or read the quick help available through '-h' or '--help'.""")) if __name__ == "__main__": sys.exit(main()) speech-dispatcher-0.8.3/src/api/Makefile.in0000664000175000017500000005026012536424263015457 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_PYTHON_TRUE@am__append_1 = python subdir = src/api DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = c python DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = c $(am__append_1) EXTRA_DIST = cl guile all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/api/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/api/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/api/Makefile.am0000644000175000017500000000020612233560613015431 00000000000000## Process this file with automake to produce Makefile.in SUBDIRS= c if HAVE_PYTHON SUBDIRS += python endif EXTRA_DIST = cl guile speech-dispatcher-0.8.3/src/api/c/0000775000175000017500000000000012536424374013714 500000000000000speech-dispatcher-0.8.3/src/api/c/libspeechd_version.h.in0000664000175000017500000000235412530733575020265 00000000000000/* * libspeechd_version.h - Shared library for easy access to Speech Dispatcher functions (header) * * Copyright (C) 2001, 2002, 2003, 2004 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: libspeechd.h,v 1.29 2008-07-30 09:47:00 hanke Exp $ */ #ifndef _LIBSPEECHD_VERSION_H #define _LIBSPEECHD_VERSION_H #define LIBSPEECHD_MAJOR_VERSION @LIBSPEECHD_MAJOR_VERSION@ #define LIBSPEECHD_MINOR_VERSION @LIBSPEECHD_MINOR_VERSION@ #define LIBSPEECHD_MICRO_VERSION @LIBSPEECHD_MICRO_VERSION@ #endif /* ifndef _LIBSPEECHD_VERSION_H */ speech-dispatcher-0.8.3/src/api/c/libspeechd_version.h0000664000175000017500000000224112536424350017645 00000000000000/* * libspeechd_version.h - Shared library for easy access to Speech Dispatcher functions (header) * * Copyright (C) 2001, 2002, 2003, 2004 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: libspeechd.h,v 1.29 2008-07-30 09:47:00 hanke Exp $ */ #ifndef _LIBSPEECHD_VERSION_H #define _LIBSPEECHD_VERSION_H #define LIBSPEECHD_MAJOR_VERSION 0 #define LIBSPEECHD_MINOR_VERSION 8 #define LIBSPEECHD_MICRO_VERSION 3 #endif /* ifndef _LIBSPEECHD_VERSION_H */ speech-dispatcher-0.8.3/src/api/c/Makefile.in0000664000175000017500000006222012536424263015700 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/api/c DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(spdinclude_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(spdincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libspeechd_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libspeechd_la_OBJECTS = libspeechd_la-libspeechd.lo libspeechd_la_OBJECTS = $(am_libspeechd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libspeechd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libspeechd_la_CFLAGS) \ $(CFLAGS) $(libspeechd_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libspeechd_la_SOURCES) DIST_SOURCES = $(libspeechd_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(spdinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ spdinclude_HEADERS = libspeechd.h libspeechd_version.h inc_local = -I$(top_srcdir)/include/ BUILT_SOURCES = libspeechd_version.h lib_LTLIBRARIES = libspeechd.la libspeechd_la_SOURCES = libspeechd.c libspeechd_la_CFLAGS = $(ERROR_CFLAGS) libspeechd_la_CPPFLAGS = $(inc_local) -D_GNU_SOURCE $(GLIB_CFLAGS) -DSPD_SPAWN_CMD=\""$(prefix)/bin/speech-dispatcher"\" libspeechd_la_LDFLAGS = -version-info $(LIB_SPD_CURRENT):$(LIB_SPD_REVISION):$(LIB_SPD_AGE) libspeechd_la_LIBADD = $(GLIB_LIBS) CLEANFILES = libspeechd_version.h EXTRA_DIST = libspeechd_version.h.in edit_version = sed \ -e 's:[@]LIBSPEECHD_MAJOR_VERSION[@]:$(MAJOR_VERSION):' \ -e 's:[@]LIBSPEECHD_MINOR_VERSION[@]:$(MINOR_VERSION):' \ -e 's:[@]LIBSPEECHD_MICRO_VERSION[@]:$(MICRO_VERSION):' all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/api/c/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/api/c/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libspeechd.la: $(libspeechd_la_OBJECTS) $(libspeechd_la_DEPENDENCIES) $(EXTRA_libspeechd_la_DEPENDENCIES) $(AM_V_CCLD)$(libspeechd_la_LINK) -rpath $(libdir) $(libspeechd_la_OBJECTS) $(libspeechd_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libspeechd_la-libspeechd.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libspeechd_la-libspeechd.lo: libspeechd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libspeechd_la_CPPFLAGS) $(CPPFLAGS) $(libspeechd_la_CFLAGS) $(CFLAGS) -MT libspeechd_la-libspeechd.lo -MD -MP -MF $(DEPDIR)/libspeechd_la-libspeechd.Tpo -c -o libspeechd_la-libspeechd.lo `test -f 'libspeechd.c' || echo '$(srcdir)/'`libspeechd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libspeechd_la-libspeechd.Tpo $(DEPDIR)/libspeechd_la-libspeechd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libspeechd.c' object='libspeechd_la-libspeechd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libspeechd_la_CPPFLAGS) $(CPPFLAGS) $(libspeechd_la_CFLAGS) $(CFLAGS) -c -o libspeechd_la-libspeechd.lo `test -f 'libspeechd.c' || echo '$(srcdir)/'`libspeechd.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-spdincludeHEADERS: $(spdinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(spdinclude_HEADERS)'; test -n "$(spdincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(spdincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(spdincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(spdincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(spdincludedir)" || exit $$?; \ done uninstall-spdincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(spdinclude_HEADERS)'; test -n "$(spdincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(spdincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(spdincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-spdincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-spdincludeHEADERS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am \ install-spdincludeHEADERS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-spdincludeHEADERS libspeechd_version.h: $(srcdir)/libspeechd_version.h.in libspeechd_version.h: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(edit_version) $${srcdir}$@.in > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/api/c/libspeechd.h0000664000175000017500000002145412536417045016112 00000000000000/* * libspeechd.h - Shared library for easy acces to Speech Dispatcher functions (header) * * Copyright (C) 2001, 2002, 2003, 2004 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: libspeechd.h,v 1.29 2008-07-30 09:47:00 hanke Exp $ */ #ifndef _LIBSPEECHD_H #define _LIBSPEECHD_H #include #include #include #include "libspeechd_version.h" /* * Since the API includes speechd_types.h directly, we only need this * include if we are not being included by the API. */ #ifndef SPEECHD_TYPES_H #include #endif /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ /* Speech Dispatcher's default port for inet communication */ #define SPEECHD_DEFAULT_PORT 6560 /* Arguments for spd_send_data() */ #define SPD_WAIT_REPLY 1 /* Wait for reply */ #define SPD_NO_REPLY 0 /* No reply requested */ /* --------------------- Public data types ------------------------ */ typedef enum { SPD_MODE_SINGLE = 0, SPD_MODE_THREADED = 1 } SPDConnectionMode; typedef enum { SPD_METHOD_UNIX_SOCKET = 0, SPD_METHOD_INET_SOCKET = 1, } SPDConnectionMethod; typedef struct { SPDConnectionMethod method; char *unix_socket_name; char *inet_socket_host; int inet_socket_port; char *dbus_bus; } SPDConnectionAddress; void SPDConnectionAddress__free(SPDConnectionAddress * address); typedef void (*SPDCallback) (size_t msg_id, size_t client_id, SPDNotificationType state); typedef void (*SPDCallbackIM) (size_t msg_id, size_t client_id, SPDNotificationType state, char *index_mark); typedef struct { /* PUBLIC */ SPDCallback callback_begin; SPDCallback callback_end; SPDCallback callback_cancel; SPDCallback callback_pause; SPDCallback callback_resume; SPDCallbackIM callback_im; /* PRIVATE */ int socket; FILE *stream; SPDConnectionMode mode; pthread_mutex_t *ssip_mutex; pthread_t *events_thread; pthread_mutex_t *comm_mutex; pthread_cond_t *cond_reply_ready; pthread_mutex_t *mutex_reply_ready; pthread_cond_t *cond_reply_ack; pthread_mutex_t *mutex_reply_ack; char *reply; } SPDConnection; /* -------------- Public functions --------------------------*/ /* Openning and closing Speech Dispatcher connection */ SPDConnectionAddress *spd_get_default_address(char **error); SPDConnection *spd_open(const char *client_name, const char *connection_name, const char *user_name, SPDConnectionMode mode); SPDConnection *spd_open2(const char *client_name, const char *connection_name, const char *user_name, SPDConnectionMode mode, SPDConnectionAddress * address, int autospawn, char **error_result); void spd_close(SPDConnection * connection); /* Speaking */ int spd_say(SPDConnection * connection, SPDPriority priority, const char *text); int spd_sayf(SPDConnection * connection, SPDPriority priority, const char *format, ...); /* Speech flow */ int spd_stop(SPDConnection * connection); int spd_stop_all(SPDConnection * connection); int spd_stop_uid(SPDConnection * connection, int target_uid); int spd_cancel(SPDConnection * connection); int spd_cancel_all(SPDConnection * connection); int spd_cancel_uid(SPDConnection * connection, int target_uid); int spd_pause(SPDConnection * connection); int spd_pause_all(SPDConnection * connection); int spd_pause_uid(SPDConnection * connection, int target_uid); int spd_resume(SPDConnection * connection); int spd_resume_all(SPDConnection * connection); int spd_resume_uid(SPDConnection * connection, int target_uid); /* Characters and keys */ int spd_key(SPDConnection * connection, SPDPriority priority, const char *key_name); int spd_char(SPDConnection * connection, SPDPriority priority, const char *character); int spd_wchar(SPDConnection * connection, SPDPriority priority, wchar_t wcharacter); /* Sound icons */ int spd_sound_icon(SPDConnection * connection, SPDPriority priority, const char *icon_name); /* Setting parameters */ int spd_set_voice_type(SPDConnection *, SPDVoiceType type); int spd_set_voice_type_all(SPDConnection *, SPDVoiceType type); int spd_set_voice_type_uid(SPDConnection *, SPDVoiceType type, unsigned int uid); SPDVoiceType spd_get_voice_type(SPDConnection *); int spd_set_synthesis_voice(SPDConnection *, const char *voice_name); int spd_set_synthesis_voice_all(SPDConnection *, const char *voice_name); int spd_set_synthesis_voice_uid(SPDConnection *, const char *voice_name, unsigned int uid); int spd_set_data_mode(SPDConnection * connection, SPDDataMode mode); int spd_set_notification_on(SPDConnection * connection, SPDNotification notification); int spd_set_notification_off(SPDConnection * connection, SPDNotification notification); int spd_set_notification(SPDConnection * connection, SPDNotification notification, const char *state); int spd_set_voice_rate(SPDConnection * connection, signed int rate); int spd_set_voice_rate_all(SPDConnection * connection, signed int rate); int spd_set_voice_rate_uid(SPDConnection * connection, signed int rate, unsigned int uid); int spd_get_voice_rate(SPDConnection * connection); int spd_set_voice_pitch(SPDConnection * connection, signed int pitch); int spd_set_voice_pitch_all(SPDConnection * connection, signed int pitch); int spd_set_voice_pitch_uid(SPDConnection * connection, signed int pitch, unsigned int uid); int spd_get_voice_pitch(SPDConnection * connection); int spd_set_volume(SPDConnection * connection, signed int volume); int spd_set_volume_all(SPDConnection * connection, signed int volume); int spd_set_volume_uid(SPDConnection * connection, signed int volume, unsigned int uid); int spd_get_volume(SPDConnection * connection); int spd_set_punctuation(SPDConnection * connection, SPDPunctuation type); int spd_set_punctuation_all(SPDConnection * connection, SPDPunctuation type); int spd_set_punctuation_uid(SPDConnection * connection, SPDPunctuation type, unsigned int uid); int spd_set_capital_letters(SPDConnection * connection, SPDCapitalLetters type); int spd_set_capital_letters_all(SPDConnection * connection, SPDCapitalLetters type); int spd_set_capital_letters_uid(SPDConnection * connection, SPDCapitalLetters type, unsigned int uid); int spd_set_spelling(SPDConnection * connection, SPDSpelling type); int spd_set_spelling_all(SPDConnection * connection, SPDSpelling type); int spd_set_spelling_uid(SPDConnection * connection, SPDSpelling type, unsigned int uid); int spd_set_language(SPDConnection * connection, const char *language); int spd_set_language_all(SPDConnection * connection, const char *language); int spd_set_language_uid(SPDConnection * connection, const char *language, unsigned int uid); char *spd_get_language(SPDConnection * connection); int spd_set_output_module(SPDConnection * connection, const char *output_module); int spd_set_output_module_all(SPDConnection * connection, const char *output_module); int spd_set_output_module_uid(SPDConnection * connection, const char *output_module, unsigned int uid); int spd_get_client_list(SPDConnection * connection, char **client_names, int *client_ids, int *active); int spd_get_message_list_fd(SPDConnection * connection, int target, int *msg_ids, char **client_names); char **spd_list_modules(SPDConnection * connection); void free_spd_modules(char **); char *spd_get_output_module(SPDConnection * connection); char **spd_list_voices(SPDConnection * connection); SPDVoice **spd_list_synthesis_voices(SPDConnection * connection); void free_spd_voices(SPDVoice ** voices); char **spd_execute_command_with_list_reply(SPDConnection * connection, char *command); /* Direct SSIP communication */ int spd_execute_command(SPDConnection * connection, char *command); int spd_execute_command_with_reply(SPDConnection * connection, char *command, char **reply); int spd_execute_command_wo_mutex(SPDConnection * connection, char *command); char *spd_send_data(SPDConnection * connection, const char *message, int wfr); char *spd_send_data_wo_mutex(SPDConnection * connection, const char *message, int wfr); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* __cplusplus */ /* *INDENT-ON* */ #endif /* ifndef _LIBSPEECHD_H */ speech-dispatcher-0.8.3/src/api/c/Makefile.am0000664000175000017500000000176112530733575015675 00000000000000## Process this file with automake to produce Makefile.in spdinclude_HEADERS = libspeechd.h libspeechd_version.h inc_local = -I$(top_srcdir)/include/ BUILT_SOURCES = libspeechd_version.h lib_LTLIBRARIES = libspeechd.la libspeechd_la_SOURCES = libspeechd.c libspeechd_la_CFLAGS = $(ERROR_CFLAGS) libspeechd_la_CPPFLAGS = $(inc_local) -D_GNU_SOURCE $(GLIB_CFLAGS) -DSPD_SPAWN_CMD=\""$(prefix)/bin/speech-dispatcher"\" libspeechd_la_LDFLAGS = -version-info $(LIB_SPD_CURRENT):$(LIB_SPD_REVISION):$(LIB_SPD_AGE) libspeechd_la_LIBADD = $(GLIB_LIBS) libspeechd_version.h: $(srcdir)/libspeechd_version.h.in CLEANFILES = libspeechd_version.h EXTRA_DIST = libspeechd_version.h.in libspeechd_version.h: Makefile rm -f $@ srcdir=; \ test -f ./$@.in || srcdir=$(srcdir)/; \ $(edit_version) $${srcdir}$@.in > $@ edit_version = sed \ -e 's:[@]LIBSPEECHD_MAJOR_VERSION[@]:$(MAJOR_VERSION):' \ -e 's:[@]LIBSPEECHD_MINOR_VERSION[@]:$(MINOR_VERSION):' \ -e 's:[@]LIBSPEECHD_MICRO_VERSION[@]:$(MICRO_VERSION):' speech-dispatcher-0.8.3/src/api/c/libspeechd.c0000664000175000017500000014247612536417045016115 00000000000000/* libspeechd.c - Shared library for easy acces to Speech Dispatcher functions * * Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: libspeechd.c,v 1.37 2008-12-23 09:15:32 pdm Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * This is needed because speechd_types.h is in a different location in * the source tree's include directory than it will be when it is * installed on the user's system. */ #include #include #include "libspeechd.h" /* Comment/uncomment to switch debugging on/off */ // #define LIBSPEECHD_DEBUG 1 /* Unless there is an fatal error, it doesn't print anything */ #define SPD_FATAL(msg) { printf("Fatal error (libspeechd) [%s:%d]:"msg, __FILE__, __LINE__); fflush(stdout); exit(EXIT_FAILURE); } /* -------------- Private functions headers ------------------------*/ #ifdef LIBSPEECHD_DEBUG static FILE *spd_debug = NULL; #endif static int spd_set_priority(SPDConnection * connection, SPDPriority priority); static char *escape_dot(const char *text); static int isanum(char *str); static char *get_reply(SPDConnection * connection); static int get_err_code(char *reply); static char *get_param_str(char *reply, int num, int *err); static int get_param_int(char *reply, int num, int *err); static int ret_ok(char *reply); static void SPD_DBG(char *format, ...); static void *spd_events_handler(void *); const int range_low = -100; const int range_high = 100; pthread_mutex_t spd_logging_mutex; #if !(defined(__GLIBC__) && defined(_GNU_SOURCE)) /* Added by Willie Walker - strndup and getline are gcc-isms */ char *strndup(const char *s, size_t n) { size_t nAvail; char *p; if (!s) return 0; if (strlen(s) > n) nAvail = n + 1; else nAvail = strlen(s) + 1; p = malloc(nAvail); memcpy(p, s, nAvail); p[nAvail - 1] = '\0'; return p; } #define BUFFER_LEN 256 ssize_t getline(char **lineptr, size_t * n, FILE * f) { char ch; size_t m = 0; ssize_t buf_len = 0; char *buf = NULL; char *p = NULL; if (errno != 0) { SPD_DBG("getline: errno came in as %d!!!\n", errno); errno = 0; } while ((ch = getc(f)) != EOF) { if (errno != 0) return -1; if (m++ >= buf_len) { buf_len += BUFFER_LEN; buf = (char *)realloc(buf, buf_len + 1); if (buf == NULL) { SPD_DBG("buf==NULL"); return -1; } p = buf + buf_len - BUFFER_LEN; } *p = ch; p++; if (ch == '\n') break; } if (m == 0) { SPD_DBG("getline: m=%d!", m); return -1; } else { *p = '\0'; *lineptr = buf; *n = m; return m; } } #endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */ /* --------------------- Public functions ------------------------- */ #define SPD_REPLY_BUF_SIZE 65536 /* Determine address for the unix socket */ static char *_get_default_unix_socket_name(void) { GString *socket_filename; char *h; const char *rundir = g_get_user_runtime_dir(); socket_filename = g_string_new(""); g_string_printf(socket_filename, "%s/speech-dispatcher/speechd.sock", rundir); // Do not return glib string, but glibc string... h = strdup(socket_filename->str); g_string_free(socket_filename, 1); return h; } void SPDConnectionAddress__free(SPDConnectionAddress * address) { if (!address) return; free(address->unix_socket_name); free(address->inet_socket_host); free(address->dbus_bus); free(address); } SPDConnectionAddress *spd_get_default_address(char **error) { const gchar *env_address = g_getenv("SPEECHD_ADDRESS"); gchar **pa; /* parsed address */ SPDConnectionAddress *address = malloc(sizeof(SPDConnectionAddress)); address->unix_socket_name = NULL; address->inet_socket_host = NULL; address->dbus_bus = NULL; if (env_address == NULL) { // Default method = unix sockets address->method = SPD_METHOD_UNIX_SOCKET; address->unix_socket_name = _get_default_unix_socket_name(); } else { pa = g_strsplit(env_address, ":", 0); assert(pa); if (!g_strcmp0(pa[0], "unix_socket") || pa[0] == NULL) { // Unix sockets address->method = SPD_METHOD_UNIX_SOCKET; if (pa[1] == NULL) { address->unix_socket_name = _get_default_unix_socket_name(); } else { address->unix_socket_name = strdup(pa[1]); } } else if (!g_strcmp0(pa[0], "inet_socket")) { // Inet sockets address->method = SPD_METHOD_INET_SOCKET; if (pa[1] == NULL) { address->inet_socket_host = strdup("127.0.0.1"); address->inet_socket_port = 6560; } else { address->inet_socket_host = strdup(pa[1]); if (pa[2] == NULL) { address->inet_socket_port = SPEECHD_DEFAULT_PORT; } else { address->inet_socket_port = atoi(pa[2]); } } } else { // Unknown or unsupported method requested *error = strdup ("Unknown or unsupported communication method"); SPDConnectionAddress__free(address); address = NULL; } g_strfreev(pa); } return address; } static void _init_debug(void) { #ifdef LIBSPEECHD_DEBUG if (!spd_debug) { spd_debug = fopen("/tmp/libspeechd.log", "w"); if (spd_debug == NULL) SPD_FATAL("COULDN'T ACCES FILE INTENDED FOR DEBUG"); if (pthread_mutex_init(&spd_logging_mutex, NULL)) { fprintf(stderr, "Mutex initialization failed"); fflush(stderr); exit(1); } SPD_DBG("Debugging started"); } #endif /* LIBSPEECHD_DEBUG */ } /* Opens a new Speech Dispatcher connection. * Returns socket file descriptor of the created connection * or -1 if no connection was opened. */ SPDConnection *spd_open(const char *client_name, const char *connection_name, const char *user_name, SPDConnectionMode mode) { char *error; int autospawn = 1; SPDConnection *conn; conn = spd_open2(client_name, connection_name, user_name, mode, NULL, autospawn, &error); if (!conn) { _init_debug(); assert(error); SPD_DBG("Could not connect to Speech Dispatcher: %s", error); free(error); } return conn; } #define MAX_IP_SIZE 16+1 /* TODO: This only works in IPV4 */ static char *resolve_host(char *host_name_or_ip, int *is_localhost, gchar ** error) { struct addrinfo *addr_result; int err; char *resolve_buffer = malloc(MAX_IP_SIZE * sizeof(char)); const char *resolved_ip = NULL; char *ip; *error = NULL; struct sockaddr_in *addr_in; if (resolve_buffer == NULL) { *error = g_strdup("Failed to allocate memory."); return NULL; } err = getaddrinfo(host_name_or_ip, 0, NULL, &addr_result); if (err) { *error = g_strdup_printf("Can't resolve address %d due to error %s:", err, gai_strerror(err)); free(resolve_buffer); return NULL; } /* Take the first address returned as we are only interested in host ip */ addr_in = (struct sockaddr_in *)addr_result->ai_addr; resolved_ip = inet_ntop(AF_INET, &(addr_in->sin_addr.s_addr), resolve_buffer, MAX_IP_SIZE); if (resolved_ip == NULL) { *error = g_strdup_printf ("Could not convert address, due to the following error: %s", strerror(errno)); freeaddrinfo(addr_result); free(resolve_buffer); return NULL; } if (!strncmp(resolved_ip, "127.", 4)) { *is_localhost = 1; /* In case of local addresses, use 127.0.0.1 which is guaranteed to be local and the server listens on it */ free(resolve_buffer); ip = strdup("127.0.0.1"); } else { *is_localhost = 0; ip = resolve_buffer; } freeaddrinfo(addr_result); return ip; } static int spawn_server(SPDConnectionAddress * address, int is_localhost, gchar ** spawn_error) { gchar **speechd_cmd = malloc(16 * sizeof(char *)); gchar *stderr_output; gboolean spawn_ok; GError *gerror = NULL; int exit_status; int i; if ((address->method == SPD_METHOD_INET_SOCKET) && (!is_localhost)) { *spawn_error = g_strdup ("Spawn failed, the given network address doesn't seem to be on localhost"); return 1; } speechd_cmd[0] = g_strdup(SPD_SPAWN_CMD); speechd_cmd[1] = g_strdup("--spawn"); speechd_cmd[2] = g_strdup("--communication-method"); if (address->method == SPD_METHOD_INET_SOCKET) { speechd_cmd[3] = g_strdup("inet_socket"); speechd_cmd[4] = g_strdup("--port"); speechd_cmd[5] = g_strdup_printf("%d", address->inet_socket_port); speechd_cmd[6] = NULL; } else if (address->method == SPD_METHOD_UNIX_SOCKET) { speechd_cmd[3] = g_strdup("unix_socket"); speechd_cmd[4] = g_strdup("--socket-path"); speechd_cmd[5] = g_strdup_printf("%s", address->unix_socket_name); speechd_cmd[6] = NULL; } else assert(0); spawn_ok = g_spawn_sync(NULL, (gchar **) speechd_cmd, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL, NULL, NULL, NULL, &stderr_output, &exit_status, &gerror); for (i = 0; speechd_cmd[i] != NULL; i++) g_free(speechd_cmd[i]); if (!spawn_ok) { *spawn_error = g_strdup_printf("Autospawn failed. Spawn error %d: %s", gerror->code, gerror->message); return 1; } else { if (exit_status) { *spawn_error = g_strdup_printf ("Autospawn failed. Speech Dispatcher refused to start with error code, " "stating this as a reason: %s", stderr_output); return 1; } else { *spawn_error = NULL; return 0; } } assert(0); } SPDConnection *spd_open2(const char *client_name, const char *connection_name, const char *user_name, SPDConnectionMode mode, SPDConnectionAddress * address, int autospawn, char **error_result) { SPDConnection *connection; SPDConnectionAddress *defaultAddress = NULL; char *set_client_name; char *conn_name; char *usr_name; int ret; char tcp_no_delay = 1; /* Autospawn related */ int spawn_err; gchar *spawn_report; char *host_ip; int is_localhost = 1; struct sockaddr_in address_inet; struct sockaddr_un address_unix; struct sockaddr *sock_address; size_t sock_address_len; gchar *resolve_error; _init_debug(); if (client_name == NULL) { *error_result = strdup("ERROR: Client name not specified"); SPD_DBG(*error_result); return NULL; } if (user_name == NULL) { usr_name = strdup((char *)g_get_user_name()); } else usr_name = strdup(user_name); if (connection_name == NULL) conn_name = strdup("main"); else conn_name = strdup(connection_name); if (address == NULL) { char *err = NULL; defaultAddress = spd_get_default_address(&err); address = defaultAddress; if (!address) { assert(err); *error_result = err; SPD_DBG(*error_result); return NULL; } } /* Connect to server using the selected method */ connection = malloc(sizeof(SPDConnection)); if (address->method == SPD_METHOD_INET_SOCKET) { host_ip = resolve_host(address->inet_socket_host, &is_localhost, &resolve_error); if (host_ip == NULL) { *error_result = strdup(resolve_error); g_free(resolve_error); SPDConnectionAddress__free(defaultAddress); return NULL; } address_inet.sin_addr.s_addr = inet_addr(host_ip); address_inet.sin_port = htons(address->inet_socket_port); address_inet.sin_family = AF_INET; connection->socket = socket(AF_INET, SOCK_STREAM, 0); sock_address = (struct sockaddr *)&address_inet; sock_address_len = sizeof(address_inet); } else if (address->method == SPD_METHOD_UNIX_SOCKET) { /* Create the unix socket */ address_unix.sun_family = AF_UNIX; strncpy(address_unix.sun_path, address->unix_socket_name, sizeof(address_unix.sun_path)); address_unix.sun_path[sizeof(address_unix.sun_path) - 1] = '\0'; connection->socket = socket(AF_UNIX, SOCK_STREAM, 0); sock_address = (struct sockaddr *)&address_unix; sock_address_len = SUN_LEN(&address_unix); } else SPD_FATAL("Unsupported connection method for spd_open2()"); ret = connect(connection->socket, sock_address, sock_address_len); if (ret == -1) { /* Suppose server might not be running, try to autospawn (autostart) it */ if (autospawn) { spawn_err = spawn_server(address, is_localhost, &spawn_report); if (!spawn_err) spawn_report = g_strdup("Server successfully autospawned"); ret = connect(connection->socket, sock_address, sock_address_len); } else { spawn_report = g_strdup("Autospawn disabled"); } if (ret == -1) { if (address->method == SPD_METHOD_INET_SOCKET) *error_result = g_strdup_printf ("Error: Can't connect to %s on port %d using inet sockets: %s. " "Autospawn: %s", address->inet_socket_host, address->inet_socket_port, strerror(errno), spawn_report); else if (address->method == SPD_METHOD_UNIX_SOCKET) *error_result = g_strdup_printf ("Error: Can't connect to unix socket %s: %s. Autospawn: %s", address->unix_socket_name, strerror(errno), spawn_report); else assert(0); SPD_DBG(*error_result); close(connection->socket); SPDConnectionAddress__free(defaultAddress); return NULL; } g_free(spawn_report); } if (address->method == SPD_METHOD_INET_SOCKET) setsockopt(connection->socket, IPPROTO_TCP, TCP_NODELAY, &tcp_no_delay, sizeof(int)); connection->callback_begin = NULL; connection->callback_end = NULL; connection->callback_im = NULL; connection->callback_pause = NULL; connection->callback_resume = NULL; connection->callback_cancel = NULL; connection->mode = mode; /* Create a stream from the socket */ connection->stream = fdopen(connection->socket, "r"); if (!connection->stream) SPD_FATAL("Can't create a stream for socket, fdopen() failed."); /* Switch to line buffering mode */ ret = setvbuf(connection->stream, NULL, _IONBF, SPD_REPLY_BUF_SIZE); if (ret) SPD_FATAL("Can't set buffering, setvbuf failed."); connection->ssip_mutex = malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(connection->ssip_mutex, NULL); if (mode == SPD_MODE_THREADED) { SPD_DBG ("Initializing threads, condition variables and mutexes..."); connection->events_thread = malloc(sizeof(pthread_t)); connection->cond_reply_ready = malloc(sizeof(pthread_cond_t)); connection->mutex_reply_ready = malloc(sizeof(pthread_mutex_t)); connection->cond_reply_ack = malloc(sizeof(pthread_cond_t)); connection->mutex_reply_ack = malloc(sizeof(pthread_mutex_t)); pthread_cond_init(connection->cond_reply_ready, NULL); pthread_mutex_init(connection->mutex_reply_ready, NULL); pthread_cond_init(connection->cond_reply_ack, NULL); pthread_mutex_init(connection->mutex_reply_ack, NULL); ret = pthread_create(connection->events_thread, NULL, spd_events_handler, connection); if (ret != 0) { *error_result = strdup("Thread initialization failed"); SPD_DBG(*error_result); SPDConnectionAddress__free(defaultAddress); return NULL; } } /* By now, the connection is created and operational */ set_client_name = g_strdup_printf("SET SELF CLIENT_NAME \"%s:%s:%s\"", usr_name, client_name, conn_name); ret = spd_execute_command_wo_mutex(connection, set_client_name); free(usr_name); free(conn_name); free(set_client_name); SPDConnectionAddress__free(defaultAddress); return connection; } #define RET(r) \ { \ pthread_mutex_unlock(connection->ssip_mutex); \ return r; \ } /* Close a Speech Dispatcher connection */ void spd_close(SPDConnection * connection) { pthread_mutex_lock(connection->ssip_mutex); if (connection->mode == SPD_MODE_THREADED) { pthread_cancel(*connection->events_thread); pthread_mutex_destroy(connection->mutex_reply_ready); pthread_mutex_destroy(connection->mutex_reply_ack); pthread_cond_destroy(connection->cond_reply_ready); pthread_cond_destroy(connection->cond_reply_ack); pthread_join(*connection->events_thread, NULL); connection->mode = SPD_MODE_SINGLE; free(connection->mutex_reply_ready); free(connection->mutex_reply_ack); free(connection->cond_reply_ready); free(connection->cond_reply_ack); } /* close the socket */ close(connection->socket); pthread_mutex_unlock(connection->ssip_mutex); pthread_mutex_destroy(connection->ssip_mutex); free(connection->ssip_mutex); free(connection); } /* Helper functions for spd_say. */ static inline int spd_say_prepare(SPDConnection * connection, SPDPriority priority, const char *text, char **escaped_text) { int ret = 0; SPD_DBG("Text to say is: %s", text); /* Insure that there is no escape sequence in the text */ *escaped_text = escape_dot(text); /* Caller is now responsible for escaped_text. */ if (*escaped_text == NULL) { /* Out of memory. */ SPD_DBG("spd_say could not allocate memory."); ret = -1; } else { /* Set priority */ SPD_DBG("Setting priority"); ret = spd_set_priority(connection, priority); if (!ret) { /* Start the data flow */ SPD_DBG("Sending SPEAK"); ret = spd_execute_command_wo_mutex(connection, "speak"); if (ret) { SPD_DBG("Error: Can't start data flow!"); } } } return ret; } static inline int spd_say_sending(SPDConnection * connection, const char *text) { int msg_id = -1; int err = 0; char *reply = NULL; char *pret = NULL; /* Send data */ SPD_DBG("Sending data"); pret = spd_send_data_wo_mutex(connection, text, SPD_NO_REPLY); if (pret == NULL) { SPD_DBG("Can't send data wo mutex"); } else { /* Terminate data flow */ SPD_DBG("Terminating data flow"); err = spd_execute_command_with_reply(connection, "\r\n.", &reply); if (err) { SPD_DBG("Can't terminate data flow"); } else { msg_id = get_param_int(reply, 1, &err); if (err < 0) { SPD_DBG ("Can't determine SSIP message unique ID parameter."); msg_id = -1; } } } free(reply); free(pret); return msg_id; } /* Say TEXT with priority PRIORITY. * Returns msg_uid on success, -1 otherwise. */ int spd_say(SPDConnection * connection, SPDPriority priority, const char *text) { char *escaped_text = NULL; int msg_id = -1; int prepare_failed = 0; if (text != NULL) { pthread_mutex_lock(connection->ssip_mutex); prepare_failed = spd_say_prepare(connection, priority, text, &escaped_text); if (!prepare_failed) msg_id = spd_say_sending(connection, escaped_text); free(escaped_text); pthread_mutex_unlock(connection->ssip_mutex); } else { SPD_DBG("spd_say called with a NULL argument for "); } SPD_DBG("Returning from spd_say"); return msg_id; } /* The same as spd_say, accepts also formated strings */ int spd_sayf(SPDConnection * connection, SPDPriority priority, const char *format, ...) { static int ret; va_list args; char *buf; if (format == NULL) return -1; /* Print the text to buffer */ va_start(args, format); buf = g_strdup_vprintf(format, args); va_end(args); /* Send the buffer to Speech Dispatcher */ ret = spd_say(connection, priority, buf); free(buf); return ret; } int spd_stop(SPDConnection * connection) { return spd_execute_command(connection, "STOP SELF"); } int spd_stop_all(SPDConnection * connection) { return spd_execute_command(connection, "STOP ALL"); } int spd_stop_uid(SPDConnection * connection, int target_uid) { static char command[16]; sprintf(command, "STOP %d", target_uid); return spd_execute_command(connection, command); } int spd_cancel(SPDConnection * connection) { return spd_execute_command(connection, "CANCEL SELF"); } int spd_cancel_all(SPDConnection * connection) { return spd_execute_command(connection, "CANCEL ALL"); } int spd_cancel_uid(SPDConnection * connection, int target_uid) { static char command[16]; sprintf(command, "CANCEL %d", target_uid); return spd_execute_command(connection, command); } int spd_pause(SPDConnection * connection) { return spd_execute_command(connection, "PAUSE SELF"); } int spd_pause_all(SPDConnection * connection) { return spd_execute_command(connection, "PAUSE ALL"); } int spd_pause_uid(SPDConnection * connection, int target_uid) { char command[16]; sprintf(command, "PAUSE %d", target_uid); return spd_execute_command(connection, command); } int spd_resume(SPDConnection * connection) { return spd_execute_command(connection, "RESUME SELF"); } int spd_resume_all(SPDConnection * connection) { return spd_execute_command(connection, "RESUME ALL"); } int spd_resume_uid(SPDConnection * connection, int target_uid) { static char command[16]; sprintf(command, "RESUME %d", target_uid); return spd_execute_command(connection, command); } int spd_key(SPDConnection * connection, SPDPriority priority, const char *key_name) { char *command_key; int ret; if (key_name == NULL) return -1; pthread_mutex_lock(connection->ssip_mutex); ret = spd_set_priority(connection, priority); if (ret) RET(-1); command_key = g_strdup_printf("KEY %s", key_name); ret = spd_execute_command_wo_mutex(connection, command_key); free(command_key); if (ret) RET(-1); pthread_mutex_unlock(connection->ssip_mutex); return 0; } int spd_char(SPDConnection * connection, SPDPriority priority, const char *character) { static char command[16]; int ret; if (character == NULL) return -1; if (strlen(character) > 6) return -1; pthread_mutex_lock(connection->ssip_mutex); ret = spd_set_priority(connection, priority); if (ret) RET(-1); sprintf(command, "CHAR %s", character); ret = spd_execute_command_wo_mutex(connection, command); if (ret) RET(-1); pthread_mutex_unlock(connection->ssip_mutex); return 0; } int spd_wchar(SPDConnection * connection, SPDPriority priority, wchar_t wcharacter) { static char command[16]; char character[8]; int ret; pthread_mutex_lock(connection->ssip_mutex); ret = wcrtomb(character, wcharacter, NULL); if (ret <= 0) RET(-1); ret = spd_set_priority(connection, priority); if (ret) RET(-1); assert(character != NULL); sprintf(command, "CHAR %s", character); ret = spd_execute_command_wo_mutex(connection, command); if (ret) RET(-1); pthread_mutex_unlock(connection->ssip_mutex); return 0; } int spd_sound_icon(SPDConnection * connection, SPDPriority priority, const char *icon_name) { char *command; int ret; if (icon_name == NULL) return -1; pthread_mutex_lock(connection->ssip_mutex); ret = spd_set_priority(connection, priority); if (ret) RET(-1); command = g_strdup_printf("SOUND_ICON %s", icon_name); ret = spd_execute_command_wo_mutex(connection, command); free(command); if (ret) RET(-1); pthread_mutex_unlock(connection->ssip_mutex); return 0; } int spd_w_set_punctuation(SPDConnection * connection, SPDPunctuation type, const char *who) { char command[32]; int ret; if (type == SPD_PUNCT_ALL) sprintf(command, "SET %s PUNCTUATION all", who); if (type == SPD_PUNCT_NONE) sprintf(command, "SET %s PUNCTUATION none", who); if (type == SPD_PUNCT_SOME) sprintf(command, "SET %s PUNCTUATION some", who); ret = spd_execute_command(connection, command); return ret; } int spd_w_set_capital_letters(SPDConnection * connection, SPDCapitalLetters type, const char *who) { char command[64]; int ret; if (type == SPD_CAP_NONE) sprintf(command, "SET %s CAP_LET_RECOGN none", who); if (type == SPD_CAP_SPELL) sprintf(command, "SET %s CAP_LET_RECOGN spell", who); if (type == SPD_CAP_ICON) sprintf(command, "SET %s CAP_LET_RECOGN icon", who); ret = spd_execute_command(connection, command); return ret; } int spd_w_set_spelling(SPDConnection * connection, SPDSpelling type, const char *who) { char command[32]; int ret; if (type == SPD_SPELL_ON) sprintf(command, "SET %s SPELLING on", who); if (type == SPD_SPELL_OFF) sprintf(command, "SET %s SPELLING off", who); ret = spd_execute_command(connection, command); return ret; } int spd_set_data_mode(SPDConnection * connection, SPDDataMode mode) { char command[32]; int ret; if (mode == SPD_DATA_TEXT) sprintf(command, "SET SELF SSML_MODE off"); if (mode == SPD_DATA_SSML) sprintf(command, "SET SELF SSML_MODE on"); ret = spd_execute_command(connection, command); return ret; } int spd_w_set_voice_type(SPDConnection * connection, SPDVoiceType type, const char *who) { static char command[64]; switch (type) { case SPD_MALE1: sprintf(command, "SET %s VOICE_TYPE MALE1", who); break; case SPD_MALE2: sprintf(command, "SET %s VOICE_TYPE MALE2", who); break; case SPD_MALE3: sprintf(command, "SET %s VOICE_TYPE MALE3", who); break; case SPD_FEMALE1: sprintf(command, "SET %s VOICE_TYPE FEMALE1", who); break; case SPD_FEMALE2: sprintf(command, "SET %s VOICE_TYPE FEMALE2", who); break; case SPD_FEMALE3: sprintf(command, "SET %s VOICE_TYPE FEMALE3", who); break; case SPD_CHILD_MALE: sprintf(command, "SET %s VOICE_TYPE CHILD_MALE", who); break; case SPD_CHILD_FEMALE: sprintf(command, "SET %s VOICE_TYPE CHILD_FEMALE", who); break; default: return -1; } return spd_execute_command(connection, command); } static int spd_w_set_command_int(SPDConnection * connection, const char *ssip_name, signed int val, const char *who) { static char command[64]; // NOTE: if any new int ssip_name are added that don't use -100 - 100 as their // range, these values will need to become parameters (or the new ssip_name) // methods will need to call a different helper method. if (val < range_low || val > range_high) return -1; sprintf(command, "SET %s %s %d", who, ssip_name, val); return spd_execute_command(connection, command); } static int spd_get_command_int(SPDConnection * connection, const char *ssip_name) { char *command; int ret = 0; int err; char *reply = NULL; command = g_strdup_printf("GET %s", ssip_name); spd_execute_command_with_reply(connection, command, &reply); free(command); ret = get_param_int(reply, 1, &err); free(reply); return ret; } static int spd_w_set_command_str(SPDConnection * connection, const char *ssip_name, const char *str, const char *who) { char *command; int ret; if (str == NULL) return -1; command = g_strdup_printf("SET %s %s %s", who, ssip_name, str); ret = spd_execute_command(connection, command); free(command); return ret; } static char *spd_get_command_str(SPDConnection * connection, const char *ssip_name) { char *command; char *ret = NULL; int err; char *reply = NULL; command = g_strdup_printf("GET %s", ssip_name); spd_execute_command_with_reply(connection, command, &reply); free(command); ret = get_param_str(reply, 1, &err); free(reply); return ret; } #define SPD_SET_COMMAND_SPECIAL(param, type) \ int \ spd_set_ ## param (SPDConnection *connection, type val) \ { \ return spd_w_set_ ## param (connection, val, SPD_SELF); \ } \ int \ spd_set_ ## param ## _all(SPDConnection *connection, type val) \ { \ return spd_w_set_ ## param (connection, val, SPD_ALLCLIENTS); \ } \ int \ spd_set_ ## param ## _uid(SPDConnection *connection, type val, unsigned int uid) \ { \ char who[8]; \ sprintf(who, "%d", uid); \ return spd_w_set_ ## param (connection, val, who); \ } #define SPD_GET_COMMAND_SPECIAL(param, type) \ type \ spd_get_ ## param (SPDConnection *connection) \ { \ char *command; \ type ret; \ int err; \ char *reply = NULL; \ command = g_strdup_printf("GET " #param); \ spd_execute_command_with_reply(connection, command, &reply); \ free(command); \ ret = get_param_int(reply, 1, &err); \ free(reply); \ return ret; \ } // Set methods for rate int spd_set_voice_rate(SPDConnection * connection, signed int rate) { return spd_w_set_command_int(connection, SPD_RATE, rate, SPD_SELF); } int spd_set_voice_rate_all(SPDConnection * connection, signed int rate) { return spd_w_set_command_int(connection, SPD_RATE, rate, SPD_ALLCLIENTS); } int spd_set_voice_rate_uid(SPDConnection * connection, signed int rate, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_int(connection, SPD_RATE, rate, who); } // Get method for rate int spd_get_voice_rate(SPDConnection * connection) { return spd_get_command_int(connection, SPD_RATE); } // Set methods for pitch int spd_set_voice_pitch(SPDConnection * connection, signed int pitch) { return spd_w_set_command_int(connection, SPD_PITCH, pitch, SPD_SELF); } int spd_set_voice_pitch_all(SPDConnection * connection, signed int pitch) { return spd_w_set_command_int(connection, SPD_PITCH, pitch, SPD_ALLCLIENTS); } int spd_set_voice_pitch_uid(SPDConnection * connection, signed int pitch, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_int(connection, SPD_PITCH, pitch, who); } // Get method for pitch int spd_get_voice_pitch(SPDConnection * connection) { return spd_get_command_int(connection, SPD_PITCH); } // Set methods for volume int spd_set_volume(SPDConnection * connection, signed int volume) { return spd_w_set_command_int(connection, SPD_VOLUME, volume, SPD_SELF); } int spd_set_volume_all(SPDConnection * connection, signed int volume) { return spd_w_set_command_int(connection, SPD_VOLUME, volume, SPD_ALLCLIENTS); } int spd_set_volume_uid(SPDConnection * connection, signed int volume, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_int(connection, SPD_VOLUME, volume, who); } // Get method for volume int spd_get_volume(SPDConnection * connection) { return spd_get_command_int(connection, SPD_VOLUME); } // Set methods for language int spd_set_language(SPDConnection * connection, const char *language) { return spd_w_set_command_str(connection, SPD_LANGUAGE, language, SPD_SELF); } int spd_set_language_all(SPDConnection * connection, const char *language) { return spd_w_set_command_str(connection, SPD_LANGUAGE, language, SPD_ALLCLIENTS); } int spd_set_language_uid(SPDConnection * connection, const char *language, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_str(connection, SPD_LANGUAGE, language, who); } // Get method for language char *spd_get_language(SPDConnection * connection) { return spd_get_command_str(connection, SPD_LANGUAGE); } // Set methods for output_module int spd_set_output_module(SPDConnection * connection, const char *output_module) { return spd_w_set_command_str(connection, SPD_OUTPUT_MODULE, output_module, SPD_SELF); } int spd_set_output_module_all(SPDConnection * connection, const char *output_module) { return spd_w_set_command_str(connection, SPD_OUTPUT_MODULE, output_module, SPD_ALLCLIENTS); } int spd_set_output_module_uid(SPDConnection * connection, const char *output_module, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_str(connection, SPD_OUTPUT_MODULE, output_module, who); } // Get method for output_module char *spd_get_output_module(SPDConnection * connection) { return spd_get_command_str(connection, SPD_OUTPUT_MODULE); } // Set methods for synthesis_voice int spd_set_synthesis_voice(SPDConnection * connection, const char *voice_name) { return spd_w_set_command_str(connection, SPD_SYNTHESIS_VOICE, voice_name, SPD_SELF); } int spd_set_synthesis_voice_all(SPDConnection * connection, const char *voice_name) { return spd_w_set_command_str(connection, SPD_SYNTHESIS_VOICE, voice_name, SPD_ALLCLIENTS); } int spd_set_synthesis_voice_uid(SPDConnection * connection, const char *voice_name, unsigned int uid) { char who[8]; sprintf(who, "%d", uid); return spd_w_set_command_str(connection, SPD_SYNTHESIS_VOICE, voice_name, who); } SPD_SET_COMMAND_SPECIAL(punctuation, SPDPunctuation) SPD_SET_COMMAND_SPECIAL(capital_letters, SPDCapitalLetters) SPD_SET_COMMAND_SPECIAL(spelling, SPDSpelling) SPD_SET_COMMAND_SPECIAL(voice_type, SPDVoiceType) SPD_GET_COMMAND_SPECIAL(voice_type, SPDVoiceType) #undef SPD_SET_COMMAND_SPECIAL int spd_set_notification_on(SPDConnection * connection, SPDNotification notification) { if (connection->mode == SPD_MODE_THREADED) return spd_set_notification(connection, notification, "on"); else return -1; } int spd_set_notification_off(SPDConnection * connection, SPDNotification notification) { if (connection->mode == SPD_MODE_THREADED) return spd_set_notification(connection, notification, "off"); else return -1; } #define NOTIFICATION_SET(val, ssip_val) \ if (notification & val){ \ sprintf(command, "SET SELF NOTIFICATION "ssip_val" %s", state);\ ret = spd_execute_command_wo_mutex(connection, command);\ if (ret < 0) RET(-1);\ } int spd_set_notification(SPDConnection * connection, SPDNotification notification, const char *state) { static char command[64]; int ret; if (connection->mode != SPD_MODE_THREADED) return -1; if (state == NULL) { SPD_DBG("Requested state is NULL"); return -1; } if (strcmp(state, "on") && strcmp(state, "off")) { SPD_DBG("Invalid argument for spd_set_notification: %s", state); return -1; } pthread_mutex_lock(connection->ssip_mutex); NOTIFICATION_SET(SPD_INDEX_MARKS, "index_marks"); NOTIFICATION_SET(SPD_BEGIN, "begin"); NOTIFICATION_SET(SPD_END, "end"); NOTIFICATION_SET(SPD_CANCEL, "cancel"); NOTIFICATION_SET(SPD_PAUSE, "pause"); NOTIFICATION_SET(SPD_RESUME, "resume"); NOTIFICATION_SET(SPD_ALL, "all"); pthread_mutex_unlock(connection->ssip_mutex); return 0; } #undef NOTIFICATION_SET /* spd_list_modules retrieves information about the available output modules. The return value is a null-terminated array of strings containing output module names. */ char **spd_list_modules(SPDConnection * connection) { char **available_modules; available_modules = spd_execute_command_with_list_reply(connection, "LIST OUTPUT_MODULES"); return available_modules; } void free_spd_modules(char **modules) { int i = 0; while (modules != NULL && modules[i] != NULL) { free(modules[i]); ++i; } free(modules); } char **spd_list_voices(SPDConnection * connection) { char **voices; voices = spd_execute_command_with_list_reply(connection, "LIST VOICES"); return voices; } SPDVoice **spd_list_synthesis_voices(SPDConnection * connection) { char **svoices_str; SPDVoice **svoices; int i, num_items; svoices_str = spd_execute_command_with_list_reply(connection, "LIST SYNTHESIS_VOICES"); if (svoices_str == NULL) return NULL; for (i = 0;; i++) if (svoices_str[i] == NULL) break; num_items = i; svoices = (SPDVoice **) malloc((num_items + 1) * sizeof(SPDVoice *)); for (i = 0; i <= num_items; i++) { const char delimiters[] = " "; char *running; if (svoices_str[i] == NULL) break; running = strdup(svoices_str[i]); svoices[i] = (SPDVoice *) malloc(sizeof(SPDVoice)); svoices[i]->name = strsep(&running, delimiters); svoices[i]->language = strsep(&running, delimiters); svoices[i]->variant = strsep(&running, delimiters); assert(svoices[i]->name != NULL); } svoices[num_items] = NULL; return svoices; } void free_spd_voices(SPDVoice ** voices) { int i = 0; while (voices != NULL && voices[i] != NULL) { free(voices[i]->name); free(voices[i]); ++i; } free(voices); } char **spd_execute_command_with_list_reply(SPDConnection * connection, char *command) { char *reply = NULL; char *line; int err; int max_items = 50; char **result; int i; spd_execute_command_with_reply(connection, command, &reply); if (!ret_ok(reply)) { if (reply != NULL) free(reply); return NULL; } result = malloc((max_items + 1) * sizeof(char *)); for (i = 0;; i++) { line = get_param_str(reply, i + 1, &err); if ((err) || (line == NULL)) break; result[i] = line; if (i >= max_items - 2) { max_items *= 2; result = realloc(result, max_items * sizeof(char *)); } } result[i] = NULL; free(reply); return result; } //int //spd_get_client_list(SPDConnection *connection, char **client_names, int *client_ids, int* active){ // SPD_DBG("spd_get_client_list: History is not yet implemented."); // return -1; // //} int spd_get_message_list_fd(SPDConnection * connection, int target, int *msg_ids, char **client_names) { SPD_DBG("spd_get_client_list: History is not yet implemented."); return -1; #if 0 sprintf(command, "HISTORY GET MESSAGE_LIST %d 0 20\r\n", target); reply = spd_send_data(fd, command, 1); /* header_ok = parse_response_header(reply); if(header_ok != 1){ free(reply); return -1; } */ for (count = 0;; count++) { record = (char *)parse_response_data(reply, count + 1); if (record == NULL) break; record_int = get_rec_int(record, 0); msg_ids[count] = record_int; record_str = (char *)get_rec_str(record, 1); assert(record_str != NULL); client_names[count] = record_str; } return count; #endif } int spd_execute_command(SPDConnection * connection, char *command) { char *reply; int ret; pthread_mutex_lock(connection->ssip_mutex); ret = spd_execute_command_with_reply(connection, command, &reply); if (ret) { SPD_DBG("Can't execute command in spd_execute_command"); } free(reply); pthread_mutex_unlock(connection->ssip_mutex); return ret; } int spd_execute_command_wo_mutex(SPDConnection * connection, char *command) { char *reply; int ret; SPD_DBG("Executing command wo_mutex"); ret = spd_execute_command_with_reply(connection, command, &reply); if (ret) SPD_DBG ("Can't execute command in spd_execute_command_wo_mutex"); free(reply); return ret; } int spd_execute_command_with_reply(SPDConnection * connection, char *command, char **reply) { char *buf; int r; SPD_DBG("Inside execute_command_with_reply"); buf = g_strdup_printf("%s\r\n", command); *reply = spd_send_data_wo_mutex(connection, buf, SPD_WAIT_REPLY); free(buf); buf = NULL; if (*reply == NULL) { SPD_DBG ("Can't send data wo mutex in spd_execute_command_with_reply"); return -1; } r = ret_ok(*reply); if (!r) return -1; else return 0; } char *spd_send_data(SPDConnection * connection, const char *message, int wfr) { char *reply; pthread_mutex_lock(connection->ssip_mutex); if (connection->stream == NULL) RET(NULL); reply = spd_send_data_wo_mutex(connection, message, wfr); if (reply == NULL) { SPD_DBG("Can't send data wo mutex in spd_send_data"); RET(NULL); } pthread_mutex_unlock(connection->ssip_mutex); return reply; } char *spd_send_data_wo_mutex(SPDConnection * connection, const char *message, int wfr) { char *reply; int bytes; SPD_DBG("Inside spd_send_data_wo_mutex"); if (connection->stream == NULL) return NULL; if (connection->mode == SPD_MODE_THREADED) { /* Make sure we don't get the cond_reply_ready signal before we are in cond_wait() */ pthread_mutex_lock(connection->mutex_reply_ready); } /* write message to the socket */ SPD_DBG("Writing to socket"); if (!write(connection->socket, message, strlen(message))) { SPD_DBG("Can't write to socket: %s", strerror(errno)); pthread_mutex_unlock(connection->mutex_reply_ready); return NULL; } SPD_DBG("Written to socket"); SPD_DBG(">> : |%s|", message); /* read reply to the buffer */ if (wfr) { if (connection->mode == SPD_MODE_THREADED) { /* Wait until the reply is ready */ SPD_DBG ("Waiting for cond_reply_ready in spd_send_data_wo_mutex"); pthread_cond_wait(connection->cond_reply_ready, connection->mutex_reply_ready); SPD_DBG("Condition for cond_reply_ready satisfied"); pthread_mutex_unlock(connection->mutex_reply_ready); SPD_DBG ("Reading the reply in spd_send_data_wo_mutex threaded mode"); /* Read the reply */ if (connection->reply != NULL) { reply = strdup(connection->reply); } else { SPD_DBG ("Error: Can't read reply, broken socket in spd_send_data."); return NULL; } free(connection->reply); bytes = strlen(reply); if (bytes == 0) { SPD_DBG("Error: Empty reply, broken socket."); return NULL; } /* Signal the reply has been read */ pthread_mutex_lock(connection->mutex_reply_ack); pthread_cond_signal(connection->cond_reply_ack); pthread_mutex_unlock(connection->mutex_reply_ack); } else { reply = get_reply(connection); } if (reply != NULL) SPD_DBG("<< : |%s|\n", reply); } else { if (connection->mode == SPD_MODE_THREADED) pthread_mutex_unlock(connection->mutex_reply_ready); SPD_DBG("<< : no reply expected"); return strdup("NO REPLY"); } if (reply == NULL) SPD_DBG ("Reply from get_reply is NULL in spd_send_data_wo_mutex"); SPD_DBG("Returning from spd_send_data_wo_mutex"); return reply; } /* --------------------- Internal functions ------------------------- */ static int spd_set_priority(SPDConnection * connection, SPDPriority priority) { static char p_name[16]; static char command[64]; switch (priority) { case SPD_IMPORTANT: strcpy(p_name, "IMPORTANT"); break; case SPD_MESSAGE: strcpy(p_name, "MESSAGE"); break; case SPD_TEXT: strcpy(p_name, "TEXT"); break; case SPD_NOTIFICATION: strcpy(p_name, "NOTIFICATION"); break; case SPD_PROGRESS: strcpy(p_name, "PROGRESS"); break; default: SPD_DBG("Error: Can't set priority! Incorrect value."); return -1; } sprintf(command, "SET SELF PRIORITY %s", p_name); return spd_execute_command_wo_mutex(connection, command); } static char *get_reply(SPDConnection * connection) { GString *str; char *line = NULL; size_t N = 0; int bytes; char *reply; gboolean errors = FALSE; str = g_string_new(""); /* Wait for activity on the socket, when there is some, read all the message line by line */ do { bytes = getline(&line, &N, connection->stream); if (bytes == -1) { SPD_DBG ("Error: Can't read reply, broken socket in get_reply!"); if (connection->stream != NULL) fclose(connection->stream); connection->stream = NULL; errors = TRUE; } else { g_string_append(str, line); } /* terminate if we reached the last line (without '-' after numcode) */ } while (!errors && !((strlen(line) < 4) || (line[3] == ' '))); free(line); /* getline allocates with malloc. */ if (errors) { /* Free the GString and its character data, and return NULL. */ g_string_free(str, TRUE); reply = NULL; } else { /* The resulting message received from the socket is stored in reply */ reply = str->str; /* Free the GString, but not its character data. */ g_string_free(str, FALSE); } return reply; } static void *spd_events_handler(void *conn) { char *reply; int reply_code; SPDConnection *connection = conn; while (1) { /* Read the reply/event (block if none is available) */ SPD_DBG("Getting reply in spd_events_handler"); reply = get_reply(connection); if (reply == NULL) { SPD_DBG("ERROR: BROKEN SOCKET"); reply_code = -1; } else { SPD_DBG("<< : |%s|\n", reply); reply_code = get_err_code(reply); } if ((reply_code >= 700) && (reply_code < 800)) { int msg_id; int client_id; int err; SPD_DBG("Callback detected: %s", reply); /* This is an index mark */ /* Extract message id */ msg_id = get_param_int(reply, 1, &err); if (err < 0) { SPD_DBG ("Bad reply from Speech Dispatcher: %s (code %d)", reply, err); free(reply); break; } client_id = get_param_int(reply, 2, &err); if (err < 0) { SPD_DBG ("Bad reply from Speech Dispatcher: %s (code %d)", reply, err); free(reply); break; } /* Decide if we want to call a callback */ if ((reply_code == 701) && (connection->callback_begin)) connection->callback_begin(msg_id, client_id, SPD_EVENT_BEGIN); if ((reply_code == 702) && (connection->callback_end)) connection->callback_end(msg_id, client_id, SPD_EVENT_END); if ((reply_code == 703) && (connection->callback_cancel)) connection->callback_cancel(msg_id, client_id, SPD_EVENT_CANCEL); if ((reply_code == 704) && (connection->callback_pause)) connection->callback_pause(msg_id, client_id, SPD_EVENT_PAUSE); if ((reply_code == 705) && (connection->callback_resume)) connection->callback_resume(msg_id, client_id, SPD_EVENT_RESUME); if ((reply_code == 700) && (connection->callback_im)) { char *im; int err; im = get_param_str(reply, 3, &err); if ((err < 0) || (im == NULL)) { SPD_DBG ("Broken reply from Speech Dispatcher: %s", reply); free(reply); break; } /* Call the callback */ connection->callback_im(msg_id, client_id, SPD_EVENT_INDEX_MARK, im); free(im); } free(reply); } else { /* This is a protocol reply */ pthread_mutex_lock(connection->mutex_reply_ready); /* Prepare the reply to the reply buffer in connection */ if (reply != NULL) { connection->reply = reply; } else { SPD_DBG("Connection reply is NULL"); connection->reply = NULL; break; } /* Signal the reply is available on the condition variable */ /* this order is correct and necessary */ pthread_cond_signal(connection->cond_reply_ready); pthread_mutex_lock(connection->mutex_reply_ack); pthread_mutex_unlock(connection->mutex_reply_ready); /* Wait until it has bean read */ pthread_cond_wait(connection->cond_reply_ack, connection->mutex_reply_ack); pthread_mutex_unlock(connection->mutex_reply_ack); /* Continue */ } } /* In case of broken socket, we must still signal reply ready */ if (connection->reply == NULL) { SPD_DBG("Signalling reply ready after communication failure"); pthread_mutex_unlock(connection->mutex_reply_ready); pthread_mutex_unlock(connection->mutex_reply_ack); if (connection->stream != NULL) fclose(connection->stream); connection->stream = NULL; pthread_cond_signal(connection->cond_reply_ready); pthread_exit(0); } return 0; /* to please gcc */ } static int ret_ok(char *reply) { int err; if (reply == NULL) return -1; err = get_err_code(reply); if ((err >= 100) && (err < 300)) return 1; if (err >= 300) return 0; SPD_FATAL("Internal error during communication."); } static char *get_param_str(char *reply, int num, int *err) { int i; char *tptr; char *pos; char *pos_begin; char *pos_end; char *rep; assert(err != NULL); if (num < 1) { *err = -1; return NULL; } pos = reply; for (i = 0; i <= num - 2; i++) { pos = strstr(pos, "\r\n"); if (pos == NULL) { *err = -2; return NULL; } pos += 2; } if (strlen(pos) < 4) return NULL; *err = strtol(pos, &tptr, 10); if (*err >= 300 && *err <= 399) return NULL; if ((*tptr != '-') || (tptr != pos + 3)) { *err = -3; return NULL; } pos_begin = pos + 4; pos_end = strstr(pos_begin, "\r\n"); if (pos_end == NULL) { *err = -4; return NULL; } rep = (char *)strndup(pos_begin, pos_end - pos_begin); *err = 0; return rep; } static int get_param_int(char *reply, int num, int *err) { char *rep_str; char *tptr; int ret; rep_str = get_param_str(reply, num, err); if (rep_str == NULL) { /* err is already set to the error return code, just return */ return 0; } ret = strtol(rep_str, &tptr, 10); if (*tptr != '\0') { /* this is not a number */ *err = -3; return 0; } free(rep_str); return ret; } static int get_err_code(char *reply) { char err_code[4]; int err; if (reply == NULL) return -1; SPD_DBG("spd_send_data: reply: %s\n", reply); err_code[0] = reply[0]; err_code[1] = reply[1]; err_code[2] = reply[2]; err_code[3] = '\0'; SPD_DBG("ret_ok: err_code: |%s|\n", err_code); if (isanum(err_code)) { err = atoi(err_code); } else { SPD_DBG("ret_ok: not a number\n"); return -1; } return err; } /* isanum() tests if the given string is a number, * returns 1 if yes, 0 otherwise. */ static int isanum(char *str) { int i; if (str == NULL) return 0; for (i = 0; i <= strlen(str) - 1; i++) { if (!isdigit(str[i])) return 0; } return 1; } /* * escape_dot: Replace . with .. at the start of lines. * @text: text to escape * @Returns: An allocated string, containing the escaped text. */ static char *escape_dot(const char *text) { size_t orig_len = 0; const char *orig_end; char *result = NULL; char *result_ptr; static const char *ESCAPED_DOTLINE = "\r\n.."; static const size_t ESCAPED_DOTLINELEN = 4; static const size_t DOTLINELEN = 3; if (text == NULL) return NULL; orig_len = strlen(text); orig_end = text + orig_len; result = malloc((orig_len * 2 + 1) * sizeof(char)); if (result == NULL) return NULL; result_ptr = result; /* We're over-allocating. Even if we replaced every character * in text with "..", the length of the escaped string can be no more * than orig_len * 2. We could tighten that upper bound with * a little more work. */ if ((orig_len >= 1) && (text[0] == '.')) { *(result_ptr++) = '.'; *(result_ptr++) = '.'; text += 1; } while (text < orig_end) { if ((text[0] == '\r') && (text[1] == '\n') && (text[2] == '.')) { memcpy(result_ptr, ESCAPED_DOTLINE, ESCAPED_DOTLINELEN); result_ptr += ESCAPED_DOTLINELEN; text += DOTLINELEN; } else { *(result_ptr++) = *(text++); } } *result_ptr = '\0'; return result; } #ifdef LIBSPEECHD_DEBUG static void SPD_DBG(char *format, ...) { va_list args; pthread_mutex_lock(&spd_logging_mutex); va_start(args, format); vfprintf(spd_debug, format, args); va_end(args); fprintf(spd_debug, "\n"); fflush(spd_debug); pthread_mutex_unlock(&spd_logging_mutex); } #else /* LIBSPEECHD_DEBUG */ static void SPD_DBG(char *format, ...) { } #endif /* LIBSPEECHD_DEBUG */ speech-dispatcher-0.8.3/src/modules/0000775000175000017500000000000012536424374014371 500000000000000speech-dispatcher-0.8.3/src/modules/festival_client.c0000664000175000017500000005220012522771346017626 00000000000000/*************************************************************************/ /* */ /* Centre for Speech Technology Research */ /* University of Edinburgh, UK */ /* Copyright (c) 1999 */ /* All Rights Reserved. */ /* */ /* Permission is hereby granted, free of charge, to use and distribute */ /* this software and its documentation without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of this work, and to */ /* permit persons to whom this work is furnished to do so, subject to */ /* the following conditions: */ /* 1. The code must retain the above copyright notice, this list of */ /* conditions and the following disclaimer. */ /* 2. Any modifications must be clearly marked as such. */ /* 3. Original authors' names are not deleted. */ /* 4. The authors' names are not used to endorse or promote products */ /* derived from this software without specific prior written */ /* permission. */ /* */ /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */ /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */ /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ /* THIS SOFTWARE. */ /* */ /*************************************************************************/ /* Author : Alan W Black (awb@cstr.ed.ac.uk) */ /* Date : March 1999 */ /* Modified: Hynek Hanke (hanke@brailcom.org) (2003-2005) */ /*-----------------------------------------------------------------------*/ /* */ /* Client end of Festival server API in C designed specifically formerly */ /* for Galaxy Communicator use, but rewritten to suit Speech Dispatcher */ /* needs. Please look also at the original festival_client.c library */ /* that can be found in festival/examples/festival_client.c -- it will */ /* be probably more up-to-date. */ /* */ /* This can be also compiled as a stand-alone program for testing */ /* purposes: */ /* gcc -o festival_client -DSTANDALONE festival_client.c */ /* and run as: */ /* ./festival_client */ /* This creates a file test.snd, containing the synthesized waveform */ /* You can run for example: */ /* play test.snd */ /* to hear the message */ /*=======================================================================*/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include /* I'm including my local .h, not the Alan's one! */ #include "festival_client.h" #include "module_utils.h" /* For testing endianness */ int fapi_endian_loc = 1; static char *socket_receive_file_to_buff(int fd, int *size); /* --- MANAGING FT STRUCTURES --- */ void delete_FT_Wave(FT_Wave * wave) { if (wave != 0) { if (wave->samples != 0) g_free(wave->samples); g_free(wave); } } int save_FT_Wave_snd(FT_Wave * wave, const char *filename) { FILE *fd; struct { unsigned int magic; /* magic number */ unsigned int hdr_size; /* size of this header */ int data_size; /* length of data (optional) */ unsigned int encoding; /* data encoding format */ unsigned int sample_rate; /* samples per second */ unsigned int channels; /* number of interleaved channels */ } header; short sw_short; int i; if ((filename == 0) || (strcmp(filename, "stdout") == 0) || (strcmp(filename, "-") == 0)) fd = stdout; else if ((fd = fopen(filename, "wb")) == NULL) { fprintf(stderr, "save_FT_Wave: can't open file \"%s\" for writing\n", filename); return -1; } header.magic = (unsigned int)0x2e736e64; header.hdr_size = sizeof(header); header.data_size = 2 * wave->num_samples; header.encoding = 3; /* short */ header.sample_rate = wave->sample_rate; header.channels = 1; if (FAPI_LITTLE_ENDIAN) { /* snd is always sparc/68000 byte order */ header.magic = SWAPINT(header.magic); header.hdr_size = SWAPINT(header.hdr_size); header.data_size = SWAPINT(header.data_size); header.encoding = SWAPINT(header.encoding); header.sample_rate = SWAPINT(header.sample_rate); header.channels = SWAPINT(header.channels); } /* write header */ if (fwrite(&header, sizeof(header), 1, fd) != 1) return -1; if (FAPI_BIG_ENDIAN) fwrite(wave->samples, sizeof(short), wave->num_samples, fd); else { /* have to swap */ for (i = 0; i < wave->num_samples; i++) { sw_short = SWAPSHORT(wave->samples[i]); fwrite(&sw_short, sizeof(short), 1, fd); } } if (fd != stdout) fclose(fd); return 0; } void delete_FT_Info(FT_Info * info) { if (info != 0) g_free(info); } /* --- FESTIVAL REPLY PARSING --- */ static int nist_get_param_int(char *hdr, char *field, int def_val) { char *p; int val; if (((p = strstr(hdr, field)) != NULL) && (strncmp(" -i ", p + strlen(field), 4) == 0)) { sscanf(p + strlen(field) + 4, "%d", &val); return val; } else return def_val; } static int nist_require_swap(char *hdr) { char *p; char *field = "sample_byte_format"; if ((p = strstr(hdr, field)) != NULL) { if (((strncmp(" -s2 01", p + strlen(field), 7) == 0) && FAPI_BIG_ENDIAN) || ((strncmp(" -s2 10", p + strlen(field), 7) == 0) && FAPI_LITTLE_ENDIAN)) return 1; } return 0; /* if unknown assume native byte order */ } /* --- FESTIVAL SOCKET MANIPULATION --- */ /* Return an FD to a remote server */ static int festival_socket_open(const char *host, int port) { struct sockaddr_in serv_addr; struct hostent *serverhost; int fd; fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { fprintf(stderr, "festival_client: can't get socket\n"); return -1; } memset(&serv_addr, 0, sizeof(serv_addr)); if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) { /* its a name rather than an ipnum */ serverhost = gethostbyname(host); if (serverhost == (struct hostent *)0) { fprintf(stderr, "festival_client: gethostbyname failed\n"); return -1; } memmove(&serv_addr.sin_addr, serverhost->h_addr, serverhost->h_length); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) { fprintf(stderr, "festival_client: connect to server failed\n"); return -1; } return fd; } /* Receive file (probably a waveform file) from socket using */ /* Festival key stuff technique, but long winded I know, sorry */ /* but will receive any file without closing the stream or */ /* using OOB data */ static char *socket_receive_file_to_buff(int fd, int *size) { static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */ char *buff; int bufflen; int n, k, i; char c; if (fd < 0) return NULL; bufflen = 1024; buff = (char *)g_malloc(bufflen); *size = 0; for (k = 0; file_stuff_key[k] != '\0';) { n = read(fd, &c, 1); if (n <= 0) { DBG("ERROR: FESTIVAL CLOSED CONNECTION (1)"); close(fd); festival_connection_crashed = 1; g_free(buff); return NULL; /* hit stream eof before end of file */ } if ((*size) + k + 1 >= bufflen) { /* +1 so you can add a NULL if you want */ bufflen += bufflen / 4; buff = (char *)g_realloc(buff, bufflen); } if (file_stuff_key[k] == c) k++; else if ((c == 'X') && (file_stuff_key[k + 1] == '\0')) { /* It looked like the key but wasn't */ for (i = 0; i < k; i++, (*size)++) buff[*size] = file_stuff_key[i]; k = 0; /* omit the stuffed 'X' */ } else { for (i = 0; i < k; i++, (*size)++) buff[*size] = file_stuff_key[i]; k = 0; buff[*size] = c; (*size)++; } } return buff; } static char *client_accept_s_expr(int fd) { /* Read s-expression from server, as a char * */ char *expr; int filesize; if (fd < 0) return NULL; expr = socket_receive_file_to_buff(fd, &filesize); expr[filesize] = '\0'; return expr; } static FT_Wave *client_accept_waveform(int fd, int *stop_flag, int stop_by_close) { /* Read waveform from server */ char *wavefile; int filesize; int num_samples, sample_rate, i; FT_Wave *wave; if (fd < 0) return NULL; wavefile = socket_receive_file_to_buff(fd, &filesize); if (wavefile == NULL) return NULL; wave = NULL; /* I know this is NIST file and its an error if it isn't */ if (filesize >= 1024) { /* If this doesn't work, probably you forgot to set the output file type to NIST ! by Parameter.set */ num_samples = nist_get_param_int(wavefile, "sample_count", 1); sample_rate = nist_get_param_int(wavefile, "sample_rate", 16000); if ((num_samples * sizeof(short)) + 1024 == filesize) { wave = (FT_Wave *) g_malloc(sizeof(FT_Wave)); DBG("Number of samples from festival: %d", num_samples); wave->num_samples = num_samples; wave->sample_rate = sample_rate; if (num_samples != 0) { wave->samples = (short *)g_malloc(num_samples * sizeof(short)); memmove(wave->samples, wavefile + 1024, num_samples * sizeof(short)); if (nist_require_swap(wavefile)) for (i = 0; i < num_samples; i++) wave->samples[i] = SWAPSHORT(wave->samples[i]); } else { wave->samples = NULL; } } } g_free(wavefile); return wave; } int festival_get_ack(FT_Info ** info, char *ack) { int read_bytes; int n; if (*info == NULL) return -1; if ((*info)->server_fd < 0) return -1; for (n = 0; n < 3;) { read_bytes = read((*info)->server_fd, ack + n, 3 - n); if (read_bytes <= 0) { /* WARNING: This is a very strange situation but it happens often, I don't really know why??? */ DBG("ERROR: FESTIVAL CLOSED CONNECTION (2)"); close((*info)->server_fd); festival_connection_crashed = 1; return -1; } n += read_bytes; } ack[3] = '\0'; return 0; } int festival_read_response(FT_Info * info, char **expr) { char buf[4]; char *r; DBG("Com: Reading response"); if (info == NULL) return 1; if (info->server_fd < 0) return 1; if (festival_get_ack(&info, buf)) return 1; buf[3] = 0; DBG("<- Festival: |%s|", buf); if (!strcmp(buf, "ER\n")) { if (expr != NULL) *expr = NULL; return 1; } else { if (expr != NULL) { *expr = client_accept_s_expr(info->server_fd); } else { r = client_accept_s_expr(info->server_fd); if (r != NULL) g_free(r); } } if (festival_get_ack(&info, buf)) return 1; DBG("<- Festival: |%s|", buf); return 0; } int festival_accept_any_response(FT_Info * info) { char ack[4]; int r; char *expr; DBG("Com: Accepting any response"); do { if ((r = festival_get_ack(&info, ack))) return r; DBG("<- Festival: |%s|", ack); if (strcmp(ack, "WV\n") == 0) { /* receive a waveform */ client_accept_waveform(info->server_fd, NULL, 0); } else if (strcmp(ack, "LP\n") == 0) { /* receive an s-expr */ expr = client_accept_s_expr(info->server_fd); if (expr != NULL) g_free(expr); } else if (strcmp(ack, "ER\n") == 0) { /* server got an error */ /* This message ER is returned even if it was because there was no sound produced, for this reason, the warning is disabled */ /* fprintf(stderr,"festival_client: server returned error\n"); */ break; } } while (strcmp(ack, "OK\n") != 0); return 0; } /* --- HELPER FUNCTIONS --- */ int festival_check_info(FT_Info * info, char *fnname) { assert(fnname != NULL); if ((info == NULL) || (info->server_fd == -1)) { DBG("%s called with info = NULL or server_fd == -1\n", fnname); return -1; } return 0; } /***********************************************************************/ /* Public Functions to this API */ /***********************************************************************/ /* Opens a connection to Festival server (which must be running) * and returns it's identification in new FT_Info */ FT_Info *festivalOpen(FT_Info * info) { char *resp; int ret; DBG("Openning socket fo Festival server"); festival_connection_crashed = 0; if (info == 0) info = festivalDefaultInfo(); info->server_fd = festival_socket_open(info->server_host, info->server_port); if (info->server_fd == -1) { delete_FT_Info(info); festival_connection_crashed = 1; return NULL; } FEST_SEND_CMD("(require 'speech-dispatcher)"); ret = festival_read_response(info, &resp); if (ret || resp == NULL || strcmp(resp, "t\n")) { DBG("ERROR: Can't load speech-dispatcher module into Festival." "Reason: %s", resp); return NULL; } g_free(resp); FEST_SEND_CMD("(Parameter.set 'Wavefiletype 'nist)\n"); ret = festival_read_response(info, &resp); if (ret || resp == NULL || strcmp(resp, "nist\n")) { DBG("ERROR: Can't set Wavefiletype to nist in Festival. Reason: %s", resp); return NULL; } g_free(resp); return info; } int festival_speak_command(FT_Info * info, char *command, const char *text, int symbol, int resp) { FILE *fd; const char *p; char *str; int ret; if (festival_check_info(info, "festival_speak_command") == -1) return -1; if (command == NULL) return -1; if (text == NULL) return -1; DBG("(festival_speak_command): %s", text); /* Opens a stream associated to the socket */ fd = fdopen(dup(info->server_fd), "wb"); /* Send the command and data */ if (symbol == 0) str = g_strdup_printf("(%s \"", command); else str = g_strdup_printf("(%s '", command); fputs(str, fd); /* Copy text over to server, escaping any quotes */ for (p = text; p && (*p != '\0'); p++) { if ((*p == '"') || (*p == '\\')) putc('\\', fd); putc(*p, fd); } if (symbol == 0) fprintf(fd, "\")\n"); else fprintf(fd, ")\n"); DBG("-> Festival: escaped text is %s", text); DBG("-> Festival: |%sthe text is displayed above\")|", str); g_free(str); /* Close the stream (but not the socket) */ fclose(fd); DBG("Resources freed"); if (resp) { ret = festival_read_response(info, NULL); if (ret) { DBG("ERROR: Festival reported error in speak command);"); return -1; } } return 0; } #define FEST_SPEAK_CMD(name, cmd, symbol, resp) \ int \ name(FT_Info *info, const char *text) \ { \ return festival_speak_command(info, cmd, text, symbol, resp); \ } /* Sends a TEXT to Festival server for synthesis. Doesn't * wait for reply (see festivalStringToWaveGetData()). * Please make sure that the socket is empty before calling * this command -- otherwise, you would get another message * in response. * Returns 0 if everything is ok, -1 otherwise. */ FEST_SPEAK_CMD(festivalStringToWaveRequest, "speechd-speak-ssml", 0, 1) FEST_SPEAK_CMD(festivalSpell, "speechd-spell", 0, 1) FEST_SPEAK_CMD(festivalSoundIcon, "speechd-sound-icon", 1, 0) FEST_SPEAK_CMD(festivalCharacter, "speechd-character", 0, 0) FEST_SPEAK_CMD(festivalKey, "speechd-key", 0, 0) /* Reads the wavefile sent back after festivalStringToWaveRequest() * has been called. This function blocks until all the data is * available. Note that for longer messages this can be quite long * on some slower machines. */ FT_Wave *festivalStringToWaveGetData(FT_Info * info) { FT_Wave *wave = NULL; char ack[5]; /* Read back info from server */ /* This assumes only one waveform will come back, also LP is unlikely */ do { if (festival_get_ack(&info, ack)) return NULL; DBG("<- Festival: %s", ack); if (strcmp(ack, "WV\n") == 0) { wave = client_accept_waveform(info->server_fd, NULL, 0); } else if (strcmp(ack, "LP\n") == 0) { client_accept_s_expr(info->server_fd); } else if (strcmp(ack, "ER\n") == 0) { // fprintf(stderr,"festival_client: server returned error\n"); break; } } while (strcmp(ack, "OK\n") != 0); return wave; } FT_Wave *festivalGetDataMulti(FT_Info * info, char **callback, int *stop_flag, int stop_by_close) { FT_Wave *wave = NULL; char ack[5]; char *resp = NULL; FILE *fd; if (festival_check_info(info, "festival_speak_command") == -1) { return NULL; } /* Read back info from server */ /* This assumes only one waveform will come back */ wave = NULL; *callback = NULL; DBG("Stop by close mode : %d", stop_by_close); DBG("-> Festival: (speechd-next)"); fd = fdopen(dup(info->server_fd), "wb"); fprintf(fd, "(speechd-next)\n"); fflush(fd); fclose(fd); do { if (festival_get_ack(&info, ack)) { DBG("Get ack failed"); return NULL; } DBG("<- Festival: %s", ack); if (strcmp(ack, "WV\n") == 0) { wave = client_accept_waveform(info->server_fd, stop_flag, stop_by_close); } else if (strcmp(ack, "LP\n") == 0) { if (resp != NULL) g_free(resp); resp = client_accept_s_expr(info->server_fd); if (resp == NULL) { DBG("ERROR: Something wrong in communication with Festival, s_expr = NULL"); return NULL; } if (strlen(resp) != 0) resp[strlen(resp) - 1] = 0; DBG("<- Festival: |%s|", resp); if (!strcmp(resp, "nil")) { DBG("festival_client: end of samples\n"); g_free(resp); wave = NULL; resp = NULL; } } else if (strcmp(ack, "ER\n") == 0) { DBG("festival_client: server returned error\n"); return NULL; } } while (strcmp(ack, "OK\n") != 0); if (resp) { if ((strlen(resp) > 0) && (resp[0] != '#')) *callback = resp; else g_free(resp); } return wave; } /* Closes the Festival server socket connection */ int festivalClose(FT_Info * info) { if (info == 0) return 0; if (info->server_fd != -1) { FILE *fd; fd = fdopen(dup(info->server_fd), "wb"); if (fd != NULL) { fprintf(fd, "(quit)\n"); fclose(fd); } close(info->server_fd); } return 0; } /* --- INFORMATION RETRIEVAL COMMANDS --- */ char **lisp_list_get_vect(char *expr) { size_t len; char *helper; gchar **vect; size_t i, j; len = strlen(expr); helper = g_malloc(sizeof(char) * (len + 1)); //Remove parenthesis j = 0; for (i = 0; i < len; i++) { if ((expr[i] != '(') && (expr[i] != ')')) { helper[j] = expr[i]; j++; } } helper[j] = '\0'; // Split into a vector of atoms vect = g_strsplit(helper, " ", 0); return vect; } char *vect_read_item(char **vect, char *field) { int i; for (i = 0;; i++) { if (vect[i] == NULL) return NULL; else { if (!strcmp(vect[i], field)) { if (vect[i + 1] != NULL) return vect[i + 1]; else return NULL; } } } } FT_Info *festivalDefaultInfo() { FT_Info *info; info = (FT_Info *) g_malloc(sizeof(FT_Info)); info->server_host = FESTIVAL_DEFAULT_SERVER_HOST; info->server_port = FESTIVAL_DEFAULT_SERVER_PORT; info->text_mode = FESTIVAL_DEFAULT_TEXT_MODE; info->server_fd = -1; return info; } /* For testing purposes, this library can be compiled as * a standalone program, please see the introduction at * the beginning of this file */ #ifdef STANDALONE int main(int argc, char **argv) { char *server = 0; int port = -1; char *text = 0; char *output = 0; char *mode = 0; int i; FT_Info *info; FT_Wave *wave; printf("Welcome to Festival client library for Speech Dispatcher\n"); info = festivalDefaultInfo(); if (server != 0) info->server_host = FESTIVAL_DEFAULT_SERVER_HOST; if (port != -1) info->server_port = FESTIVAL_DEFAULT_SERVER_PORT; if (mode != 0) info->text_mode = FESTIVAL_DEFAULT_TEXT_MODE; info = festivalOpen(info); if (info == 0) { printf("Can't open connection to festival server!\n"); exit(1); } if (info->server_fd <= 0) { printf("Can't open connection to festival server!\n"); exit(1); } festivalStringToWaveRequest(info, "Hi, how are you? I'm Festival! And who are you?"); wave = festivalStringToWaveGetData(info); if (wave != 0) { save_FT_Wave_snd(wave, "test.snd"); } else { printf("Wave null! Festival server doesn't work properly.\n"); exit(1); } festivalClose(info); printf("The synthesized text should have been written to test.snd\n"); return 0; } #endif speech-dispatcher-0.8.3/src/modules/festival_client.h0000664000175000017500000001326612522771346017644 00000000000000/*************************************************************************/ /* */ /* Centre for Speech Technology Research */ /* University of Edinburgh, UK */ /* Copyright (c) 1999 */ /* All Rights Reserved. */ /* */ /* Permission is hereby granted, free of charge, to use and distribute */ /* this software and its documentation without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of this work, and to */ /* permit persons to whom this work is furnished to do so, subject to */ /* the following conditions: */ /* 1. The code must retain the above copyright notice, this list of */ /* conditions and the following disclaimer. */ /* 2. Any modifications must be clearly marked as such. */ /* 3. Original authors' names are not deleted. */ /* 4. The authors' names are not used to endorse or promote products */ /* derived from this software without specific prior written */ /* permission. */ /* */ /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */ /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */ /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */ /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */ /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */ /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */ /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */ /* THIS SOFTWARE. */ /* */ /*************************************************************************/ /* Author : Alan W Black (awb@cstr.ed.ac.uk) */ /* Date : March 1999 */ /*-----------------------------------------------------------------------*/ /* */ /* Client end of Festival server API (in C) designed specifically for */ /* Galaxy Communicator use, though might be of use for other things */ /* */ /*=======================================================================*/ #ifndef _FESTIVAL_CLIENT_H_ #define _FESTIVAL_CLIENT_H_ #define FESTIVAL_DEFAULT_SERVER_HOST "localhost" #define FESTIVAL_DEFAULT_SERVER_PORT 1314 #define FESTIVAL_DEFAULT_TEXT_MODE "fundamental" int festival_connection_crashed; typedef struct FT_Info { int encoding; char *server_host; int server_port; char *text_mode; int server_fd; } FT_Info; typedef struct FT_Wave { int num_samples; int sample_rate; short *samples; } FT_Wave; void delete_FT_Wave(FT_Wave * wave); void delete_FT_Info(FT_Info * info); #define SWAPSHORT(x) ((((unsigned)x) & 0xff) << 8 | \ (((unsigned)x) & 0xff00) >> 8) #define SWAPINT(x) ((((unsigned)x) & 0xff) << 24 | \ (((unsigned)x) & 0xff00) << 8 | \ (((unsigned)x) & 0xff0000) >> 8 | \ (((unsigned)x) & 0xff000000) >> 24) /* Sun, HP, SGI Mips, M68000 */ #define FAPI_BIG_ENDIAN (((char *)&fapi_endian_loc)[0] == 0) /* Intel, Alpha, DEC Mips, Vax */ #define FAPI_LITTLE_ENDIAN (((char *)&fapi_endian_loc)[0] != 0) #define FEST_SEND_CMD(format) \ { \ FILE *fd; \ char *str; \ fd = fdopen(dup(info->server_fd),"wb"); \ if (fd != NULL){ \ str = g_strdup(format"\n"); \ fputs(str, fd); \ DBG("-> Festival: |%s|", str); \ g_free(str); \ fclose(fd); \ }else{ \ DBG("Can't open connection"); \ } \ } #define FEST_SEND_CMDA(format, args...) \ { \ FILE *fd; \ char *str; \ fd = fdopen(dup(info->server_fd),"wb"); \ if (fd != NULL){ \ str = g_strdup_printf(format"\n", args); \ fputs(str, fd); \ DBG("-> Festival: |%s|", str); \ g_free(str); \ fclose(fd); \ }else{ \ DBG("Can't open connection"); \ } \ } /*****************************************************************/ /* Public functions to interface */ /*****************************************************************/ /* If called with NULL will attempt to access using defaults */ FT_Info *festivalOpen(FT_Info * info); int festivalClose(FT_Info * info); int festivalStringToWaveRequest(FT_Info * info, const char *text); int festivalSoundIcon(FT_Info * info, const char *text); int festivalCharacter(FT_Info * info, const char *text); int festivalKey(FT_Info * info, const char *text); int festivalSpell(FT_Info * info, const char *text); FT_Wave *festivalStringToWaveGetData(FT_Info * info); FT_Info *festivalDefaultInfo(); void festivalEmptySocket(FT_Info * info); int save_FT_Wave_snd(FT_Wave * wave, const char *filename); FT_Wave *festivalGetDataMulti(FT_Info * info, char **callback, int *stop_flag, int stop_by_close); int festival_check_info(FT_Info * info, char *fnname); char **lisp_list_get_vect(char *expr); int festival_read_response(FT_Info * info, char **expr); #endif speech-dispatcher-0.8.3/src/modules/spd_audio.c0000664000175000017500000002135712522771346016433 00000000000000 /* * spd_audio.c -- Spd Audio Output Library * * Copyright (C) 2004, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: spd_audio.c,v 1.21 2008-06-09 10:29:12 hanke Exp $ */ /* * spd_audio is a simple realtime audio output library with the capability of * playing 8 or 16 bit data, immediate stop and synchronization. This library * currently provides OSS, NAS, ALSA and PulseAudio backend. The available backends are * specified at compile-time using the directives WITH_OSS, WITH_NAS, WITH_ALSA, * WITH_PULSE, WITH_LIBAO but the user program is allowed to switch between them at run-time. */ #ifdef HAVE_CONFIG_H #include #endif #include "spd_audio.h" #include #include #include #include #include #include #include #include #include #include #include static int spd_audio_log_level; static lt_dlhandle lt_h; /* Dynamically load a library with RTLD_GLOBAL set. This is needed when a dynamically-loaded library has its own plugins that call into the parent library. Most of the credit for this function goes to Gary Vaughan. */ static lt_dlhandle my_dlopenextglobal(const char *filename) { lt_dlhandle handle = NULL; lt_dladvise advise; if (lt_dladvise_init(&advise)) return handle; if (!lt_dladvise_ext(&advise) && !lt_dladvise_global(&advise)) handle = lt_dlopenadvise(filename, advise); lt_dladvise_destroy(&advise); return handle; } /* Open the audio device. Arguments: type -- The requested device. Currently AudioOSS or AudioNAS. pars -- and array of pointers to parameters to pass to the device backend, terminated by a NULL pointer. See the source/documentation of each specific backend. error -- a pointer to the string where error description is stored in case of failure (returned AudioID == NULL). Otherwise will contain NULL. Return value: Newly allocated AudioID structure that can be passed to all other spd_audio functions, or NULL in case of failure. */ AudioID *spd_audio_open(char *name, void **pars, char **error) { AudioID *id; spd_audio_plugin_t const *p; spd_audio_plugin_t *(*fn) (void); gchar *libname; int ret; /* now check whether dynamic plugin is available */ ret = lt_dlinit(); if (ret != 0) { *error = (char *)g_strdup_printf("lt_dlinit() failed"); return (AudioID *) NULL; } ret = lt_dlsetsearchpath(PLUGIN_DIR); if (ret != 0) { *error = (char *)g_strdup_printf("lt_dlsetsearchpath() failed"); return (AudioID *) NULL; } libname = g_strdup_printf(SPD_AUDIO_LIB_PREFIX "%s", name); lt_h = my_dlopenextglobal(libname); g_free(libname); if (NULL == lt_h) { *error = (char *)g_strdup_printf("Cannot open plugin %s. error: %s", name, lt_dlerror()); return (AudioID *) NULL; } fn = lt_dlsym(lt_h, SPD_AUDIO_PLUGIN_ENTRY_STR); if (NULL == fn) { *error = (char *)g_strdup_printf("Cannot find symbol %s", SPD_AUDIO_PLUGIN_ENTRY_STR); return (AudioID *) NULL; } p = fn(); if (p == NULL || p->name == NULL) { *error = (char *)g_strdup_printf("plugin %s not found", name); return (AudioID *) NULL; } id = p->open(pars); if (id == NULL) { *error = (char *)g_strdup_printf("Couldn't open %s plugin", name); return (AudioID *) NULL; } id->function = p; #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) id->format = SPD_AUDIO_BE; #else id->format = SPD_AUDIO_LE; #endif *error = NULL; return id; } /* Play a track on the audio device (blocking). Arguments: id -- the AudioID* of the device returned by spd_audio_open track -- a track to play (see spd_audio.h) Return value: 0 if everything is ok, a non-zero value in case of failure. See the particular backend documentation or source for the meaning of these non-zero values. Comment: spd_audio_play() is a blocking function. It returns exactly when the given track stopped playing. However, it's possible to safely interrupt it using spd_audio_stop() described below. (spd_audio_stop() needs to be called from another thread, obviously.) */ int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format) { int ret; if (id && id->function->play) { /* Only perform byte swapping if the driver in use has given us audio in an endian format other than what the running CPU supports. */ if (format != id->format) { unsigned char *out_ptr, *out_end, c; out_ptr = (unsigned char *)track.samples; out_end = out_ptr + track.num_samples * 2 * track.num_channels; while (out_ptr < out_end) { c = out_ptr[0]; out_ptr[0] = out_ptr[1]; out_ptr[1] = c; out_ptr += 2; } } ret = id->function->play(id, track); } else { fprintf(stderr, "Play not supported on this device\n"); return -1; } return ret; } /* Stop playing the current track on device id Arguments: id -- the AudioID* of the device returned by spd_audio_open Return value: 0 if everything is ok, a non-zero value in case of failure. See the particular backend documentation or source for the meaning of these non-zero values. Comment: spd_audio_stop() safely interrupts spd_audio_play() when called from another thread. It shouldn't cause any clicks or unwanted effects in the sound output. It's safe to call spd_audio_stop() even if the device isn't playing any track. In that case, it does nothing. However, there is a danger when using spd_audio_stop(). Since you must obviously do it from another thread than where spd_audio_play is running, you must make yourself sure that the device is still open and the id you pass it is valid and will be valid until spd_audio_stop returns. In other words, you should use some mutex or other synchronization device to be sure spd_audio_close isn't called before or during spd_audio_stop execution. */ int spd_audio_stop(AudioID * id) { int ret; if (id && id->function->stop) { ret = id->function->stop(id); } else { fprintf(stderr, "Stop not supported on this device\n"); return -1; } return ret; } /* Close the audio device id Arguments: id -- the AudioID* of the device returned by spd_audio_open Return value: 0 if everything is ok, a non-zero value in case of failure. Comments: Please make sure no other spd_audio function with this device id is running in another threads. See spd_audio_stop() for detailed description of possible problems. */ int spd_audio_close(AudioID * id) { int ret = 0; if (id && id->function->close) { ret = (id->function->close(id)); } if (NULL != lt_h) { lt_dlclose(lt_h); lt_h = NULL; lt_dlexit(); } return ret; } /* Set volume for playing tracks on the device id Arguments: id -- the AudioID* of the device returned by spd_audio_open volume -- a value in the range <-100:100> where -100 means the least volume (probably silence), 0 the default volume and +100 the highest volume possible to make on that device for a single flow (i.e. not using mixer). Return value: 0 if everything is ok, a non-zero value in case of failure. See the particular backend documentation or source for the meaning of these non-zero values. Comments: In case of /dev/dsp, it's not possible to set volume for the particular flow. For that reason, the value 0 means the volume the track was recorded on and each smaller value means less volume (since this works by deviding the samples in the track by a constant). */ int spd_audio_set_volume(AudioID * id, int volume) { if ((volume > 100) || (volume < -100)) { fprintf(stderr, "Requested volume out of range"); return -1; } if (id == NULL) { fprintf(stderr, "audio id is NULL in spd_audio_set_volume\n"); return -1; } id->volume = volume; return 0; } void spd_audio_set_loglevel(AudioID * id, int level) { if (level) { spd_audio_log_level = level; if (id != 0 && id->function != 0) id->function->set_loglevel(level); } } char const *spd_audio_get_playcmd(AudioID * id) { if (id != 0 && id->function != 0) { return id->function->get_playcmd(); } return NULL; } speech-dispatcher-0.8.3/src/modules/ibmtts.c0000664000175000017500000016167412530733575015776 00000000000000/* * ibmtts.c - Speech Dispatcher backend for IBM TTS * * Copyright (C) 2006, 2007 Brailcom, o.p.s. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @author Gary Cramblitt (original author) * * $Id: ibmtts.c,v 1.30 2008-06-30 14:34:02 gcasse Exp $ */ /* This output module operates with four threads: The main thread called from Speech Dispatcher (module_*()). A synthesis thread that accepts messages, parses them, and forwards them to the IBM TTS via the Eloquence Command Interface (ECI). This thread receives audio and index mark callbacks from IBM TTS and queues them into a playback queue. See _ibmtts_synth(). A playback thread that acts on entries in the playback queue, either sending them to the audio output module (module_tts_output()), or emitting Speech Dispatcher events. See _ibmtts_play(). A thread which is used to stop or pause the synthesis and playback threads. See _ibmtts_stop_or_pause(). Semaphores and mutexes are used to mediate between the 4 threads. TODO: - Support list_synthesis_voices() - Limit amout of waveform data synthesised in advance. - Use SSML mark feature of ibmtts instead of handcrafted parsing. */ #ifdef HAVE_CONFIG_H #include #endif /* System includes. */ #include #include #include /* IBM Eloquence Command Interface. Won't exist unless IBM TTS or IBM TTS SDK is installed. */ #include /* Speech Dispatcher includes. */ #include "spd_audio.h" #include #include "module_utils.h" typedef enum { IBMTTS_FALSE, IBMTTS_TRUE } TIbmttsBool; typedef enum { FATAL_ERROR = -1, OK = 0, ERROR = 1 } TIbmttsSuccess; /* TODO: These defines are in src/server/index_marking.h, but including that file here causes a redefinition error on FATAL macro in speechd.h. */ #define SD_MARK_BODY_LEN 6 #define SD_MARK_BODY "__spd_" #define SD_MARK_HEAD "" #define SD_MARK_HEAD_ONLY "data.list[0]); \ if (NULL != cmd->data.list[1]) \ new_item->arg2 = g_strdup(cmd->data.list[1]); \ else \ new_item->arg2 = NULL; \ if (NULL != cmd->data.list[2]) \ new_item->arg3 = g_strdup(cmd->data.list[2]); \ else \ new_item->arg3 = NULL; \ dll = g_hash_table_lookup(name, new_key); \ dll = g_list_append(dll, new_item); \ g_hash_table_insert(name, new_key, dll); \ return NULL; \ } /* Load a double-linked list from config file. */ #define MOD_OPTION_HT_DLL_REG(name) \ name = g_hash_table_new(g_str_hash, g_str_equal); \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_LIST, name ## _cb, NULL, 0); /* Define a hash table mapping a string to 7 integer values. */ #define MOD_OPTION_6_INT_HT(name, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ typedef struct{ \ int arg1; \ int arg2; \ int arg3; \ int arg4; \ int arg5; \ int arg6; \ int arg7; \ }T ## name; \ GHashTable *name; \ \ DOTCONF_CB(name ## _cb) \ { \ T ## name *new_item; \ char* new_key; \ new_item = (T ## name *) g_malloc(sizeof(T ## name)); \ if (cmd->data.list[0] == NULL) return NULL; \ new_key = g_strdup(cmd->data.list[0]); \ new_item->arg1 = (int) strtol(cmd->data.list[1], NULL, 10); \ new_item->arg2 = (int) strtol(cmd->data.list[2], NULL, 10); \ new_item->arg3 = (int) strtol(cmd->data.list[3], NULL, 10); \ new_item->arg4 = (int) strtol(cmd->data.list[4], NULL, 10); \ new_item->arg5 = (int) strtol(cmd->data.list[5], NULL, 10); \ new_item->arg6 = (int) strtol(cmd->data.list[6], NULL, 10); \ new_item->arg7 = (int) strtol(cmd->data.list[7], NULL, 10); \ g_hash_table_insert(name, new_key, new_item); \ return NULL; \ } /* Thread and process control. */ static pthread_t ibmtts_synth_thread; static pthread_t ibmtts_play_thread; static pthread_t ibmtts_stop_or_pause_thread; static sem_t ibmtts_synth_semaphore; static sem_t ibmtts_play_semaphore; static sem_t ibmtts_stop_or_pause_semaphore; static pthread_mutex_t ibmtts_synth_suspended_mutex; static pthread_mutex_t ibmtts_play_suspended_mutex; static pthread_mutex_t ibmtts_stop_or_pause_suspended_mutex; static TIbmttsBool ibmtts_thread_exit_requested = IBMTTS_FALSE; static TIbmttsBool ibmtts_stop_synth_requested = IBMTTS_FALSE; static TIbmttsBool ibmtts_stop_play_requested = IBMTTS_FALSE; static TIbmttsBool ibmtts_pause_requested = IBMTTS_FALSE; /* Current message from Speech Dispatcher. */ static char **ibmtts_message; static SPDMessageType ibmtts_message_type; /* ECI */ static ECIHand eciHandle = NULL_ECI_HAND; static int eci_sample_rate = 0; /* ECI sends audio back in chunks to this buffer. The smaller the buffer, the higher the overhead, but the better the index mark resolution. */ typedef signed short int TEciAudioSamples; static TEciAudioSamples *audio_chunk; /* For some reason, these were left out of eci.h. */ typedef enum { eciTextModeDefault = 0, eciTextModeAlphaSpell = 1, eciTextModeAllSpell = 2, eciIRCSpell = 3 } ECITextMode; /* The playback queue. */ typedef enum { IBMTTS_QET_AUDIO, /* Chunk of audio. */ IBMTTS_QET_INDEX_MARK, /* Index mark event. */ IBMTTS_QET_SOUND_ICON, /* A Sound Icon */ IBMTTS_QET_BEGIN, /* Beginning of speech. */ IBMTTS_QET_END /* Speech completed. */ } EPlaybackQueueEntryType; typedef struct { long num_samples; TEciAudioSamples *audio_chunk; } TPlaybackQueueAudioChunk; typedef struct { EPlaybackQueueEntryType type; union { long markId; TPlaybackQueueAudioChunk audio; char *sound_icon_filename; } data; } TPlaybackQueueEntry; static GSList *playback_queue = NULL; static pthread_mutex_t playback_queue_mutex; /* A lookup table for index mark name given integer id. */ GHashTable *ibmtts_index_mark_ht = NULL; #define IBMTTS_MSG_END_MARK 0 pthread_mutex_t sound_stop_mutex; /* When a voice is set, this is the baseline pitch of the voice. SSIP PITCH commands then adjust relative to this. */ int ibmtts_voice_pitch_baseline; /* When a voice is set, this the default speed of the voice. SSIP RATE commands then adjust relative to this. */ int ibmtts_voice_speed; /* Expected input encoding for current language dialect. */ static char *ibmtts_input_encoding = "cp1252"; /* list of voices */ static SPDVoice **ibmtts_voice_list = NULL; static int *ibmtts_voice_index = NULL; /* Internal function prototypes for main thread. */ static void ibmtts_set_language(char *lang); static void ibmtts_set_voice(SPDVoiceType voice); static char *ibmtts_voice_enum_to_str(SPDVoiceType voice); static void ibmtts_set_language_and_voice(char *lang, SPDVoiceType voice, char *dialect); static void ibmtts_set_synthesis_voice(char *); static void ibmtts_set_rate(signed int rate); static void ibmtts_set_pitch(signed int pitch); static void ibmtts_set_punctuation_mode(SPDPunctuation punct_mode); static void ibmtts_set_volume(signed int pitch); /* locale_index_atomic stores the current index of the eciLocales array. The main thread writes this information, the synthesis thread reads it. */ static gint locale_index_atomic; /* Internal function prototypes for synthesis thread. */ static char *ibmtts_extract_mark_name(char *mark); static char *ibmtts_next_part(char *msg, char **mark_name); static int ibmtts_replace(char *from, char *to, GString * msg); static void ibmtts_subst_keys_cb(gpointer data, gpointer user_data); static char *ibmtts_subst_keys(char *key); static char *ibmtts_search_for_sound_icon(const char *icon_name); static TIbmttsBool ibmtts_add_sound_icon_to_playback_queue(char *filename); static void ibmtts_load_user_dictionary(); static enum ECICallbackReturn eciCallback(ECIHand hEngine, enum ECIMessage msg, long lparam, void *data); /* Internal function prototypes for playback thread. */ static TIbmttsBool ibmtts_add_audio_to_playback_queue(TEciAudioSamples * audio_chunk, long num_samples); static TIbmttsBool ibmtts_add_mark_to_playback_queue(long markId); static TIbmttsBool ibmtts_add_flag_to_playback_queue(EPlaybackQueueEntryType type); static void ibmtts_delete_playback_queue_entry(TPlaybackQueueEntry * playback_queue_entry); static TIbmttsBool ibmtts_send_to_audio(TPlaybackQueueEntry * playback_queue_entry); /* Miscellaneous internal function prototypes. */ static TIbmttsBool is_thread_busy(pthread_mutex_t * suspended_mutex); static void ibmtts_log_eci_error(); static void ibmtts_clear_playback_queue(); static void alloc_voice_list(); static void free_voice_list(); /* The synthesis thread start routine. */ static void *_ibmtts_synth(void *); /* The playback thread start routine. */ static void *_ibmtts_play(void *); /* The stop_or_pause start routine. */ static void *_ibmtts_stop_or_pause(void *); /* Module configuration options. */ /* TODO: Remove these if we decide they aren't needed. */ MOD_OPTION_1_INT(IbmttsMaxChunkLength); MOD_OPTION_1_STR(IbmttsDelimiters); MOD_OPTION_1_INT(IbmttsUseSSML); MOD_OPTION_1_STR(IbmttsPunctuationList); MOD_OPTION_1_INT(IbmttsUseAbbreviation); MOD_OPTION_1_STR(IbmttsDictionaryFolder); MOD_OPTION_1_INT(IbmttsAudioChunkSize); MOD_OPTION_1_STR(IbmttsSoundIconFolder); MOD_OPTION_6_INT_HT(IbmttsVoiceParameters, gender, breathiness, head_size, pitch_baseline, pitch_fluctuation, roughness, speed); MOD_OPTION_3_STR_HT_DLL(IbmttsKeySubstitution, lang, key, newkey); typedef struct _eciLocale { char *name; char *lang; char *dialect; enum ECILanguageDialect langID; char *charset; } eciLocale, *eciLocaleList; static eciLocale eciLocales[] = { { "American_English", "en", "US", eciGeneralAmericanEnglish, "ISO-8859-1"}, {"British_English", "en", "GB", eciBritishEnglish, "ISO-8859-1"}, {"Castilian_Spanish", "es", "ES", eciCastilianSpanish, "ISO-8859-1"}, {"Mexican_Spanish", "es", "MX", eciMexicanSpanish, "ISO-8859-1"}, {"French", "fr", "FR", eciStandardFrench, "ISO-8859-1"}, {"Canadian_French", "ca", "FR", eciCanadianFrench, "ISO-8859-1"}, {"German", "de", "DE", eciStandardGerman, "ISO-8859-1"}, {"Italian", "it", "IT", eciStandardItalian, "ISO-8859-1"}, {"Mandarin_Chinese", "zh", "CN", eciMandarinChinese, "GBK"}, {"Mandarin_Chinese GB", "zh", "CN_GB", eciMandarinChineseGB, "GBK"}, { "Mandarin_Chinese PinYin", "zh", "CN_PinYin", eciMandarinChinesePinYin, "GBK"}, {"Mandarin_Chinese UCS", "zh", "CN_UCS", eciMandarinChineseUCS, "UCS2"}, {"Taiwanese_Mandarin", "zh", "TW", eciTaiwaneseMandarin, "BIG5"}, { "Taiwanese_Mandarin Big 5", "zh", "TW_Big5", eciTaiwaneseMandarinBig5, "BIG5"}, { "Taiwanese_Mandarin ZhuYin", "zh", "TW_ZhuYin", eciTaiwaneseMandarinZhuYin, "BIG5"}, { "Taiwanese_Mandarin PinYin", "zh", "TW_PinYin", eciTaiwaneseMandarinPinYin, "BIG5"}, { "Taiwanese_Mandarin UCS", "zh", "TW_UCS", eciTaiwaneseMandarinUCS, "UCS2"}, { "Brazilian_Portuguese", "pt", "BR", eciBrazilianPortuguese, "ISO-8859-1"}, {"Japanese", "ja", "JP", eciStandardJapanese, "SJIS"}, {"Japanese_SJIS", "ja", "JP_SJIS", eciStandardJapaneseSJIS, "SJIS"}, {"Japanese_UCS", "ja", "JP_UCS", eciStandardJapaneseUCS, "UCS2"}, {"Finnish", "fi", "FI", eciStandardFinnish, "ISO-8859-1"}, {"Korean", "ko", "KR", eciStandardKorean, "UHC"}, {"Korean_UHC", "ko", "KR_UHC", eciStandardKoreanUHC, "UHC"}, {"Korean_UCS", "ko", "KR_UCS", eciStandardKoreanUCS, "UCS2"}, {"Cantonese", "zh", "HK", eciStandardCantonese, "GBK"}, {"Cantonese_GB", "zh", "HK_GB", eciStandardCantoneseGB, "GBK"}, {"Cantonese_UCS", "zh", "HK_UCS", eciStandardCantoneseUCS, "UCS2"}, {"HongKong_Cantonese", "zh", "HK", eciHongKongCantonese, "BIG5"}, { "HongKong_Cantonese Big 5", "zh", "HK_BIG5", eciHongKongCantoneseBig5, "BIG5"}, { "HongKong_Cantonese UCS", "zh", "HK_UCS", eciHongKongCantoneseUCS, "UCS-2"}, {"Dutch", "nl", "BE", eciStandardDutch, "ISO-8859-1"}, {"Norwegian", "no", "NO", eciStandardNorwegian, "ISO-8859-1"}, {"Swedish", "sv", "SE", eciStandardSwedish, "ISO-8859-1"}, {"Danish", "da", "DK", eciStandardDanish, "ISO-8859-1"}, {"Reserved", "en", "US", eciStandardReserved, "ISO-8859-1"}, {"Thai", "th", "TH", eciStandardThai, "TIS-620"}, {"ThaiTIS", "th", "TH_TIS", eciStandardThaiTIS, "TIS-620"}, {NULL, 0, NULL} }; #define MAX_NB_OF_LANGUAGES (sizeof(eciLocales)/sizeof(eciLocales[0]) - 1) /* dictionary_filename: its index corresponds to the ECIDictVolume enumerate */ static char *dictionary_filenames[] = { "main.dct", "root.dct", "abbreviation.dct", "extension.dct" }; #define NB_OF_DICTIONARY_FILENAMES (sizeof(dictionary_filenames)/sizeof(dictionary_filenames[0])) /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); /* TODO: Remove these if we decide they aren't needed. */ MOD_OPTION_1_INT_REG(IbmttsMaxChunkLength, 3000); MOD_OPTION_1_STR_REG(IbmttsDelimiters, ""); MOD_OPTION_1_INT_REG(IbmttsUseSSML, 1); MOD_OPTION_1_INT_REG(IbmttsUseAbbreviation, 1); MOD_OPTION_1_STR_REG(IbmttsPunctuationList, "()?"); MOD_OPTION_1_STR_REG(IbmttsDictionaryFolder, "/var/opt/IBM/ibmtts/dict"); MOD_OPTION_1_INT_REG(IbmttsAudioChunkSize, 20000); MOD_OPTION_1_STR_REG(IbmttsSoundIconFolder, "/usr/share/sounds/sound-icons/"); /* Register voices. */ module_register_settings_voices(); /* Register voice parameters */ MOD_OPTION_HT_REG(IbmttsVoiceParameters); /* Register key substitutions. */ MOD_OPTION_HT_DLL_REG(IbmttsKeySubstitution); return OK; } int module_init(char **status_info) { int ret; char ibmVersion[20]; int ibm_sample_rate; DBG("Ibmtts: Module init()."); INIT_INDEX_MARKING(); *status_info = NULL; ibmtts_thread_exit_requested = IBMTTS_FALSE; /* Report versions. */ eciVersion(ibmVersion); DBG("Ibmtts: IBM TTS Output Module version %s, IBM TTS Engine version %s", MODULE_VERSION, ibmVersion); /* Setup IBM TTS engine. */ DBG("Ibmtts: Creating ECI instance."); eciHandle = eciNew(); if (NULL_ECI_HAND == eciHandle) { DBG("Ibmtts: Could not create ECI instance.\n"); *status_info = g_strdup("Could not create ECI instance. " "Is the IBM TTS engine installed?"); return FATAL_ERROR; } /* Get ECI audio sample rate. */ ibm_sample_rate = eciGetParam(eciHandle, eciSampleRate); switch (ibm_sample_rate) { case 0: eci_sample_rate = 8000; break; case 1: eci_sample_rate = 11025; break; case 2: eci_sample_rate = 22050; break; default: DBG("Ibmtts: Invalid audio sample rate returned by ECI = %i", ibm_sample_rate); } /* Allocate a chunk for ECI to return audio. */ audio_chunk = (TEciAudioSamples *) g_malloc((IbmttsAudioChunkSize) * sizeof(TEciAudioSamples)); DBG("Ibmtts: Registering ECI callback."); eciRegisterCallback(eciHandle, eciCallback, NULL); DBG("Ibmtts: Registering an ECI audio buffer."); if (!eciSetOutputBuffer(eciHandle, IbmttsAudioChunkSize, audio_chunk)) { DBG("Ibmtts: Error registering ECI audio buffer."); ibmtts_log_eci_error(); } eciSetParam(eciHandle, eciDictionary, !IbmttsUseAbbreviation); /* enable annotations */ eciSetParam(eciHandle, eciInputType, 1); /* load possibly the ssml filter */ eciAddText(eciHandle, " `gfa1 "); /* load possibly the punctuation filter */ eciAddText(eciHandle, " `gfa2 "); ibmtts_set_punctuation_mode(msg_settings.punctuation_mode); alloc_voice_list(); /* These mutexes are locked when the corresponding threads are suspended. */ pthread_mutex_init(&ibmtts_synth_suspended_mutex, NULL); pthread_mutex_init(&ibmtts_play_suspended_mutex, NULL); /* This mutex is used to hold a stop request until audio actually stops. */ pthread_mutex_init(&sound_stop_mutex, NULL); /* This mutex mediates access to the playback queue between the synthesis and playback threads. */ pthread_mutex_init(&playback_queue_mutex, NULL); /* DBG("Ibmtts: IbmttsMaxChunkLength = %d", IbmttsMaxChunkLength); DBG("Ibmtts: IbmttsDelimiters = %s", IbmttsDelimiters); */ DBG("Ibmtts: ImbttsAudioChunkSize = %d", IbmttsAudioChunkSize); ibmtts_message = g_malloc(sizeof(char *)); *ibmtts_message = NULL; DBG("Ibmtts: Creating new thread for stop or pause."); sem_init(&ibmtts_stop_or_pause_semaphore, 0, 0); ret = pthread_create(&ibmtts_stop_or_pause_thread, NULL, _ibmtts_stop_or_pause, NULL); if (0 != ret) { DBG("Ibmtts: stop or pause thread creation failed."); *status_info = g_strdup ("The module couldn't initialize stop or pause thread. " "This could be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return FATAL_ERROR; } DBG("Ibmtts: Creating new thread for playback."); sem_init(&ibmtts_play_semaphore, 0, 0); ret = pthread_create(&ibmtts_play_thread, NULL, _ibmtts_play, NULL); if (0 != ret) { DBG("Ibmtts: play thread creation failed."); *status_info = g_strdup("The module couldn't initialize play thread. " "This could be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return FATAL_ERROR; } DBG("Ibmtts: Creating new thread for IBM TTS synthesis."); sem_init(&ibmtts_synth_semaphore, 0, 0); ret = pthread_create(&ibmtts_synth_thread, NULL, _ibmtts_synth, NULL); if (0 != ret) { DBG("Ibmtts: synthesis thread creation failed."); *status_info = g_strdup("The module couldn't initialize synthesis thread. " "This could be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return FATAL_ERROR; } *status_info = g_strdup("Ibmtts: Initialized successfully."); return OK; } SPDVoice **module_list_voices(void) { DBG("Ibmtts: %s", __FUNCTION__); return ibmtts_voice_list; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { DBG("Ibmtts: module_speak()."); if (is_thread_busy(&ibmtts_synth_suspended_mutex) || is_thread_busy(&ibmtts_play_suspended_mutex) || is_thread_busy(&ibmtts_stop_or_pause_suspended_mutex)) { DBG("Ibmtts: Already synthesizing when requested to synthesize (module_speak)."); return IBMTTS_FALSE; } DBG("Ibmtts: Type: %d, bytes: %d, requested data: |%s|\n", msgtype, bytes, data); g_free(*ibmtts_message); *ibmtts_message = NULL; if (!g_utf8_validate(data, bytes, NULL)) { DBG("Ibmtts: Input is not valid utf-8."); /* Actually, we should just fail here, but let's assume input is latin-1 */ *ibmtts_message = g_convert(data, bytes, "utf-8", "iso-8859-1", NULL, NULL, NULL); if (*ibmtts_message == NULL) { DBG("Ibmtts: Fallback conversion to utf-8 failed."); return FALSE; } } else { *ibmtts_message = g_strndup(data, bytes); } ibmtts_message_type = msgtype; if ((msgtype == SPD_MSGTYPE_TEXT) && (msg_settings.spelling_mode == SPD_SPELL_ON)) ibmtts_message_type = SPD_MSGTYPE_SPELL; /* Setting speech parameters. */ UPDATE_STRING_PARAMETER(voice.language, ibmtts_set_language); UPDATE_PARAMETER(voice_type, ibmtts_set_voice); UPDATE_STRING_PARAMETER(voice.name, ibmtts_set_synthesis_voice); UPDATE_PARAMETER(rate, ibmtts_set_rate); UPDATE_PARAMETER(volume, ibmtts_set_volume); UPDATE_PARAMETER(pitch, ibmtts_set_pitch); UPDATE_PARAMETER(punctuation_mode, ibmtts_set_punctuation_mode); /* TODO: Handle these in _ibmtts_synth() ? UPDATE_PARAMETER(cap_let_recogn, festival_set_cap_let_recogn); */ if (!IbmttsUseSSML) { /* Strip all SSML */ char *tmp = *ibmtts_message; *ibmtts_message = module_strip_ssml(*ibmtts_message); g_free(tmp); /* Convert input to suitable encoding for current language dialect */ tmp = g_convert_with_fallback(*ibmtts_message, -1, ibmtts_input_encoding, "utf-8", "?", NULL, &bytes, NULL); if (tmp != NULL) { g_free(*ibmtts_message); *ibmtts_message = tmp; } } /* Send semaphore signal to the synthesis thread */ sem_post(&ibmtts_synth_semaphore); DBG("Ibmtts: Leaving module_speak() normally."); return TRUE; } int module_stop(void) { DBG("Ibmtts: module_stop()."); if ((is_thread_busy(&ibmtts_synth_suspended_mutex) || is_thread_busy(&ibmtts_play_suspended_mutex)) && !is_thread_busy(&ibmtts_stop_or_pause_suspended_mutex)) { /* Request both synth and playback threads to stop what they are doing (if anything). */ ibmtts_stop_synth_requested = IBMTTS_TRUE; ibmtts_stop_play_requested = IBMTTS_TRUE; /* Wake the stop_or_pause thread. */ sem_post(&ibmtts_stop_or_pause_semaphore); } return OK; } size_t module_pause(void) { /* The semantics of module_pause() is the same as module_stop() except that processing should continue until the next index mark is reached before stopping. Note that although IBM TTS offers an eciPause function, we cannot make use of it because Speech Dispatcher doesn't have a module_resume function. Instead, Speech Dispatcher resumes by calling module_speak from the last index mark reported in the text. */ DBG("Ibmtts: module_pause()."); /* Request playback thread to pause. Note we cannot stop synthesis or playback until end of sentence or end of message is played. */ ibmtts_pause_requested = IBMTTS_TRUE; /* Wake the stop_or_pause thread. */ sem_post(&ibmtts_stop_or_pause_semaphore); return OK; } int module_close(void) { DBG("Ibmtts: close()."); if (is_thread_busy(&ibmtts_synth_suspended_mutex) || is_thread_busy(&ibmtts_play_suspended_mutex)) { DBG("Ibmtts: Stopping speech"); module_stop(); } DBG("Ibmtts: De-registering ECI callback."); eciRegisterCallback(eciHandle, NULL, NULL); DBG("Ibmtts: Destroying ECI instance."); eciDelete(eciHandle); eciHandle = NULL_ECI_HAND; /* Free buffer for ECI audio. */ g_free(audio_chunk); /* Request each thread exit and wait until it exits. */ DBG("Ibmtts: Terminating threads"); ibmtts_thread_exit_requested = IBMTTS_TRUE; sem_post(&ibmtts_synth_semaphore); sem_post(&ibmtts_play_semaphore); sem_post(&ibmtts_stop_or_pause_semaphore); if (0 != pthread_join(ibmtts_synth_thread, NULL)) return -1; if (0 != pthread_join(ibmtts_play_thread, NULL)) return -1; if (0 != pthread_join(ibmtts_stop_or_pause_thread, NULL)) return -1; ibmtts_clear_playback_queue(); /* Free index mark lookup table. */ if (ibmtts_index_mark_ht) { g_hash_table_destroy(ibmtts_index_mark_ht); ibmtts_index_mark_ht = NULL; } free_voice_list(); sem_destroy(&ibmtts_synth_semaphore); sem_destroy(&ibmtts_play_semaphore); sem_destroy(&ibmtts_stop_or_pause_semaphore); return 0; } /* Internal functions */ /* Return true if the thread is busy, i.e., suspended mutex is not locked. */ static TIbmttsBool is_thread_busy(pthread_mutex_t * suspended_mutex) { if (EBUSY == pthread_mutex_trylock(suspended_mutex)) return IBMTTS_FALSE; else { pthread_mutex_unlock(suspended_mutex); return IBMTTS_TRUE; } } /* Given a string containing an index mark in the form , returns some_name. Calling routine is responsible for freeing returned string. If an error occurs, returns NULL. */ static char *ibmtts_extract_mark_name(char *mark) { if ((SD_MARK_HEAD_ONLY_LEN + SD_MARK_TAIL_LEN + 1) > strlen(mark)) return NULL; mark = mark + SD_MARK_HEAD_ONLY_LEN; char *tail = strstr(mark, SD_MARK_TAIL); if (NULL == tail) return NULL; return (char *)g_strndup(mark, tail - mark); } /* Returns the portion of msg up to, but not including, the next index mark, or end of msg if no index mark is found. If msg begins with and index mark, returns the entire index mark clause () and returns the mark name. If msg does not begin with an index mark, mark_name will be NULL. If msg is empty, returns a zero-length string (not NULL). Caller is responsible for freeing both returned string and mark_name (if not NULL). */ /* TODO: This routine needs to be more tolerant of custom index marks with spaces. */ /* TODO: Should there be a MaxChunkLength? Delimiters? */ static char *ibmtts_next_part(char *msg, char **mark_name) { char *mark_head = strstr(msg, SD_MARK_HEAD_ONLY); if (NULL == mark_head) return (char *)g_strndup(msg, strlen(msg)); else if (mark_head == msg) { *mark_name = ibmtts_extract_mark_name(mark_head); if (NULL == *mark_name) return strcat((char *) g_strndup(msg, SD_MARK_HEAD_ONLY_LEN), ibmtts_next_part(msg + SD_MARK_HEAD_ONLY_LEN, mark_name)); else return (char *)g_strndup(msg, SD_MARK_HEAD_ONLY_LEN + strlen(*mark_name) + SD_MARK_TAIL_LEN); } else return (char *)g_strndup(msg, mark_head - msg); } /* Stop or Pause thread. */ static void *_ibmtts_stop_or_pause(void *nothing) { DBG("Ibmtts: Stop or pause thread starting.......\n"); /* Block all signals to this thread. */ set_speaking_thread_parameters(); while (!ibmtts_thread_exit_requested) { /* If semaphore not set, set suspended lock and suspend until it is signaled. */ if (0 != sem_trywait(&ibmtts_stop_or_pause_semaphore)) { pthread_mutex_lock (&ibmtts_stop_or_pause_suspended_mutex); sem_wait(&ibmtts_stop_or_pause_semaphore); pthread_mutex_unlock (&ibmtts_stop_or_pause_suspended_mutex); if (ibmtts_thread_exit_requested) break; } DBG("Ibmtts: Stop or pause semaphore on."); /* The following is a hack. The condition should never be true, but sometimes it is true for unclear reasons. */ if (!(ibmtts_stop_synth_requested || ibmtts_pause_requested)) continue; if (ibmtts_stop_synth_requested) { /* Stop synthesis (if in progress). */ if (eciHandle) { DBG("Ibmtts: Stopping synthesis."); eciStop(eciHandle); } /* Stop any audio playback (if in progress). */ if (module_audio_id) { pthread_mutex_lock(&sound_stop_mutex); DBG("Ibmtts: Stopping audio."); int ret = spd_audio_stop(module_audio_id); if (0 != ret) DBG("Ibmtts: WARNING: Non 0 value from spd_audio_stop: %d", ret); pthread_mutex_unlock(&sound_stop_mutex); } } DBG("Ibmtts: Waiting for synthesis thread to suspend."); while (is_thread_busy(&ibmtts_synth_suspended_mutex)) g_usleep(100); DBG("Ibmtts: Waiting for playback thread to suspend."); while (is_thread_busy(&ibmtts_play_suspended_mutex)) g_usleep(100); DBG("Ibmtts: Clearing playback queue."); ibmtts_clear_playback_queue(); DBG("Ibmtts: Clearing index mark lookup table."); if (ibmtts_index_mark_ht) { g_hash_table_destroy(ibmtts_index_mark_ht); ibmtts_index_mark_ht = NULL; } if (ibmtts_stop_synth_requested) module_report_event_stop(); else module_report_event_pause(); ibmtts_stop_synth_requested = IBMTTS_FALSE; ibmtts_stop_play_requested = IBMTTS_FALSE; ibmtts_pause_requested = IBMTTS_FALSE; DBG("Ibmtts: Stop or pause completed."); } DBG("Ibmtts: Stop or pause thread ended.......\n"); pthread_exit(NULL); } static int process_text_mark(char *part, int part_len, char *mark_name) { /* Handle index marks. */ if (NULL != mark_name) { /* Assign the mark name an integer number and store in lookup table. */ int *markId = (int *)g_malloc(sizeof(int)); *markId = 1 + g_hash_table_size(ibmtts_index_mark_ht); g_hash_table_insert(ibmtts_index_mark_ht, markId, mark_name); if (!eciInsertIndex(eciHandle, *markId)) { DBG("Ibmtts: Error sending index mark to synthesizer."); ibmtts_log_eci_error(); /* Try to keep going. */ } else DBG("Ibmtts: Index mark |%s| (id %i) sent to synthesizer.", mark_name, *markId); /* If pause is requested, skip over rest of message, but synthesize what we have so far. */ if (ibmtts_pause_requested) { DBG("Ibmtts: Pause requested in synthesis thread."); return 1; } return 0; } /* Handle normal text. */ if (part_len > 0) { DBG("Ibmtts: Returned %d bytes from get_part.", part_len); DBG("Ibmtts: Text to synthesize is |%s|\n", part); DBG("Ibmtts: Sending text to synthesizer."); if (!eciAddText(eciHandle, part)) { DBG("Ibmtts: Error sending text."); ibmtts_log_eci_error(); return 2; } return 0; } /* Handle end of text. */ DBG("Ibmtts: End of data in synthesis thread."); /* Add index mark for end of message. This also makes sure the callback gets called at least once */ eciInsertIndex(eciHandle, IBMTTS_MSG_END_MARK); DBG("Ibmtts: Trying to synthesize text."); if (!eciSynthesize(eciHandle)) { DBG("Ibmtts: Error synthesizing."); ibmtts_log_eci_error(); return 2;; } /* Audio and index marks are returned in eciCallback(). */ DBG("Ibmtts: Waiting for synthesis to complete."); if (!eciSynchronize(eciHandle)) { DBG("Ibmtts: Error waiting for synthesis to complete."); ibmtts_log_eci_error(); return 2; } DBG("Ibmtts: Synthesis complete."); return 3; } /* Synthesis thread. */ static void *_ibmtts_synth(void *nothing) { char *pos = NULL; char *part = NULL; int part_len = 0; int ret; DBG("Ibmtts: Synthesis thread starting.......\n"); /* Block all signals to this thread. */ set_speaking_thread_parameters(); /* Allocate a place for index mark names to be placed. */ char *mark_name = NULL; while (!ibmtts_thread_exit_requested) { /* If semaphore not set, set suspended lock and suspend until it is signaled. */ if (0 != sem_trywait(&ibmtts_synth_semaphore)) { pthread_mutex_lock(&ibmtts_synth_suspended_mutex); sem_wait(&ibmtts_synth_semaphore); pthread_mutex_unlock(&ibmtts_synth_suspended_mutex); if (ibmtts_thread_exit_requested) break; } DBG("Ibmtts: Synthesis semaphore on."); /* This table assigns each index mark name an integer id for fast lookup when ECI returns the integer index mark event. */ if (ibmtts_index_mark_ht) g_hash_table_destroy(ibmtts_index_mark_ht); ibmtts_index_mark_ht = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free); pos = *ibmtts_message; ibmtts_load_user_dictionary(); switch (ibmtts_message_type) { case SPD_MSGTYPE_TEXT: eciSetParam(eciHandle, eciTextMode, eciTextModeDefault); break; case SPD_MSGTYPE_SOUND_ICON: /* IBM TTS does not support sound icons. If we can find a sound icon file, play that, otherwise speak the name of the sound icon. */ part = ibmtts_search_for_sound_icon(*ibmtts_message); if (NULL != part) { ibmtts_add_flag_to_playback_queue (IBMTTS_QET_BEGIN); ibmtts_add_sound_icon_to_playback_queue(part); part = NULL; ibmtts_add_flag_to_playback_queue (IBMTTS_QET_END); /* Wake up the audio playback thread, if not already awake. */ if (!is_thread_busy (&ibmtts_play_suspended_mutex)) sem_post(&ibmtts_play_semaphore); continue; } else eciSetParam(eciHandle, eciTextMode, eciTextModeDefault); break; case SPD_MSGTYPE_CHAR: eciSetParam(eciHandle, eciTextMode, eciTextModeAllSpell); break; case SPD_MSGTYPE_KEY: /* Map unspeakable keys to speakable words. */ DBG("Ibmtts: Key from Speech Dispatcher: |%s|", pos); pos = ibmtts_subst_keys(pos); DBG("Ibmtts: Key to speak: |%s|", pos); g_free(*ibmtts_message); *ibmtts_message = pos; eciSetParam(eciHandle, eciTextMode, eciTextModeDefault); break; case SPD_MSGTYPE_SPELL: if (SPD_PUNCT_NONE != msg_settings.punctuation_mode) eciSetParam(eciHandle, eciTextMode, eciTextModeAllSpell); else eciSetParam(eciHandle, eciTextMode, eciTextModeAlphaSpell); break; } ibmtts_add_flag_to_playback_queue(IBMTTS_QET_BEGIN); while (TRUE) { if (ibmtts_stop_synth_requested) { DBG("Ibmtts: Stop in synthesis thread, terminating."); break; } /* TODO: How to map these msg_settings to ibm tts? ESpellMode spelling_mode; SPELLING_ON already handled in module_speak() ECapLetRecogn cap_let_recogn; RECOGN_NONE = 0, RECOGN_SPELL = 1, RECOGN_ICON = 2 */ part = ibmtts_next_part(pos, &mark_name); if (NULL == part) { DBG("Ibmtts: Error getting next part of message."); /* TODO: What to do here? */ break; } part_len = strlen(part); pos += part_len; ret = process_text_mark(part, part_len, mark_name); g_free(part); part = NULL; mark_name = NULL; if (ret == 1) pos += strlen(pos); else if (ret > 1) break; } } DBG("Ibmtts: Synthesis thread ended.......\n"); pthread_exit(NULL); } static void ibmtts_set_rate(signed int rate) { /* Setting rate to midpoint is too fast. An eci value of 50 is "normal". See chart on pg 38 of the ECI manual. */ assert(rate >= -100 && rate <= +100); int speed; /* Possible ECI range is 0 to 250. */ /* Map rate -100 to 100 onto speed 0 to 140. */ if (rate < 0) /* Map -100 to 0 onto 0 to ibmtts_voice_speed */ speed = ((float)(rate + 100) * ibmtts_voice_speed) / (float)100; else /* Map 0 to 100 onto ibmtts_voice_speed to 140 */ speed = (((float)rate * (140 - ibmtts_voice_speed)) / (float)100) + ibmtts_voice_speed; assert(speed >= 0 && speed <= 140); int ret = eciSetVoiceParam(eciHandle, 0, eciSpeed, speed); if (-1 == ret) { DBG("Ibmtts: Error setting rate %i.", speed); ibmtts_log_eci_error(); } else DBG("Ibmtts: Rate set to %i.", speed); } static void ibmtts_set_volume(signed int volume) { /* Setting volume to midpoint makes speech too soft. An eci value of 90 to 100 is "normal". See chart on pg 38 of the ECI manual. TODO: Rather than setting volume in the synth, maybe control volume on playback? */ assert(volume >= -100 && volume <= +100); int vol; /* Possible ECI range is 0 to 100. */ if (volume < 0) /* Map -100 to 0 onto 0 to 90 */ vol = (((float)volume + 100) * 90) / (float)100; else /* Map 0 to 100 onto 90 to 100 */ vol = ((float)(volume * 10) / (float)100) + 90; assert(vol >= 0 && vol <= 100); int ret = eciSetVoiceParam(eciHandle, 0, eciVolume, vol); if (-1 == ret) { DBG("Ibmtts: Error setting volume %i.", vol); ibmtts_log_eci_error(); } else DBG("Ibmtts: Volume set to %i.", vol); } static void ibmtts_set_pitch(signed int pitch) { /* Setting pitch to midpoint is to low. eci values between 65 and 89 are "normal". See chart on pg 38 of the ECI manual. */ assert(pitch >= -100 && pitch <= +100); int pitchBaseline; /* Possible range 0 to 100. */ if (pitch < 0) /* Map -100 to 0 onto 0 to ibmtts_voice_pitch_baseline */ pitchBaseline = ((float)(pitch + 100) * ibmtts_voice_pitch_baseline) / (float)100; else /* Map 0 to 100 onto ibmtts_voice_pitch_baseline to 100 */ pitchBaseline = (((float)pitch * (100 - ibmtts_voice_pitch_baseline)) / (float)100) + ibmtts_voice_pitch_baseline; assert(pitchBaseline >= 0 && pitchBaseline <= 100); int ret = eciSetVoiceParam(eciHandle, 0, eciPitchBaseline, pitchBaseline); if (-1 == ret) { DBG("Ibmtts: Error setting pitch %i.", pitchBaseline); ibmtts_log_eci_error(); } else DBG("Ibmtts: Pitch set to %i.", pitchBaseline); } static void ibmtts_set_punctuation_mode(SPDPunctuation punct_mode) { const char *fmt = "`Pf%d%s"; char *msg = NULL; int real_punct_mode = 0; switch (punct_mode) { case SPD_PUNCT_NONE: real_punct_mode = 0; break; case SPD_PUNCT_SOME: real_punct_mode = 2; break; case SPD_PUNCT_ALL: real_punct_mode = 1; break; } msg = g_strdup_printf(fmt, real_punct_mode, IbmttsPunctuationList); eciAddText(eciHandle, msg); g_free(msg); } static char *ibmtts_voice_enum_to_str(SPDVoiceType voice) { /* TODO: Would be better to move this to module_utils.c. */ char *voicename; switch (voice) { case SPD_MALE1: voicename = g_strdup("male1"); break; case SPD_MALE2: voicename = g_strdup("male2"); break; case SPD_MALE3: voicename = g_strdup("male3"); break; case SPD_FEMALE1: voicename = g_strdup("female1"); break; case SPD_FEMALE2: voicename = g_strdup("female2"); break; case SPD_FEMALE3: voicename = g_strdup("female3"); break; case SPD_CHILD_MALE: voicename = g_strdup("child_male"); break; case SPD_CHILD_FEMALE: voicename = g_strdup("child_female"); break; default: voicename = g_strdup("no voice"); break; } return voicename; } /* Given a language, dialect and SD voice codes sets the IBM voice */ static void ibmtts_set_language_and_voice(char *lang, SPDVoiceType voice, char *variant) { char *variant_name = variant; char *voicename = ibmtts_voice_enum_to_str(voice); int eciVoice; int ret = -1; int i = 0; int j = 0; DBG("Ibmtts: %s, lang=%s, voice=%d, dialect=%s", __FUNCTION__, lang, (int)voice, variant ? variant : NULL); SPDVoice **v = ibmtts_voice_list; assert(v); if (variant_name) { for (i = 0; v[i]; i++) { DBG("%d. variant=%s", i, v[i]->variant); if (!strcmp(v[i]->variant, variant_name)) { j = ibmtts_voice_index[i]; ret = eciSetParam(eciHandle, eciLanguageDialect, eciLocales[j].langID); DBG("Ibmtts: set langID=0x%x (ret=%d)", eciLocales[j].langID, ret); ibmtts_input_encoding = eciLocales[j].charset; break; } } } else { for (i = 0; v[i]; i++) { DBG("%d. language=%s", i, v[i]->language); if (!strcmp(v[i]->language, lang)) { j = ibmtts_voice_index[i]; variant_name = v[i]->name; ret = eciSetParam(eciHandle, eciLanguageDialect, eciLocales[j].langID); DBG("Ibmtts: set langID=0x%x (ret=%d)", eciLocales[j].langID, ret); ibmtts_input_encoding = eciLocales[j].charset; break; } } } if (-1 == ret) { DBG("Ibmtts: Unable to set language"); ibmtts_log_eci_error(); } else { g_atomic_int_set(&locale_index_atomic, j); } /* Set voice parameters (if any are defined for this voice.) */ TIbmttsVoiceParameters *params = g_hash_table_lookup(IbmttsVoiceParameters, voicename); if (NULL == params) { DBG("Ibmtts: Setting default VoiceParameters for voice %s", voicename); switch (voice) { case SPD_MALE1: eciVoice = 1; break; /* Adult Male 1 */ case SPD_MALE2: eciVoice = 4; break; /* Adult Male 2 */ case SPD_MALE3: eciVoice = 5; break; /* Adult Male 3 */ case SPD_FEMALE1: eciVoice = 2; break; /* Adult Female 1 */ case SPD_FEMALE2: eciVoice = 6; break; /* Adult Female 2 */ case SPD_FEMALE3: eciVoice = 7; break; /* Elderly Female 1 */ case SPD_CHILD_MALE: eciVoice = 3; break; /* Child */ case SPD_CHILD_FEMALE: eciVoice = 3; break; /* Child */ default: eciVoice = 1; break; /* Adult Male 1 */ } ret = eciCopyVoice(eciHandle, eciVoice, 0); if (-1 == ret) DBG("Ibmtts: ERROR: Setting default voice parameters (voice %i).", eciVoice); } else { DBG("Ibmtts: Setting custom VoiceParameters for voice %s", voicename); ret = eciSetVoiceParam(eciHandle, 0, eciGender, params->gender); if (-1 == ret) DBG("Ibmtts: ERROR: Setting gender %i", params->gender); ret = eciSetVoiceParam(eciHandle, 0, eciBreathiness, params->breathiness); if (-1 == ret) DBG("Ibmtts: ERROR: Setting breathiness %i", params->breathiness); ret = eciSetVoiceParam(eciHandle, 0, eciHeadSize, params->head_size); if (-1 == ret) DBG("Ibmtts: ERROR: Setting head size %i", params->head_size); ret = eciSetVoiceParam(eciHandle, 0, eciPitchBaseline, params->pitch_baseline); if (-1 == ret) DBG("Ibmtts: ERROR: Setting pitch baseline %i", params->pitch_baseline); ret = eciSetVoiceParam(eciHandle, 0, eciPitchFluctuation, params->pitch_fluctuation); if (-1 == ret) DBG("Ibmtts: ERROR: Setting pitch fluctuation %i", params->pitch_fluctuation); ret = eciSetVoiceParam(eciHandle, 0, eciRoughness, params->roughness); if (-1 == ret) DBG("Ibmtts: ERROR: Setting roughness %i", params->roughness); ret = eciSetVoiceParam(eciHandle, 0, eciSpeed, params->speed); if (-1 == ret) DBG("Ibmtts: ERROR: Setting speed %i", params->speed); } g_free(voicename); /* Retrieve the baseline pitch and speed of the voice. */ ibmtts_voice_pitch_baseline = eciGetVoiceParam(eciHandle, 0, eciPitchBaseline); if (-1 == ibmtts_voice_pitch_baseline) DBG("Ibmtts: Cannot get pitch baseline of voice."); ibmtts_voice_speed = eciGetVoiceParam(eciHandle, 0, eciSpeed); if (-1 == ibmtts_voice_speed) DBG("Ibmtts: Cannot get speed of voice."); } static void ibmtts_set_voice(SPDVoiceType voice) { if (msg_settings.voice.language) { ibmtts_set_language_and_voice(msg_settings.voice.language, voice, NULL); } } static void ibmtts_set_language(char *lang) { ibmtts_set_language_and_voice(lang, msg_settings.voice_type, NULL); } /* sets the IBM voice according to its name. */ static void ibmtts_set_synthesis_voice(char *synthesis_voice) { int i = 0; if (synthesis_voice == NULL) { return; } DBG("Ibmtts: %s, synthesis voice=%s", __FUNCTION__, synthesis_voice); for (i = 0; i < MAX_NB_OF_LANGUAGES; i++) { if (!strcasecmp(eciLocales[i].name, synthesis_voice)) { ibmtts_set_language_and_voice(eciLocales[i].lang, msg_settings.voice_type, eciLocales[i].dialect); break; } } } static void ibmtts_log_eci_error() { /* TODO: This routine is not working. Not sure why. */ char buf[100]; eciErrorMessage(eciHandle, buf); DBG("Ibmtts: ECI Error Message: %s", buf); } /* IBM TTS calls back here when a chunk of audio is ready or an index mark has been reached. The good news is that it returns the audio up to each index mark or when the audio buffer is full. */ static enum ECICallbackReturn eciCallback(ECIHand hEngine, enum ECIMessage msg, long lparam, void *data) { int ret; /* This callback is running in the same thread as called eciSynchronize(), i.e., the _ibmtts_synth() thread. */ /* If module_stop was called, discard any further callbacks until module_speak is called. */ if (ibmtts_stop_synth_requested || ibmtts_stop_play_requested) return eciDataProcessed; switch (msg) { case eciWaveformBuffer: DBG("Ibmtts: %ld audio samples returned from IBM TTS.", lparam); /* Add audio to output queue. */ ret = ibmtts_add_audio_to_playback_queue(audio_chunk, lparam); /* Wake up the audio playback thread, if not already awake. */ if (!is_thread_busy(&ibmtts_play_suspended_mutex)) sem_post(&ibmtts_play_semaphore); return eciDataProcessed; break; case eciIndexReply: DBG("Ibmtts: Index mark id %ld returned from IBM TTS.", lparam); if (lparam == IBMTTS_MSG_END_MARK) { ibmtts_add_flag_to_playback_queue(IBMTTS_QET_END); } else { /* Add index mark to output queue. */ ret = ibmtts_add_mark_to_playback_queue(lparam); } /* Wake up the audio playback thread, if not already awake. */ if (!is_thread_busy(&ibmtts_play_suspended_mutex)) sem_post(&ibmtts_play_semaphore); return eciDataProcessed; break; default: return eciDataProcessed; } } /* Adds a chunk of pcm audio to the audio playback queue. */ static TIbmttsBool ibmtts_add_audio_to_playback_queue(TEciAudioSamples * audio_chunk, long num_samples) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); if (NULL == playback_queue_entry) return IBMTTS_FALSE; playback_queue_entry->type = IBMTTS_QET_AUDIO; playback_queue_entry->data.audio.num_samples = (int)num_samples; int wlen = sizeof(TEciAudioSamples) * num_samples; playback_queue_entry->data.audio.audio_chunk = (TEciAudioSamples *) g_malloc(wlen); memcpy(playback_queue_entry->data.audio.audio_chunk, audio_chunk, wlen); pthread_mutex_lock(&playback_queue_mutex); playback_queue = g_slist_append(playback_queue, playback_queue_entry); pthread_mutex_unlock(&playback_queue_mutex); return IBMTTS_TRUE; } /* Adds an Index Mark to the audio playback queue. */ static TIbmttsBool ibmtts_add_mark_to_playback_queue(long markId) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); if (NULL == playback_queue_entry) return IBMTTS_FALSE; playback_queue_entry->type = IBMTTS_QET_INDEX_MARK; playback_queue_entry->data.markId = markId; pthread_mutex_lock(&playback_queue_mutex); playback_queue = g_slist_append(playback_queue, playback_queue_entry); pthread_mutex_unlock(&playback_queue_mutex); return IBMTTS_TRUE; } /* Adds a begin or end flag to the playback queue. */ static TIbmttsBool ibmtts_add_flag_to_playback_queue(EPlaybackQueueEntryType type) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); if (NULL == playback_queue_entry) return IBMTTS_FALSE; playback_queue_entry->type = type; pthread_mutex_lock(&playback_queue_mutex); playback_queue = g_slist_append(playback_queue, playback_queue_entry); pthread_mutex_unlock(&playback_queue_mutex); return IBMTTS_TRUE; } /* Add a sound icon to the playback queue. */ static TIbmttsBool ibmtts_add_sound_icon_to_playback_queue(char *filename) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); if (NULL == playback_queue_entry) return IBMTTS_FALSE; playback_queue_entry->type = IBMTTS_QET_SOUND_ICON; playback_queue_entry->data.sound_icon_filename = filename; pthread_mutex_lock(&playback_queue_mutex); playback_queue = g_slist_append(playback_queue, playback_queue_entry); pthread_mutex_unlock(&playback_queue_mutex); return IBMTTS_TRUE; } /* Deletes an entry from the playback audio queue, freeing memory. */ static void ibmtts_delete_playback_queue_entry(TPlaybackQueueEntry * playback_queue_entry) { switch (playback_queue_entry->type) { case IBMTTS_QET_AUDIO: g_free(playback_queue_entry->data.audio.audio_chunk); break; case IBMTTS_QET_SOUND_ICON: g_free(playback_queue_entry->data.sound_icon_filename); break; default: break; } g_free(playback_queue_entry); } /* Erases the entire playback queue, freeing memory. */ static void ibmtts_clear_playback_queue() { pthread_mutex_lock(&playback_queue_mutex); while (NULL != playback_queue) { TPlaybackQueueEntry *playback_queue_entry = playback_queue->data; ibmtts_delete_playback_queue_entry(playback_queue_entry); playback_queue = g_slist_remove(playback_queue, playback_queue->data); } playback_queue = NULL; pthread_mutex_unlock(&playback_queue_mutex); } /* Sends a chunk of audio to the audio player and waits for completion or error. */ static TIbmttsBool ibmtts_send_to_audio(TPlaybackQueueEntry * playback_queue_entry) { AudioTrack track; #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) AudioFormat format = SPD_AUDIO_BE; #else AudioFormat format = SPD_AUDIO_LE; #endif int ret; track.num_samples = playback_queue_entry->data.audio.num_samples; track.num_channels = 1; track.sample_rate = eci_sample_rate; track.bits = 16; track.samples = playback_queue_entry->data.audio.audio_chunk; if (track.samples == NULL) return IBMTTS_TRUE; DBG("Ibmtts: Sending %i samples to audio.", track.num_samples); ret = module_tts_output(track, format); if (ret < 0) { DBG("ERROR: Can't play track for unknown reason."); return IBMTTS_FALSE; } DBG("Ibmtts: Sent to audio."); return IBMTTS_TRUE; } /* Playback thread. */ static void *_ibmtts_play(void *nothing) { int markId; char *mark_name; TPlaybackQueueEntry *playback_queue_entry = NULL; DBG("Ibmtts: Playback thread starting.......\n"); /* Block all signals to this thread. */ set_speaking_thread_parameters(); while (!ibmtts_thread_exit_requested) { /* If semaphore not set, set suspended lock and suspend until it is signaled. */ if (0 != sem_trywait(&ibmtts_play_semaphore)) { pthread_mutex_lock(&ibmtts_play_suspended_mutex); sem_wait(&ibmtts_play_semaphore); pthread_mutex_unlock(&ibmtts_play_suspended_mutex); } /* DBG("Ibmtts: Playback semaphore on."); */ while (!ibmtts_stop_play_requested && !ibmtts_thread_exit_requested) { pthread_mutex_lock(&playback_queue_mutex); if (NULL != playback_queue) { playback_queue_entry = playback_queue->data; playback_queue = g_slist_remove(playback_queue, playback_queue->data); } pthread_mutex_unlock(&playback_queue_mutex); if (NULL == playback_queue_entry) break; switch (playback_queue_entry->type) { case IBMTTS_QET_AUDIO: ibmtts_send_to_audio(playback_queue_entry); break; case IBMTTS_QET_INDEX_MARK: /* Look up the index mark integer id in lookup table to find string name and emit that name. */ markId = playback_queue_entry->data.markId; mark_name = g_hash_table_lookup(ibmtts_index_mark_ht, &markId); if (NULL == mark_name) { DBG("Ibmtts: markId %d returned by IBM TTS not found in lookup table.", markId); } else { DBG("Ibmtts: reporting index mark |%s|.", mark_name); module_report_index_mark(mark_name); DBG("Ibmtts: index mark reported."); /* If pause requested, wait for an end-of-sentence index mark. */ if (ibmtts_pause_requested) { if (0 == strncmp(mark_name, SD_MARK_BODY, SD_MARK_BODY_LEN)) { DBG("Ibmtts: Pause requested in playback thread. Stopping."); ibmtts_stop_play_requested = IBMTTS_TRUE; } } } break; case IBMTTS_QET_SOUND_ICON: module_play_file(playback_queue_entry-> data.sound_icon_filename); break; case IBMTTS_QET_BEGIN: module_report_event_begin(); break; case IBMTTS_QET_END: module_report_event_end(); break; } ibmtts_delete_playback_queue_entry (playback_queue_entry); playback_queue_entry = NULL; } if (ibmtts_stop_play_requested) DBG("Ibmtts: Stop or pause in playback thread."); } DBG("Ibmtts: Playback thread ended.......\n"); pthread_exit(NULL); } /* Replaces all occurrences of "from" with "to" in msg. Returns count of replacements. */ static int ibmtts_replace(char *from, char *to, GString * msg) { int count = 0; int pos; int from_len = strlen(from); int to_len = strlen(to); char *p = msg->str; while (NULL != (p = strstr(p, from))) { pos = p - msg->str; g_string_erase(msg, pos, from_len); g_string_insert(msg, pos, to); p = msg->str + pos + to_len; ++count; } return count; } static void ibmtts_subst_keys_cb(gpointer data, gpointer user_data) { TIbmttsKeySubstitution *key_subst = data; GString *msg = user_data; ibmtts_replace(key_subst->key, key_subst->newkey, msg); } /* Given a Speech Dispatcher !KEY key sequence, replaces unspeakable or incorrectly spoken keys or characters with speakable ones. The subsitutions come from the KEY NAME SUBSTITUTIONS section of the config file. Caller is responsible for freeing returned string. */ static char *ibmtts_subst_keys(char *key) { GString *tmp = g_string_sized_new(30); g_string_append(tmp, key); GList *keyTable = g_hash_table_lookup(IbmttsKeySubstitution, msg_settings.voice.language); if (keyTable) g_list_foreach(keyTable, ibmtts_subst_keys_cb, tmp); /* Hyphen hangs IBM TTS */ if (0 == strcmp(tmp->str, "-")) g_string_assign(tmp, "hyphen"); return g_string_free(tmp, FALSE); } /* Given a sound icon name, searches for a file to play and if found returns the filename. Returns NULL if none found. Caller is responsible for freeing the returned string. */ /* TODO: These current assumptions should be dealt with: Sound icon files are in a single directory (IbmttsSoundIconFolder). The name of each icon is symlinked to a .wav file. If you have installed the free(b)soft sound-icons package under Debian, then these assumptions are true, but what about other distros and OSes? */ static char *ibmtts_search_for_sound_icon(const char *icon_name) { char *fn = NULL; if (0 == strlen(IbmttsSoundIconFolder)) return fn; GString *filename = g_string_new(IbmttsSoundIconFolder); filename = g_string_append(filename, icon_name); if (g_file_test(filename->str, G_FILE_TEST_EXISTS)) fn = filename->str; /* else { filename = g_string_assign(filename, g_utf8_strdown(filename->str, -1)); if (g_file_test(filename->str, G_FILE_TEST_EXISTS)) fn = filename->str; } */ /* * if the file was found, the pointer *fn points to the character data * of the string filename. In this situation the string filename must be * freed but its character data must be preserved. * If the file is not found, the pointer *fn contains NULL. In this * situation the string filename must be freed, including its character * data. */ g_string_free(filename, (fn == NULL)); return fn; } void alloc_voice_list() { enum ECILanguageDialect aLanguage[MAX_NB_OF_LANGUAGES]; int nLanguages = MAX_NB_OF_LANGUAGES; int i = 0; if (eciGetAvailableLanguages(aLanguage, &nLanguages)) return; ibmtts_voice_list = g_malloc((nLanguages + 1) * sizeof(SPDVoice *)); ibmtts_voice_index = g_malloc((nLanguages + 1) * sizeof(SPDVoice *)); if (!ibmtts_voice_list) return; DBG("Ibmtts: nLanguages=%d/%d", nLanguages, MAX_NB_OF_LANGUAGES); for (i = 0; i < nLanguages; i++) { /* look for the language name */ int j; ibmtts_voice_list[i] = g_malloc(sizeof(SPDVoice)); DBG("Ibmtts: aLanguage[%d]=0x%08x", i, aLanguage[i]); for (j = 0; j < MAX_NB_OF_LANGUAGES; j++) { DBG("Ibmtts: eciLocales[%d].langID=0x%08x", j, eciLocales[j].langID); if (eciLocales[j].langID == aLanguage[i]) { ibmtts_voice_list[i]->name = eciLocales[j].name; ibmtts_voice_list[i]->language = eciLocales[j].lang; ibmtts_voice_list[i]->variant = eciLocales[j].dialect; ibmtts_voice_index[i] = j; DBG("Ibmtts: alloc_voice_list %s", ibmtts_voice_list[i]->name); break; } } assert(j < MAX_NB_OF_LANGUAGES); } ibmtts_voice_list[nLanguages] = NULL; DBG("Ibmtts: LEAVE %s", __func__); } static void free_voice_list() { int i = 0; if (ibmtts_voice_index) { g_free(ibmtts_voice_index); ibmtts_voice_index = NULL; } if (!ibmtts_voice_list) return; for (i = 0; ibmtts_voice_list[i]; i++) { g_free(ibmtts_voice_list[i]); } g_free(ibmtts_voice_list); ibmtts_voice_list = NULL; } static void ibmtts_load_user_dictionary() { GString *dirname = NULL; GString *filename = NULL; int i = 0; int dictionary_is_present = 0; static guint old_index = MAX_NB_OF_LANGUAGES; guint new_index; const char *language = NULL; const char *region = NULL; ECIDictHand eciDict = eciGetDict(eciHandle); new_index = g_atomic_int_get(&locale_index_atomic); if (new_index >= MAX_NB_OF_LANGUAGES) { DBG("Ibmtts: %s, unexpected index (0x%x)", __FUNCTION__, new_index); return; } if (old_index == new_index) { DBG("Ibmtts: LEAVE %s, no change", __FUNCTION__); return; } language = eciLocales[new_index].lang; region = eciLocales[new_index].dialect; /* Fix locale name for French Canadian */ if (!strcmp(language, "ca") && !strcmp(region, "FR")) { language = "fr"; region = "CA"; } if (eciDict) { DBG("Ibmtts: delete old dictionary"); eciDeleteDict(eciHandle, eciDict); } eciDict = eciNewDict(eciHandle); if (eciDict) { old_index = new_index; } else { old_index = MAX_NB_OF_LANGUAGES; DBG("Ibmtts: can't create new dictionary"); return; } /* Look for the dictionary directory */ dirname = g_string_new(NULL); g_string_printf(dirname, "%s/%s_%s", IbmttsDictionaryFolder, language, region); if (!g_file_test(dirname->str, G_FILE_TEST_IS_DIR)) { g_string_printf(dirname, "%s/%s", IbmttsDictionaryFolder, language); if (!g_file_test(dirname->str, G_FILE_TEST_IS_DIR)) { g_string_printf(dirname, "%s", IbmttsDictionaryFolder); if (!g_file_test(dirname->str, G_FILE_TEST_IS_DIR)) { DBG("Ibmtts: %s is not a directory", dirname->str); return; } } } DBG("Ibmtts: Looking in dictionary directory %s", dirname->str); filename = g_string_new(NULL); for (i = 0; i < NB_OF_DICTIONARY_FILENAMES; i++) { g_string_printf(filename, "%s/%s", dirname->str, dictionary_filenames[i]); if (g_file_test(filename->str, G_FILE_TEST_EXISTS)) { enum ECIDictError error = eciLoadDict(eciHandle, eciDict, i, filename->str); if (!error) { dictionary_is_present = 1; DBG("Ibmtts: %s dictionary loaded", filename->str); } else { DBG("Ibmtts: Can't load %s dictionary (%d)", filename->str, error); } } else { DBG("Ibmtts: No %s dictionary", filename->str); } } g_string_free(filename, TRUE); g_string_free(dirname, TRUE); if (dictionary_is_present) { eciSetDict(eciHandle, eciDict); } } speech-dispatcher-0.8.3/src/modules/ivona.c0000664000175000017500000003225612530733575015601 00000000000000 /* * ivona.c - Speech Dispatcher backend for Ivona (IVO Software) * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: ivona.c,v 1.3 2008-06-27 12:29:32 hanke Exp $ */ /* this file is strictly based on flite.c */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "spd_audio.h" #include #include "module_utils.h" #include "ivona_client.h" #include #define MODULE_NAME "ivona" #define MODULE_VERSION "0.2" #define DEBUG_MODULE 1 DECLARE_DEBUG(); /* Thread and process control */ static int ivona_speaking = 0; static pthread_t ivona_speak_thread; static sem_t ivona_semaphore; static char **ivona_message; static SPDMessageType ivona_message_type; signed int ivona_volume = 0; signed int ivona_cap_mode = 0; int ivona_punct_mode = 0; /* Internal functions prototypes */ static int ivona_get_msgpart(struct dumbtts_conf *conf, SPDMessageType type, char **msg, char *icon, char **buf, int *len, int cap_mode, char *delimeters, int punct_mode, char *punct_some); static void ivona_set_volume(signed int volume); static void ivona_set_punctuation_mode(SPDPunctuation punct_mode); static void ivona_set_cap_let_recogn(SPDCapitalLetters cap_mode); static void *_ivona_speak(void *); int ivona_stop = 0; MOD_OPTION_1_STR(IvonaDelimiters); MOD_OPTION_1_STR(IvonaPunctuationSome); MOD_OPTION_1_INT(IvonaMinCapLet); MOD_OPTION_1_STR(IvonaSoundIconPath); MOD_OPTION_1_STR(IvonaServerHost); MOD_OPTION_1_INT(IvonaServerPort); MOD_OPTION_1_INT(IvonaSampleFreq); MOD_OPTION_1_STR(IvonaSpeakerLanguage); MOD_OPTION_1_STR(IvonaSpeakerName); static struct dumbtts_conf *ivona_conf; /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); MOD_OPTION_1_STR_REG(IvonaDelimiters, ".;:,!?"); MOD_OPTION_1_INT_REG(IvonaMinCapLet, 0); MOD_OPTION_1_STR_REG(IvonaSoundIconPath, "/usr/share/sound/sound-icons/"); MOD_OPTION_1_STR_REG(IvonaServerHost, "127.0.0.1"); MOD_OPTION_1_INT_REG(IvonaServerPort, 9123); MOD_OPTION_1_INT_REG(IvonaSampleFreq, 16000); MOD_OPTION_1_STR_REG(IvonaSpeakerLanguage, "pl"); MOD_OPTION_1_STR_REG(IvonaSpeakerName, "Jacek"); MOD_OPTION_1_STR_REG(IvonaPunctuationSome, "()"); ivona_init_cache(); return 0; } #define ABORT(msg) g_string_append(info, msg); \ DBG("FATAL ERROR:", info->str); \ *status_info = info->str; \ g_string_free(info, 0); \ return -1; int module_init(char **status_info) { int ret; GString *info; DBG("Module init"); *status_info = NULL; info = g_string_new(""); /* Init Ivona */ if (ivona_init_sock(IvonaServerHost, IvonaServerPort)) { DBG("Couldn't init socket parameters"); *status_info = g_strdup("Can't initialize socket. " "Check server host/port."); return -1; } ivona_conf = dumbtts_TTSInit(IvonaSpeakerLanguage); DBG("IvonaDelimiters = %s\n", IvonaDelimiters); ivona_message = g_malloc(sizeof(char *)); *ivona_message = NULL; sem_init(&ivona_semaphore, 0, 0); DBG("Ivona: creating new thread for ivona_speak\n"); ivona_speaking = 0; ret = pthread_create(&ivona_speak_thread, NULL, _ivona_speak, NULL); if (ret != 0) { DBG("Ivona: thread failed\n"); *status_info = g_strdup("The module couldn't initialize threads " "This could be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return -1; } *status_info = g_strdup("Ivona initialized successfully."); return 0; } #undef ABORT static SPDVoice voice_jacek; static SPDVoice *voice_ivona[] = { &voice_jacek, NULL }; SPDVoice **module_list_voices(void) { voice_jacek.name = IvonaSpeakerName; voice_jacek.language = IvonaSpeakerLanguage; return voice_ivona; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { DBG("write()\n"); if (ivona_speaking) { DBG("Speaking when requested to write"); return 0; } DBG("Requested data: |%s|\n", data); if (*ivona_message != NULL) { g_free(*ivona_message); *ivona_message = NULL; } *ivona_message = module_strip_ssml(data); ivona_message_type = msgtype; if ((msgtype == SPD_MSGTYPE_TEXT) && (msg_settings.spelling_mode == SPD_SPELL_ON)) ivona_message_type = SPD_MSGTYPE_SPELL; /* Setting voice */ UPDATE_PARAMETER(volume, ivona_set_volume); UPDATE_PARAMETER(cap_let_recogn, ivona_set_cap_let_recogn); UPDATE_PARAMETER(punctuation_mode, ivona_set_punctuation_mode); /* Send semaphore signal to the speaking thread */ ivona_speaking = 1; sem_post(&ivona_semaphore); DBG("Ivona: leaving write() normally\n\r"); return bytes; } int module_stop(void) { int ret; DBG("ivona: stop()\n"); ivona_stop = 1; if (module_audio_id) { DBG("Stopping audio"); ret = spd_audio_stop(module_audio_id); if (ret != 0) DBG("WARNING: Non 0 value from spd_audio_stop: %d", ret); } return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (ivona_speaking) { DBG("Ivona doesn't support pause, stopping\n"); module_stop(); return -1; } else { return 0; } } int module_close(void) { DBG("ivona: close()\n"); DBG("Stopping speech"); if (ivona_speaking) { module_stop(); } DBG("Terminating threads"); if (module_terminate_thread(ivona_speak_thread) != 0) return -1; sem_destroy(&ivona_semaphore); return 0; } /* Internal functions */ static int get_unichar(char **str) { wchar_t wc; int n; wc = *(*str)++ & 255; if ((wc & 0xe0) == 0xc0) { wc &= 0x1f; n = 1; } else if ((wc & 0xf0) == 0xe0) { wc &= 0x0f; n = 2; } else if ((wc & 0xf8) == 0xf0) { wc &= 0x07; n = 3; } else if ((wc & 0xfc) == 0xf8) { wc &= 0x03; n = 4; } else if ((wc & 0xfe) == 0xfc) { wc &= 0x01; n = 5; } else return wc; while (n--) { if ((**str & 0xc0) != 0x80) { wc = '?'; break; } wc = (wc << 6) | ((*(*str)++) & 0x3f); } return wc; } static int ivona_get_msgpart(struct dumbtts_conf *conf, SPDMessageType type, char **msg, char *icon, char **buf, int *len, int cap_mode, char *delimeters, int punct_mode, char *punct_some) { int rc; int isicon; int n, bytes; unsigned int pos; wchar_t wc; char xbuf[1024]; if (!*msg) return 1; if (!**msg) return 1; isicon = 0; icon[0] = 0; if (*buf) **buf = 0; DBG("Ivona message %s type %d\n", *msg, type); switch (type) { case SPD_MSGTYPE_SOUND_ICON: if (strlen(*msg) < 63) { strcpy(icon, *msg); rc = 0; } else { rc = 1; } *msg = NULL; return rc; case SPD_MSGTYPE_SPELL: wc = get_unichar(msg); if (!wc) { *msg = NULL; return 1; } n = dumbtts_WCharString(conf, wc, *buf, *len, cap_mode, &isicon); if (n > 0) { *len = n + 128; *buf = g_realloc(*buf, *len); n = dumbtts_WCharString(conf, wc, *buf, *len, cap_mode, &isicon); } if (n) { *msg = NULL; return 1; } if (isicon) strcpy(icon, "capital"); return 0; case SPD_MSGTYPE_KEY: case SPD_MSGTYPE_CHAR: if (type == SPD_MSGTYPE_KEY) { n = dumbtts_KeyString(conf, *msg, *buf, *len, cap_mode, &isicon); } else { n = dumbtts_CharString(conf, *msg, *buf, *len, cap_mode, &isicon); } DBG("Got n=%d", n); if (n > 0) { *len = n + 128; *buf = g_realloc(*buf, *len); if (type == SPD_MSGTYPE_KEY) { n = dumbtts_KeyString(conf, *msg, *buf, *len, cap_mode, &isicon); } else { n = dumbtts_CharString(conf, *msg, *buf, *len, cap_mode, &isicon); } } *msg = NULL; if (!n && isicon) strcpy(icon, "capital"); return n; case SPD_MSGTYPE_TEXT: pos = 0; bytes = module_get_message_part(*msg, xbuf, &pos, 1023, delimeters); DBG("Got bytes %d, %s", bytes, xbuf); if (bytes <= 0) { *msg = NULL; return 1; } *msg += pos; xbuf[bytes] = 0; n = dumbtts_GetString(conf, xbuf, *buf, *len, punct_mode, punct_some, ",.;:!?"); if (n > 0) { *len = n + 128; *buf = g_realloc(*buf, *len); n = dumbtts_GetString(conf, xbuf, *buf, *len, punct_mode, punct_some, ",.;:!?"); } if (n) { *msg = NULL; return 1; } DBG("Returning to Ivona |%s|", *buf); return 0; default: *msg = NULL; DBG("Unknown message type\n"); return 1; } } void *_ivona_speak(void *nothing) { AudioTrack track; char *buf; int len; char *msg, *audio; char icon[64]; int samples, offset; int fd; char *next_audio; int next_samples, next_offset; char next_icon[64]; char next_cache[16]; DBG("ivona: speaking thread starting.......\n"); set_speaking_thread_parameters(); while (1) { sem_wait(&ivona_semaphore); DBG("Semaphore on\n"); ivona_stop = 0; ivona_speaking = 1; module_report_event_begin(); msg = *ivona_message; DBG("To say: %s\n", msg); buf = NULL; len = 0; fd = -1; audio = NULL; next_audio = NULL; next_icon[0] = 0; while (1) { if (ivona_stop) { DBG("Stop in child, terminating"); ivona_speaking = 0; module_report_event_stop(); break; } audio = NULL; if (next_audio) { audio = next_audio; samples = next_samples; offset = next_offset; strcpy(icon, next_icon); next_audio = NULL; DBG("Got wave from next_audio"); } else if (fd >= 0) { audio = ivona_get_wave_fd(fd, &samples, &offset); strcpy(icon, next_icon); if (audio && next_cache[0]) { ivona_store_wave_in_cache(next_cache, audio + 2 * offset, samples); } fd = -1; DBG("Got wave from fd"); } else if (next_icon[0]) { strcpy(icon, next_icon); DBG("Got icon"); } if (!audio && !icon[0]) { if (!msg || !*msg || ivona_get_msgpart(ivona_conf, ivona_message_type, &msg, icon, &buf, &len, ivona_cap_mode, IvonaDelimiters, ivona_punct_mode, IvonaPunctuationSome)) { ivona_speaking = 0; if (ivona_stop) module_report_event_stop(); else module_report_event_end(); break; } if (buf && *buf) { audio = ivona_get_wave(buf, &samples, &offset); DBG("Got wave from direct"); } } /* tu mamy audio albo icon, mozna gadac */ if (ivona_stop) { DBG("Stop in child, terminating"); ivona_speaking = 0; module_report_event_stop(); break; } next_icon[0] = 0; if (msg && *msg) { if (!ivona_get_msgpart (ivona_conf, ivona_message_type, &msg, next_icon, &buf, &len, ivona_cap_mode, IvonaDelimiters, ivona_punct_mode, IvonaPunctuationSome)) { if (buf && *buf) { next_offset = 0; next_audio = ivona_get_wave_from_cache (buf, &next_samples); if (!next_audio) { DBG("Sending %s to ivona", buf); next_cache[0] = 0; if (strlen(buf) <= IVONA_CACHE_MAX_STRLEN) strcpy (next_cache, buf); fd = ivona_send_string (buf); } } } } if (ivona_stop) { DBG("Stop in child, terminating"); ivona_speaking = 0; module_report_event_stop(); break; } if (icon[0]) { play_icon(IvonaSoundIconPath, icon); if (ivona_stop) { ivona_speaking = 0; module_report_event_stop(); break; } icon[0] = 0; } if (audio) { track.num_samples = samples; track.num_channels = 1; track.sample_rate = IvonaSampleFreq; track.bits = 16; track.samples = ((short *)audio) + offset; DBG("Got %d samples", track.num_samples); module_tts_output(track, SPD_AUDIO_LE); g_free(audio); audio = NULL; } if (ivona_stop) { ivona_speaking = 0; module_report_event_stop(); break; } } ivona_stop = 0; g_free(buf); g_free(audio); g_free(next_audio); if (fd >= 0) close(fd); fd = -1; audio = NULL; next_audio = NULL; } ivona_speaking = 0; DBG("Ivona: speaking thread ended.......\n"); pthread_exit(NULL); } static void ivona_set_volume(signed int volume) { assert(volume >= -100 && volume <= +100); ivona_volume = volume; } static void ivona_set_cap_let_recogn(SPDCapitalLetters cap_mode) { ivona_cap_mode = 0; switch (cap_mode) { case SPD_CAP_SPELL: ivona_cap_mode = 2; break; case SPD_CAP_ICON: ivona_cap_mode = 1; break; case SPD_CAP_NONE: ivona_cap_mode = 0; break; } if (ivona_cap_mode < IvonaMinCapLet) { ivona_cap_mode = IvonaMinCapLet; } } static void ivona_set_punctuation_mode(SPDPunctuation punct_mode) { ivona_punct_mode = 1; switch (punct_mode) { case SPD_PUNCT_ALL: ivona_punct_mode = 2; break; case SPD_PUNCT_SOME: ivona_punct_mode = 1; break; case SPD_PUNCT_NONE: ivona_punct_mode = 0; break; } } speech-dispatcher-0.8.3/src/modules/ivona_client.h0000644000175000017500000000257212233560613017127 00000000000000/* * ivona_client.h - Declarations from ivona_client.c * * Copyright (C) Bohdan R. Rau 2008 * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef IVONA_CLIENT_H #define IVONA_CLIENT_H /* A constant, used in both ivona.c and ivona_client.c */ #define IVONA_CACHE_MAX_STRLEN 11 int ivona_init_sock(char *host, int port); int ivona_send_string(char *to_say); char *ivona_get_wave_fd(int fd, int *nsamples, int *offset); char *ivona_get_wave(char *to_say, int *nsamples, int *offset); void play_icon(char *path, char *name); void ivona_init_cache(void); void ivona_store_wave_in_cache(char *to_say, char *wave, int nsamples); char *ivona_get_wave_from_cache(char *to_say, int *nsamples); #endif speech-dispatcher-0.8.3/src/modules/dummy.c0000664000175000017500000001364512522771346015620 00000000000000 /* * dummy.c - Speech Dispatcher dummy output module * * A simplific output module that just tries to play an * an error message in various ways. * * Copyright (C) 2008 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: dummy.c,v 1.3 2008-06-09 10:32:00 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "module_utils.h" #define MODULE_NAME "dummy" #define MODULE_VERSION "0.1" //#define Debug 0 /* Thread and process control */ static int dummy_speaking = 0; static pthread_t dummy_speak_thread; static pid_t dummy_pid; static sem_t dummy_semaphore; /* Internal functions prototypes */ static void *_dummy_speak(void *); static void _dummy_child(); /* Fill the module_info structure with pointers to this modules functions */ /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); return 0; } int module_init(char **status_info) { int ret; *status_info = NULL; sem_init(&dummy_semaphore, 0, 0); DBG("Dummy: creating new thread for dummy_speak\n"); dummy_speaking = 0; ret = pthread_create(&dummy_speak_thread, NULL, _dummy_speak, NULL); if (ret != 0) { DBG("Dummy: thread failed\n"); *status_info = g_strdup("The module couldn't initialize threads" "This can be either an internal problem or an" "architecture problem. If you are sure your architecture" "supports threads, please report a bug."); return -1; } *status_info = g_strdup("Everything ok so far."); DBG("Ok, now debugging"); return 0; } SPDVoice **module_list_voices(void) { return NULL; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { DBG("speak()\n"); if (dummy_speaking) { DBG("Speaking when requested to write"); return 0; } DBG("Requested data: |%s|\n", data); /* Send semaphore signal to the speaking thread */ dummy_speaking = 1; sem_post(&dummy_semaphore); DBG("Dummy: leaving write() normaly\n\r"); return bytes; } int module_stop(void) { DBG("dummy: stop(), dummy_speaking=%d, dummy_pid=%d\n", dummy_speaking, dummy_pid); if (dummy_speaking && dummy_pid) { DBG("dummy: stopping process group pid %d\n", dummy_pid); kill(-dummy_pid, SIGKILL); } DBG("Already stopped, no action"); return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (dummy_speaking) { DBG("Dummy module can't pause\n"); return 0; } else { return -1; } } char *module_is_speaking(void) { return NULL; } int module_close(void) { DBG("dummy: close()\n"); if (dummy_speaking) { module_stop(); } if (module_terminate_thread(dummy_speak_thread) != 0) return -1; sem_destroy(&dummy_semaphore); return 0; } /* Internal functions */ void *_dummy_speak(void *nothing) { int status; DBG("dummy: speaking thread starting.......\n"); set_speaking_thread_parameters(); while (1) { sem_wait(&dummy_semaphore); DBG("Semaphore on\n"); module_report_event_begin(); /* Create a new process so that we could send it signals */ dummy_pid = fork(); switch (dummy_pid) { case -1: DBG("Can't say the message. fork() failed!\n"); dummy_speaking = 0; continue; case 0:{ /* Set this process as a process group leader (so that SIGKILL is also delivered to the child processes created by system()) */ if (setpgid(0, 0) == -1) DBG("Can't set myself as project group leader!"); DBG("Starting child...\n"); _dummy_child(); } break; default: /* This is the parent. Send data to the child. */ DBG("Waiting for child..."); waitpid(dummy_pid, &status, 0); dummy_speaking = 0; DBG("Child exited"); // Report CANCEL if the process was signal-terminated // and END if it terminated normally if (WIFSIGNALED(status)) module_report_event_stop(); else module_report_event_end(); DBG("child terminated -: status:%d signal?:%d signal number:%d.\n", WIFEXITED(status), WIFSIGNALED(status), WTERMSIG(status)); } } dummy_speaking = 0; DBG("dummy: speaking thread ended.......\n"); pthread_exit(NULL); } void _dummy_child() { sigset_t some_signals; int ret; char *try1, *try2, *try3; sigfillset(&some_signals); module_sigunblockusr(&some_signals); DBG("Entering child loop\n"); /* Read the waiting data */ try1 = g_strdup("play " DATADIR "/dummy-message.wav > /dev/null 2> /dev/null"); try2 = g_strdup("aplay " DATADIR "/dummy-message.wav > /dev/null 2> /dev/null"); try3 = g_strdup("paplay " DATADIR "/dummy-message.wav > /dev/null 2> /dev/null"); DBG("child: synth commands = |%s|%s|%s|", try1, try2, try3); DBG("Speaking in child..."); module_sigblockusr(&some_signals); ret = system(try1); DBG("Executed shell command '%s' returned with %d", try1, ret); if ((ret != 0)) { DBG("Execution failed, trying seccond command"); ret = system(try2); DBG("Executed shell command '%s' returned with %d", try1, ret); if ((ret != 0)) { DBG("Execution failed, trying third command"); ret = system(try3); DBG("Executed shell command '%s' returned with %d", try1, ret); if ((ret != 0) && (ret != 256)) { DBG("Failed, giving up."); } } } module_sigunblockusr(&some_signals); g_free(try1); g_free(try2); g_free(try3); DBG("Done, exiting from child."); exit(0); } speech-dispatcher-0.8.3/src/modules/module_utils.c0000664000175000017500000005655312536417045017175 00000000000000/* * module_utils.c - Module utilities * Functions to help writing output modules for Speech Dispatcher * Copyright (C) 2003,2006, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: module_utils.c,v 1.55 2008-07-10 15:37:18 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "module_utils.h" static char *module_audio_pars[10]; extern char *module_index_mark; pthread_mutex_t module_stdout_mutex = PTHREAD_MUTEX_INITIALIZER; char *do_message(SPDMessageType msgtype) { int ret; char *cur_line; GString *msg; size_t n; int nlines = 0; msg = g_string_new(""); printf("202 OK RECEIVING MESSAGE\n"); fflush(stdout); while (1) { cur_line = NULL; n = 0; ret = spd_getline(&cur_line, &n, stdin); nlines++; if (ret == -1) return g_strdup("401 ERROR INTERNAL"); if (!strcmp(cur_line, "..\n")) { g_free(cur_line); cur_line = g_strdup(".\n"); } else if (!strcmp(cur_line, ".\n")) { /* Strip the trailing \n */ msg->str[strlen(msg->str) - 1] = 0; g_free(cur_line); break; } g_string_append(msg, cur_line); g_free(cur_line); } if ((msgtype != SPD_MSGTYPE_TEXT) && (nlines > 2)) { return g_strdup("305 DATA MORE THAN ONE LINE"); } if ((msgtype == SPD_MSGTYPE_CHAR) && (!strcmp(msg->str, "space"))) { g_string_free(msg, 1); msg = g_string_new(" "); } /* no sure we need this check here at all */ if (msg->str == NULL || msg->str[0] == 0) { DBG("requested data NULL or empty\n"); g_string_free(msg, TRUE); return g_strdup("301 ERROR CANT SPEAK"); } /* check voice and synthesis_voice settings for consistency */ if (msg_settings.voice.name == NULL && msg_settings_old.voice.name != NULL && msg_settings.voice_type == msg_settings_old.voice_type) { /* force to set voice again, since synthesis_voice changed to NULL */ msg_settings_old.voice_type = -1; } /* Volume is controlled by the synthesizer. Always play at normal on audio device. */ if (spd_audio_set_volume(module_audio_id, 85) < 0) { DBG("Can't set volume. audio not initialized?"); } ret = module_speak(msg->str, strlen(msg->str), msgtype); g_string_free(msg, 1); if (ret <= 0) return g_strdup("301 ERROR CANT SPEAK"); return g_strdup("200 OK SPEAKING"); } char *do_speak(void) { return do_message(SPD_MSGTYPE_TEXT); } char *do_sound_icon(void) { return do_message(SPD_MSGTYPE_SOUND_ICON); } char *do_char(void) { return do_message(SPD_MSGTYPE_CHAR); } char *do_key(void) { return do_message(SPD_MSGTYPE_KEY); } void do_stop(void) { module_stop(); return; } void do_pause(void) { int ret; ret = module_pause(); if (ret) { DBG("WARNING: Can't pause"); return; } return; } #define SET_PARAM_NUM(name, cond) \ if(!strcmp(cur_item, #name)){ \ number = strtol(cur_value, &tptr, 10); \ if(!(cond)){ err = 2; continue; } \ if (tptr == cur_value){ err = 2; continue; } \ msg_settings.name = number; \ } #define SET_PARAM_STR(name) \ if(!strcmp(cur_item, #name)){ \ g_free(msg_settings.name); \ if(!strcmp(cur_value, "NULL")) msg_settings.name = NULL; \ else msg_settings.name = g_strdup(cur_value); \ } #define SET_PARAM_STR_C(name, fconv) \ if(!strcmp(cur_item, #name)){ \ ret = fconv(cur_value); \ if (ret != -1) msg_settings.name = ret; \ else err = 2; \ } char *do_set(void) { char *cur_item = NULL; char *cur_value = NULL; char *line = NULL; int ret; size_t n; int number; char *tptr; int err = 0; /* Error status */ printf("203 OK RECEIVING SETTINGS\n"); fflush(stdout); while (1) { line = NULL; n = 0; ret = spd_getline(&line, &n, stdin); if (ret == -1) { err = 1; break; } if (!strcmp(line, ".\n")) { g_free(line); break; } if (!err) { cur_item = strtok(line, "="); if (cur_item == NULL) { err = 1; continue; } cur_value = strtok(NULL, "\n"); if (cur_value == NULL) { err = 1; continue; } SET_PARAM_NUM(rate, ((number >= -100) && (number <= 100))) else SET_PARAM_NUM(pitch, ((number >= -100) && (number <= 100))) else SET_PARAM_NUM(volume, ((number >= -100) && (number <= 100))) else SET_PARAM_STR_C(punctuation_mode, str2EPunctMode) else SET_PARAM_STR_C(spelling_mode, str2ESpellMode) else SET_PARAM_STR_C(cap_let_recogn, str2ECapLetRecogn) else if (!strcmp(cur_item, "voice")) { ret = str2EVoice(cur_value); if (ret != -1) msg_settings.voice_type = ret; else err = 2; } else if (!strcmp(cur_item, "synthesis_voice")) { g_free(msg_settings.voice.name); if (!strcmp(cur_value, "NULL")) msg_settings.voice.name = NULL; else msg_settings.voice.name = g_strdup(cur_value); } else if (!strcmp(cur_item, "language")) { g_free(msg_settings.voice.language); if (!strcmp(cur_value, "NULL")) msg_settings.voice.language = NULL; else msg_settings.voice.language = g_strdup(cur_value); } else err = 2; /* Unknown parameter */ } g_free(line); } if (err == 0) return g_strdup("203 OK SETTINGS RECEIVED"); if (err == 1) return g_strdup("302 ERROR BAD SYNTAX"); if (err == 2) return g_strdup("303 ERROR INVALID PARAMETER OR VALUE"); return g_strdup("401 ERROR INTERNAL"); /* Can't be reached */ } #define SET_AUDIO_STR(name,idx) \ if(!strcmp(cur_item, #name)){ \ g_free(module_audio_pars[idx]); \ if(!strcmp(cur_value, "NULL")) module_audio_pars[idx] = NULL; \ else module_audio_pars[idx] = g_strdup(cur_value); \ } char *do_audio(void) { char *cur_item = NULL; char *cur_value = NULL; char *line = NULL; int ret; size_t n; int err = 0; /* Error status */ char *status = NULL; char *msg; printf("207 OK RECEIVING AUDIO SETTINGS\n"); fflush(stdout); while (1) { line = NULL; n = 0; ret = spd_getline(&line, &n, stdin); if (ret == -1) { err = 1; break; } if (!strcmp(line, ".\n")) { g_free(line); break; } if (!err) { cur_item = strtok(line, "="); if (cur_item == NULL) { err = 1; continue; } cur_value = strtok(NULL, "\n"); if (cur_value == NULL) { err = 1; continue; } SET_AUDIO_STR(audio_output_method, 0) else SET_AUDIO_STR(audio_oss_device, 1) else SET_AUDIO_STR(audio_alsa_device, 2) else SET_AUDIO_STR(audio_nas_server, 3) else SET_AUDIO_STR(audio_pulse_server, 4) else SET_AUDIO_STR(audio_pulse_min_length, 5) else err = 2; /* Unknown parameter */ } g_free(line); } if (err == 1) return g_strdup("302 ERROR BAD SYNTAX"); if (err == 2) return g_strdup("303 ERROR INVALID PARAMETER OR VALUE"); err = module_audio_init(&status); if (err == 0) msg = g_strdup_printf("203 OK AUDIO INITIALIZED"); else msg = g_strdup_printf("300-%s\n300 UNKNOWN ERROR", status); g_free(status); return msg; } #define SET_LOGLEVEL_NUM(name, cond) \ if(!strcmp(cur_item, #name)){ \ number = strtol(cur_value, &tptr, 10); \ if(!(cond)){ err = 2; continue; } \ if (tptr == cur_value){ err = 2; continue; } \ log_level = number; \ spd_audio_set_loglevel(module_audio_id, number); \ } char *do_loglevel(void) { char *cur_item = NULL; char *cur_value = NULL; char *line = NULL; int ret; size_t n; int number; char *tptr; int err = 0; /* Error status */ char *msg; printf("207 OK RECEIVING LOGLEVEL SETTINGS\n"); fflush(stdout); while (1) { line = NULL; n = 0; ret = spd_getline(&line, &n, stdin); if (ret == -1) { err = 1; break; } if (!strcmp(line, ".\n")) { g_free(line); break; } if (!err) { cur_item = strtok(line, "="); if (cur_item == NULL) { err = 1; continue; } cur_value = strtok(NULL, "\n"); if (cur_value == NULL) { err = 1; continue; } SET_LOGLEVEL_NUM(log_level, 1) else err = 2; /* Unknown parameter */ } g_free(line); } if (err == 1) return g_strdup("302 ERROR BAD SYNTAX"); if (err == 2) return g_strdup("303 ERROR INVALID PARAMETER OR VALUE"); msg = g_strdup_printf("203 OK LOG LEVEL SET"); return msg; } char *do_debug(char *cmd_buf) { /* TODO: Develop the full on/off logic etc. */ char **cmd; char *filename; cmd = g_strsplit(cmd_buf, " ", -1); if (!cmd[1]) { g_strfreev(cmd); return g_strdup("302 ERROR BAD SYNTAX"); } if (!strcmp(cmd[1], "ON")) { if (!cmd[2]) { g_strfreev(cmd); return g_strdup("302 ERROR BAD SYNTAX"); } filename = cmd[2]; DBG("Additional logging into specific path %s requested", filename); CustomDebugFile = fopen(filename, "w+"); if (CustomDebugFile == NULL) { DBG("ERROR: Can't open custom debug file for logging: %d (%s)", errno, strerror(errno)); return g_strdup("303 CANT OPEN CUSTOM DEBUG FILE"); } if (Debug == 1) Debug = 3; else Debug = 2; DBG("Additional logging initialized"); } else if (!strcmp(cmd[1], "OFF")) { if (Debug == 3) Debug = 1; else Debug = 0; if (CustomDebugFile != NULL) fclose(CustomDebugFile); CustomDebugFile = NULL; DBG("Additional logging into specific path terminated"); } else { return g_strdup("302 ERROR BAD SYNTAX"); } g_strfreev(cmd); return g_strdup("200 OK DEBUGGING ON"); } char *do_list_voices(void) { SPDVoice **voices; int i; char *lang, *variant; GString *voice_list; voices = module_list_voices(); if (voices == NULL) { return g_strdup("304 CANT LIST VOICES"); } voice_list = g_string_new(""); for (i = 0; voices[i] != NULL; i++) { if (voices[i]->name == NULL) { /* Shouldn't happen! */ DBG("Unnamed voice found; ignoring it."); continue; } if (voices[i]->language == NULL) lang = "none"; else lang = voices[i]->language; if (voices[i]->variant == NULL) variant = "none"; else variant = voices[i]->variant; g_string_append_printf(voice_list, "200-%s %s %s\n", voices[i]->name, lang, variant); } /* check whether we found at least one voice */ if (voice_list->len == 0) { g_string_free(voice_list, TRUE); return g_strdup("304 CANT LIST VOICES"); } g_string_append(voice_list, "200 OK VOICE LIST SENT"); DBG("Voice prepared to send to speechd"); return g_string_free(voice_list, FALSE); } #undef SET_PARAM_NUM #undef SET_PARAM_STR /* This has to return int (although it doesn't return at all) so that we could * call it from PROCESS_CMD() macro like the other commands that return * something */ void do_quit(void) { printf("210 OK QUIT\n"); fflush(stdout); spd_audio_close(module_audio_id); module_audio_id = NULL; module_close(); return; } int module_get_message_part(const char *message, char *part, unsigned int *pos, size_t maxlen, const char *dividers) { int i, n; int num_dividers; int len; assert(part != NULL); assert(message != NULL); len = strlen(message); if (message[*pos] == 0) return -1; if (dividers != NULL) { num_dividers = strlen(dividers); } else { num_dividers = 0; } for (i = 0; i <= maxlen - 1; i++) { part[i] = message[*pos]; if (part[i] == 0) { return i; } // DBG("pos: %d", *pos); if ((len - 1 - i) > 2) { if ((message[*pos + 1] == ' ') || (message[*pos + 1] == '\n') || (message[*pos + 1] == '\r')) { for (n = 0; n <= num_dividers - 1; n++) { if ((part[i] == dividers[n])) { part[i + 1] = 0; (*pos)++; return i + 1; } } if ((message[*pos] == '\n') && (message[*pos + 1] == '\n')) { part[i + 1] = 0; (*pos)++; return i + 1; } if ((len - 1 - i) > 4) { if (((message[*pos] == '\r') && (message[*pos + 1] == '\n')) && ((message[*pos + 2] == '\r') && (message[*pos + 3] == '\n'))) { part[i + 1] = 0; (*pos)++; return i + 1; } } } } (*pos)++; } part[i] = 0; return i; } void module_strip_punctuation_some(char *message, char *punct_chars) { int len; char *p = message; int i; assert(message != NULL); if (punct_chars == NULL) return; len = strlen(message); for (i = 0; i <= len - 1; i++) { if (strchr(punct_chars, *p)) { DBG("Substitution %d: char -%c- for whitespace\n", i, *p); *p = ' '; } p++; } } char *module_strip_ssml(char *message) { int len; char *out; int i, n; int omit = 0; assert(message != NULL); len = strlen(message); out = (char *)g_malloc(sizeof(char) * (len + 1)); for (i = 0, n = 0; i <= len; i++) { if (message[i] == '<') { omit = 1; continue; } if (message[i] == '>') { omit = 0; continue; } if (!strncmp(&(message[i]), "<", 4)) { i += 3; out[n++] = '<'; } else if (!strncmp(&(message[i]), ">", 4)) { i += 3; out[n++] = '>'; } else if (!strncmp(&(message[i]), "&", 5)) { i += 4; out[n++] = '&'; } else if (!omit || i == len) out[n++] = message[i]; } DBG("In stripping ssml: |%s|", out); return out; } void module_strip_punctuation_default(char *buf) { assert(buf != NULL); module_strip_punctuation_some(buf, "~#$%^&*+=|<>[]_"); } size_t module_parent_wfork(TModuleDoublePipe dpipe, const char *message, SPDMessageType msgtype, const size_t maxlen, const char *dividers, int *pause_requested) { unsigned int pos = 0; char msg[16]; char *buf; int bytes; size_t read_bytes = 0; DBG("Entering parent process, closing pipes"); buf = (char *)g_malloc((maxlen + 1) * sizeof(char)); module_parent_dp_init(dpipe); pos = 0; while (1) { DBG(" Looping...\n"); bytes = module_get_message_part(message, buf, &pos, maxlen, dividers); DBG("Returned %d bytes from get_part\n", bytes); if (*pause_requested) { DBG("Pause requested in parent"); module_parent_dp_close(dpipe); *pause_requested = 0; return 0; } if (bytes > 0) { DBG("Sending buf to child:|%s| %d\n", buf, bytes); module_parent_dp_write(dpipe, buf, bytes); DBG("Waiting for response from child...\n"); while (1) { read_bytes = module_parent_dp_read(dpipe, msg, 8); if (read_bytes == 0) { DBG("parent: Read bytes 0, child stopped\n"); break; } if (msg[0] == 'C') { DBG("Ok, received report to continue...\n"); break; } } } if ((bytes == -1) || (read_bytes == 0)) { DBG("End of data in parent, closing pipes"); module_parent_dp_close(dpipe); break; } } return 0; } int module_parent_wait_continue(TModuleDoublePipe dpipe) { char msg[16]; int bytes; DBG("parent: Waiting for response from child...\n"); while (1) { bytes = module_parent_dp_read(dpipe, msg, 8); if (bytes == 0) { DBG("parent: Read bytes 0, child stopped\n"); return 1; } if (msg[0] == 'C') { DBG("parent: Ok, received report to continue...\n"); return 0; } } } void module_parent_dp_init(TModuleDoublePipe dpipe) { close(dpipe.pc[0]); close(dpipe.cp[1]); } void module_parent_dp_close(TModuleDoublePipe dpipe) { close(dpipe.pc[1]); close(dpipe.cp[0]); } void module_child_dp_init(TModuleDoublePipe dpipe) { close(dpipe.pc[1]); close(dpipe.cp[0]); } void module_child_dp_close(TModuleDoublePipe dpipe) { close(dpipe.pc[0]); close(dpipe.cp[1]); } void module_child_dp_write(TModuleDoublePipe dpipe, const char *msg, size_t bytes) { int ret; assert(msg != NULL); ret = write(dpipe.cp[1], msg, bytes); assert(ret); } int module_parent_dp_write(TModuleDoublePipe dpipe, const char *msg, size_t bytes) { ssize_t ret; assert(msg != NULL); DBG("going to write %lu bytes", (long unsigned)bytes); ret = write(dpipe.pc[1], msg, bytes); DBG("written %ld bytes", (long)ret); return ret; } int module_child_dp_read(TModuleDoublePipe dpipe, char *msg, size_t maxlen) { int bytes; while ((bytes = read(dpipe.pc[0], msg, maxlen)) < 0) { if (errno != EINTR) { FATAL("Unable to read data"); } } return bytes; } int module_parent_dp_read(TModuleDoublePipe dpipe, char *msg, size_t maxlen) { int bytes; while ((bytes = read(dpipe.cp[0], msg, maxlen)) < 0) { if (errno != EINTR) { FATAL("Unable to read data"); } } return bytes; } void module_sigblockall(void) { int ret; sigset_t all_signals; DBG("Blocking all signals"); sigfillset(&all_signals); ret = sigprocmask(SIG_BLOCK, &all_signals, NULL); if (ret != 0) DBG("Can't block signals, expect problems with terminating!\n"); } void module_sigunblockusr(sigset_t * some_signals) { int ret; DBG("UnBlocking user signal"); sigdelset(some_signals, SIGUSR1); ret = sigprocmask(SIG_SETMASK, some_signals, NULL); if (ret != 0) DBG("Can't block signal set, expect problems with terminating!\n"); } void module_sigblockusr(sigset_t * some_signals) { int ret; DBG("Blocking user signal"); sigaddset(some_signals, SIGUSR1); ret = sigprocmask(SIG_SETMASK, some_signals, NULL); if (ret != 0) DBG("Can't block signal set, expect problems when terminating!\n"); } void set_speaking_thread_parameters() { int ret; sigset_t all_signals; ret = sigfillset(&all_signals); if (ret == 0) { ret = pthread_sigmask(SIG_BLOCK, &all_signals, NULL); if (ret != 0) DBG("Can't set signal set, expect problems when terminating!\n"); } else { DBG("Can't fill signal set, expect problems when terminating!\n"); } pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); } int module_terminate_thread(pthread_t thread) { int ret; ret = pthread_cancel(thread); if (ret != 0) { DBG("Cancellation of speak thread failed"); return 1; } ret = pthread_join(thread, NULL); if (ret != 0) { DBG("join failed!\n"); return 1; } return 0; } char *module_recode_to_iso(char *data, int bytes, char *language, char *fallback) { char *recoded; if (language == NULL) recoded = g_strdup(data); if (!strcmp(language, "cs")) recoded = (char *)g_convert_with_fallback(data, bytes, "ISO8859-2", "UTF-8", fallback, NULL, NULL, NULL); else recoded = (char *)g_convert_with_fallback(data, bytes, "ISO8859-1", "UTF-8", fallback, NULL, NULL, NULL); if (recoded == NULL) DBG("festival: Conversion to ISO coding failed\n"); return recoded; } void module_send_asynchronous(char *text) { pthread_mutex_lock(&module_stdout_mutex); DBG("Printing reply: %s", text); fputs(text, stdout); fflush(stdout); DBG("Printed"); pthread_mutex_unlock(&module_stdout_mutex); } void module_report_index_mark(char *mark) { char *reply; DBG("Event: Index mark %s", mark); if (mark != NULL) reply = g_strdup_printf("700-%s\n700 INDEX MARK\n", mark); else return; module_send_asynchronous(reply); g_free(reply); } void module_report_event_begin(void) { module_send_asynchronous("701 BEGIN\n"); } void module_report_event_end(void) { module_send_asynchronous("702 END\n"); } void module_report_event_stop(void) { module_send_asynchronous("703 STOP\n"); } void module_report_event_pause(void) { module_send_asynchronous("704 PAUSE\n"); } /* --- CONFIGURATION --- */ configoption_t *module_add_config_option(configoption_t * options, int *num_options, char *name, int type, dotconf_callback_t callback, info_t * info, unsigned long context) { configoption_t *opts; int num_config_options = *num_options; assert(name != NULL); num_config_options++; opts = (configoption_t *) g_realloc(options, (num_config_options + 1) * sizeof(configoption_t)); opts[num_config_options - 1].name = (char *)g_strdup(name); opts[num_config_options - 1].type = type; opts[num_config_options - 1].callback = callback; opts[num_config_options - 1].info = info; opts[num_config_options - 1].context = context; *num_options = num_config_options; return opts; } void *module_get_ht_option(GHashTable * hash_table, const char *key) { void *option; assert(key != NULL); option = g_hash_table_lookup(hash_table, key); if (option == NULL) DBG("Requested option by key %s not found.\n", key); return option; } int module_audio_init(char **status_info) { char *error = 0; gchar **outputs; int i = 0; DBG("Openning audio output system"); if (NULL == module_audio_pars[0]) { *status_info = g_strdup ("Sound output method specified in configuration not supported. " "Please choose 'oss', 'alsa', 'nas', 'libao' or 'pulse'."); return -1; } outputs = g_strsplit(module_audio_pars[0], ",", 0); while (NULL != outputs[i]) { module_audio_id = spd_audio_open(outputs[i], (void **)&module_audio_pars[1], &error); if (module_audio_id) { DBG("Using %s audio output method", outputs[i]); g_strfreev(outputs); *status_info = g_strdup("audio initialized successfully."); return 0; } i++; } *status_info = g_strdup_printf("Opening sound device failed. Reason: %s. ", error); g_free(error); /* g_malloc'ed, in spd_audio_open. */ g_strfreev(outputs); return -1; } int module_tts_output(AudioTrack track, AudioFormat format) { if (spd_audio_play(module_audio_id, track, format) < 0) { DBG("Can't play track for unknown reason."); return -1; } return 0; } /* Plays the specified audio file. */ int module_play_file(const char *filename) { int result = 0; int subformat; sf_count_t items; sf_count_t readcount; SNDFILE *sf; SF_INFO sfinfo; DBG("Playing |%s|", filename); memset(&sfinfo, 0, sizeof(sfinfo)); sf = sf_open(filename, SFM_READ, &sfinfo); if (NULL == sf) { DBG("%s", sf_strerror(NULL)); return -1; } if (sfinfo.channels < 1 || sfinfo.channels > 2) { DBG("ERROR: channels = %d.\n", sfinfo.channels); result = FALSE; goto cleanup1; } if (sfinfo.frames > 0x7FFFFFFF || sfinfo.frames == 0) { DBG("ERROR: Unknown number of frames."); result = FALSE; goto cleanup1; } subformat = sfinfo.format & SF_FORMAT_SUBMASK; items = sfinfo.channels * sfinfo.frames; DBG("Frames = %ld, channels = %ld", sfinfo.frames, (long)sfinfo.channels); DBG("Samplerate = %i, items = %Ld", sfinfo.samplerate, (long long)items); DBG("Major format = 0x%08X, subformat = 0x%08X, endian = 0x%08X", sfinfo.format & SF_FORMAT_TYPEMASK, subformat, sfinfo.format & SF_FORMAT_ENDMASK); if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) { /* Set scaling for float to integer conversion. */ sf_command(sf, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); } AudioTrack track; track.num_samples = sfinfo.frames; track.num_channels = sfinfo.channels; track.sample_rate = sfinfo.samplerate; track.bits = 16; track.samples = g_malloc(items * sizeof(short)); readcount = sf_read_short(sf, (short *)track.samples, items); DBG("Read %Ld items from audio file.", (long long)readcount); if (readcount > 0) { track.num_samples = readcount / sfinfo.channels; DBG("Sending %i samples to audio.", track.num_samples); int ret = module_tts_output(track, SPD_AUDIO_LE); if (ret < 0) { DBG("ERROR: Can't play track for unknown reason."); result = -1; goto cleanup2; } DBG("Sent to audio."); } cleanup2: g_free(track.samples); cleanup1: sf_close(sf); return result; } speech-dispatcher-0.8.3/src/modules/pico.c0000664000175000017500000003654712536417045015423 00000000000000/* * pico.c - Speech Dispatcher SVOX pico output module * * A SVOX pico output module * * Copyright (C) 2010 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "spd_audio.h" #include #include "module_utils.h" #define MODULE_NAME "pico" #define MODULE_VERSION "0.1" DECLARE_DEBUG(); #define MAX_OUTBUF_SIZE (128) #define PICO_MEM_SIZE (10000000) #define PICO_VOICE_SPEED_MIN (20) #define PICO_VOICE_SPEED_MAX (500) #define PICO_VOICE_SPEED_DEFAULT (100) #define PICO_VOICE_PITCH_MIN (50) #define PICO_VOICE_PITCH_MAX (200) #define PICO_VOICE_PITCH_DEFAULT (100) #define PICO_VOICE_VOLUME_MIN (0) #define PICO_VOICE_VOLUME_MAX (500) #define PICO_VOICE_VOLUME_DEFAULT (100) static pico_System picoSystem; static pico_Resource picoTaResource; static pico_Resource picoSgResource; static pico_Engine picoEngine; static pico_Char *picoInp; static const char *PICO_LINGWARE_PATH = "/usr/share/pico/lang/"; static const int PICO_SAMPLE_RATE = 16000; static const char *picoInternalTaLingware[] = { "en-US_ta.bin", "en-GB_ta.bin", "de-DE_ta.bin", "es-ES_ta.bin", "fr-FR_ta.bin", "it-IT_ta.bin" }; static const char *picoInternalSgLingware[] = { "en-US_lh0_sg.bin", "en-GB_kh0_sg.bin", "de-DE_gl0_sg.bin", "es-ES_zl0_sg.bin", "fr-FR_nk0_sg.bin", "it-IT_cm0_sg.bin" }; static const SPDVoice pico_voices[] = { {"samantha", "en", "en-US"}, {"serena", "en", "en-GB"}, {"sabrina", "de", "de-DE"}, {"isabel", "es", "es-ES"}, {"virginie", "fr", "fr-FR"}, {"silvia", "it", "it-IT"} }; static const SPDVoice *pico_voices_list[] = { &pico_voices[0], &pico_voices[1], &pico_voices[2], &pico_voices[3], &pico_voices[4], &pico_voices[5], NULL }; static GThread *pico_play_thread; static sem_t pico_play_semaphore; static sem_t pico_idle_semaphore; enum states { STATE_IDLE, STATE_PLAY, STATE_PAUSE, STATE_STOP, STATE_CLOSE }; static enum states pico_state; /* Module configuration options */ MOD_OPTION_1_STR(PicoLingwarePath) static int pico_set_rate(signed int value) { int speed; if (value < 0) speed = PICO_VOICE_SPEED_MIN + (value - (-100)) * (PICO_VOICE_SPEED_DEFAULT - PICO_VOICE_SPEED_MIN) / (0 - (-100)); else speed = PICO_VOICE_SPEED_DEFAULT + (value - 0) * (PICO_VOICE_SPEED_MAX - PICO_VOICE_SPEED_DEFAULT) / (100 - 0); return speed; } static int pico_set_volume(signed int value) { int volume; volume = PICO_VOICE_VOLUME_MIN + (value - (-100)) * (PICO_VOICE_VOLUME_DEFAULT - PICO_VOICE_VOLUME_MIN) / (100 - (-100)); return volume; } static int pico_set_pitch(signed int value) { int pitch; if (value < 0) pitch = PICO_VOICE_PITCH_MIN + (value - (-100)) * (PICO_VOICE_PITCH_DEFAULT - PICO_VOICE_PITCH_MIN) / (0 - (-100)); else pitch = PICO_VOICE_PITCH_DEFAULT + (value - 0) * (PICO_VOICE_PITCH_MAX - PICO_VOICE_PITCH_DEFAULT) / (100 - 0); return pitch; } static int pico_process_tts(void) { pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type; int ret, getstatus; short outbuf[MAX_OUTBUF_SIZE]; pico_Retstring outMessage; AudioTrack track; #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) AudioFormat format = SPD_AUDIO_BE; #else AudioFormat format = SPD_AUDIO_LE; #endif pico_Char *buf = picoInp; text_remaining = strlen((const char *)buf) + 1; DBG(MODULE_NAME " Text: %s\n", picoInp); /* synthesis loop */ while (text_remaining) { /* Feed the text into the engine. */ if ((ret = pico_putTextUtf8(picoEngine, buf, text_remaining, &bytes_sent))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot put Text (%i): %s\n", ret, outMessage); return -1; } text_remaining -= bytes_sent; buf += bytes_sent; do { /* Retrieve the samples and add them to the buffer. SVOX pico TTS sample rate is 16K */ getstatus = pico_getData(picoEngine, (void *)outbuf, MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type); if ((getstatus != PICO_STEP_BUSY) && (getstatus != PICO_STEP_IDLE)) { pico_getSystemStatusMessage(picoSystem, getstatus, outMessage); DBG(MODULE_NAME "Cannot get Data (%i): %s\n", getstatus, outMessage); return -1; } if (bytes_recv) { track.num_samples = bytes_recv / 2; track.samples = (short *)g_memdup((gconstpointer) outbuf, bytes_recv); track.num_channels = 1; track.sample_rate = PICO_SAMPLE_RATE; track.bits = 16; DBG(MODULE_NAME ": Sending %i samples to audio.", track.num_samples); if (module_tts_output(track, format) < 0) { DBG(MODULE_NAME "Can't play track for unknown reason."); return -1; } } if (g_atomic_int_get(&pico_state) != STATE_PLAY) { text_remaining = 0; break; } } while (PICO_STEP_BUSY == getstatus); } g_free(picoInp); picoInp = NULL; return 0; } /* Playback thread. */ static gpointer pico_play_func(gpointer nothing) { DBG(MODULE_NAME ": Playback thread starting"); set_speaking_thread_parameters(); while (g_atomic_int_get(&pico_state) != STATE_CLOSE) { sem_wait(&pico_play_semaphore); if (g_atomic_int_get(&pico_state) != STATE_PLAY) continue; DBG(MODULE_NAME ": Sending to TTS engine"); module_report_event_begin(); if (0 != pico_process_tts()) { DBG(MODULE_NAME ": ERROR in TTS"); } if (g_atomic_int_get(&pico_state) == STATE_PLAY) { module_report_event_end(); g_atomic_int_set(&pico_state, STATE_IDLE); } if (g_atomic_int_get(&pico_state) == STATE_STOP) { module_report_event_stop(); g_atomic_int_set(&pico_state, STATE_IDLE); sem_post(&pico_idle_semaphore); } if (g_atomic_int_get(&pico_state) == STATE_PAUSE) { module_report_event_pause(); g_atomic_int_set(&pico_state, STATE_IDLE); sem_post(&pico_idle_semaphore); } DBG(MODULE_NAME ": state %d", pico_state); } return 0; } /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); MOD_OPTION_1_INT_REG(Debug, 0); MOD_OPTION_1_STR_REG(PicoLingwarePath, PICO_LINGWARE_PATH); return 0; } int pico_init_voice(int voice_index) { int ret; pico_Retstring outMessage; pico_Char picoTaFileName[PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE]; pico_Char picoSgFileName[PICO_MAX_DATAPATH_NAME_SIZE + PICO_MAX_FILE_NAME_SIZE]; pico_Char picoTaResourceName[PICO_MAX_RESOURCE_NAME_SIZE]; pico_Char picoSgResourceName[PICO_MAX_RESOURCE_NAME_SIZE]; /* Load the text analysis Lingware resource file. */ strcpy((char *)picoTaFileName, PicoLingwarePath); strcat((char *)picoTaFileName, (const char *)picoInternalTaLingware[voice_index]); if ((ret = pico_loadResource(picoSystem, picoTaFileName, &picoTaResource))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot load TA Lingware resource file (%i): %s\n", ret, outMessage); return -1; } /* Load the signal generation Lingware resource file. */ strcpy((char *)picoSgFileName, PicoLingwarePath); strcat((char *)picoSgFileName, (const char *)picoInternalSgLingware[voice_index]); if ((ret = pico_loadResource(picoSystem, picoSgFileName, &picoSgResource))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot load SG Lingware resource file (%i): %s\n", ret, outMessage); return -1; } /* Get the text analysis resource name. */ if ((ret = pico_getResourceName(picoSystem, picoTaResource, (char *)picoTaResourceName))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot get TA resource name (%i): %s\n", ret, outMessage); return -1; } /* Get the signal generation resource name. */ if ((ret = pico_getResourceName(picoSystem, picoSgResource, (char *)picoSgResourceName))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot get SG resource name (%i): %s\n", ret, outMessage); return -1; } /* Create a voice definition. */ if ((ret = pico_createVoiceDefinition(picoSystem, (const pico_Char *) pico_voices[voice_index].name))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot create voice definition (%i): %s\n", ret, outMessage); return -1; } /* Add the text analysis resource to the voice. */ if ((ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char *) pico_voices [voice_index].name, picoTaResourceName))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot add TA resource to the voice (%i): %s\n", ret, outMessage); return -1; } /* Add the signal generation resource to the voice. */ if ((ret = pico_addResourceToVoiceDefinition(picoSystem, (const pico_Char *) pico_voices [voice_index].name, picoSgResourceName))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot add SG resource to the voice (%i): %s\n", ret, outMessage); return -1; } return 0; } int module_init(char **status_info) { int ret, i; pico_Retstring outMessage; void *pmem; GError *error = NULL; if (!g_thread_supported()) g_thread_init(NULL); sem_init(&pico_play_semaphore, 0, 0); sem_init(&pico_idle_semaphore, 0, 0); if ((pico_play_thread = g_thread_create((GThreadFunc) pico_play_func, NULL, TRUE, &error)) == NULL) { *status_info = g_strdup_printf(MODULE_NAME "Failed to create a play thread : %s\n", error->message); DBG(MODULE_NAME ": %s", *status_info); g_error_free(error); return -1; } pmem = g_malloc(PICO_MEM_SIZE); if ((ret = pico_initialize(pmem, PICO_MEM_SIZE, &picoSystem))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); *status_info = g_strdup_printf(MODULE_NAME ": Cannot initialize (%i): %s\n", ret, outMessage); g_free(pmem); return -1; } /* load resource for all language, probably need only one */ for (i = 0; i < sizeof(pico_voices) / sizeof(SPDVoice); i++) { if (0 != pico_init_voice(i)) { g_free(pmem); *status_info = g_strdup_printf(MODULE_NAME ": fail init voice (%s)\n", pico_voices[i].name); return -1; } } /* Create a new Pico engine, english default */ if ((ret = pico_newEngine(picoSystem, (const pico_Char *)pico_voices[0].name, &picoEngine))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); *status_info = g_strdup_printf(MODULE_NAME ": Cannot create a new pico engine (%i): %s\n", ret, outMessage); return -1; } *status_info = g_strdup(MODULE_NAME ": Initialized successfully."); g_atomic_int_set(&pico_state, STATE_IDLE); return 0; } SPDVoice **module_list_voices(void) { return pico_voices_list; } void pico_set_synthesis_voice(char *voice_name) { int ret; pico_Retstring outMessage; /* Create a new Pico engine, english default */ if ((ret = pico_disposeEngine(picoSystem, &picoEngine))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot dispose pico engine (%i): %s\n", ret, outMessage); return; } /* Create a new Pico engine, english default */ if ((ret = pico_newEngine(picoSystem, (const pico_Char *)voice_name, &picoEngine))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot create a new pico engine (%i): %s\n", ret, outMessage); return; } return; } static void pico_set_language(char *lang) { int i; /* get voice name based on language */ for (i = 0; i < sizeof(pico_voices) / sizeof(SPDVoice); i++) { if (!strcmp(pico_voices[i].language, lang)) { pico_set_synthesis_voice(pico_voices[i].name); return; } } return; } int module_speak(char *data, size_t bytes, SPDMessageType msgtype) { int value; static pico_Char *tmp; if (g_atomic_int_get(&pico_state) != STATE_IDLE) { DBG(MODULE_NAME ": module still speaking state = %d", pico_state); return 0; } /* Setting speech parameters. */ UPDATE_STRING_PARAMETER(voice.name, pico_set_synthesis_voice); /* UPDATE_PARAMETER(voice_type, pico_set_voice); */ UPDATE_STRING_PARAMETER(voice.language, pico_set_language); picoInp = (pico_Char *) module_strip_ssml(data); value = pico_set_rate(msg_settings.rate); if (PICO_VOICE_SPEED_DEFAULT != value) { tmp = picoInp; picoInp = (pico_Char *) g_strdup_printf("%s", value, tmp); g_free(tmp); } value = pico_set_volume(msg_settings.volume); if (PICO_VOICE_VOLUME_DEFAULT != value) { tmp = picoInp; picoInp = (pico_Char *) g_strdup_printf("%s", value, tmp); g_free(tmp); } value = pico_set_pitch(msg_settings.pitch); if (PICO_VOICE_PITCH_DEFAULT != value) { tmp = picoInp; picoInp = (pico_Char *) g_strdup_printf("%s", value, tmp); g_free(tmp); } /* switch (msgtype) { case SPD_MSGTYPE_CHAR: case SPD_MSGTYPE_KEY: case SPD_MSGTYPE_TEXT: case SPD_MSGTYPE_SOUND_ICON: default: DBG(MODULE_NAME ": msgtype = %d", msgtype); break; } */ g_atomic_int_set(&pico_state, STATE_PLAY); sem_post(&pico_play_semaphore); return bytes; } int module_stop(void) { pico_Status ret; pico_Retstring outMessage; if (g_atomic_int_get(&pico_state) != STATE_PLAY) { DBG(MODULE_NAME ": STOP called when not in PLAY state"); return -1; } g_atomic_int_set(&pico_state, STATE_STOP); sem_wait(&pico_idle_semaphore); /* reset Pico engine. */ if ((ret = pico_resetEngine(picoEngine, PICO_RESET_SOFT))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot reset pico engine (%i): %s\n", ret, outMessage); return -1; } return 0; } size_t module_pause(void) { pico_Status ret; pico_Retstring outMessage; if (g_atomic_int_get(&pico_state) != STATE_PLAY) { DBG(MODULE_NAME ": PAUSE called when not in PLAY state"); return -1; } g_atomic_int_set(&pico_state, STATE_PAUSE); sem_wait(&pico_idle_semaphore); /* reset Pico engine. */ if ((ret = pico_resetEngine(picoEngine, PICO_RESET_SOFT))) { pico_getSystemStatusMessage(picoSystem, ret, outMessage); DBG(MODULE_NAME "Cannot reset pico engine (%i): %s\n", ret, outMessage); return -1; } return 0; } int module_close(void) { g_atomic_int_set(&pico_state, STATE_CLOSE); sem_post(&pico_play_semaphore); g_thread_join(pico_play_thread); if (picoSystem) { pico_terminate(&picoSystem); picoSystem = NULL; } sem_destroy(&pico_idle_semaphore); sem_destroy(&pico_play_semaphore); return 0; } speech-dispatcher-0.8.3/src/modules/festival.c0000664000175000017500000007225712530733575016307 00000000000000/* * festival.c - Speech Dispatcher backend for Festival * * Copyright (C) 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: festival.c,v 1.82 2008-06-09 10:33:38 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "fdsetconv.h" #include "festival_client.h" #include "module_utils.h" #define MODULE_NAME "festival" #define MODULE_VERSION "0.5" DECLARE_DEBUG() /* Thread and process control */ static pthread_t festival_speak_thread; static sem_t festival_semaphore; static int festival_speaking = 0; static int festival_pause_requested = 0; static char **festival_message; static SPDMessageType festival_message_type; signed int festival_volume = 0; int festival_stop_request = 0; int festival_stop = 0; int festival_process_pid = 0; FT_Info *festival_info = NULL; SPDVoice **festival_voice_list = NULL; enum { FCT_SOCKET = 0, FCT_LOCAL = 1, } FestivalComType; struct { int pipe_in[2]; int pipe_out[2]; int pid; } module_p; #define COM_SOCKET ((FestivalComType == FCT_SOCKET) ? 1 : 0) #define COM_LOCAL ((FestivalComType == FCT_LOCAL) ? 1 : 0) /* --- SETTINGS COMMANDS --- */ #define FEST_SET_STR(name, fest_param) \ int \ name(FT_Info *info, char *param, char **resp) \ { \ char *r; \ int ret; \ char *f; \ if (festival_check_info(info, #name)) return -1; \ if (param == NULL){ \ FEST_SEND_CMD("("fest_param" nil)"); \ }else{ \ f = g_ascii_strdown(param, -1); \ FEST_SEND_CMDA("("fest_param" \"%s\")", f); \ g_free(f); \ } \ ret = festival_read_response(info, &r); \ if (ret != 0) return -1; \ if (r != NULL){ \ if (resp != NULL) \ *resp = r; \ else \ g_free(r); \ } \ return ret; \ } #define FEST_SET_SYMB(name, fest_param) \ int \ name(FT_Info *info, char *param) \ { \ char *f = NULL; \ if (festival_check_info(info, #name)) return -1; \ if (param == NULL) return -1; \ FEST_SEND_CMDA("("fest_param" '%s)", f = g_ascii_strdown(param, -1)); \ g_free(f); \ return festival_read_response(info, NULL); \ } #define FEST_SET_INT(name, fest_param) \ int \ name(FT_Info *info, int param) \ { \ if (festival_check_info(info, #name)) return -1; \ FEST_SEND_CMDA("("fest_param" %d)", param); \ return festival_read_response(info, NULL); \ } FEST_SET_SYMB(FestivalSetMultiMode, "speechd-enable-multi-mode") FEST_SET_INT(FestivalSetRate, "speechd-set-rate") FEST_SET_INT(FestivalSetPitch, "speechd-set-pitch") FEST_SET_SYMB(FestivalSetPunctuationMode, "speechd-set-punctuation-mode") FEST_SET_STR(FestivalSetCapLetRecogn, "speechd-set-capital-character-recognition-mode") FEST_SET_STR(FestivalSetLanguage, "speechd-set-language") FEST_SET_STR(FestivalSetVoice, "speechd-set-voice") FEST_SET_SYMB(FestivalSetSynthesisVoice, "speechd-set-festival-voice") /* Internal functions prototypes */ static SPDVoice **festivalGetVoices(FT_Info * info); void *_festival_speak(void *); void festival_parent_clean(); void festival_set_rate(signed int rate); void festival_set_pitch(signed int pitch); void festival_set_voice(SPDVoiceType voice); void festival_set_synthesis_voice(char *synthesis_voice); void festival_set_language(char *language); void festival_set_punctuation_mode(SPDPunctuation punct); void festival_set_cap_let_recogn(SPDCapitalLetters recogn); void festival_set_volume(signed int volume); int init_festival_standalone(); int init_festival_socket(); int is_text(SPDMessageType msg_type); MOD_OPTION_1_INT(FestivalComunicationType) MOD_OPTION_1_INT(FestivalMaxChunkLength) MOD_OPTION_1_STR(FestivalDelimiters) MOD_OPTION_1_STR(FestivalServerHost) MOD_OPTION_1_STR(FestivalStripPunctChars) MOD_OPTION_1_INT(FestivalServerPort) MOD_OPTION_1_INT(FestivalPitchDeviation) MOD_OPTION_1_INT(FestivalDebugSaveOutput) MOD_OPTION_1_STR(FestivalRecodeFallback) MOD_OPTION_1_INT(FestivalCacheOn) MOD_OPTION_1_INT(FestivalCacheMaxKBytes) MOD_OPTION_1_INT(FestivalCacheDistinguishVoices) MOD_OPTION_1_INT(FestivalCacheDistinguishRate) MOD_OPTION_1_INT(FestivalCacheDistinguishPitch) MOD_OPTION_1_INT(FestivalReopenSocket) typedef struct { size_t size; GHashTable *caches; GList *cache_counter; } TCache; typedef struct { time_t start; int count; size_t size; GHashTable *p_caches; char *key; } TCounterEntry; typedef struct { TCounterEntry *p_counter_entry; FT_Wave *fwave; } TCacheEntry; TCache FestivalCache; int cache_init(); int cache_reset(); int cache_insert(char *key, SPDMessageType msgtype, FT_Wave * value); FT_Wave *cache_lookup(const char *key, SPDMessageType msgtype, int add_counter); pthread_mutex_t sound_output_mutex; /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); MOD_OPTION_1_INT_REG(FestivalComunicationType, 0); MOD_OPTION_1_STR_REG(FestivalServerHost, "localhost"); MOD_OPTION_1_INT_REG(FestivalServerPort, 1314); MOD_OPTION_1_INT_REG(FestivalDebugSaveOutput, 0); MOD_OPTION_1_STR_REG(FestivalRecodeFallback, "?"); MOD_OPTION_1_INT_REG(FestivalCacheOn, 1); MOD_OPTION_1_INT_REG(FestivalCacheMaxKBytes, 5120); MOD_OPTION_1_INT_REG(FestivalCacheDistinguishVoices, 0); MOD_OPTION_1_INT_REG(FestivalCacheDistinguishRate, 0); MOD_OPTION_1_INT_REG(FestivalCacheDistinguishPitch, 0); /* TODO: Maybe switch this option to 1 when the bug with the 40ms delay in Festival is fixed */ MOD_OPTION_1_INT_REG(FestivalReopenSocket, 0); return 0; } #define ABORT(msg) g_string_append(info, msg); \ *status_info = info->str; \ g_string_free(info, 0); \ return -1; int module_init(char **status_info) { int ret; GString *info; info = g_string_new(""); DBG("module_init()"); INIT_INDEX_MARKING(); /* Initialize appropriate communication mechanism */ FestivalComType = FestivalComunicationType; if (COM_SOCKET) { g_string_append(info, "Communicating with Festival through a socket. "); ret = init_festival_socket(); if (ret == -1) { ABORT ("Can't connect to Festival server. Check your configuration " "in etc/speechd-modules/festival.conf for the specified host and port " "and check if Festival is really running there, e.g. with telnet. " "Please see documentation for more info."); } else if (ret == -2) { ABORT("Connect to the Festival server was successful, " "but I got disconnected immediately. This is most likely " "because of authorization problems. Check the variable " "server_access_list in etc/festival.scm and consult documentation " "for more information."); } } if (COM_LOCAL) { g_string_append(info, "Communicating with Festival through a local child process."); if (init_festival_standalone()) { ABORT ("Local connect to Festival failed for unknown reasons."); } } /* Get festival voice list */ festival_voice_list = festivalGetVoices(festival_info); /* Initialize global variables */ festival_message = (char **)g_malloc(sizeof(char *)); *festival_message = NULL; /* Initialize festival_speak thread to handle communication with festival in a separate thread (to be faster in communication with Speech Dispatcher) */ sem_init(&festival_semaphore, 0, 0); DBG("Festival: creating new thread for festival_speak\n"); festival_speaking = 0; ret = pthread_create(&festival_speak_thread, NULL, _festival_speak, NULL); if (ret != 0) { DBG("Festival: thread failed\n"); g_string_append(info, "The module couldn't initialize threads" "This can be either an internal problem or an" "architecture problem. If you are sure your architecture" "supports threads, please report a bug."); *status_info = info->str; g_string_free(info, 0); return -1; } pthread_mutex_init(&sound_output_mutex, NULL); *status_info = info->str; g_string_free(info, 0); return 0; } #undef ABORT SPDVoice **module_list_voices(void) { return festival_voice_list; } int module_speak(char *data, size_t bytes, SPDMessageType msgtype) { int ret; DBG("module_speak()\n"); if (data == NULL) return -1; if (festival_speaking) { DBG("Speaking when requested to write\n"); return -1; } festival_stop_request = 0; festival_message_type = msgtype; if ((msgtype == SPD_MSGTYPE_TEXT) && (msg_settings.spelling_mode == SPD_SPELL_ON)) festival_message_type = SPD_MSGTYPE_SPELL; /* If the connection crashed or language or voice change, we will need to set all the parameters again */ if (COM_SOCKET) { if (festival_connection_crashed) { DBG("Recovering after a connection loss"); CLEAN_OLD_SETTINGS_TABLE(); festival_info = festivalOpen(festival_info); if (festival_info) festival_connection_crashed = 0; else { DBG("Can't recover. Not possible to open connection to Festival."); return -1; } ret = FestivalSetMultiMode(festival_info, "t"); if (ret != 0) return -1; } } /* If the voice was changed, re-set all the parameters */ // TODO: Handle synthesis_voice change too if ((msg_settings.voice_type != msg_settings_old.voice_type) || ((msg_settings.voice.language != NULL) && (msg_settings_old.voice.language != NULL) && (strcmp (msg_settings.voice.language, msg_settings_old.voice.language)))) { DBG("Cleaning old settings table"); CLEAN_OLD_SETTINGS_TABLE(); } /* Setting voice parameters */ DBG("Updating parameters"); UPDATE_STRING_PARAMETER(voice.language, festival_set_language); UPDATE_PARAMETER(voice_type, festival_set_voice); UPDATE_STRING_PARAMETER(voice.name, festival_set_synthesis_voice); UPDATE_PARAMETER(rate, festival_set_rate); UPDATE_PARAMETER(pitch, festival_set_pitch); UPDATE_PARAMETER(volume, festival_set_volume); UPDATE_PARAMETER(punctuation_mode, festival_set_punctuation_mode); UPDATE_PARAMETER(cap_let_recogn, festival_set_cap_let_recogn); if (festival_connection_crashed) { DBG("ERROR: Festival connection not working!"); return -1; } DBG("Requested data: |%s| \n", data); g_free(*festival_message); *festival_message = g_strdup(data); if (*festival_message == NULL) { DBG("Error: Copying data unsuccesful."); return -1; } /* Send semaphore signal to the speaking thread */ festival_speaking = 1; sem_post(&festival_semaphore); DBG("Festival: leaving write() normaly\n\r"); return bytes; } int module_stop(void) { DBG("stop()\n"); if (festival_speaking) { /* if(COM_SOCKET) */ if (0) { if (festival_info != 0) if ((festival_info->server_fd != -1) && FestivalReopenSocket) { /* TODO: Maybe use shutdown here? */ close(festival_info->server_fd); festival_info->server_fd = -1; festival_connection_crashed = 1; DBG("festival socket closed by module_stop()"); } } if (COM_LOCAL) { DBG("festival local stopped by sending SIGINT"); /* TODO: Write this function for local communication */ // festival_stop_local(); } if (!festival_stop) { pthread_mutex_lock(&sound_output_mutex); festival_stop = 1; if (festival_speaking && module_audio_id) { spd_audio_stop(module_audio_id); } pthread_mutex_unlock(&sound_output_mutex); } } return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (festival_speaking) { DBG("Sending request for pause to child\n"); festival_pause_requested = 1; DBG("Signalled to pause"); return 0; } else { return -1; } } int module_close(void) { DBG("festival: close()\n"); DBG("Stopping the module"); while (festival_speaking) { module_stop(); usleep(50); } // DBG("festivalClose()"); // festivalClose(festival_info); DBG("Terminating threads"); if (festival_speak_thread) module_terminate_thread(festival_speak_thread); if (festival_info) delete_FT_Info(festival_info); /* TODO: Solve this */ // DBG("Removing junk files in tmp/"); // system("rm -f /tmp/est* 2> /dev/null"); sem_destroy(&festival_semaphore); return 0; } /* Internal functions */ #define CLEAN_UP(code, im) \ { \ if(!wave_cached) if (fwave) delete_FT_Wave(fwave); \ pthread_mutex_lock(&sound_output_mutex); \ festival_stop = 0; \ festival_speaking = 0; \ pthread_mutex_unlock(&sound_output_mutex); \ im(); \ goto sem_wait; \ } #define CLP(code, im) \ { \ pthread_mutex_lock(&sound_output_mutex); \ festival_stop = 0; \ festival_speaking = 0; \ pthread_mutex_unlock(&sound_output_mutex); \ im(); \ goto sem_wait; \ } static SPDVoice **festivalGetVoices(FT_Info * info) { char *reply; char **voices; char *lang; char *variant; int i, j; int num_voices = 0; SPDVoice **result; FEST_SEND_CMD("(apply append (voice-list-language-codes))"); festival_read_response(info, &reply); if (reply == NULL) { DBG("ERROR: Invalid reply for voice-list"); return NULL; } /* Remove trailing newline */ reply[strlen(reply) - 1] = 0; DBG("Voice list reply: |%s|", reply); voices = lisp_list_get_vect(reply); if (voices == NULL) { DBG("ERROR: Can't parse voice listing reply into vector"); return NULL; } /* Compute number of voices */ for (i = 0;; i++, num_voices++) if (voices[i] == NULL) break; num_voices /= 3; result = g_malloc((num_voices + 1) * sizeof(SPDVoice *)); for (i = 0, j = 0;; j++) { if (voices[i] == NULL) break; else if (strlen(voices[i]) == 0) continue; else { result[j] = g_malloc(sizeof(SPDVoice)); result[j]->name = voices[i]; lang = voices[i + 1]; if ((lang != NULL) && (strcmp(lang, "nil"))) result[j]->language = g_strdup(lang); else result[j]->language = NULL; variant = voices[i + 2]; if ((variant != NULL) && (strcmp(variant, "nil"))) result[j]->variant = g_strdup(variant); else result[j]->variant = NULL; i += 3; } } result[j] = NULL; return result; } int festival_send_to_audio(FT_Wave * fwave) { AudioTrack track; #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) AudioFormat format = SPD_AUDIO_BE; #else AudioFormat format = SPD_AUDIO_LE; #endif int ret = 0; if (fwave->samples == NULL) return 0; track.num_samples = fwave->num_samples; track.num_channels = 1; track.sample_rate = fwave->sample_rate; track.bits = 16; track.samples = fwave->samples; DBG("Sending to audio"); ret = module_tts_output(track, format); if (ret < 0) DBG("ERROR: Can't play track for unknown reason."); DBG("Sent to audio."); return 0; } void *_festival_speak(void *nothing) { int ret; int bytes; int wave_cached; FT_Wave *fwave; int debug_count = 0; int r; int terminate = 0; char *callback; DBG("festival: speaking thread starting.......\n"); cache_init(); set_speaking_thread_parameters(); while (1) { sem_wait: sem_wait(&festival_semaphore); DBG("Semaphore on, speaking\n"); festival_stop = 0; festival_speaking = 1; wave_cached = 0; fwave = NULL; terminate = 0; bytes = strlen(*festival_message); module_report_event_begin(); DBG("Going to synthesize: |%s|", *festival_message); if (bytes > 0) { if (!is_text(festival_message_type)) { /* it is a raw text */ DBG("Cache mechanisms..."); fwave = cache_lookup(*festival_message, festival_message_type, 1); if (fwave != NULL) { wave_cached = 1; if (fwave->num_samples != 0) { if (FestivalDebugSaveOutput) { char filename_debug [256]; sprintf(filename_debug, "/tmp/debug-festival-%d.snd", debug_count++); save_FT_Wave_snd(fwave, filename_debug); } festival_send_to_audio(fwave); if (!festival_stop) { CLEAN_UP(0, module_report_event_end); } else { CLEAN_UP(0, module_report_event_stop); } } else { CLEAN_UP(0, module_report_event_end); } } } /* Set multi-mode for appropriate kind of events */ if (is_text(festival_message_type)) { /* it is a raw text */ ret = FestivalSetMultiMode(festival_info, "t"); if (ret != 0) CLP(0, module_report_event_stop); } else { /* it is some kind of event */ ret = FestivalSetMultiMode(festival_info, "nil"); if (ret != 0) CLP(0, module_report_event_stop); } switch (festival_message_type) { case SPD_MSGTYPE_TEXT: r = festivalStringToWaveRequest(festival_info, *festival_message); break; case SPD_MSGTYPE_SOUND_ICON: r = festivalSoundIcon(festival_info, *festival_message); break; case SPD_MSGTYPE_CHAR: r = festivalCharacter(festival_info, *festival_message); break; case SPD_MSGTYPE_KEY: r = festivalKey(festival_info, *festival_message); break; case SPD_MSGTYPE_SPELL: r = festivalSpell(festival_info, *festival_message); break; default: r = -1; } if (r < 0) { DBG("Couldn't process the request to say the object."); CLP(0, module_report_event_stop); } } while (1) { wave_cached = 0; DBG("Retrieving data\n"); /* (speechd-next) */ if (is_text(festival_message_type)) { if (festival_stop) { DBG("Module stopped 1"); CLEAN_UP(0, module_report_event_stop); } DBG("Getting data in multi mode"); fwave = festivalGetDataMulti(festival_info, &callback, &festival_stop_request, FestivalReopenSocket); if (callback != NULL) { if ((festival_pause_requested) && (!strncmp (callback, INDEX_MARK_BODY, INDEX_MARK_BODY_LEN))) { DBG("Pause requested, pausing."); module_report_index_mark (callback); g_free(callback); festival_pause_requested = 0; CLEAN_UP(0, module_report_event_pause); } else { module_report_index_mark (callback); g_free(callback); continue; } } } else { /* is event */ DBG("Getting data in single mode"); fwave = festivalStringToWaveGetData(festival_info); terminate = 1; callback = NULL; } if (fwave == NULL) { DBG("End of sound samples, terminating this message..."); CLEAN_UP(0, module_report_event_end); } if (festival_message_type == SPD_MSGTYPE_CHAR || festival_message_type == SPD_MSGTYPE_KEY || festival_message_type == SPD_MSGTYPE_SOUND_ICON) { DBG("Storing record for %s in cache\n", *festival_message); /* cache_insert takes care of not inserting the same message again */ cache_insert(g_strdup(*festival_message), festival_message_type, fwave); wave_cached = 1; } if (festival_stop) { DBG("Module stopped 2"); CLEAN_UP(0, module_report_event_stop); } if (fwave->num_samples != 0) { DBG("Sending message to audio: %lu bytes\n", (long unsigned)((fwave->num_samples) * sizeof(short))); if (FestivalDebugSaveOutput) { char filename_debug[256]; sprintf(filename_debug, "/tmp/debug-festival-%d.snd", debug_count++); save_FT_Wave_snd(fwave, filename_debug); } DBG("Playing sound samples"); festival_send_to_audio(fwave); if (!wave_cached) delete_FT_Wave(fwave); DBG("End of playing sound samples"); } if (terminate) { DBG("Ok, end of samples, returning"); CLP(0, module_report_event_end); } if (festival_stop) { DBG("Module stopped 3"); CLP(0, module_report_event_stop); } } } festival_stop = 0; festival_speaking = 0; DBG("festival: speaking thread ended.......\n"); pthread_exit(NULL); } int is_text(SPDMessageType msg_type) { if (msg_type == SPD_MSGTYPE_TEXT || msg_type == SPD_MSGTYPE_SPELL) return 1; else return 0; } void festival_set_language(char *language) { FestivalSetLanguage(festival_info, language, NULL); g_free(festival_voice_list); festival_voice_list = festivalGetVoices(festival_info); } void festival_set_voice(SPDVoiceType voice) { char *voice_name; voice_name = EVoice2str(voice); FestivalSetVoice(festival_info, voice_name, NULL); g_free(voice_name); } void festival_set_synthesis_voice(char *voice_name) { FestivalSetSynthesisVoice(festival_info, voice_name); } void festival_set_rate(signed int rate) { FestivalSetRate(festival_info, rate); } void festival_set_pitch(signed int pitch) { FestivalSetPitch(festival_info, pitch); } void festival_set_volume(signed int volume) { festival_volume = volume; } void festival_set_punctuation_mode(SPDPunctuation punct) { char *punct_mode; punct_mode = EPunctMode2str(punct); FestivalSetPunctuationMode(festival_info, punct_mode); g_free(punct_mode); } void festival_set_cap_let_recogn(SPDCapitalLetters recogn) { char *recogn_mode; if (recogn == SPD_CAP_NONE) recogn_mode = NULL; else recogn_mode = ECapLetRecogn2str(recogn); FestivalSetCapLetRecogn(festival_info, recogn_mode, NULL); g_free(recogn_mode); } /* --- Cache related functions --- */ void cache_destroy_entry(gpointer data) { TCacheEntry *entry = data; g_free(entry->fwave); g_free(entry); } void cache_destroy_table_entry(gpointer data) { g_hash_table_destroy(data); } void cache_free_counter_entry(gpointer data, gpointer user_data) { g_free(((TCounterEntry *) data)->key); g_free(data); } int cache_init() { if (FestivalCacheOn == 0) return 0; FestivalCache.size = 0; FestivalCache.caches = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, cache_destroy_table_entry); FestivalCache.cache_counter = NULL; DBG("Cache: initialized"); return 0; } int cache_destroy() { g_hash_table_destroy(FestivalCache.caches); g_list_foreach(FestivalCache.cache_counter, cache_free_counter_entry, NULL); g_list_free(FestivalCache.cache_counter); return 0; } int cache_reset() { /* TODO: it could free everything in the cache and go from start, but currently it isn't called by anybody */ return 0; } /* Compare two cache entries according to their score (how many times the entry was requested divided by the time it exists in the database) */ gint cache_counter_comp(gconstpointer a, gconstpointer b) { const TCounterEntry *A = a; const TCounterEntry *B = b; time_t t; float ret; t = time(NULL); ret = (((float)A->count / (float)(t - A->start)) - ((float)B->count / (float)(t - B->start))); if (ret > 0) return -1; if (ret == 0) return 0; if (ret < 0) return 1; return 0; } /* List scores of all entries in the cache*/ void cache_debug_foreach_list_score(gpointer a, gpointer user) { const TCounterEntry *A = a; time_t t; t = time(NULL); DBG("key: %s -> score %f (count: %d, dtime: %d)", A->key, ((float)A->count / (float)(t - A->start)), (int)A->count, (int)(t - A->start)); } /* Remove 1/3 of the least used (according to cache_counter_comp) entries (measured by size) */ int cache_clean(size_t new_element_size) { size_t req_size; GList *gl; TCounterEntry *centry; DBG("Cache: cleaning, cache size %lu kbytes (>max %d).", (unsigned long)(FestivalCache.size / 1024), FestivalCacheMaxKBytes); req_size = 2 * FestivalCache.size / 3; FestivalCache.cache_counter = g_list_sort(FestivalCache.cache_counter, cache_counter_comp); g_list_foreach(FestivalCache.cache_counter, cache_debug_foreach_list_score, NULL); while ((FestivalCache.size + new_element_size) > req_size) { gl = g_list_last(FestivalCache.cache_counter); if (gl == NULL) break; if (gl->data == NULL) { DBG("Error: Cache: gl->data in cache_clean is NULL, but shouldn't be."); return -1; } centry = gl->data; FestivalCache.size -= centry->size; DBG("Cache: Removing element with key '%s'", centry->key); if (FestivalCache.size < 0) { DBG("Error: Cache: FestivalCache.size < 0, this shouldn't be."); return -1; } /* Remove the data itself from the hash table */ g_hash_table_remove(centry->p_caches, centry->key); /* Remove the associated entry in the counter list */ cache_free_counter_entry(centry, NULL); FestivalCache.cache_counter = g_list_delete_link(FestivalCache.cache_counter, gl); } return 0; } /* Generate a key for searching between the different hash tables */ char *cache_gen_key(SPDMessageType type) { char *key; char ktype; int kpitch = 0, krate = 0, kvoice = 0; if (msg_settings.voice.language == NULL) return NULL; DBG("v, p, r = %d %d %d", FestivalCacheDistinguishVoices, FestivalCacheDistinguishPitch, FestivalCacheDistinguishRate); if (FestivalCacheDistinguishVoices) kvoice = msg_settings.voice_type; if (FestivalCacheDistinguishPitch) kpitch = msg_settings.pitch; if (FestivalCacheDistinguishRate) krate = msg_settings.rate; if (type == SPD_MSGTYPE_CHAR) ktype = 'c'; else if (type == SPD_MSGTYPE_KEY) ktype = 'k'; else if (type == SPD_MSGTYPE_SOUND_ICON) ktype = 's'; else { DBG("Invalid message type for cache_gen_key()"); return NULL; } key = g_strdup_printf("%c_%s_%d_%d_%d", ktype, msg_settings.voice.language, kvoice, krate, kpitch); return key; } /* Insert one entry into the cache */ int cache_insert(char *key, SPDMessageType msgtype, FT_Wave * fwave) { GHashTable *cache; TCacheEntry *entry; TCounterEntry *centry; char *key_table; if (FestivalCacheOn == 0) return 0; if (key == NULL) return -1; if (fwave == NULL) return -1; /* Check if the entry isn't present already */ if (cache_lookup(key, msgtype, 0) != NULL) return 0; key_table = cache_gen_key(msgtype); DBG("Cache: Inserting wave with key:'%s' into table '%s'", key, key_table); /* Clean less used cache entries if the size would exceed max. size */ if ((FestivalCache.size + fwave->num_samples * sizeof(short)) > (FestivalCacheMaxKBytes * 1024)) if (cache_clean(fwave->num_samples * sizeof(short)) != 0) return -1; /* Select the right table according to language, voice, etc. or create a new one */ cache = g_hash_table_lookup(FestivalCache.caches, key_table); if (cache == NULL) { cache = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(FestivalCache.caches, key_table, cache); } else { g_free(key_table); } /* Fill the CounterEntry structure that will later allow us to remove the less used entries from cache */ centry = (TCounterEntry *) g_malloc(sizeof(TCounterEntry)); centry->start = time(NULL); centry->count = 1; centry->size = fwave->num_samples * sizeof(short); centry->p_caches = cache; centry->key = g_strdup(key); FestivalCache.cache_counter = g_list_append(FestivalCache.cache_counter, centry); entry = (TCacheEntry *) g_malloc(sizeof(TCacheEntry)); entry->p_counter_entry = centry; entry->fwave = fwave; FestivalCache.size += centry->size; g_hash_table_insert(cache, g_strdup(key), entry); return 0; } /* Retrieve wave from the cache */ FT_Wave *cache_lookup(const char *key, SPDMessageType msgtype, int add_counter) { GHashTable *cache; TCacheEntry *entry; char *key_table; if (FestivalCacheOn == 0) return NULL; if (key == NULL) return NULL; key_table = cache_gen_key(msgtype); if (add_counter) DBG("Cache: looking up a wave with key '%s' in '%s'", key, key_table); if (key_table == NULL) return NULL; cache = g_hash_table_lookup(FestivalCache.caches, key_table); g_free(key_table); if (cache == NULL) return NULL; entry = g_hash_table_lookup(cache, key); if (entry == NULL) return NULL; entry->p_counter_entry->count++; DBG("Cache: corresponding wave found: %s", key); return entry->fwave; } int init_festival_standalone() { int ret; int fr; if ((pipe(module_p.pipe_in) != 0) || (pipe(module_p.pipe_out) != 0)) { DBG("Can't open pipe! Module not loaded."); return -1; } DBG("Starting Festival as a child process"); fr = fork(); switch (fr) { case -1: DBG("ERROR: Can't fork! Module not loaded."); return -1; case 0: ret = dup2(module_p.pipe_in[0], 0); close(module_p.pipe_in[0]); close(module_p.pipe_in[1]); ret = dup2(module_p.pipe_out[1], 1); close(module_p.pipe_out[1]); close(module_p.pipe_out[0]); /* TODO: fix festival hardcoded path */ if (execlp("festival", "", (char *)0) == -1) exit(1); default: festival_process_pid = fr; close(module_p.pipe_in[0]); close(module_p.pipe_out[1]); usleep(100); /* So that the other child has at least time to fail with the execlp */ ret = waitpid(module_p.pid, NULL, WNOHANG); if (ret != 0) { DBG("Can't execute festival. Bad filename in configuration?"); return -1; } return 0; } assert(0); } int init_festival_socket() { int r; /* Init festival and register a new voice */ festival_info = festivalDefaultInfo(); festival_info->server_host = FestivalServerHost; festival_info->server_port = FestivalServerPort; festival_info = festivalOpen(festival_info); if (festival_info == NULL) return -1; r = FestivalSetMultiMode(festival_info, "t"); if (r != 0) return -2; DBG("FestivalServerHost = %s\n", FestivalServerHost); DBG("FestivalServerPort = %d\n", FestivalServerPort); return 0; } int stop_festival_local() { if (festival_process_pid > 0) kill(festival_process_pid, SIGINT); return 0; } speech-dispatcher-0.8.3/src/modules/Makefile.in0000664000175000017500000010241512536424264016357 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ modulebin_PROGRAMS = sd_dummy$(EXEEXT) sd_generic$(EXEEXT) \ sd_festival$(EXEEXT) sd_cicero$(EXEEXT) $(am__EXEEXT_1) \ $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ $(am__EXEEXT_5) @flite_support_TRUE@am__append_1 = sd_flite @ibmtts_support_TRUE@am__append_2 = sd_ibmtts @espeak_support_TRUE@am__append_3 = sd_espeak @ivona_support_TRUE@am__append_4 = sd_ivona @pico_support_TRUE@am__append_5 = sd_pico subdir = src/modules DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_snddata_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @flite_support_TRUE@am__EXEEXT_1 = sd_flite$(EXEEXT) @ibmtts_support_TRUE@am__EXEEXT_2 = sd_ibmtts$(EXEEXT) @espeak_support_TRUE@am__EXEEXT_3 = sd_espeak$(EXEEXT) @ivona_support_TRUE@am__EXEEXT_4 = sd_ivona$(EXEEXT) @pico_support_TRUE@am__EXEEXT_5 = sd_pico$(EXEEXT) am__installdirs = "$(DESTDIR)$(modulebindir)" \ "$(DESTDIR)$(snddatadir)" PROGRAMS = $(modulebin_PROGRAMS) am__objects_1 = spd_audio.$(OBJEXT) am__objects_2 = module_main.$(OBJEXT) module_utils.$(OBJEXT) am_sd_cicero_OBJECTS = cicero.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) sd_cicero_OBJECTS = $(am_sd_cicero_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) sd_cicero_DEPENDENCIES = $(top_builddir)/src/common/libcommon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_sd_dummy_OBJECTS = dummy.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) module_utils_addvoice.$(OBJEXT) sd_dummy_OBJECTS = $(am_sd_dummy_OBJECTS) sd_dummy_DEPENDENCIES = $(top_builddir)/src/common/libcommon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am__sd_espeak_SOURCES_DIST = espeak.c spd_audio.c spd_audio.h \ module_main.c module_utils.c module_utils.h @espeak_support_TRUE@am_sd_espeak_OBJECTS = espeak.$(OBJEXT) \ @espeak_support_TRUE@ $(am__objects_1) $(am__objects_2) sd_espeak_OBJECTS = $(am_sd_espeak_OBJECTS) @espeak_support_TRUE@sd_espeak_DEPENDENCIES = \ @espeak_support_TRUE@ $(top_builddir)/src/common/libcommon.la \ @espeak_support_TRUE@ $(am__DEPENDENCIES_1) \ @espeak_support_TRUE@ $(am__DEPENDENCIES_1) \ @espeak_support_TRUE@ $(am__DEPENDENCIES_2) am_sd_festival_OBJECTS = festival.$(OBJEXT) festival_client.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) sd_festival_OBJECTS = $(am_sd_festival_OBJECTS) sd_festival_DEPENDENCIES = $(top_builddir)/src/common/libcommon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_1) am__sd_flite_SOURCES_DIST = flite.c spd_audio.c spd_audio.h \ module_main.c module_utils.c module_utils.h @flite_support_TRUE@am_sd_flite_OBJECTS = flite.$(OBJEXT) \ @flite_support_TRUE@ $(am__objects_1) $(am__objects_2) sd_flite_OBJECTS = $(am_sd_flite_OBJECTS) @flite_support_TRUE@sd_flite_DEPENDENCIES = \ @flite_support_TRUE@ $(top_builddir)/src/common/libcommon.la \ @flite_support_TRUE@ $(am__DEPENDENCIES_1) \ @flite_support_TRUE@ $(am__DEPENDENCIES_1) \ @flite_support_TRUE@ $(am__DEPENDENCIES_1) \ @flite_support_TRUE@ $(am__DEPENDENCIES_2) am_sd_generic_OBJECTS = generic.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) module_utils_addvoice.$(OBJEXT) sd_generic_OBJECTS = $(am_sd_generic_OBJECTS) sd_generic_DEPENDENCIES = $(top_builddir)/src/common/libcommon.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am__sd_ibmtts_SOURCES_DIST = ibmtts.c spd_audio.c spd_audio.h \ module_main.c module_utils.c module_utils.h \ module_utils_addvoice.c @ibmtts_support_TRUE@am_sd_ibmtts_OBJECTS = ibmtts.$(OBJEXT) \ @ibmtts_support_TRUE@ $(am__objects_1) $(am__objects_2) \ @ibmtts_support_TRUE@ module_utils_addvoice.$(OBJEXT) sd_ibmtts_OBJECTS = $(am_sd_ibmtts_OBJECTS) @ibmtts_support_TRUE@sd_ibmtts_DEPENDENCIES = \ @ibmtts_support_TRUE@ $(top_builddir)/src/common/libcommon.la \ @ibmtts_support_TRUE@ $(am__DEPENDENCIES_1) \ @ibmtts_support_TRUE@ $(am__DEPENDENCIES_2) am__sd_ivona_SOURCES_DIST = ivona.c ivona_client.c ivona_client.h \ spd_audio.c spd_audio.h module_main.c module_utils.c \ module_utils.h @ivona_support_TRUE@am_sd_ivona_OBJECTS = ivona.$(OBJEXT) \ @ivona_support_TRUE@ ivona_client.$(OBJEXT) $(am__objects_1) \ @ivona_support_TRUE@ $(am__objects_2) sd_ivona_OBJECTS = $(am_sd_ivona_OBJECTS) @ivona_support_TRUE@sd_ivona_DEPENDENCIES = \ @ivona_support_TRUE@ $(top_builddir)/src/common/libcommon.la \ @ivona_support_TRUE@ $(am__DEPENDENCIES_1) \ @ivona_support_TRUE@ $(am__DEPENDENCIES_2) am__sd_pico_SOURCES_DIST = pico.c spd_audio.c spd_audio.h \ module_main.c module_utils.c module_utils.h @pico_support_TRUE@am_sd_pico_OBJECTS = pico.$(OBJEXT) \ @pico_support_TRUE@ $(am__objects_1) $(am__objects_2) sd_pico_OBJECTS = $(am_sd_pico_OBJECTS) @pico_support_TRUE@sd_pico_DEPENDENCIES = \ @pico_support_TRUE@ $(top_builddir)/src/common/libcommon.la \ @pico_support_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(sd_cicero_SOURCES) $(sd_dummy_SOURCES) \ $(sd_espeak_SOURCES) $(sd_festival_SOURCES) \ $(sd_flite_SOURCES) $(sd_generic_SOURCES) $(sd_ibmtts_SOURCES) \ $(sd_ivona_SOURCES) $(sd_pico_SOURCES) DIST_SOURCES = $(sd_cicero_SOURCES) $(sd_dummy_SOURCES) \ $(am__sd_espeak_SOURCES_DIST) $(sd_festival_SOURCES) \ $(am__sd_flite_SOURCES_DIST) $(sd_generic_SOURCES) \ $(am__sd_ibmtts_SOURCES_DIST) $(am__sd_ivona_SOURCES_DIST) \ $(am__sd_pico_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_snddata_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ inc_local = -I$(top_srcdir)/include audio_SOURCES = spd_audio.c spd_audio.h common_SOURCES = module_main.c module_utils.c module_utils.h common_LDADD = $(SNDFILE_LIBS) $(DOTCONF_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS) AM_CFLAGS = $(ERROR_CFLAGS) AM_CPPFLAGS = $(inc_local) -DDATADIR=\"$(snddatadir)\" -D_GNU_SOURCE \ -DPLUGIN_DIR="\"$(audiodir)\"" \ $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \ $(ibmtts_include) $(SNDFILE_CFLAGS) sd_dummy_SOURCES = dummy.c $(audio_SOURCES) $(common_SOURCES) \ module_utils_addvoice.c sd_dummy_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) dist_snddata_DATA = dummy-message.wav sd_festival_SOURCES = festival.c festival_client.c festival_client.h \ $(audio_SOURCES) $(common_SOURCES) sd_festival_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) $(EXTRA_SOCKET_LIBS) sd_generic_SOURCES = generic.c $(audio_SOURCES) $(common_SOURCES) \ module_utils_addvoice.c sd_generic_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) sd_cicero_SOURCES = cicero.c $(audio_SOURCES) $(common_SOURCES) sd_cicero_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) @flite_support_TRUE@sd_flite_SOURCES = flite.c $(audio_SOURCES) $(common_SOURCES) @flite_support_TRUE@sd_flite_LDADD = $(top_builddir)/src/common/libcommon.la \ @flite_support_TRUE@ $(audio_dlopen_modules) \ @flite_support_TRUE@ $(flite_kal) $(flite_basic) \ @flite_support_TRUE@ $(common_LDADD) @ibmtts_support_TRUE@sd_ibmtts_SOURCES = ibmtts.c $(audio_SOURCES) $(common_SOURCES) \ @ibmtts_support_TRUE@ module_utils_addvoice.c @ibmtts_support_TRUE@sd_ibmtts_LDADD = $(top_builddir)/src/common/libcommon.la \ @ibmtts_support_TRUE@ $(audio_dlopen_modules) \ @ibmtts_support_TRUE@ -libmeci \ @ibmtts_support_TRUE@ $(common_LDADD) @espeak_support_TRUE@sd_espeak_SOURCES = espeak.c $(audio_SOURCES) $(common_SOURCES) @espeak_support_TRUE@sd_espeak_LDADD = $(top_builddir)/src/common/libcommon.la \ @espeak_support_TRUE@ $(audio_dlopen_modules) \ @espeak_support_TRUE@ -lespeak $(EXTRA_ESPEAK_LIBS) \ @espeak_support_TRUE@ $(common_LDADD) @ivona_support_TRUE@sd_ivona_SOURCES = ivona.c ivona_client.c ivona_client.h $(audio_SOURCES) \ @ivona_support_TRUE@ $(common_SOURCES) @ivona_support_TRUE@sd_ivona_LDADD = $(top_builddir)/src/common/libcommon.la \ @ivona_support_TRUE@ $(audio_dlopen_modules) \ @ivona_support_TRUE@ -ldumbtts \ @ivona_support_TRUE@ $(common_LDADD) @pico_support_TRUE@sd_pico_SOURCES = pico.c $(audio_SOURCES) $(common_SOURCES) @pico_support_TRUE@sd_pico_LDADD = $(top_builddir)/src/common/libcommon.la \ @pico_support_TRUE@ $(audio_dlopen_modules) -lttspico \ @pico_support_TRUE@ $(common_LDADD) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/modules/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/modules/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-modulebinPROGRAMS: $(modulebin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(modulebin_PROGRAMS)'; test -n "$(modulebindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(modulebindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(modulebindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(modulebindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(modulebindir)$$dir" || exit $$?; \ } \ ; done uninstall-modulebinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(modulebin_PROGRAMS)'; test -n "$(modulebindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(modulebindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(modulebindir)" && rm -f $$files clean-modulebinPROGRAMS: @list='$(modulebin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list sd_cicero$(EXEEXT): $(sd_cicero_OBJECTS) $(sd_cicero_DEPENDENCIES) $(EXTRA_sd_cicero_DEPENDENCIES) @rm -f sd_cicero$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_cicero_OBJECTS) $(sd_cicero_LDADD) $(LIBS) sd_dummy$(EXEEXT): $(sd_dummy_OBJECTS) $(sd_dummy_DEPENDENCIES) $(EXTRA_sd_dummy_DEPENDENCIES) @rm -f sd_dummy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_dummy_OBJECTS) $(sd_dummy_LDADD) $(LIBS) sd_espeak$(EXEEXT): $(sd_espeak_OBJECTS) $(sd_espeak_DEPENDENCIES) $(EXTRA_sd_espeak_DEPENDENCIES) @rm -f sd_espeak$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_espeak_OBJECTS) $(sd_espeak_LDADD) $(LIBS) sd_festival$(EXEEXT): $(sd_festival_OBJECTS) $(sd_festival_DEPENDENCIES) $(EXTRA_sd_festival_DEPENDENCIES) @rm -f sd_festival$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_festival_OBJECTS) $(sd_festival_LDADD) $(LIBS) sd_flite$(EXEEXT): $(sd_flite_OBJECTS) $(sd_flite_DEPENDENCIES) $(EXTRA_sd_flite_DEPENDENCIES) @rm -f sd_flite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_flite_OBJECTS) $(sd_flite_LDADD) $(LIBS) sd_generic$(EXEEXT): $(sd_generic_OBJECTS) $(sd_generic_DEPENDENCIES) $(EXTRA_sd_generic_DEPENDENCIES) @rm -f sd_generic$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_generic_OBJECTS) $(sd_generic_LDADD) $(LIBS) sd_ibmtts$(EXEEXT): $(sd_ibmtts_OBJECTS) $(sd_ibmtts_DEPENDENCIES) $(EXTRA_sd_ibmtts_DEPENDENCIES) @rm -f sd_ibmtts$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_ibmtts_OBJECTS) $(sd_ibmtts_LDADD) $(LIBS) sd_ivona$(EXEEXT): $(sd_ivona_OBJECTS) $(sd_ivona_DEPENDENCIES) $(EXTRA_sd_ivona_DEPENDENCIES) @rm -f sd_ivona$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_ivona_OBJECTS) $(sd_ivona_LDADD) $(LIBS) sd_pico$(EXEEXT): $(sd_pico_OBJECTS) $(sd_pico_DEPENDENCIES) $(EXTRA_sd_pico_DEPENDENCIES) @rm -f sd_pico$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sd_pico_OBJECTS) $(sd_pico_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cicero.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/espeak.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/festival.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/festival_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flite.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibmtts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ivona.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ivona_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_utils_addvoice.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pico.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spd_audio.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_snddataDATA: $(dist_snddata_DATA) @$(NORMAL_INSTALL) @list='$(dist_snddata_DATA)'; test -n "$(snddatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(snddatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(snddatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(snddatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(snddatadir)" || exit $$?; \ done uninstall-dist_snddataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_snddata_DATA)'; test -n "$(snddatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(snddatadir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(modulebindir)" "$(DESTDIR)$(snddatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-modulebinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_snddataDATA install-modulebinPROGRAMS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_snddataDATA uninstall-modulebinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-modulebinPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dist_snddataDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-modulebinPROGRAMS install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-dist_snddataDATA \ uninstall-modulebinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/modules/Makefile.am0000644000175000017500000000514312233560613016335 00000000000000## Process this file with automake to produce Makefile.in inc_local = -I$(top_srcdir)/include audio_SOURCES = spd_audio.c spd_audio.h common_SOURCES = module_main.c module_utils.c module_utils.h common_LDADD = $(SNDFILE_LIBS) $(DOTCONF_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS) AM_CFLAGS = $(ERROR_CFLAGS) AM_CPPFLAGS = $(inc_local) -DDATADIR=\"$(snddatadir)\" -D_GNU_SOURCE \ -DPLUGIN_DIR="\"$(audiodir)\"" \ $(DOTCONF_CFLAGS) $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \ $(ibmtts_include) $(SNDFILE_CFLAGS) modulebin_PROGRAMS = sd_dummy sd_generic sd_festival sd_cicero sd_dummy_SOURCES = dummy.c $(audio_SOURCES) $(common_SOURCES) \ module_utils_addvoice.c sd_dummy_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) dist_snddata_DATA = dummy-message.wav sd_festival_SOURCES = festival.c festival_client.c festival_client.h \ $(audio_SOURCES) $(common_SOURCES) sd_festival_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) $(EXTRA_SOCKET_LIBS) sd_generic_SOURCES = generic.c $(audio_SOURCES) $(common_SOURCES) \ module_utils_addvoice.c sd_generic_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) sd_cicero_SOURCES = cicero.c $(audio_SOURCES) $(common_SOURCES) sd_cicero_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(common_LDADD) if flite_support modulebin_PROGRAMS += sd_flite sd_flite_SOURCES = flite.c $(audio_SOURCES) $(common_SOURCES) sd_flite_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ $(flite_kal) $(flite_basic) \ $(common_LDADD) endif if ibmtts_support modulebin_PROGRAMS += sd_ibmtts sd_ibmtts_SOURCES = ibmtts.c $(audio_SOURCES) $(common_SOURCES) \ module_utils_addvoice.c sd_ibmtts_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ -libmeci \ $(common_LDADD) endif if espeak_support modulebin_PROGRAMS += sd_espeak sd_espeak_SOURCES = espeak.c $(audio_SOURCES) $(common_SOURCES) sd_espeak_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ -lespeak $(EXTRA_ESPEAK_LIBS) \ $(common_LDADD) endif if ivona_support modulebin_PROGRAMS += sd_ivona sd_ivona_SOURCES = ivona.c ivona_client.c ivona_client.h $(audio_SOURCES) \ $(common_SOURCES) sd_ivona_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) \ -ldumbtts \ $(common_LDADD) endif if pico_support modulebin_PROGRAMS += sd_pico sd_pico_SOURCES = pico.c $(audio_SOURCES) $(common_SOURCES) sd_pico_LDADD = $(top_builddir)/src/common/libcommon.la \ $(audio_dlopen_modules) -lttspico \ $(common_LDADD) endif speech-dispatcher-0.8.3/src/modules/dummy-message.wav0000644000175000017500000050007512233560613017601 00000000000000RIFF5€WAVEfmt @@data€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‰Ž’•—–••••–”“’‘ŒŒ‹Š‰ˆ‡‡††……„„„ƒƒ‚‚‚‚‚€€€€€€€€€€€‰‘’•˜–”””””‘ŒŠŠˆ†„€€€~€€‚‚‚€€€€€€€€€€€€€€€…˜¢žžŸ ¤¥›‘Ž‹‡€yy|}{yy{€‚€ƒ…†ƒ‚ƒƒ‚€~€€~~€€€€€€€€€”®¨¢©¥§ª›ˆ„†€yunp|~z}…‹‡„ˆ‰…‚~{}€}z{}„„ƒ‚€‚~€~‚œ°¥£©¦ª©–†…†~xsow‚‚~ƒ‰ŽŒ……ˆ†zxy~}yzƒ…„‚‚†‡ƒ~€|{}€€€»©©¥¥¥‹v€ˆznpt€Œƒyˆ•‰‚…Š~qv€zx‚‹„{~……{yƒ~y}‚„‚ƒ†’¸­›©¦›–‚mpzoepy‚ŽŒ‡‘š‘†ƒ~|}tmt|}~„ŠŽ‰ƒ„…}ywz~|z~ƒ……„‚…„‰©µ £¨¢¡–€}Š„xz|ƒˆ~„Š„€|‚‡~x}‚ƒ‚~}„‡}ƒ||‚ƒ€~~„~~‚ƒŸ¥¨«©ª©Œ‹†‚~}„ˆ†„‡‰Šˆƒƒ„‚}€~~~ƒ‚ƒ…„…„ƒ„„ƒ‚ƒ‚ƒ„‚€€€€€€~~~}~~~~~~~€~ƒƒ„…„„…„„ƒƒƒ„„‚€~|}}{zzzz|}~~€€€‚€‚€‚‚€€€€€€€€€€€€€‚€‚‚‚€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€‚€€‚€~€€€€€~€‚‚‚€‚€€~€€~€~~~~~~€€€€€€€€€€€€x{|z}{|ƒ‚‚ƒ‚ƒ‚~~~~}}~‚ƒ‚€~~~€€€‚‚‚€€~„¤³§¦¤¢¤˜‚qnrojhm|‹•š—Œ€yywqlkr{ƒ…Š’ˆƒ{uqsw{}~‚‡‹Œ‰††ƒ’­¨Ÿœžœ‹zquwrnow†Œ‹Ž“”Ž„|z{xrorz€ƒƒ…ŠŽˆƒ€~zutw{}~ƒ‡‰ˆ…„ƒ…ž¯£Ÿ  —…tryqfmv€Šˆ‰“𓉄‚~yplsyyz€ˆŽŠˆ‰ˆ€zwwxwvy„……‡‰‰†€€}‹³°•¨²¥ž‹ux~p_hw~†‰ˆ–¡˜Œ‰†yohnvvv~‡Ž‘Ž‹Œ„{vuutsu|ƒ…‡‰ŒŠ†€}|›¯•™¬£Ÿ˜y}heq|„‚‰—œ“Ž‹€utyytsy‡‡„ˆŒ†€€~zvw|~}}€„‡†„„†…‚•©žœ¤  ‹tmopx{}Š‹‰‹‰~xzzxvuw‚€†‰‰‡ƒ‚„‚}zyy{{yy}€ƒ„“¤›•žžœ‚ƒ…}tposzyu{ƒˆŠ‰‡ŠŽŒ…€€|wvz||{|„†„ƒ„††„€€|{|~}‚š –›ž¢œŒ†‰…~yrqxzvv{„‡„ƒˆŠˆ†‚‚ƒ{{|~~|{~‚€ƒ„ƒ€~~€~‚‘•‘”””˜•‹†‡…~xv{|zz|~‚…ƒ‚…††…‚‚‚€~}}~~}~€€€‚‚‚€€€€Œ‘Ž““‰‰ˆ‡†~€€~}‚€€ƒ€€€€€€€€€€€€€€€€€€€‚’Ž“•Ž‹ŽŒŠŒ‰†Š‹ˆŠ‹‰‰Š†„…‚€‚€}}|yz{z{|zz{{||z|}{|~~‚‚ƒ……„ƒ€€€~~}}}||}{|||}|}~€€‚ƒ‚‚ƒƒ…„ƒƒ„……„…ƒ„†„„„„†……††‡‡†‡†††…††…†„„„„„„ƒƒ‚€€~~~~~€€‚‚ƒ„„„„ƒ„……†…„…………„„……ƒ„„„„…„…††††††‡†††…„„„ƒƒƒ‚‚‚‚‚‚‚‚ƒ‚ƒƒ‚‚‚€€€€~~~~~~~~~~~~~€€‚‚‚‚ƒƒƒƒƒ‚ƒƒ‚‚‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}~€€€€€€€€€€€€€€€€€€€€€€€€€…‡‡‡‡ˆˆˆˆ‡‡‡††………„„„ƒƒƒƒ‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€‰Œˆ„ƒƒ„ƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‡Œ‰…ƒƒ„ƒ}}~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€…“šœ˜–•’ŽŠ„~~~~~ƒ…†……„„ƒ‚€~~~~€‚‚‚€€€€€€˜µ¹¼¸Ÿ’ŠxiaWUcmu„Ž” ¤ž™‘ƒztjdfflw†”•—•‡€wrolmrv|ƒˆŒ‘ŽŠ„€{y}ƒ‰‘—œ¡¥¤¢ž–ˆ€ytqoqtx}ƒ‡Œ‘Œˆ„{wuttvx{‚…ˆ‰ŠŠˆ†ƒ€~{zxxyz€‰’œ¤ª­°¯­©£›“‹ƒ|vrommoruy~‚†‰‹ŽŒ‹ˆ†ƒ€}{zyxxyz{}€‚ƒ„………„„ƒ„‡ŠŽ’•˜ššš™—”‘ˆ„~{yxxxy{}‚„…†‡‡†…„ƒ‚€~}}||}}~~€‚‚ƒƒƒ„…‡ˆŠŒŽ‘’’’‘‘ŽŒŠˆ†„‚€~}||{{{{||}~€€‚‚‚ƒƒƒƒ‚‚‚€€€€ƒ…ˆŠ’’“’‘‹‰‡„‚€~}{zyxwwwwxxyz{|}~€€‚‚ƒƒƒ„„„ƒƒƒƒ‚‚ƒ„„…†‡ˆ‰ŠŠ‹‹‹ŠŠ‰‰ˆ‡†…„ƒ‚€~~}}}}~~~€€€€€€€€€€€€€€€€€€€€€€€€‚€~‚‚€ƒ„„‡‡…„„‚~{z|{xxz{}~~€‚ƒƒƒƒƒƒ‚†””‘“”•–†„„€{wtvzzy{ƒ‡‡„„…„‚|{|}||}‚ƒƒ‚ƒƒƒ‚€~~~~~}~‹ª´­®©¥¦›ƒsqomokm}ŠŽ‘‘”•‹}vsuyzy~†Œ‡‚{xuv|‚„……††‡‚„¥¹³®‹ŒŠyifjwŠ‹•–”Šyprtvxx|‡Œ‡‚€ztsv|‚………‡ˆ†ƒ|yz{™ÁÆ¿°’ƒvibeq‡œ œ—‰‚xlgkt€ŠŽŽŽŠƒ{spsx}‚…ˆ‹‹ˆƒ}yxwz{…¯ÌÊÁ¦†|wlbahy“¤£ž•Š„|pffmy‡‘‘Œ‡voosz€…ˆ‹ŒŠ‡€zwvyz‹¸ÍÉ¿ž~upjgin~˜¥¥Ÿ€zuolmr}‹“”‘Šƒ~zursv}…ЋЇƒ€}zwyx‹¹Îɾœ|urkgin~™¥¥žŽ€zvplmr}Œ“”‰‚{ussw~†Š‹‰‡ƒ€~yxw¬ËÉÁ¤‚wunihkx’£¤Ÿ’‚|yrmmpzˆ’“‘‹„€|wsqsx„††‡†…ƒ|z|𻹱¦ˆŠ„ulmp~Ž‹Œ‹Š‹‡|uvx|€€‚†‡‡…€|}~~~~~‚„ƒ‚‚µ¾²ª•„††znnqy‹“‹‹‰‰ˆ€vux{€ƒ…‡†…‚}|~~~~~„ƒ‚‚ž½º°£‹ƒ‡ƒumos€‘’Œ‹Šˆ‰†{tvy|‚ƒ€‚†‡†„€||~~~~~‚„‚‚€‰®¿µ¬š……‡~qlmnw†‰„†ˆ†‡Š†}{}||€€}~‚ƒƒ€€€~~€€™·½ºµ¤•’’Š}yvs{…‡„†‡†‡Š‡€}~€€}~ƒ‚€€€€€~€‡¦½»¸¯ž“’‘…yxuu‡†„†ˆ†ˆŠ„~}~}‚ƒ‚€‚€€€€˜³´µÃÅ»½Â·««©›”—‘†‡Š‚~ƒ„}„}‚„€„ƒ„‚ƒ‚~€‚‡ž§£ª³­©¯­¡Ÿ˜‡ƒ‡…€„€}‚ƒƒ‚~ƒ€‚‚€‚€‚‚£§¥­±¬¬¯© ž›’Œ‡€}|~}|}‚‚ƒ‚‚‚€€€€€€€€‹Ÿ¦¤¬²¬«°ª Ÿœ’ˆ}{~}{}€‚ƒ‚‚‚‚€€€€€„—¤£§±¯«°¯£ŸŸ–‰€~{wz{yz~~}€‚‚„„‚ƒ„‚‚‚€€€‚’¡¡£­®¨­¯¤žž–ŒŠ‡{{xtvwvx{|}‚‚‚„„ƒƒ„‚€~¤ª­ÀÌÆÉÏǼ¹²£™”Œ||xsvzwy€„ˆ†…ˆˆ……†„~}~~Œ£©©¼ÍÅÅÏɺ¸µ¥˜•Ž€z{voqusry}|~„†„‡Šˆ†ˆˆ„ƒƒ‚~}}~}}‹ ¤¢´Ã½¹ÂÁ´­­£•‚zzxrqvvtx}~~ƒ†„…ˆˆ††‡„‚‚‚€~}~‡¨£«¾Âº¸¾º­¨¦’Ž‹ƒ}}|wwzzy{„ƒƒ„…„ƒ„ƒ‚‚€~ˆž¨¤¬½Âº¸¾¹­¨¦œ’ŽŠƒ}}|wwzzy{„ƒƒ„…„ƒ„ƒ‚€€™¶›²¸¡“”ˆwtlktohs…ƒ†’–‘Љƒ{wwwsquz|}…ˆ‰‰‰ˆˆ„®‹‹±­˜Ž–ˆzxpsypkw‚ƒƒ‘Œ‹ŠŠˆ‚|z{zutx||}€„†‡‡‡‰‰ƒ…ƒ† ™…¤©– š’›Ž~‚„ypttsusv‚~†‹‹‹ŠŠŒ‰ƒƒzyyyyxy}~~ƒ„„†„•«””³¦¤”–˜‚y|okpprur|‡‚ƒŽŽ‹‹Œ†€€zwwvxxwz€ƒ††‡†ˆ£§‹¡´œŸŸ‘™‘{{wlnsqsuu†€†ŽŒ‹ŒŠƒ€xwxwwwx|~€„††…ˆ†•©“’³¤˜£•”—ƒz}omsrquu{…‚‚Ž‹ŒŒ‹‹†€{wxxwxxz~ƒ……†…ˆ…¦—•°¢›¤•–˜…ƒ~tqutsxw|…‚ƒŒ‹Œ‹Šˆ…zwyxwyz|€„†…††‡„‰¤š‡§ª’Ÿ™Ž–‰z€tmsuqvxy„…‹‹‹ŒŠˆ†~{vxywxz{~€€ƒ††††‡…†Ÿ † ®”œœŽ•{}wnrxtv||…‰…‰‰Š‰…‚~{zzuuyyy|€‚„…†ˆˆ†…„ƒ€€œŸ›°–˜‘”|yyinxrsz|„І‰’ŠŠ‹‡‚zzytsxyx{‚„†‡ˆŠ‡…†ƒ}‚ ˜€£­“››’•‹}z€{lq|yzƒŠŠ‰ŽŽ†‚€{wvxyyy~ƒ„„†‰ˆ†„ƒƒ|{z|xˆ®š‡³¶››–‹|mkunam|}€†Ž––Ž‘zzxrnpuxy|ƒŠŠŠŒ‹†‚€~zwuwyv±–Š®®—Š…ˆslly}sw‰‹†‹Œ‚|}€{su|€}|‚ˆ‡ƒƒ…†‚}}~{z~€€„„…«µŠ–µ Šƒ„wols‚~u‚‘ˆ†ŒŽ…|z~wsy}†‰…‚‚…„~{}€}z|€‚€€‚„…˜»™…¬­~{„|sss†‰“|‚|vv}ƒ~ˆ‰„€ƒ|z}€€~~‚…ƒ€€‚ƒ~}~ƒ¬¿‡«©Šor|rnu‹“‡€‹—Ž{w‚{ru€‡ƒ~‚‹‹‚|ƒ€yx}‚~„†ƒ‚‚}}|¾¯•±Ÿ}kyxom}’‚ƒ’–†wy|z{ˆ‰ƒ€ƒ†‚|z|€€ƒ…‚€€€€}~ƒ¬Ì¥‡–™‹sglrˆ„’š’ƒ}~|xuty‚‡†„†‰†|z{|||~‚……ƒ‚‚}|}~€€ƒ‚£Ë­†‘™Žwglr}ˆƒ‚™”…}~}yvtx‡‡„†ˆ‡|z{|}|~……ƒ‚‚€~|}~€€ÁÚ±Ž‰†ƒxmhmŠ¢˜ˆˆŒŒ„wpnz‰‡€‚ˆ‹ˆ€zwz}}‚†‡ƒ}~€}|‚„‚€€„±Ú¼”Œˆ…|pji€ž›Šˆ‹Œ‡{rnv†ˆ†ŠŠƒ|wy€‚}}…‡„€}}€~|~ƒƒ€¦×ÆšŒ‰…~rkhzšžˆ‹Œˆ}snsƒ‰‚€…ŠŠ„}xx‚~|€„ˆŠ‰‚{z}€€„„‚~}’Äãßʨ‡ss~{xŒ™£¤—€trty‚‚…Œ‹„}wvz€‚ƒ„„…„|z|~€‚‚‚‚~~~”Åãà˨†rr}zy‚𣤗€trty‚‚…Œ‹„}wuz‚‚ƒ„„…„€|z|~€‚‚‚~~~”Åãà˨†rr}zy‚𣤗€trty‚‚…Œ‹„}wuz‚‚ƒ‚‚„„‚|||~‚‚€~‘¼ÚáØº•xmqqv„Žš¢ ”‡zppuzƒ‡Š‹Œ‰‚}yxy|€‚ƒ……„ƒ}|}~€‚‚‚‚€‘»Ùß×¹•ynrrv…Ž™¡ “‡{qpuzƒ‡ŠŠ‹‰‚}yxy|€‚ƒ„…„ƒ}|}~€‚‚‚‚€€€˜ÄÜàÓ²unrrx†œ¢ž‘„vlmpuz„†‰ŒŠ‡ƒ~zxy{}‚„„„ƒ€~}}}€‚…£ÃÐÔÆ©Œwqmnux|†—™—…}xuvx{~…‡ˆˆ†ƒ}|{|~€‚ƒƒ‚€~~~€€€‰«ÇÒÔ£‡uplovx~ˆ’˜™—Žƒ|wuvx|~†‡ˆˆ…‚}|{|~€‚ƒƒƒƒ‚€€€Ž­ÀÉɸŸŠ~xtvwvy…Œ‘’މ…€}||||}~€‚„„„ƒ‚€€€€€€€€€€‚™¶ÄËÄ®–…|vtxvv{ˆŽ’‘Œˆƒ~}||{|}ƒ„„„ƒ€€€€€€€~{yxvuvwwyz{|}~}|~}{zxuuwz€‚ƒƒ€}|{{}~~€€ƒ†‰‰‡†ƒ€€„ƒƒ††ˆ‰‰ˆ‰Š‰‡†‚}|ywz}~‚ƒ‚„†‡ˆˆ„{wuvvxxvwwux{|‚„„ƒ€zurqswyxwvuvxzzzzyxz{|}}}|}}}~~~~~~~€€€€€‚‚‚‚‚€‚‚‚‚‚‚‚ƒ‚‚ƒƒ„„„ƒ„„„„„ƒƒ„„„…………†…††††††……„ƒ‚~~}}||{{{|||||||}}}}}}}}}~~~~~~~~~}}}}}~~}}}}~~~~€€‚‚‚€€~}}}~~~~}}}~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€}€‚€~€‚~‚€~ƒ~€~€€€‚€‚€‚€‚€€‚~€€‚€€‚€€€€€€€€€€‚€‚‚‚ƒ„‚ƒƒƒƒ‚‚‚‚€€€€€~€~~~~~~~~€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒƒƒƒ„„„ƒ‚‚ƒ„ƒ‚‚ƒƒ‚‚‚‚‚ƒƒ‚‚„…„„ƒ…†…ƒƒƒ‚ƒ„‚‚ƒƒ‚ƒƒ„†††…ƒƒ…„ƒƒƒ‚‚€‚ƒ}~€€€~€€‚€ƒƒ‚‚€€€}€€‚ƒ‚‚‚ƒ‚ƒ‚€€€€~~}}€}}~||€~~€€}|}ƒ~|~€€}}‚„…„‚‚‚~}}}€ƒ„ƒ€}z{}‚~ƒƒ„ƒ~‚ƒƒ‚‚……„‚~~}}~}}}€~~{zz{~{z|€‚}{|~€‚‚€‚‚‚€€€€€€€€€€€€€€€€€€€‡³ÃÌÊÀ·°©¡˜Ž„~€ƒ…†…†‡ˆ‰ˆ†ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€§ºÇÍǼ±¥—‡ueZW]gs‰“¤¦£œ„yqjfefks}‡”——”Šƒ{tommpty~„‰ŽŠ…{‚¦ÀÂ˨¢Ÿ’…vdWWcox…Œš¢£ ˜‹~vpliiimv€‰””“‘ˆztonprw{€…ŠŠ‡ƒ{Ч·ÁÈÁ»»²¢‘lca__elv…‘™ž¡Ÿœ˜„{rkihilsy‰Ž’””‘މ‚}xsqqqtw|€…ˆ‹ŒŠ¥¼ÄÊǺ³¯¡na`bbhqy…’›ž¡¢œ—’†|vplmopu|‚ˆŽ‘‘Šˆ†„ƒ€€€‡“––˜—•”’‹‰‡†„ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‹‘”•——–•“‘ŒŠˆ‡…„ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€…‡ˆ‰‰ˆˆˆ†…„‚€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ†‡‰‹‹‹Œ‹ŠŠ‰‡†…„ƒƒƒ‚‚€€~~~~~~~€€€€€€€~~~~~€€€‚‚ƒƒƒƒƒƒƒ‚‚€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒ€€~€‚‚€‚‚‚‚ƒ€‚€~€~~€€~€€€€€€~}~}~€~€~€~€€~~~~~}~€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€‚€€€€€€€‚€€€€€€€€~~~~~~~}~~~~~~~~~~€€~~~~~€€~~€€€€€€€€€€€€€€€€€~~~~~~~~~~~~~~}~~~}~~}}~~~~~~€€€€€‚‚€€€€€€€€€€€€€€~~}~†— ª´¼ÂÈÉÉÈÅ¿¹²«¤ž˜“Œ‹‹ŒŽ‘‘’’‘‹Šˆ†„ƒ‚‚‚‚ƒƒƒƒƒƒƒƒ‚‚„•¦°ºÁÇËÌÌÊÆÀ¸¯§ž–Žˆƒ}{{|}~€‚ƒ…†††††…„ƒ‚€€€€€€€ˆš§­³¹¼»¹¶­¤–އ‚}ywxxxz|~‚ƒ„…††……„ƒ‚€~€€€€€€€€€€€‰œ¡ ²¼´ºÂ¸±µ¬ ž˜‡„ywwusvwvx|{}ƒ„ƒ„…„ƒƒƒ‚€€€€€€€Šž¢¢´¹¯·½°­±§žžšŒ‡‚‚‚~}€|€~‚€‚‚€‚€€€€€€€€€€€€€€€€€‡›¨¬ºÄ¼ÀÇ¿¹¼µ©¨£™”“‡…„€~€~{}}}€~€‚‚‚€‚€€€€€€€€€‘¢§¯¾»¸Á¿µ·¶ª¥¤œ”’ˆ……‚~}}~~€€‚‚‚€€€€€€€€€€€€€€€ˆž¯¸ÆÍÆÄ޶´ªŸš“‹‡ƒ€~|||{}~~€‚ƒƒ‚ƒƒ‚‚‚€€€€€€€€€€€€€€€€€€§³¾ËÉÁ¹©—‰|soou{‚Š’“‘ŽŠ„|yxyz}€‚„…†…„ƒ~}}}~€‚‚‚€€…ŸÀÞøýëË x]QTap€‹”•–˜—“Œ‚yqmnrz‡Š‹Š‡„€}{zzz|‚„††„‚€~||}~€€®ÍéüïË¡nJAG_€˜¨®¨Ÿ•‰yqmkmtŠ“—•…|ursv{€„†‡‡†…‚€}{zz|~‚ƒ„…„™»ÂÄ¿–wo_aux{ˆŽ’œŸ•‰~phnsv‚‡‡Œ‹‰…|wutv|ƒ‡ˆ††…€}|zy|~€ƒ„„…„˜ºÁý’uobgyyx‚ˆž¤šŠ~nfpuw‚ƒ€ŠŽŠ}utsu~‚€„‡…ˆŠƒ}wv{~„„‚„…¿ÁÀµŠtsjozspy„“¡¦š‰~spwwtvw{ˆ’”’Šyyyyzyw|ƒ‡‹‹†‚€~{xy{ƒ…œ¹¹¹±‘„‚vsoeco€Ž™œ”Š…€tkkow††‡ŠŒŒ…|wvvwwuw{~‚„ƒ‚ƒ„ƒƒ€~}~“ª©¬§˜›ž•Œvsz~{}||…‹‰ˆ…‚ƒ†ƒ€~{{€€~‚ƒ‚€‚~|}~~~}||}~‚Š”˜˜šžŸ¡¡ž›™—–”Œˆ†…„‚€}||}}}|{|}~‚‚‚€€€€€„Œ’—š˜šŸ¢£¡žœš—”’‰‡„‚€~}||||}}~€€‚‚‚‚‚‚‚€€€€€€ƒŠ•›Ÿ¢££¢ œ™•‘І‚€~|{zzz{{|}~€‚‚ƒƒƒƒ‚‚‚‚€€~~~~}}}}}‚„‡Š‹‘“•––——––•”“‘ŽŒŠ‡…ƒ~|zyxwvvuuuvvwwxyz{|}~€‚ƒƒ„„…ˆ‹’“•—˜™šš™™˜—–”’ŽŒ‰‡…ƒ}|{zyyxxxyyyzz{{||}}~~~€€€€€€‚„†ˆŠ‹ŽŽŒ‹‹‰ˆˆ‡†…„„ƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒ„…††‡ˆˆ‰‰‰ŠŠ‰‰‰‰ˆˆ‡‡††……„„ƒƒ‚‚€€€€€€€‚‚ƒƒƒƒƒƒƒƒƒƒƒƒƒƒ‚‚‚‚€€€€€€€€€€€€€€€€‚‚‚ƒ‚‚‚€€€€ƒƒ€~~~}€}~~€‚‚‚‚€€}}‚‚‚‚€~~€}~€ƒƒƒ‚‚€~~€€€‚€€‚‚‚…„ƒ„„„„„ƒ„…ƒ‚„‚‚‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€€‚ƒƒƒƒƒ‚ƒ‚‚ƒƒƒ‚ƒƒ‚ƒ‚‚‚‚‚€€€€€€€…†…ŠŒŒ‘“’‘’Ž‹‰‡„‚€~|{yyxwwwxxyz{|~€‚ƒ„…………………„„ƒ‚‚€~€„ƒ„‰‰‹ŽŽŽŒŠ‰‡…ƒ~}{{zzzzz{|}~€‚ƒƒƒ„ƒƒƒƒ‚‚€€~ƒ‰ˆ’“˜™™œ™™—”’Šˆƒ€~{yxuuvuvwxz{|€ƒ„„…………„ƒƒ€~}~}}~}~‹ŒŽ——œŸ›Ÿž˜˜“Œ†‚|yyvvwuxyy|~‚ƒ„…„„„ƒ‚‚€€~~~~~~~~€€€‚‚‚’Œ–žšŸŸ¢—˜•‰‡‚~|wuwsruuvxz}€‚…‡‡ˆ‰ˆˆ‡……„€€~}||{|{{}}}€Ž•‹–¡›žž›ž˜Ž‡}{{usqputrw|}~†ˆˆˆŠŒŠ‡ˆ‡„~{yz{zy{|}}~‚‚ƒ„……ƒ’›–¥žžšž™ŽŒ‡{y{ussqvxvx~‚‚ƒˆ‰‰‰ˆ‰‰†ƒ‚‚|||{zzz|}}~‚‚‚„„„„‚„ƒƒ—œ‰˜©žœ››•ކ‡‡xszvqqswyyz†…ƒ‰ŒŠ‰ˆˆˆ…€€~zz{{zz{}~~ƒ‚‚„„„ƒ‚ƒ…›ˆ¬Ÿš™œ™Ž‡€pkttomt|}~‡‰‘އ„†„~yxzyttx{{z~ƒ„„…‡‰ˆ……†„€~~zˆŠ¥¦œœŸ˜ˆ‚…}mouqlmuzz}€ˆŽŠŠ‘ˆ‡ˆ„~zyzwstxzyzƒƒƒ…ˆ‰‡††‡„€z~™˜„šª œ›Ÿ“Ž„…xlqusopy~‚ƒŠŠŒŽŒ…‚‚|xvxxwvy}…‡‡††‡‡„‚€|{|{‘¤®¯£Ÿ¢—Œ„z~zhfornku„†‹”“އ€~zursvvuw|‚†‰Š‰ˆˆˆ†‚~{yyz{y¦’“°²§¡¡£˜Ž„x{xgdkomkt‚†ˆŒ••Žˆ€~}yuqruutv|‚ƒ†Š‹Šˆ‰ˆ†‚}zxxyzyŠ®¹«¬ºÆÁ¬¡›‘Ž…rgirtjhu€…‡†‰“”Œ„†‰…}ww{{yxv{‚€‚‡‡„‚‚ƒ„~}}€}{}€€€–¸¼­®¼Æ¼§•Ž‹nejuujkyƒˆˆ†Š”’‰‚†ˆ„|vx{{zww}‚ƒ€ƒˆ‡„ƒ„~|}€||}€€†¦Àµ©²ÂƳ ™’‰yhfpwqhp†‰††Œ’”„‚ˆˆ€xuz|{yvy€ƒ‚€†‰…‚‚„ƒ}|~||´¿®ª¹ÆÁªœ—„peitwlhvƒˆˆ…ˆ“”‹‚…І}vw||yww|‚ƒ€~‚ˆˆ„„„~}}€€}{}€€~€¬½±«¹ÈÄ®¡ž–ކvjiqulfs€…„„‰’“…†Š‡wx}{xww{€‡ˆ„‚‚„„~~}{}~€ˆ¥¼µ«µÅdz¢Ÿ˜ˆzlhouofo~„…„ˆŽ‘“‡…‰ˆxw||ywwz€…ˆ…‚‚„…‚~~€~||€~…žº¸«²Âɸ¤Ÿ™Š}nhmuqgl|„…„‡‘“ˆ…ˆ‰ƒzv{}ywwy~€„ˆ†ƒ‚„…ƒ€~~~||~€€~~‚…›¹»¯³Ä̽©£ž”‹€qhjqpfhwƒ‚†‘’’ˆ‰‹†}wz}yuux{~‚‡‡„‚„†…~}|}€~~€‚…›¹»¯³Ä̾©£Ÿ”‹€qhjqpfgwƒ‚…Ž’’’ˆ‰‹†}wz}yuux{~‚‡‡„‚„†…~||}€~~€‚…›¹»¯³Ä̾©£Ÿ”‹€qhjqpfgvƒ‚†Ž“““‹‹‹‡yy{xttvz{}~€‚†‡†……‡†ƒ€€}|||}~~~‡¡ºµ«²ÂƵ£Ÿš†{ohinmfiw€‚‚†’’’‹‹Š…yz{xutwz{}€ƒ†‡†……†…‚€~}|||}~~~Ѝ¼²«µÄű¡Ÿ˜Ž„xmhjolelyƒ‚‡““‘Œ‹‰…~zzzxvuwz|}~€ƒ…†………†…ƒ€€~}|}}~~~€‚”²¹®«¶Ã¾©™”tljnpkipz‚ƒƒˆŽ’’ދЉˆƒ}zz{yvvx{}~~€ƒ………„……„‚€€~}|}~~~€‡ ·³©¬¹À´£™•‘‰|pjkookks}ƒ„…‰’‘ދЉ‡‚|zzzxvvx{}~ƒ…†…………„‚€~}|}}~~~€£¬§§¬³´¬ —“‘Š}sprspmnt|€€…ŠŽŠˆ‰Šˆƒ}~~|yxz|}}}~ƒƒ‚‚ƒ„„ƒ€€~}}~~~~~€†š§ §«««¤—‘Ž‚vqpopoklt|€‚†‹Š‹ŒŠ…}|||ywwz}€‚…‡‡†………„‚€~}}}|{{|~€€‚”ª¬­®©­°¨œ‹xsy~~„…ƒ‡ŠŠŒŒŠ…ƒ}}~|}~}~€‚ƒ‚‚ƒ€€~€€€€€€€€€€€€€€‹£³ÃÐʾ³¤—‹ƒ}|wty|~„ˆ‡ˆ‰‡…†…~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ”§·ÆËú®£›˜”Œˆ‚‚‚„††„„„‚ƒ„ƒ‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€Š˜§µ¿Á½·³¯®®®­«©§§¦¥¤¢ žœ›™˜˜–•”“’‘ŽŒ‹‹Š‰‰ˆˆ‡‡†††……„„„„ƒƒƒ‚‚‚‚‚‚†“˜ ¡¤§©«®¯¯®¯®®®­¬ª©§¦¥£¢ Ÿœš™˜–•”’‘ŽŒ‹‹Š‰ˆˆ‡‡††……„„„ƒƒƒ‚‚‚‚…‹ŽŽŽŽ‘‘‘‘‘‘‘‘ŽŽŽŽŽŽŒŒŒŒŒŒŒŒ‹‹‹‹‹‹‹‹ŠŠŠŠ‰‰‰‰‰Œ’––——••––˜™™™˜˜———˜˜˜———–––––––••••”””””“““““’’’’’‘‘‘‘‘ŽŽŽŽŽŽ–šš››™™šš›œœ›››››››››šššš™™™™˜˜˜˜—————––––••••”””””““““’’’’’‘‘‘‘‘‘‘—œœ›››œžŸžžœœ››››››ššš™™™™˜˜˜˜————––––•••••””””“““““’’’’’‘‘‘‘‘’—›ž ŸœšššŸŸžœ›ššš›››š™˜™™š››››š™˜—–•””““’ŽŒ‹‰ˆˆ‰ˆˆˆ‡‡‡‡ˆ‰‰‰ˆ†…………………„„ƒ‚ƒƒ„……„ƒƒƒƒƒƒƒ„„„„„„……†††††††††‡‡‡‡‡†…„„…††††…„„……††††††………………†………………†‡‡‡‡†††††††††…„ƒƒ„…††…„ƒƒƒ„„………†……„„„„„…………„ƒ‚€~~€‚€€€€‚‚‚€€€€€€€€€€€~}}~€€~}}}}~~~~~~€‚‚‚‚‚€€€€‚‚ƒƒƒ‚‚‚ƒƒƒƒƒ‚‚‚‚‚‚‚ƒ‚‚‚‚‚‚‚‚ƒ„„„„„„ƒƒƒƒ„„…………„„„„„……†‡ˆˆˆˆ‡††…„„……†……ƒ‚‚‚ƒƒƒ‚‚‚‚‚ƒƒƒ„„…†††………„„„ƒƒ‚€€€~}|||{{{zzzyyyyyyyxxxxxyyzzyxyyzzzzzzz{{{{{{{{{|}}€€‚‚‚€~~~}{z{{}}}|zyyyz{{{zzz{}~}}||}}~~}|||}~~~~}}}~€€€€€€€‚‚‚‚‚‚‚‚‚‚ƒƒ‚‚‚ƒƒ„„…………„„ƒƒƒƒƒƒƒƒ‚‚‚‚‚‚‚€€€€€€€‚‚ƒ‚‚‚‚‚‚ƒƒƒ‚‚‚‚‚‚‚‚‚‚‚‚ƒƒƒ„„„„„„ƒƒƒƒ‚‚‚‚‚‚‚‚‚‚‚ƒƒ„„„ƒƒ‚€‚‚€€€€€€€€€€€€€‚‚‚‚‚‚€€€€‚‚ƒƒƒƒ‚‚‚‚‚‚€~~~~~€~~~~~~~~~~~~€€€€€€€€€€€€€€€€€€‚ƒƒƒƒ‚€€€€€€€€€€€€€~}}}~~~~}||||}}}}}}|}~~~~€€~~~~~~~€€€~}}}~~~~~~~~~€€‚‚ƒƒƒƒ‚‚‚‚‚€€€€‚‚‚‚‚‚‚‚‚ƒƒƒƒ‚‚‚‚‚‚‚‚‚ƒƒ„„ƒƒ‚‚€€€‚‚€€€‚ƒ„ƒƒƒ‚‚‚‚‚‚€€€€€€€€€€€€‚‚ƒƒƒƒ‚‚€€€€€~~~~~~~~~}}}}}}||||}~~~~}||||}~~~~~~€€€‚‚‚‚ƒƒƒƒ‚‚‚‚‚‚‚‚‚‚‚€€€€€~~~~~~~~~}}}}}}~}}||{{|}}}}|}}}~~~~~~~~~~~€€€€€€€€€€€€€€€€€€€‚‚‚‚‚€€~~~~~~}}}}}}}}||||||}|||||}}}}}}}}}||}}~~}}|}}~~~~}}~~~€€€€€€€€€€~~~~~~~~~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚ƒ‚‚‚€€€€€€€~~~~~~€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€†­¶“´©žŽ|zvdZo|vyƒšš’‘”‡wtuspkmw€ƒ‚‡”Ї†„}uruwuuy€…‡†ˆŒ‹‰‚†¬³Œ“ª¡™‰{|}k`uƒ{{Š–•Œ‡“ƒvxyxsnr|~‡Ž‰†‡ˆ„|xz{xux}€ƒˆˆ‡„†©·“˜±§›€€€xecwzrx‚Œ”‘Œ–‘‚|~{vpntz{zˆŒŠ‰Š‹Šƒ}||zuux{}}ƒˆ†‹¨±¤ª²¯ªŸˆŠ€ljonopr|ˆŠ†•“Œ‡‡†}uvyvtux}€†Šˆ††††ƒ~|}~zyzšªœ¢³µ¯¦š““‰qlrojjlu‚„‰••ŽŽ…‚„‚{yyyzzx{€~‚ƒ‚„„ƒ†‡„†‡„ƒƒ‚€€€€~~}|||{|}|}~~~~~}~~€~~ƒ…„†‡†‡‡†…………†„‚‚~|{|zwwxwxy{|}€€‚‚ƒ„‚ƒƒƒ‚ƒ‚‚‚€€€€€€€‚‚‚‚‚‚‚€€€€€€€€‚‚ƒƒ‚‚‚‚‚‚€€€~€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚ƒ€~~~}}}}}~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‡Ž“‘‹ˆ„€~€‚‚ƒ‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‡ŠŒ‰†„ƒ„……„‚€‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~€€€€€€€€€€‚‚‚‚‚€€~~€‚€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~‚}ƒ‚ƒƒƒ€}€‚€~~€~€‚~‚}‚ƒ}ƒƒƒ~€ƒƒ‚~‚ƒƒ€~ƒ‚€€‚‚‚€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€~€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€‚€€€€‚€€€€€€€€€€€€€€€€€€€€€€€~€‚‚‚„„ƒƒ‚‚€~~}}}~~~~~€€€~€€€€€€~€€€‚‚ƒ…„ƒ„…„ƒ€€}}}|||{||||}}~}}~}}|}~~~~€~{z}z¡Ÿ¤­°³¬ —“‹{rnlnllt}„†‹””ŒŠ‡{wvutsuz~€‚…ˆŠ‰‡‡„Œ¡¤ ¨«­ªž•‘urprqpu}„†ˆŒ’Šˆ‡‚}xwwwvvz€ƒ†‡†…††—­ ™°´¦ ˜•”‡vs|xlnx~~€‹‘ЅЉ€~€|uw~yy€…„€†ˆ„~Š«¬–£¸±¥™“˜’|mx}iapustu€Œˆ‚Œ–‡‰Œˆ‚|{€|su|{wy~‚€¯Ÿ“µ¶£¨¡šœ|{€vemvnpvw‚‡†‘ˆ‹Šˆ‡ƒ|wz|zzz}~ƒ“ž˜Ÿ­­ª¦£¤œ‰Šwuuvtqv~~}‚‡ˆ††ˆ‰…ƒƒ}}~~||€œ˜¡¯¯¯­ªª¢–‘‡~}}|{z„‚ƒˆŠ‰‡†ˆ†€‚€}|~~}‚€€‚ƒ›—£²­±²¬¯¥˜˜“‡ƒ‚€€†‰ˆŠ‹‹‰‡„€€€}|}~~‚ƒƒƒ…ƒƒ“œ˜§³±··²µ«Ÿž—Œˆ…ƒ‚‚ƒ‡Š‰ŒŽŠˆ…‚€}|}~~‚ƒƒ„„…”𩵲··³±¨žš“‰ƒƒ€~ƒ…‰ŠŒŽŒŠ‡„~|{|~~‚„„„„…”™©µ²¶·´±¨¢š’ƒ}|‚…†ˆŒŒŒ‹‰‰†‚}||}}}€‚‚‚„…”£Ÿ¨¼½¸¸º¶¨Ÿš’‰€|}z}„‡†ˆŒ‹‹Š…€€€}zz}~|~‚ƒ‚‚„…†—­°­·È˼³·³¢”Š€zyvtw}~|Š‹†‡ŒŒ†„…„€~~~{|~~|~‚‚•®³®¸Ìпµ¹µ¤•Šyxurv~~|‹Œ‡‡‡„†„€}~}{{~~|~‚‚…±¯®½ÎË»·¹®›“‘…vrtnfhoomrz|{€‡‡…ˆ‹Š†‡ˆ†‚‚€}}~}{‚˜®±³ÂÏÍÈÊɾ²­§™ˆ„zsstposwwx}‚‚†‰ˆ†ˆˆ†„„„‚€€€~ƒ—ª«¬¹ÄÁ¾Á¿µ«§ “ˆ„~tnnmiimpquz„ˆŠ‹‹‹‰‰‡„‚}|„™¨¨¬ºÂ¿¾Á½³«§Ÿ’‰„}tonlijnpqu{~€„‡ˆ‰‹‹Š‰ˆ‡…ƒ‚€}~Šž¦¤­º¼¸¹º´ª¦¡—Œ‡ƒ{tsronppruwy|~~€‚€€€‚•¢¢ª¯¬¬«¤™’‹ˆ„}}{{}}~€‚ƒƒƒƒ‚€€€€€€€€€€€…– ¤°¶µ¶µ®¦¢™‹‡~~}€‚‚„†……†…ƒƒƒ€€€€€€€€‰™¢ª¶¹ºº¸°¨¢™‹†€~}~~‚ƒ„……†………„ƒ‚€€€€€‰›§²ÁÈÉËÇÀ¹®¤›ˆ‚{wvtuwx{~€‚„…‡‡‡††„„ƒ€€€€€€€€‹™¥°¼ÁÆÉÄ¿¸®¤›‘Š…}}|~€‚„‡‡ˆ‰ˆ‡†„ƒ‚€€~~€€„‘ž©µ¾ÂÇÇÁ¼´©¡—Žˆƒ~}}}ƒ…‡ˆ‰ŠŠ‰ˆ†„‚€~}|||}~€€‚Š’š¡¡Ÿœ—“‹…€zvttuwy{~€ƒ†‡‰ˆˆ†…ƒ‚€~}||||}}~€‚‚„”› Ÿ™•‘މ„zwuuwxz|„†‡ˆˆ‡†„ƒ€~‚ƒƒƒƒ‚‚‚‚ƒƒ‚ƒƒ„………††‡‡††ƒ‚€€€‚ƒ„ƒ‚€~}}|||zzzxxzy{||}~}€}|zy{{z{yxxwxzyz{yy{y{}|}~}}}}~}~~~~}}~€‚ƒƒ‚‚€€€‚ƒ‚ƒƒ‚‚€€‚‚‚ƒƒ‚ƒƒ‚ƒƒƒ„…„„…„„…„ƒ„ƒƒ„…„…†††‡†††………ƒƒ~}{zyxxwvuttttttsrsrruttvwwxyyzz{{{|||}~}~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€‚‚ƒƒ€€ƒ€„„‚‚ƒ€ƒ‚€€€€€€€€€~€€‚†‹‡Š‘‘““’’ŒŠ†ƒ~{zxvvvuvwxz|}ƒ„†‡‡ˆˆ‡‡†…„‚‚€‡†ƒˆ‹‹ŒŽŽŒ‹‹‰†„ƒ€}{zzxxyyz{|}€‚ƒƒ„„„„ƒƒƒ‚…—š žš—•’ˆ…„€}||{zz|}}~€‚‚‚ƒƒƒ‚ƒƒ‚€€ˆ”™œŸžŸ ™–”‹‡„‚||{{z{|}}€‚‚ƒ„ƒƒƒƒ‚€€~€~‚Œ˜š™œ™›œ•‘‘އ„~ywzywx{|}}ƒ‚‚„……„ƒ„„‚€~~‡Šš˜››™š“‘‘‹†ƒ€|wyzxwy{}}~ƒ‚‚ƒƒƒ‚€~}|}}~}€±œ—­º¯—’šujlokedr~†“™•’“ˆ~zzxrlntwvx~…‰ˆŠ‹˜·³™ µ´†ŒŽxtlls||v€Ž‹†|yywtqsxz~ƒ†‰‹‹ˆˆ…“µ¶¢¢«±¦“Šxyrfciuzy€‰––”‘ˆ~xusrppsw}‚„‡‹Ž‹Š‡† ¹«ž™—‘ކqktvuvy}‡’‹‹‹‰…‚€yuxyyy|€ƒ‡‡……†„‚˜·º²¯ª¦ šzllmlmpuyƒ“’’’Œˆ„{uuuttwz}†ˆ‰‰‰ˆ…„‚ž¹¶®¬¨¤™vljgjry|}…Ž’Žˆ„~yyyww{}„…„……„‚€}…¦»¼¿»«œ•’‡wsohku|€…ŒŽŒ‘‹‡„€{xzywz}~€ƒ……„……‚~†¥¼¼¿º«œ”’‡wsohku}€…‹‰‡Œ‹‡†„zyzyz~ƒƒƒ…„‚€}†¤¸ÀÊ휅{wwojoty„‘‘‘‰†…|{ywwz}‚„„„……ƒ‚‚~}…¢¸ÁÊ|wwpjosyƒ‘‘‘І…}|{yy|~‚…„„…ƒ€}‚œ³¾Í͹¥”soqoow{}†‘“ˆ„{xyyy|„…„……‚€€~}}€•°½Ëоª—…vnponuz|„Œ‘“‘Š„|xyyx{~„††††„€~|}}Ž«¹ÇѬ™ƒqiikkrz{ƒ’•˜–އyttuux}…ˆ‡ˆˆ…€~{{{‡¥·ÄÑȱˆujikkpxz€‹‘”˜—ˆ‚{ttutw|~€„‡ˆˆˆ…€|zz–®¿ÕØÇ·Ÿ€pe]_fms}ˆ–žœš—‹€{rlnprx‚†ŒŒ‹Œ‰„‚~ywzާ¹ÐÚ˽§‡ti__ekpz…Š“œœš™ƒ}umnpqv}„‹Œ‹ŒŠ…‚zw…ž¯ÄØÍ½®Žulb_gnrzƒ‰Ž˜›—˜‘„~wnnqrw}„ˆ‹ŠŠŠ…‚€|x}•«¼ÔÕöœ|oe]ckpv€ˆŒ”›™˜–‰€zqmpqt{€ƒ‡‹‹Š‹‡ƒ}yyŠ£´ËÙ˽ªˆumackns|‡—˜š˜Ž…~tppptz}…‡ˆŠŠˆ†ƒ|zx„ ²ÆØÍ¼«‹skaaios{‚‡Ž–™™˜…~uopqsy~…ˆˆŠŠˆ†ƒ{zx€›¯Á×ÒÀ°‘vlb_fmqx‚†—™˜™„~voprsy€„ˆˆ‰Š‡„ƒ{zzxƒž±ÅÚÒÀ°ulb`ios{ƒ‡Ž˜™˜˜Žƒ~uoqrtz…ˆˆ‰Š‡„ƒ~zzzxƒž±ÅÚÒÀ°ukb`ios{„‡˜™›™‡wuutw|…ˆˆ‰Š†„ƒ}|{y{|‰¥·ËÚ̺¥…qibemqv|ƒˆ™š˜–Š€zrortx}€‚…‡ˆ‰Š‡ƒ}zzyz}ª»ÐÚÈ· ngafnrw~„Š’š™˜”‡yrquvz~€…‡‡‰‰…‚€{z{z}~„ž±¾ÏůŸ„pmklswx{‚…Œ––“‘†}zutxz{~€€‚††‡ˆ„€|{||}€ލµÅϺ¨•ymmjovyy~„‡—”“Ž{xsuzz|‚†…ƒ…‚€|~~~†›ª¸Å¾°¤’ƒzvy{z€…†‹Š‰ˆ‚€€}|}~€€ƒ‚ƒ‚€~€€€€€€„”§µÂÀ´¦•‡{xxzz~ƒ†ŠŒ‹‰‡ƒ€€~}~~~€€€€€€€€€€€€€€€€€‰“›¢¥¤£¢ ž›—•“‘ŽŒ‹Š‰ˆ‡‡†……„„ƒƒƒ‚‚‚‚‚€€€‡‘𡥤££¡Ÿœ˜•“’‘ŽŒŒ‹‹‹‰ŠŠˆ‰ˆ‡ˆ‡‡‡ˆ‡††„„…ƒƒ„‚‚‚‚‚‚‚‚€€€€‚‚€‚€‚‚‚‚ƒ‚ƒƒ‚ƒ‚‚‚‚€€€‚€‚‚€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€~‚~€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€~€‚€€€€€€€‚€€~€€€€€€€€€€~€€€€€€€€€~€~€€€€€€‚€€€€€€€~€€~€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒ‚‚‚‚€€€~€~~}}~~}}}|}~}~~~~~€€€€ƒ„ƒƒ‚‚‚}€€}|}}}}~~€}~~}}|||{z|}|}}~~€‚‚ƒ…†…†‡ˆˆ†„………„‚‚‚€€ƒ‚€„‚‚ƒ€ƒ‚‚ƒƒ‚…€~‚€‚„ƒ€„}€€~€€~€~~‚€€ƒ€‚€„„ƒ…€ƒ€}€€}~~€€€€€€€€€€€€€€ƒˆ“™’‘ŽŒ…~ytxzxy{€ƒ‚ƒ‡‰‡…††ƒ€~{z|}||~€‚„„ƒƒƒƒ€€†ˆ‰–”ŽŠ„€wvzyxz|€‚ƒ‡ˆ……‡…‚€€}{{}|{}€€‚„ƒ‚ƒƒƒ€€—ž®¢žž›˜Ž‚~€wkpurrv}ƒ„„‹‰ŒŒ‡‚}xuxzxx|€ƒ†‡……†…ƒ€€|Š‘–¯«ª¯«°«›™˜Œ€zxsjhjmlks{|…ŒŽ“’‹‹‰ƒ~}|xttvvuw{}}‚†…‰ž —§°©ª¦¤¦˜Žˆ}tsrlhjnoos{…ŠŽ‘‹Šˆ„€~}zwvwvvwy{|~‚„„‡™ž’£¯¢§¨¡¦š•Œ~|yupknpmnsyzy†…‡‰Œ‰‰‹ˆ„ƒƒ}{}|yyz|{{}€‚ƒ‘˜ž«§ª¢«¡—¡–І~vwxrquvtvz|~†……ˆˆˆˆ‡ˆ‡„„ƒ€~~|||}||~|ˆ‘†“ •¢›£—–‰{vwsosqotuvz{~‚ƒ„ˆ‰‰‹ŠŠŠˆ‡†ƒ‚}|{zzyy{yЂЖ˜š¥£Ÿ¨§¢¦¤¡£š—’”Ž‹‹…„„}}~yyyvwwtwwuwxwzyy|||~€‚ƒ†‡‡‹Œ‘‘‘’‘ŽŽŒ‹Š‰ˆ‡‡†…„„ƒƒ‚‚€€€€€€€€€€€€€€€€€€€€ƒ‚ƒ…„…†…††††††††……………„„„ƒƒƒ‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚†‹Ž‘ŽŒŒŠ‰ˆ‰‰‰Š‰‡‡†…ƒ‚‚‚€€€€€‚€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚~€€~‚}ƒ~ƒ~€‚~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ„„…†…‚~||zz~€}}}||}€~~}~€|}}‚„ƒ„…ƒ„ƒ~~|{}~€ƒƒ‚ƒ…„ƒƒ‚ƒ€€}}€‚€‚…‡ˆ……‰‹‰†„†‡†‚€ƒ„‚€„…ƒ„†ˆ‰‹Š‡‰ˆ†„€€~|zyz{{}}}€€€‚ƒ„€}ˆž¢™ «¬©œ“”’‚srtqminz~Š’’ŽŒŽ‰€}}{vrrwzxy~„†††ˆ‹‰„‚ƒ‚~zy{|zy{§¦¢­±±¬“’‹ynmlkiho|‡•–’†~zzwroqw{{~…ŠŒŠŠ‹‹†€}|zwtuy{|~‡ˆ‰¤º«©¸µ«ŸŒwa[gkkqy†•™•™¡‡|vmehoppw‚Š‘••ކ‚zsnnrttx†ŠŠŒŽŽ„”µ¥‘¦¨ ›ˆ}‚ƒpamxuwz€’˜‹•˜‚}z|vjjuzxy€‰Ž‰‹Œ‚|{{xrpt{|{…‰‰†‚‚„~€§¶š¨žšŽtlxzjjzƒ’Š‹˜–†{{yxunp†ƒƒˆŽŠ~wtvz~~‚ˆ‰†„ƒƒ~yz|}}|€‚‡«¾¤£°¤šŒtjsrchy‚Œ’’š‹ƒ{ytlny~}€†ŠŽ†„†ƒ}xvw{|z|‚††…„…†ƒ|}}||{~…¥»©¦®©£–~ouwhfox…‹ƒ†’“Š„„uw‚}ƒ‰…~‚ƒ‚}{ƒ}~€ƒƒ}ƒ}‚‚~}€‚ƒ’¢¥¨¬ªª¦šŠ„…‡……ˆ‰‰†‚‚„‚~€~‚€€€‚‚‚„„„…………ƒƒƒ„„ƒ‚‚ƒ„ƒ€‚€‚‚ƒ‚‚„†………††‡†„„ƒ‚~€~~‚ƒ„„„…„ƒ‚€€~~}|}}}|{||}}}~€€€‚ƒ‚„†„„…ƒ„…‚ƒ„‚„€ƒ€ƒƒ‚‚€€€€€€~~~€€€€€€€€€€€~€~€€~€€€€‚€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€‚‚€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€~~€€€€€€€~~€€~€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~~~~~~}~~}}}}}}}}}}~}~~}~~~~~~~~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~€€€€€€€€€€‚‚ƒ†‡ŠŒ‹‹‹‹Šˆ††‡‡…„ƒ€‚‚ƒ‚‚„†‡‡Š‰‡‡†„„„„††††‡†…†…„‚‚‚„…„‚‚‚‚‚‚‚‚ƒƒ€‚€ƒ‚‚€€ƒƒ‚ƒƒ€€~~~€‚€€~|€€€€€€‚€‚‚‚‚€€€~~}€€€€}}~~~~€€€~}~~€€|‚€~€€~€‚€‚‚‚ƒƒ‚‚‚€}}}~€€ƒ}{{~‚„„~|{€ƒ€€€‚ƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€”³¿µŸ‰~~|ƒŽ——z{~~ƒˆŠ†€||~€€€ƒ„ƒ~}~€€€€‚‚€€€€€€€€–Á¾¡’}tzxol{Ž™“…€{uqrz†‰…ƒ~yvw}‚…†…„„‚{z{~€‚ƒƒƒƒ‚}}}~€‚‚‚‚•¿¼ ‘|t{zpm{˜œ’…|vrt|‡ŽŒ‡ƒ€}yvy…‡†„‚‚~{z|€‚ƒ‚‚‚‚€~}}~€‚~”¿ yr|{rn|‘œœ€{}|wst~Š…}yvy€†ˆ…‚€}{{~ƒƒ‚€~}~€}•¼œzu}{rp€“™—Œ}|wuy‚Šˆƒ€|zy}‚……ƒ‚}|}€‚€~~€€€€~¸½¡“‚|zrp€”“‹ƒƒ|vv{‚‡‡…„„‚|{|‚‚‚‚‚~€€€€€€€€€€€€€€€‹¯»ªšŽ…„xuƒŽˆƒ„„z|€ƒ…„‚ƒ‚~~€€€€€€€€€€€€€€€€€€€€€€€ƒ–«®©¥Ÿš”‰ƒ‹–šš™–•††‰Š‹ŒŒ…~‚ƒ„‡ˆ…€ƒ…„‚€€€~~€‚‚‚€€~‰‹ˆŠŠŠ‹Š‰‰‰ˆˆ‡‡‡†………„„„ƒƒƒƒ‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€ˆŒŠ‹‹‹Œ‹ŠŠŠ‰‰ˆˆˆ‡†††……„„„ƒƒƒƒƒƒƒ‚‚€€€€€€€~~~~~~~€€€€‚‚‚ƒƒƒ‚‚‚ƒ„‚‚ƒƒƒƒ‚‚ƒ„„„„„……„„„„„ƒ‚‚‚‚‚€€€€€€€€€€€€€€€€€€‚‚‚€‚‚‚‚‚‚€€€€€€€€€‚‚‚€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€‚€€‚€~€‚€€€€€€€‚€€€€‚€‚€‚‚€~€‚€€‚€‚€‚€€€€~~~~~~}}~~~~}}€|€€|€€~~€€~€~€~€~€€~€}‚}ƒ}‚~€‚ƒ~~€€€~~ƒ}ƒ{€‚}€‚}ƒ€|€€€}‚~€€~ƒ|ƒ~~‚}ƒ}‚ƒ~~„~}„~ƒ‚|‚ƒ{ƒ}€€€€€~€~‚€€€€‚~€ƒ|€ƒ€‚€€€‚~€~€€|‚}~€~‚€€‚€€}€€‚€€€~€‚€}ƒ€€€ƒ~€€~~ƒ~}ƒ‚ƒ~…‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‡‘“—œœ™“‘‡„‚~}~}}€€€‚ƒ‚ƒ„‚‚ƒ€€€€€€€€€€€€€€€€€€€€€Š£¥ž¡ž¡˜…z|xuslkw‚ƒ†‰”އ…„‚€zttyzz{|€†ˆ†…†††„€|}~}{zz}€€€ƒ„„ƒš¨¡¢¢Ÿ¥¤•‡…ƒ}|vms{{{x|……||{}~~~€ƒƒ‚~€€€€~€‚€€€€€€€²ÐãèÖ¶š†vle[TZj˜«±¬¤™…{nc]]etƒ–™˜•“„zqjhlrz‡‹Žˆztrqsvy~‚¬Ïäîäǧ|k_TJL\u¨µµ°©ž‘ƒq_SPVew†‘š £¢’‚sg``eks}†˜œ›–ƒyrmkkmsz„ŸÇãóóÛ¹›„o^QFBPh…¢¶¼¹²§™ŠwbRKKTcs‚𢧧¢—Š{neaadjq{…–šš—ˆ€ysnllot‡§¾ËÑůŸui\ST]l› £¢Ÿš‘…wlcadjqz‚‰–˜˜“Œƒ{uqnnpsx~…ŠŽ‰…€{wtss~™®´¸¶¥˜”Š|qg][dp{†–˜œ™‡|qkjikpv}„’””’Œ†€zuqpprw|‚‡‹Ž‹ˆ…‚}{zy–¸ÓßÚÍĽ³§™ƒyojjnsvy~ƒˆ‹ŒŒŠ‡„‚€~|{{{|}~€‚‚‚‚‚€€€€€€…š¹ÒÜÖʽ´¨›‘‰sjimrstx„‡ˆŠŽ‰†…„‚||||{{|~€€‚ƒ‚‚‚‚‚€€€€€€€†žÄßäØÉÃÀ´¡vi]Y_ioqv”––˜˜•†‚€{uqqtvvx|„…†ˆ‰‰‡„ƒ‚€~|{||||}‚‰¢ÆàåÙɾ³ Žti`ajqrt}š››œš“Š„€yojlqsrszƒˆŠ‹‘މ††„~wuwxwux|€‚…‰‰‡·åñÙ¹®»Á«Šsf[SSapkg^AG`€˜¢››¡œ˜“~k_RTev‹Ÿ¤¢œŽ‚|tqroosv}ˆ•˜“ŠwopoyŸÃÚôíÆ£tG>@Jj‚Žž¦¥¤{j_\ao‹”˜–‘‹ƒ{tpnqw~…‹Ž‰…€|ywxx}~¾×Ðͳ}b^W^t€„™Ÿ—„vmefr|ƒ‹ŽŒŒˆ}xtsv{€…‰‰ˆ†ƒ€~|zz{~~޼ÒÎÒºŒwl_alsx€Ž—š Žƒ{plpsw}„ˆ‹ŽŒˆ…zxxxz|ƒ…††…ƒ~~{ˆ³ÉÇË·‘~wrrstpmy‡œ ™Ž†ƒ€~vrsw}…‰‰…‚‚‚„†„€|yy{ƒ‚€~€¸ÍÌ̸™†€ƒ‚{xlajy‡”˜–Ž†ŠŽŠ€wrv{~€|{|†ˆˆ…€€‚‚|{~~‹¬¾ÂĹ©œ•˜’‡€shioy€‚…ƒ†‹Ž‹†€{}~€~{yy}€‚ƒ‚€€ƒ……„‚€€€‡—¤¨ª¨¤ Ÿ¢ ™‡~zy{zwusrv{€ƒƒƒ‚ƒ…ˆŠˆ†ƒ€€}{{|~€€~‚ˆ™¥ª­«¦¡ ¢Ÿ˜‡~yvuspnlknqux{}„‡‰ŠŠŠ‰ˆˆ‡…„‚€~}}||{{{{|}€‰– ©¯±±±²²°«¤œ”‡‚|wsomlmnprux{~„‡ˆŠŠŠ‹Š‰ˆ†„ƒ€~}|{{{{{Š– ©­¯¯®­©¥ ™’Œ†|xtrpppprtvx{}ƒ…†‡‡‡‡††…„ƒ‚€~~}}}}€‡—ž¥ª­°±±¯­©¤ž˜“‡‚~zwutsstuvxz|~€‚„…‡ˆ‰‰ŠŠŠŠŠ‰‰ˆ‡†…„ƒƒ„†‰Œ’•—™›œœœœ›™˜–”‘‹ˆ†„‚€~||{zzzzzzz{{||}}~~~€€€‚„†ˆŠ‹ŒŽŽŽŽŽŽŒŒ‹‹ŠŠ‰ˆˆ‡‡††……„„„ƒƒƒƒ‚‚‚‚‚‚€‚‚ƒƒ‚‚‚‚ƒ‚}|~‚‚€~~€‚‚‚ƒƒ‚€~€€~}~€€}~~}~€€€€€€~€}}€€€‚€‚€€‚‚€‚‚€€€‚€€€~€€€€€€€€€€~‚‚‚€€€€€€€€€€€~€€€€€€€€€~€‚€€€€€€€€€€€€€€€€€€€€€~‚~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€‚€€€€€€€€€€€‚€€~€€€€€€‚€€‚€€€€€€€€€~€€€€~€€€€~€€€€€€€€€€€€€€€€€€‚‚€~€€€€~€~€€~€€€~€€€€€‚‚‚€€‚‚€€‚€‚€‚‚‚‚‚€€€€€€~€€‚€€€€‚€€€‚‚ƒ‚€€€‚„ƒ‚€~€‚‚€‚‚€€~~€€‚€€‚ƒ‚€~}~~~‚‚‚€}~€€~~€‚‚‚~~~€‚ƒƒ‚‚‚‚~}{|€‚‚€€€€€€„ž½ÍÔÊ«Ž{ooy…Ž”˜–‘Œ„|yxz~ƒ‡ˆˆ†ƒ€~}}~‚ƒƒ‚€€€€€€€„ž¾ÍÔÊ«Ž{onv|…‹‘—š–‹uoqx…ˆˆ‡†…„‚~{xy|€„†…„‚€~~~€ƒƒ~Š´ÍÌÈ¥t`[av‰ŽŒ‹”•Š{qilx„ŒŽ‹…|yz}…ˆ†ƒ€}|}~€€€‚‚‚~~~œÆÎͼŠg[VgŒ“•“’ކ{rlmvŠŠ„|{zz{}ƒ†‡†ƒ€}{|}‚ƒƒ‚€~~~~€¹ÎȺiabq‚Œ“–š˜Žƒtkmu€‹ŽŽ‹†|yww|†‰ˆ…~|{|}‚ƒ„„‚€~}}~‚‚‚~‹¹Îóˆfciw‚‰Ž‘š›ƒsjnx‚‰‹‹‰‡„~yvv{†ˆ‡„~|||~ƒ„„‚€~~~~‚ƒ‚€~”Ä˸¢zgnwzx‚‹–¤›‡ynov}€€‡Œƒzvw|}~€‚‡‰†‚}{|}~„…„~}~€ƒ‚‚€ªÏ»Ÿ‡or}~pl‚“ £|‚}qls~‘ˆ„†ˆ„{try‚ƒ‚‚…ˆ‡‚|y{~~~~…†„€~~}}ƒ„€—žœ‚}}vkd|–—•Žˆ‹ˆ|niu~€„‹†}{|zww{‚†‡………ƒ€|z{}~€ƒ……ƒ~}}}€€‰´Æ¤‘‘ƒmhgq‡‰‹–›Ž€xtuvvw}ˆŠˆˆˆƒ|xxz{{~‚†‡…„ƒ‚|{|}~ƒ„ƒ‚€€~}~~À¬’—ž—xgmt{zy†“™‘†‡‡€vpt{~€†Œ‹†‚€|yx{€ƒ…††ƒ€€~||}€€€ƒƒƒ€‚Œ²®”™ žŽwrv~ylvˆ‘„ˆ„wxwsz…‡‚„‹ˆz~‚€yx~„ƒ~~ƒ‡„~}ƒ{|€ƒ€}€‚…€…­·š•ž•‚sq~€ml|ˆ‰‚€ˆ‘€z‚‡wu}„‚zzƒ‰…~}„‡‚{z„z|‚…|~ƒ…€|~ƒƒ|}ƒƒŸ´¡ž¥¥ ‘ƒ{‚smw€…€††„‡ƒ|w{€{z€†…€~ƒ†ƒ~|€ƒ~|‚ƒ€}ƒƒ€~‚‚~~‚–¬¢›¤©§œ”‰…‹‚tsy~|{|~‡‹„…Ї‚€~€ƒz{€‚~~„ƒ„~~€€€‚€€‘£¡Ÿ¡¦¬©¤™‘Œ„{rrqrqmpv{€€ƒ‡ŠŽ‹Š‰Š‡ƒ€}}|zywxz{~~‚ƒ††…†…†…ƒ‚€~}|{z}‰œ¯Àŧxkfglrw}†˜ŸŸ˜~rjghkotz‰‘––“Œ„|vrqqruy~„ŠŽŽŠ†|ywuuwy}…‰”¢­¶¶¬žŽtlfb`afnx‚‹’–˜˜•‘‹…~xspooruz~ƒ‡ŠŒŒŒŠ‡„€}zxwwxz|~€ƒ„†††…„ƒ€‡Ž–œ›˜”‹†€{wtstvy}€„ˆŠŽŽ‹‰†ƒ€}{yxwwxy{}‚„…††††…„‚€}}||||}~~‚…ŠŽ’•———•’‹‡‚~{xvuuuwy{~€ƒ…‡ˆ‰‰ˆ‡†„‚€}|{zz{{|}€‚ƒƒ„„„„…„„„„„„„ƒƒƒƒƒƒƒƒƒƒƒƒƒƒ‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ‚‚€‚€ƒ€‚€‚€€€€€€€€€~€~‚€‚„~€~‚€}‚€}€€€€~€€€€€~‚~‚‚€ƒ‚ƒ€‚~~‚|€~~€€€~€}‚€~~~€€€~~}€‚€ƒ}‚‚~€}‚‚~‚€‚‚‚‚€„‚€‚}‚~~„€~‚€ƒ~€ƒ}}€~}~€€€€€~~~~~~€}‚~€€ƒ‚‚ƒ‚ƒ‹”—™˜——š™”‘‘ˆ…‚‚{xxxwutuwwwxz|}~ƒ„„„†‡‡†…††…ƒƒ‚‚~}||}}}|}~~†ŒŠŒ’—˜˜™™œœ—”””‹ˆ…„|yz{zxy|€ƒ……„ƒ„…ƒ€€€~}~~~~€€€€‚‚€¯§”¤¶¶§š–Ž}u}~tjly|wv{„Їƒ…Œ‰‚ƒ††€{{~|xy~~|~ƒ…ƒ€„†ƒ€€‚ƒ€}}€}}€‚€•° ”ª¸´¤œ£Ÿ–€ysilzzqry‚†ƒ„Œ‰‚…‹‰‚|~‚|xy~€|y|‚„€~€„†‚€„„}~€}}€—²¥˜«·µ¨››—“Žyoz}ulky}}{‚ކƒ†Ž‹‚‚„|wy~}x|ƒ‚~ƒ†„€~‚„‚~|‚~|~‚~~„ ´ ™­¹´¡šž—“‹yv}~vkq~}{{}…‰ˆ…‚ˆ†€‚„€|||{{~‚~‚ƒ€‚‚~€~€€€~€€†¢¬™ ±³® Ÿ˜’„y€upow{vx{ˆ„‚‡ŠŒ‡‚…†„|}€~|z|€~}~‚‚€‚ƒƒ€€‚~€€~~€€€~‰¨©—¡¯³®Ÿ›š™—‚v~zpkv{{yu‰‡„†ŽŠ„‚ˆ…}{|zy|€‚}{ƒ…€~„„}€ƒ‚€|~|€‹¦¥•£¯±ª›˜”y€xomwzywwˆ‡……Œ‰†ˆŠ…|}|xwy|{zz~‚‚„††„ƒ„…ƒ€€|}|ƒ–˜— §¤››šš”‡€~zpnqstqry~‚ˆŒ‹‰‹‹‰…€~zyyyzxxyz|z|‚ƒƒ„„†…„ˆ†„„‚‚‚‚}€}€€„ƒ„…‚…‡‡†††…‰‡ƒ…„‚ƒƒ€„…„„†……††……„~|zwvurponlllmnnomnqnppppprqrrrtqtsststsuttututvwuvwvvwwwyxyyx|yz{x€~~yzzzzxywyxvyuxxwxvywxywywyzwywzxx{y{xz{y}y{||||~|~~~~€~€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€‚€€€€€€€€~€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€‚€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€~‚€€€€€€€€€€€€€€€€€€€€€€€‚€‚~€‚€€‚~€~‚€€€‚~€~ƒ~‚}‚‚~€€€‚€€€€€€€€€€€€€€€€€€~‚€€€€~‚‚‚€€€€€€€~~€€€€€€€€€€€€€€€€€€€€€€‚€‚~€€€€€€€€€€€€~€‚~€~€€€€€€€€€€‚€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€‚€€€€‚€€‚€€‚€€€€€€€€€€€€€€€€€€€€~~€‚ƒƒƒƒ‚ƒƒ‚€€}~€€€‚‚‚ƒƒ„ƒ‚‚‚€€€~}}}~}{}}|}}~€€‚€€~~€~€~~‚€‚ƒƒ‚€‚€‚‰ˆ ·°®´·¶¨™‹…sjkmqoq{†ŒŒŽ“–”‡†ƒ}vstuuux~‚„…‡Š‹ˆ†„ƒ}{z{zzz|€‚„˜«¨ª²´´«›’ކvmklnmox‚ˆŠ’•”Šˆ…xttusrv{~~…ˆˆ††‡†‚}zz|}}}~‚‚•¯¥Ÿµ¹¬¥œ–”ˆupxuiku|Œ“‡ŒŠ‚~€|tu|~yy„„†‰„€„‚}{~€~{|€‚~‹«ªœ­¹°©ž”–Œumuoaakmpsv‚Œˆˆ’–ŒŒˆ‚|{}wruywwz~‚‚„ˆˆ……‡…‚€€€~}z…¢™ˆª´ž¤¤Ÿ”ƒ‚†|joypmuu}ƒ~‚Žˆ‰ŽŒ‡…ƒ‚{w{|ww{}}~ƒ†ƒ„ˆ†…„ƒ„~’‘ƒ™ ’š˜•šƒ‹†wxystrpz{v…ƒ†‰‰‹†‰‰‚€€}|ywyzwy}}‚…†„†‡…„ƒ‚‚~Š˜‡¡–•š’—”„…Š}uzutvpv~xyƒƒƒ††‰Š„…‰„€€~{||{~€‚ƒ€ƒ‚‚€ƒ‘“’£¤¦£¥¥œ•”†~|zutyywz‚‚…ˆ‡…‡‡…ƒ‚‚~}~~||~~~~€‚‚‚Š—Ÿ¤¢¢¤Ÿš—“ˆƒ}xvwvvwy|}„……†‡‡†……„‚€~}}}}}}~€€€‚€ƒ’œŸ£¥¢¥¤™–‘‹…€~{vvvvvwz}~ƒ……‡‡‡ˆ††…ƒ‚~~|||{||}~~€‚ƒ‰•›™ŸžœŸš–•Ї‚}|wuvstvux{|‚ƒ…‡‡‰ˆ‡ˆ†…„‚€~}|{{|{|}}~€ƒ‚…ššœŸžžœ™—”Œ‹…ƒƒ~‚‚ƒ„ƒ„„ƒƒ‚‚‚€€€€€€€€€€€€€€€‡ŒŠ–šš£¤¥¨¥¤£žš˜“Œ‡„„€€€‚ƒƒ„…„……ƒ„ƒ‚€€€€€€€€€€‡ŒŠ•››¥¨©®­¬¬¨¤¢—•ŒŒ‡†‡…†‡†ˆ‰‰Š‹ŠŠŠˆˆ‡……„‚‚€€€€€€‚‚‚‚‚‚€‡ŒŠ•œ›¥¨©®­¬­¨¤£œ˜–މ‹ŠŠŽ“”•˜——˜–•”ŠŠ‡††…………†ˆˆ‰ŠŠ‹‹‹‹Š‰ˆˆŒŽ–šŸ¥¨®²²µ¶´²¯¬¨£Ÿ˜•”’’‘’”•–˜š›œœœœš˜—”’Ž‹‰‰‰ˆ‰‰ŠŠ‹ŒŽŽŽŽŽŽ‘‘”˜šž¡¤§©ª¬­¬¬«©§¤¢Ÿœ™—•“’ŽŽŽŽŒŒ‹Š‰ˆˆ‡††…………………„…„…ˆ‹Œ‘•™œ ¤§¨ª««ª©§¥£ š—•’‹‰†„ƒ‚€€~~}|}}|}}|~~~€‚ƒƒƒ„„ƒ„„ƒƒ‚‚‚€€€€~~}|||{{zzyyyxyxxxxyyyzzz|||}~~€‚‚‚‚‚€€€~~~~~~~~}~~}~~~~~~€€€‚€‚ƒ‚ƒ‚€‚€‚€€€€€‚‚‚‚‚€‚‚‚‚‚€€€€€€€€€€€€€€€€‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€~€€€‚‚‚‚‚€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€~~~~~~~~~~~~~~~~~~~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚ƒƒ„„„„„„„„„„ƒƒ‚€€~~~}}}}}}}}}}}~~~€€‚‚ƒ„„„……††††‡‡‡‡††††………„„„ƒƒƒ„„„„„„„„„„„„ƒƒ‚‚‚‚‚‚‚‚‚‚‚‚€€~~}}}|||||||||||}}~~€‚ƒ„……††‡‡‡‡‡††……„„„ƒƒƒƒƒƒƒƒƒ‚‚‚‚€€~|{ywvtqonnnqtw{€ƒ…ˆ‰‡…‚}zxwxyy{{{{zxwvvx{„‰Ž‘“’‰†„ƒ„…†‡‡†„}xtqnmnoqtwz|€ƒ…ˆŒ’“”–˜š››š˜“Žˆztoljijkmpsvy|~€€€€~}||{{{|}}~€€€€€€€€€€€€€€€€ˆ•¦¸ÇÓÛáâàÙÏõ¨›‡€|zz}€„‰Œ‘’‘Ї„~}|{{|}€‚ƒ„„ƒƒ‚€€~‹š«ÀÑÜãåáÚд¥—Š{xx{ƒˆŒ’’‘Œˆ…~|{z{|}‚ƒ„„ƒƒ‚~~~~~€‚Ž¢µÌáêíéÜ̺¥’ƒvnlot}‡—œžœ™“Œ…~xusrtvy|‚„‡‰Š‹‹‰‡„~{yxxyz|~‚…“©¾Úñ÷õèȧ‡gRIFKU`js|ƒ‹–Ÿ¦¬­¨Ÿ’ƒuia^`djry…‰Œ’““‘Œ†€yspoquz„†Š³ÇâñêÝÁ–sWB?HVhz†Œ’–˜££¡›~obZ[`jx„Œ’”’Ž‹ˆ‡ƒzupoorx…Š‹ˆ…ƒ—«ÀÛåÞÑ´Žr[LNXdr~„‡‹Ž‘˜žŸŸ—‰|oebfoz†Ž’”’І}zvtssv{‡ŒŽ‹†}yxv€š­ÁÙÓÁ°ŠhYLK[ky‹•˜œŸ›˜–Œwjaadky†˜›—’Œƒ|wsrvy†‰‹Œ‰„€|yyy{ƒ……„–¶ÍæðÕ²ŠYEHRr’ ¬¬ž”‹zwpoqs{…“•ˆ€xssuy‚„††……ƒ€}|{|}ƒ„„‚‚€}ˆ§½Òâϲ—veimu„€ƒ“Šˆˆ†„……€€~|€~|‚}~~ƒ‚~‚„‚~€ƒƒ‚€€~€€€~~~€€~~}€~~}~€~€€‚‚‚‚€€€€€€€€€€€€‚€€€€€€€€‚‚‚‚€€€€€€€€€€€€€€€€€‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~~€}|}~~~€~}~€~€€€€€€€€€€~€€~€~€~~€~€‚€~€€€~~‚~‚€€ƒ~~ƒ‚~€€ƒ‚~€„~‚€~€ƒ~ƒ€€€€€€~€~€€€€€€€€~€€€~€‚€‚‚‚‚€€€€~~}€}|~€€‚€€ƒšª§¨¯²­¢•Œˆ‚upswyz~„ŠŒŠŠ‹‹†~}{yz}€‚„„„ƒ‚‚~~~~~€€€‚€€€€~ˆ¡«§ª²³«Ÿ“‹ˆsptxyz†ŒŒŠ‹ŒŠ…€~~|zxz~€‚…‡‡†„ƒ‚€}{{|||}‚ƒƒ„„„ƒ€}|}}˜µ¥œ­®¥—„wyve]it{€„Ž›ž–Œ‚womopnr|…ŠŒŽ‘’އ~zvrquz}„‰ŒŒ‰‡…ƒ~zwwyx{|‰·Ã¥®½®£qltiU\r}‡ŽŽ›ª Ž‰‡~tjbittsŒ“•‘ŽŽƒwrrqqps|…ˆ‰Œ‹…|zvrsv{~€„ˆªÉ­¡µ©œ‘rclm_Zl}†’’”£¥•‰ƒ~wnfcmutxƒŒ’“ŒŽ‹ywuutru}‚ƒ…ˆ‹‹‰„zxxy{}{†¨±£ª¯¬«›„}xgdgmy|x„”—”‘†xuxvrpqy‚€…‹Œˆ„„…ywyzzyy~ƒ„ƒ„†‡‡…~|œ”’™˜ž‘†‡ˆztpt{xtx„ˆ‡„ˆŒ‡ƒ‚‚~ywz||{z}‚„ƒ‚ƒ…†…€‚€}||~~}~€‚‚€Œ¡“› –‡‡‹…}ysu}{vx}††ƒ‰‰†„„‚}{|~~||€‚€€ƒ„€€~€€~€˜’’””˜–Œ…††~xuz}{y{~‚…ƒ„‡†…‚€‚€}}}~~}}€€€€€€€€€€€€€ˆ’‘•‰ˆˆ‡‡ƒ~~€~}~‚€ƒ‚€‚€€€€€€€€€~|~~~€‚‚‚€‚€€‚‚‚ƒ„„„„ƒƒƒƒƒƒ€€€€ƒ„ƒ„††††„„„„ƒ‚‚‚‚ƒ‚€€€€€€€€€€€€€€€€€€€‚ƒ‚ƒ‚ƒ……††‡‡‡‡‡‡†††………†…„ƒƒƒ‚‚€€‚‚ƒ„„…††……„ƒƒ‚~~}|}}||{{|{{|z{|{{||}~~~€€€€€€€€€‚‚‚ƒƒƒƒƒ„„„„„„„ƒƒƒƒƒ‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€‚‚‚ƒƒƒƒƒƒƒƒƒƒ‚‚‚‚‚‚‚€€€€€€€€€€€€€€…‡‡‡‡ˆˆˆˆ‡‡‡††………„„ƒƒ‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€†ŒŠ…ƒƒ„„‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Š—›œ—–”‘‡‚€~~~~€‚ƒƒƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚˜­±·°¢¡ –Œ~okptuyy|‡‘’‡‡‡„€{uv{}~€†ŠŒ‹ˆ„~}{zyxxz~ƒ„…„„ƒƒ€~}|}„œ¦¬¬§ ™‘‰yroosx…‰ŽŒŠ‡…„ƒ‚‚‚ƒƒ„„„„„ƒƒ‚‚‚€€€€€€€€€‚„…‡‰ŠŠ‹ŠŠ‰ˆ‡††………„„„„„„ƒƒƒƒƒ‚‚‚‚€€€€€~~~~~~~~~~~~~~~~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ†‡ˆ‡…ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ…‡ˆ‡…ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒ„„ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~€€€€~€‚ƒ„ƒ‚‚‚~~~~|}~~~~€€€~€~}}€€€€~€€€‚ƒ‚€‚~€€‚‚~ƒƒ€€‚ƒ€€€‚‚~~~€}~~€~€€€€‚‚}}~€€}|}€€}~€‚‚€€€€€€€€€€}‚……„‚~|~€€~~„…„€|{~‚€€€ƒƒ€~~‚‚€€‚ƒ‚~‚‚€~‚‚ƒ‚€€€€€€€~}}}~€~||}~€|{|~€€}}~€€€€~{ywvvvvvtsrsuwvuuvvwxy{}~~€‚ƒƒƒƒ‚€€}{zzzyvvvwvtstuvvwxyzzxwxzyvtuvvwyzz{|~€€ƒƒ‚‚…‡‡†ˆ‰‰ˆ†………„„……‚}yy|~~ƒ„ƒ‚€~~~€‚€€€€€ƒ’¼ðÿÿòÇ©¤ ’tWHLZixˆ—¢¦¥¤¥¤ ™‘‹‡ƒ€|{{{||}ƒ„„„……„ƒ‚‚€†œ¹ÐÙÓȽ·¬…|tokloruy}‚‡ŠŒŒŒŒŠˆ…ƒ~|{{{|}~€‚‚ƒƒƒ‚‚€€ƒ–¸ØçáÑÅÁ»­˜ƒume_]ajsy‡—™˜–“Œ…zwutssvz}‚„‡ˆˆ‡†…„‚€~}|…ŸÄßæÛÌÅÁ¸§‘~skc^]cmuz‰’˜™—•’Šƒ}yvsqrtx{~…ˆ‹‹Š‰ˆ‡…~|{}’¿åîÜÀ´»º©sd^VRYeqwzƒ”£¨¤œ—•…zsomhgksz~…Œ‘’‹‰„zxwvy•ÆéíØ¾¸À¼§‰pd\TQZbis€šš˜˜“Œƒ}xtnnrvy}†‰‰‰‰‡„~}{zz{|~‹·äíÝÊ»²¡ŒvcX[hw~‚•—™™–‘†}zxtrsvz|€…ˆˆˆˆ‡…‚|yxz|~€ƒƒ’¿ÛÔμ–€zvqgcfiwžŸ™‰…zqmmov‡‰‹‹Š‰‡…zxvvy}€ƒ…††……Œ·ÓÎʺ—‚}{wvzwxˆ•˜ Ÿ…~urtuuy€…‰‹‡‚{xxww{~€„ˆˆ‡†ƒ}{zy‹·ËÌÒ·‹|n^bjjp~˜¢©¡‘‡xiknmvˆ’‘ˆ}vtqsz}€†ˆ‡‰‰…~ywx‚¦ÅÏÕÁ–{i[bosw†Žœ§£—‰uffkp|ƒƒ‡Œ‘‹zsnqx|‚‡‡‡ˆ‡…„|yxv‚¥ÀÏÛÉ¡‡mY^hkuƒŒ›¢¢ ’}pidju{‰‹Œ‘‹‡€uqqrwƒ†‰‰‡‡…~{xv~™·Íãáȯ‘reb`fpu|‰•›¢£™Ž„vlmmow}€†ŒŒŽŠƒ€{uvww{€ƒ‡†…†„€…µÇÜÚÀªpffdjuy~Š”˜ž –‹ƒvmopotwtv{}ŠŒ‹…ƒƒ~}yzzx{~‚“©¶ÄÌ÷¬œ‰‚ysnfchmt€ˆ‹‘ŽŠˆ„|ywttxyz}‚……‡ˆ†„ƒ~~|”¤±ÃƼ´¨—‹ƒ|vnfbbcfkoqtwx|€‚„††……„„ƒƒ‚€€~~~€€‚™¢­³²°­¨¥£ ›–Š„}}}|{{{|~€‚‚‚‚‚‚‚‚‚€€€€€€€€€€€€€„𤝲°®«¨©ª¨¥Ÿ˜‘ŒŠ‰‰‰†ƒ~‚ƒ‚€‚ƒ‚€€€€€ƒŠ“©°´¶µ³³³²°¬¦Ÿ™”‘Ž‹ˆ†ƒ€‚‚‚‚€€‚‚‚€€‚€€€€…Š˜Ÿ£§©ªª¬¬¬«©¥¡˜”‘І‚|yxvvuuuuuvwyz|}~€‚ƒƒ„„„„„„„„ˆŽ”›¡¥§©©ª«¬«ª§£Ÿ›–“Œˆ…‚~|zyxwvvvvwxyz{|}~€‚ƒƒ„„„„„„„ƒ…‰“˜œŸ¢¤¦¨©ª©¨¥¢Ÿœ™•’ŽŠ†ƒ€}{ywvutttuuvwxy{|~€‚ƒ„„……………†ŠŽŽŽŽŽŽŒŒ‹‹Š‰‰ˆˆ‡‡††………„„„ƒƒƒƒ‚‚‚‚‚€€€€€€€€€„ˆŠŠŠŠ‹‹‹‹ŠŠŠ‰‰ˆˆ‡‡‡††………„„„ƒƒƒƒ‚‚‚‚‚‚€€€€€€€€€€ƒˆŠ‰‹‹Š‰ŠŠ‰‰‰ˆ‡‡‡†………„„„ƒƒƒƒ‚‚‚‚‚€€€€€€€€€€€€€€€†Š‰Š‹Š‰ŠŠŠ‰‰ˆ‡‡‡†………„„„„ƒƒƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€‹£«·³¯±¦œ—Œ„zxwx{|„„†‰‡‡‡…„‚€~~~}~‚ƒƒƒƒ‚‚€€~~~~~‰¡¬¸Å¶®¬š—”ƒxl`^aipz‚‹‘’›˜‘…~|vqmifhmpuz|‚‡‹‘ŽŒŠ‡…€|yvtuuw†”ž«­©­¬ªª¡“‡}tpmfbaafpw}ƒˆ”™›š—‘ŽŠ…€zsomlnpqtx|‡ŠŒŽŽŽŽŠ‡‚„•™ž—”˜———…}z{ysrtw~ƒ„„……ˆŠˆ…~|}}|{zz}€‚ƒƒ‚ƒ„„ƒ‚~~~~~}~€€‡š¥ª®¥œ›—‘‹~qmnpuxwz‡Ž’‹‰‡†…€zwuvz||}~€…ˆˆ‡…‚‚‚}{z|~‚„‚‡ž¯´¸ª—“Œƒ~qddmwƒ‹ŠŒ’”–“ˆ|wssvutw}ƒ‹ŽŒ‰‡„ƒ|xvvy}‚„†ˆˆ…‚}}}||{…¢´¹¼«–•Ž}uj\`nw‹Œ–˜’Žƒustrtwv{…ŠŽŠ„„‚~|yuv{~„ƒ„†‡†„€}{|}~€ƒ„ˆ ½ÎÓʱ˜„wmhgkt„•£««¥šŽƒxpjhioyƒŒ“••‘Œ…~xsqqsx}ƒˆ‹Œ‹‰†‚~zxwwxz|}‚„…‰–§°·¹°£š‘‡€{rkhikr{‡Œ‘’Œˆƒ|yvttuwx{‚„‡ˆˆˆ‡…ƒ}|{zz{|~€‚ƒ„„„„ƒ‡–¥®¶¹±¨£œ•‘‹uoifjorv{~‚‡Œ‘’ŒŠ†‚€}zxvuuwy{}€‚ƒ…†‡‡‡†„‚~}|||||}~‡š©²¼½´¬§Ÿ—’‰}slechlpu{~ƒ‰Ž‘””‘Ž‹‡ƒ€}ywuttvxy|~€‚„…†‡‡†…„‚€~}|||}}~ˆ™¦°¹¹²­©¢œ˜ƒzsmkmnosvx}ƒ‡ŠŽŒ‹‰‡…‚}{yxyyz{}~‚ƒ„„„„ƒ‚€€~~}~~~~‚Ÿª´¹´«¥”‹‚ysmikosx}€ƒ‡ŠŒŽ‹ˆ„}{zyxxz{}‚ƒ„„„„„ƒƒ‚€~}}}}~~€Šš§±¹¸±¬¦ž™”‹xqjikmptx{„ˆŒ‹‡…ƒ€}{yxxyz{}€‚ƒ„……„ƒ‚€€~~~}}~~€€ˆ™§°¹¹°¨¢™“ˆ}umfehmrx~ƒ‡Œ‘‘ŽŠ‡…‚€~}|{{|||}~€‚‚‚‚‚€€€€€€‚Š‘–¢£¤¦¥£¡ ™—”Œ‰†…„‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚…†ˆŠŒŽŒ‹‹Š‰ˆˆ‡‡‡†………„„„„ƒƒƒ‚‚‚‚‚‚€€€€€€€€€€€€€€€„†ˆŠŒŽŽŒ‹‹‰‡†…ƒ‚€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚ƒ„…††‡‡‡‡‡†……„ƒƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‹Š”˜˜œž¡š›™“‘‰‡‚}}zvutttstwxx{}~€ƒ…††‡‡‡‡††…„ƒ‚€~~}}|}||†‹‡——œœ¢ œ›–’‹‡ƒ}{zustrsttwyz}€‚„†‡ˆ‰‰‰‰ˆ‡†„ƒ€~}|{{zz{{||‚‹Žœ›ž£Ÿ¤¤››•ŽŠ†~ytvsorssvwz}€„‡‡ˆ‰‰‰‰‡††ƒ~||{{{z{|}}‘’‹›¡›¡ ¢›”•“Šƒƒ~yxsswrrwyz}€ƒ…‡‡‰‹‰ˆ‰‡…ƒ|{{{zy{{|}~€‚„ƒŽœ”§ ž¢Ÿœ‘ˆ|y{uqqotuqv}~~‡‰‰‰Š‹‡‡ˆ„~~|zy{|z{~€ƒƒ„ƒ…›ŸŒœ­ žœœ”Œ„†…upxuoprwzz{ˆ†„Š‹‰ˆˆˆ„€€~yy{zyy{}~~‚„ƒƒ…„…‚‹¡–Œ¤§œ››™‘‰ƒˆruysqqty{{}„Ї†Œ‹ˆ†‡…€}{}zvwzzzz}‚‚ƒ†‡†„…‡ƒ£’§¦š˜˜š’‰ƒ}zkowsoqy~€„‹Š‰ŽŠ„„…{xxzwtvz|{|„„„…‡ˆ†ƒƒ„‚”¦ªª—™œ‘ˆy}{kjsvspy‚ƒ…‡Š‘‹ŠŒ‹…~~~zwtvyxxy~‚‚‚…ˆ‰‡†††„€–®¤• ´º¤‘™ –„wy~xqmoy~zy}ˆŽ‡„ˆ†€‚„‚~yz}}{y{€€€„…‚ƒ„€•®¦•œ²¼¦– š†vx}ztkjt}~wuƒŒƒ‚Œ“Œ„…ˆ„}zz~zvx~‚~z}ƒ†ƒ€…†„ƒ›°¥–œµ½¥’—¢‰z{~|vmkqz}vr}ŠŒ‚Š“…ƒ‰Œ†|~€~zwx|~{y{ƒ€~…‡ƒ„—¨¡—œ®´¡”™Ÿ™‡~zrnoqtvsu|ƒ…ƒŠŒ‡‡‹‹†€}ywyzzxx{~~……„ƒˆ–›–‘—¢¢–‘–„}}|tpquwusw}‚€ƒ‰ŒŠ‡‡Š‹‡‚‚‚~zyz|{xy{~~}~ƒ„ƒ‚Š—›’‹š›•’—˜“‘“••“‘‘ŽŽŒ‹Œ‹‰‡ˆ‰ˆ‡‡ˆ†…„„„ƒ„„„ƒ‚‚ƒ‚€‚ƒƒ€€ƒ„„€‚„ƒ‚€‚……ƒ€‚‚~‚~|}€‚€~€€€~~~~~~€€€€‚€‚‚€€€€‚‚‚‚€€€~€€€ƒ„ƒ‚‚ƒƒ‚€€~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚~~€~€‚~€€€€€~‚~‚€€‚|ƒ‚€}‚€€~‚€~~ƒƒ€‚ƒ…ƒ||‚ƒ€€ƒ‚}„~}„‚„„ƒ€‚€}€€€€}‚€~€€~‚‚€‚‚‚€€€~}~€€€€€~~€}~€€~€ƒ‚~€ƒ‚€~‚‚ƒ~€~‚€€€€€€€€€€‚~~ƒ}‚‚‚‚‚~‚€}€~~€‚€~~€ƒ~}‚€€‚ƒ‚~‚€~~€}€€€}ƒ~„‚‚~€ƒ€ƒ€‚€€‚‚ƒ€€€~‚‚€€€‚~~€€‚‚}~‚‚ƒƒ„„‚……‚‚„…„‚ƒ„…„€‚…ƒ†…„„„†‰‰††ˆ‰‡…ƒ„ƒ€‚€€ƒ…†ˆ‰‡„…„~|~€~~~||€~z{|}~}€~}}€€€‚…„„‡ˆ‡†…„……‚€€€‚€€€€€€€€€€€ºÁ™Œ˜˜…qnvƒ‹ƒ~‹–z€‚zx‡‡€~ƒ†‚}{~‚~}„ƒ~€‚€~~€‚‚€€~»Á™‹˜š…pnuˆœ”†‰Œ†xot‡…ƒ„‡Š‡}wy}€„‡…€||~€~‚„„~€~~ŽÀË£Žs}|ii–ž™€„zpovƒŽ†„†…xtx†…‚ƒ„…{y{€‚€ƒ„}|~€†²Ñ´—‡u{oiz•¡šŽ|„~pox†‘Ž…ƒ…~wtxƒ‰†„„€zx|ƒ„€ƒ„€|{~‚€~†²Ï²—ˆz€ni|—¡—‹~‡}oozŠ‘‹…†}ut|‡‰‚~†…~xy€…ƒ~…ƒ~z|‚ƒ~€¤ÌÀ£“„…‡uiv‘Ÿ™‚Š‚roxˆŠ€‡Švs{†ˆ|€‡ˆ€xx€…ƒ}|†…z|‚„€}}™ÃÆ­ž‘~lqˆš™…†Šyot‚Œ‰€~†Œ‡{ty‚†€z|…‰…|y~„„~z}„†‚||…‚~zŒµÆ·¨™›Žwnz”ކ†‘”ˆyt{…‡z€Š„{y€†ƒ{y‡‡{|ƒ†{z„„|~ƒ„|ƒ ¶µ¬ª«¬§˜‡„ŒŠ„„Š‘‰ƒˆ‰ƒ~}†…€}€……~~„‚~}€ƒƒ€~~ƒ~~€‚€~† µ³­¬¬«¥—ˆ…Œ‰…†‹‰‚€|ustpnqrqtxxy~~ƒ‚ƒ‚‚‚€€€€€‚’¥©­¼¿·¹»°§§Ÿ’ƒ~€|xz|y{~~‚ƒƒ…ƒƒ„ƒ‚‚€€€€€€€€€€€€£ª¬¹À¸·»²§¦ ’Œƒ|}{vx{xy}~}ƒ‚ƒ…„ƒ„„‚‚ƒ€€€€€€€€€€€‹Ÿª¬µ¾º¹½¶«©¤˜‘އ~}xxzyx|~}€ƒ‚‚……„……ƒƒƒ‚€~~~~€€€€ˆ›ª¬²»¸´º¸­©¥˜„|zvppqoquvx|€„††ˆ‰ˆˆˆ‡…„ƒ€~}}}||}}}~€…—ª®³½¼·½¾³­«ž’‘Š~zyqmpomruuy~€‚†‰‰ŠŒ‹ŠŠˆ†…ƒ‚€~~~~~~€€„•§¯»Ä¾º¹¯¥¢™Ž‰ƒzwvrsvvx|~€ƒ……‡‡†‡†„ƒ‚€~~~~~~~~€€€‰”šŸ¤©®°­ª¨¦£ž™–•”‘ŽŽŽ‹Š‹Š‰ˆ‡‡†…„„„„ƒ‚‚‚‚‚‚€€€…ŠŠŒŽŽŽŽŽŒŒŒ‹‹‹ŠŠŠ‰‰‰ˆˆˆ‡‡‡‡††††……………„„„„„„„ƒ‡ŒŽ‘’‘‘’‘‘ŽŒŒ‹‹‹Š‰‰‡‡‡††…„„„ƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€‚€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€‚€€‚€~‚€€€‚ƒ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€‚€€€€‚€‚€‚‚€€€€€€€€~€~~~~€~~€~€~€€€€€~~€€€€€€€€€€€€€€€€€~€~€~~€€€€€~€€~~€€€‚€‚€€€€‚€‚€€€€€€‚€€€€€~~€‚ƒ‚€~}~ƒ~~€‚ƒ‚€€€‚ƒ„}{|~‚€‚‚€€~~~€ƒƒ€€€€€€€€€€€‚ƒ‚€€€€~ƒ„…„‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‡¥ÂÏÔŤŠxnq|‡–˜•Š‚{yx{€„‡ˆˆ…‚~|}~€‚ƒ‚‚€€‡­ÎÎ˯{aZ]p†ŽŒŽ“–Œ}rjju‚‹‡‚€|yx{…ˆˆ„~|~~€¢ÉÏλˆe[YiŒŽŒ’–ukhq‰Š„~}}{zz}…‡‡…~{|}~€€žÈÏνŠfYSe~Œ•—•“ކ{rlmv‹‘‹…|zzz{}€ƒ†‡†ƒ€}|||~¸ËÈ¿˜tg`ivˆ”™—“‡yqnqy€†Š‹Šˆ„€|yxy}„…†…ƒ}}|~ƒ¦Èȧ~meit{„ˆ—˜”‹}tprx~„‡ˆ‰ˆ†‚~zyz|€‚„„„ƒ€~~}}€“¾ÊÁ±tmnuw}ƒ‰•˜•ytuy|€ƒ…ˆ‰‡„}{|}~‚ƒ„ƒ€~~~šÂ²Ÿ„zxzxox…Ž—“Œ†ƒƒ}yww~‚……„…„ƒ}||~€‚ƒ‚€~€~…­È¶£”†ƒxkbk‚‰‡ŠŽ”†}w{|yx|ƒ‡†„ƒ„ƒ€|{}€‚ƒƒ€‘½½Ÿ˜›˜ˆwpn|ˆŽš“‡‡‡„~xx|€€}‚ˆ‡ƒ‚‚€}|~€€‚ƒƒ¤¼¢”¢¦’zy|z|wy†Œƒ‡‡{}}|{€…„‚†…€}~€€„€‹¯®—¢®¢„‡‚~xt‚ˆˆˆƒ„„z~|}„„€„~~€‚}€›¶¡–«®š……ˆ€{syˆƒ{Ž‹€‚‡…|}‚|{ƒ…~~‚ƒ‚}€‚€}€‹ª©›­¶¦—•”‡‚~yƒ„|€Š‹ƒ„Іƒ~|€„~‚ƒ€€€~‚€~€˜¯¡Ÿ´² ”˜’…ƒ~†ƒ€…Š‚‡Š…€‚€€~‚‚€ƒƒ€€‚€€€€€Š¤¨¢¯º³¥¢¡•Žˆƒ††ƒƒ‰‡‡‹‰†ƒƒ‚€~€‚€€ƒ‚€€€€€€•ª£¥¶¹­¢£‘‹„{x{zsv|€…ƒ…„€€ƒ|~~}€~~‚€‚€~…›ª«¯¼Ä¼¶·¯£ž›ˆ‹Šƒ‚ˆˆ„†‹ˆ…ˆ‰„‚…„€ƒ~ƒ€~‚‚€ƒ¦°°¹ÄÁº»¸ªŸœ“…~wprurry}|†‡…ˆ‹ˆ†ˆ‡ƒƒ}}}{}}}€€‹¤²±¸Åļ½¼®¡Ÿ—ˆ€€yoqtrtxyz‚„ˆŠŠ‹‹Š‰ˆ†„‚€~|{{z{{{}€”§´ÙøøýÿúøüäÏе•”…mrsbgrjn€~Žˆ’•‹Ž’‡…‰|}w}}w|€ƒ•«¸ÇÕÖÖÚÔÊÄ·§•‰……‚„‹•ž¤¦ª¬©¦£›”‰‚€}{|€„‰‹Ž‘’’’”™Ÿ§¯µ»ÀÄÆÆÄÀ»´®¨¢œ˜•””•–˜›Ÿ  Ÿ›˜•‘Іƒ€}zxvtsrqqsw{€†‹”˜œŸ¡£¤¥¥¥¤£¡Ÿš—•’Šˆ†ƒ‚€~}|{{zzzzzz{{{|}}ƒ‡Œ‘–𡣦¨¨©©¨§¥£¡žœ™–“‹ˆ†ƒ€~}|{zzzzzzzz{{|}}~‚…‡‹Ž‘”—™œžŸ ¡¡¡¡ Ÿœš—•’Šˆ…ƒ€~|zywvutsssssttuvwx{~…‰”—š ¢£¥¥¦¦¦¥¥¤¢¡Ÿ›™–”‘Šˆ†„‚€~}{{{|~€ƒƒ„„‚ƒ…„~}‚€}~‚„ƒ‚‚ƒ‚|||yvxzyxz|}€€„‡„ƒƒ„„‚€€‚~~~€€ƒ„‚…ˆ†ˆ†„……ƒƒ‚‚‚ƒ€‚€€ƒƒ‚‚€‚ƒ~‚€“¦ Ÿª®®¦™““‹ypppmjjs~€€†”“Ž…}|{xspsxyy{‚†‡†ˆŠ‹ˆ„–¨žš¤§§ ’Šyqttsonw‚€…Ž‘‹‰Œ‹ƒ|||zusv{|z|‚†‡…†ˆ‰†–²¦›¬±«¢‘†‡ƒm`jqmns~“Ž›’‰…‚~ujkrsps}…ŠŠ‹”‡ƒƒyss’©™™²¹³¨™“”ˆlaklccjxˆ‹‰’¢¢–Ž‹ƒvjkpmhmy‚‡ˆŒ”™“‹ˆ‡‚xrm}¤ŸŠ¦¹²®‘•‘x^epgbfp…ŠŒ§Œ‰†|jdmpjis€‰ŒŒ–˜„€{tlnr}¤®’¦Áµ¨šŒ‡s_Ugphn|‹˜š—˜œŽ}yxqhbfouw{†‘“‘‘’‘Š€zyvqnnvx‚«´œ°Â²©›‹ƒ{nYZihfsŠ–™—Ÿ§‘މ‚|rjmrnlt|…‡‰’‰‰ˆƒ~zwzwz—£š£°±¯¨œ”•Štormkkks€‚€‰““‘“–”’ŒŒ‰‡ˆˆ‡††…„ƒ}zzxvuuttuuvvwyxz|{|~~~€‚‚…†„…†…‚€€€~{{{zxz{|}}}€ƒ‚‚„„ƒ„„……„†††‡†††………„…ƒƒƒ€€€€€€€€‚‚€€€€‚‚‚‚€‚€€€€€€€€€€€‚€€€~~}~}}~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚€€€€~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}|~}{z{}}|~€€~€€€€€€€€€€€€€~~€€‚‚€‚ƒ€€€€}€‚~~€~~€‚~€€€~€‚~€‚‚‚€€~€‚~€~€‚~‚ƒƒ„ƒ€ƒ…ƒ€‚„‚€„€‚‚‚ƒƒ‚‚„ƒ‚~€~€€€€€€€€‚€~€€€‚„€ƒ‚€€€€‚—«ª¨¯³°¤—‰ƒwprwyz}ƒŠ‹Š‹‹‡‚~}{yy|€„…„ƒ‚‚‚€~~~~~~€€€Ž§¬¨¬³²¨›‰†{qpuyy{ˆŒŠ‹Œ‰ƒ~}|zy{ƒ…‡‡…ƒƒ‚|{{||}~€ƒƒ„‚³²›¤¬£˜†usxm`gv~ƒ†Œ—ž˜Ž‹Šƒxolorrs{…‹Ž‡|zvrqsy}‚‡‹Œˆ‰ƒ’º¦ƒ ¦“Ž{pzsdu‰‡…ˆ‰”˜ˆ|€…}spt|€{{…Ž‹…„†‡ƒzvz~{xz€……‚ƒ†ˆ„~}޵¡„£«˜‘€v|€r`p…‚„‰”™Œ€„Šsqty|xv€‹Š„…‰Š†z|{vw}€†ˆ†€ƒ€”±˜Š§£”Žy|pew„~€†‰‘”І‰~uuuwywv|…†ƒ„ˆ‰ˆ„€€~zx{}~}~€ƒ…ƒ‚„„²™’¥¤œƒ~|tfp}}}~„‘އ†Œˆzy{{xvxƒ‚„‡ˆ†‚‚‚~}}||||||}~}ƒ˜¤ž¢­­©««¢›ž™Ž‹Œ…{{~z~~}‚ƒ„‚€‚„€€ƒ‚€‚€~~€€€†¤¤®¬¨«ªŸ›ž—ŒŒŒ„‚z{€}z}~ƒ‚‚…‚€ƒƒ€€ƒ€~€€€‰¡¨¡«´ª§°«››œ†‰…{z~yuz}yy€€}…ƒ…†‚‚…ƒ€‚‚~€~€~€€€€”¥¢¤³°§®°¢œ —ŠŒŒ}‚x{€{z|€…„…€…‚‚ƒ~‚€}€‚~~‚€~€‚ˆ›¥¢©²¬ª±¬¡ž“Љ†}z|ytw{xx~}€„ƒ‚†‡ƒ„†„ƒƒ}€}}~|}}}~~ˆš§±º¼¹·²«¥ ˜’Žˆ„‚~~~}‚‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€‚𣫝±²±­¨£™•’ŽŒ‹‹ŠŠ‰ˆ‡†……„ƒƒƒ‚‚‚‚€€€€€€€€€€€€€€€…‡‰‹ŒŽŽŽŽŽŒŒ‹‹ŠŠŠ‰‰ˆˆˆ‡‡‡†††…………„„„„„ƒƒƒƒƒƒ‚‚‚‚‚‚‚‚„ˆ‰‹ŽŽŽŒŒŒŠŠŠ‰‰ˆˆˆ‡‡‡†‡†††…†………„…ƒƒ„ƒ‚ƒ‚‚ƒ‚‚ƒ‚ƒƒ‚‚ƒ‚‚€‚€€€€€€€€€€€€€€€€€€‚€€€€€‚ƒƒ‚ƒ‚€~€€€~~}~}€~~‚€€€~€€~}}‚‚€€~€€}€€~€€€ƒƒ€‚‚€€}€‚ƒ€~€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~€€€€~€€€€€€€€€‚€€€€€€€€€€~€€~~€€€€€€€€€€€~€€€€€‚€€€€€€€€€€€€€€€€€€‚€‚ƒ‚ƒ‚ƒ‚ƒƒƒƒƒƒ‚‚‚‚‚‚‚‚‚‚‚‚ƒ‚ƒƒ‚‚‚‚€}}}||{zzyzyyyyyyzzyzyzzyzz{{{||}|||{||||||||{}||}}}}}}~~€€€€€~~}}}}}~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‰”Ÿ¬´¶·²«¤›’Š‚zuqoqtx}‚†‹Ž‘‘Ž‹‡ƒ|xvuuvxz}€ƒ…‡‰‰‰ˆ‡…ƒ€~|{yzy~’¢ª´²©¬«¤¢–‚xoijifgjpz…‹’‘“—“‹‚}|ywvsrux|€ƒ„†ˆŠŠŠˆ…ƒ€~~{yyxƒ˜¤¬³¬¨«§¢œŒ}unkljhjovˆŒŠ‡†‚|xtsux{~„†ˆˆ‡…‚}|{{{{}€ƒ„„„…ž¶¸¼´™’|vgdksŠŽ‘”’‘yuqrvwy}…ŠŒ‹‰†‚~{yxxz}€‚„………„ƒ‚~{†¤µ·½¬——‹{yqm|‹“™˜ˆ†€xvss}†‰Œ…„ƒ}zywyƒ…‡†ƒ‚~||z|€‚ƒ„ƒ‚€~˜ÆÒÎÓw{nktlrŸ§¨˜‚wvrptrw‰“”•Š}{yvwxw}†‹Œ‹„~}|z{|}‚†‡…‚}|~}ƒ°ÛÖŨxjtqry‚’¥­Ÿ†vnlv|z‚Œ‘•‚vruy}‚…Š‹†€zvy}€‚„……ƒ|{|~‚•ÈÝʶkowsx~‰›©§’{rlq||}‡Ž’’‰}xy{{}€…Љ„}|}}}‚……ƒ€~~~~€‚‚„ªÍ·™†tx|vr{‘™€z}|wu{…‡€}{y|††ƒ€€}|}€‚ƒ‚€€~€‚€‚޽ɩ’~u||spšŸ–Š|{|us}‰„~€}yx|ƒˆ‡‚€€|{}„ƒ€€~}~‚‚–ÆÊ¥|v|zqp†žŸ•‡{{zss€ŒŒƒ~€|wx~…‰†€~{{~‚„ƒ€~}~€‚„«Ë°“„y||unsŒš˜…€yrt~‡‹‰„ƒƒ‚~yx|„„‚‚ƒƒ€}|}‚‚~~€¾Æ£Žx|yrm{”š–Œ‚€}uqx‚ˆˆ…ƒƒ„€{y{‚‚ƒƒ~}~€€€‚€€€¡Å´™Œ€€wnuŠ““…„…yuy€…†„ƒ„…}{|€‚ƒ~~€€€€€€€€€‰³Æ·©™Œ‹Š~v‚‹Ž‘‹„…ˆƒ~~~…„ƒ‚€~€€€€€€€€€€€€€€€€€€€€€’²¶¨‰‰†{z…‰ŒŒ†ƒ……€~‚„‚€‚€~€€€€€€€€€€€€€€€€€€€€€„™ª«¨¤Ÿš”‹‰“œŸŸš—‘ˆ„ˆŒ‘‘‘‘Œ†‚‚„†‡ˆŠ‹‰…€€‚ƒ…‡†„€€€€€‚„„ƒ‚€‹¡«©§£Ÿš‘Š—žžœš–ކ†Š‹‹ŽŠ‡‡‡††ˆˆˆˆ†………„„…………„„„ƒƒƒƒƒƒƒƒ‚ƒ…’—–™š—•“’•””—–””’ŒŒ‹‹‹‹ŠŠŠ‰‰‰ˆ‡ˆ‡‡‡††††………„……„„„„ƒ„™—”›™•œš–——”’”’‰Œ‹†‡ˆ…„‡…‚…„‚‚€€~~€€~€~€~€‚€€ƒƒ€ƒ…‚…„‚€„ƒ€„„ƒ€€‚‚‚€€~€€€~€€€~‚€}‚€€€€ƒ€„ƒ€€€‚€€~€}€}€~€‚‚|€‚~‚€€‚€‚€~‚~‚€€€€}ƒ}€‚‚€~„€~€€€€~ƒ€|ƒ€|ƒ~‚‚€€€€€€‚€~‚}€ƒ~„~~‚~€€‚}„|‚€€€ƒ~€…{„|‚‚€€‚€‚‚€€‚‚‚{‚ƒzƒ„zƒƒ}‚‚‚€}‚}‚|€ƒ}‚~‚}„|€…x‚…y‚„~„€{„‚zƒ}‚€}‚‚}„~„~}…{€ƒ‚~ƒ~ƒ‚z†z†‚ƒ~€„|‚ƒ{‚‚~‚‚|€‚‚~~ƒ€€€€~€„{ƒ{‚€~ƒ€ƒ~ƒ~ƒ}~€~}‚ƒ{€…~~‚€~ƒ~~‚~€€~~„}}„~}€~‚€€€€ƒ{€…{„€€~‚‚}ƒ€|ƒ‚}ƒ}€‚€~€~ƒ|‚~€|„€{€†|‚„†ƒ€ƒ‚„€~ƒ‚€~ƒ|‚‚~€€€‚ƒ}…~}ƒ~€‚~€‚€€€€~‚‚~~‚~€„~‚„~€‚~€„|ƒ€ƒ~‚€€€€‚€€€€€€€‚€~‚€‚€€€€‚€~€€€€€€€~€€~€€~€~ƒ€‚~€€€€€€€€€‚‚‚‚€€€€€€€~€~~~~€€€€€€€€€€€€€€€€€€€€€€€‚‚€‚‚€‚‚‚‚‚‚ƒ„„„„„…„„ƒƒ„ƒƒ‚‚‚‚€€€€€€€€€€€€‚‚‚‚‚‚‚ƒƒ‚ƒƒƒƒ‚‚‚ƒ‚‚ƒ‚‚ƒƒƒ„„„„…………………„„„‚‚‚€€€€€‚‚€€€€~~€~}}€~€€€€€€€€€€€€€€€€€€€€€‡‹Œ‘“”•••””“’‘ŽŒ‹Š‰ˆ‡††…„„ƒƒƒ‚‚‚‚‚€€€€€€€€€€€€€€€€ƒ‹‘‘‘‘‘ŽŽŒŒ‹‹ŠŠ‰‰‰ˆˆ‡‡‡†††…………„„ƒƒ‚‚‚‚€€€€€€€€€ˆ™¢¦¨¢›™››˜•ˆ††††…ƒ€€‚‚ƒ‚€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ž¤§¦Ÿšš›™—“Œ‡†††‡†„ƒƒƒ„…„ƒ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ž­»½¾­–ŽŠ„€yrw|€‡Š‡‡…ƒ„„€~~|}€€‚€‚‚€€€€€€€€€€€€€€€‡¯ÉÈ̶Šwpgjsqlv„Žž© ‘‡yprurswy‹’’‘‹{zxwyyy|…‰‹ˆ„~|||{{}~€ƒ†…„ƒ€›ÁÆÇÁ˜yskjuxqu„ž«¥shluww{~ƒ˜–†xpqux}~~‡‹‡~xuvz~€‚…ˆ‰†€~w†¶ÉÅÆ¡rjigu~tp}Œ™«¬•€rfgu{y{}Œ™™’…ujmt{€‚€‡ŒŽ…yqpt|‚„ƒ‚ƒ…‰‰„~vuu„µÒËȧreeboyrq€”¤²¯“xh^bs{{~‡”Ÿmchs|‚„ƒ…‹‹rlnu†‡†…†ˆ‰†wsry¼ÔÇÄ£ma_[jvw}Ÿª¯¦‹ob[`q|€†Œ’™œ”„sgbiv€‡Š‹ŒŠvnlqzƒ‰‹Šˆ‡…‚}wtty‡¬ÓÓÏ·€b[Ubtz‚ž¨«¥rd[^o|„Œ‘”—–rifmy‚ŠŽŒˆ‚{tpqw†‹‹‰‡ƒ|ywwz~ƒ‡Š¨ÉÌȱ€c[Xg{ƒŠ•œ £™„qe^fv‹’’‘‹‚yqknu~‡ŽŒ‰„{wuuy~„ˆŠ‰†‚~|zy{|‚„‡…Š©¿À¾ xeZ]p€‰•–˜˜thelw„Ž’‘މƒ~ytrsx€‡Œ‹†|yxxz|€„†ˆ‡…}{z{|~‚„„ˆ©ÍÔÖ¿Šngcv‹Ž••–—~ollv‰Ž‡€{zyx}„‰‰ˆƒ|{}|€‚ƒƒƒ~}}~€‚€€€~ˆ¯ÏÖÙ¹„ndby‹Œ•–˜˜Žznjjy‰ŽŒƒ€ƒ‚}xvz‚‡‰‰‚}|}~€~~„…ƒ}}}€‚€‚€Ž¶ÎÔШzibk‚‹Š‹Ž”š’~rjk{Ї~ƒ„ƒyuy‡Šˆ||}€‚€~}~€ƒ„‚€~}~€€€‚—»ÉÑÆœ~peo~ƒ‡Œ˜šxmq{…ˆ„„††„ƒ~xy{}‚…ƒ‚‚€€€~~}~€‚‚‚€€€€€€ƒ ÀÍÙÍ«–…uvxty„‡™”Œ|}yy~~………‡„€|~}€€‚ƒ€€~€€€€€€€€†›«·¼®œzzyx~‚†‹†€~}{}~~ƒƒ„…‚€~~€‚‚ƒ„……†††…„ƒ‚‚€€~‚„……††††„ƒ‚€€€~}{{{{{|zyyy{}€€€€€~}{{|~€€~~}}~~~}~€‚ƒ…„ƒƒ€‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€‚€€~€€‚€€€€€€€‚€€€€€€€€‚‚‚€€€~}~~~~~~~}~€€€~~€€€€€€€€€€‚€€€€€€€~~€~€€€€€€€€€€€~~~~~~€€‚‚‚‚ƒƒ‚ƒ‚‚‚‚‚‚‚€€€€€€€€€€€~€€‚€ƒ‚ƒ‚ƒ‚‚‚ƒ‚€€€€‰“Ÿ«´¶·²«¤›’Šƒ|wtrsux{‚…‡‰‰‰ˆ‡…ƒ€~}}||}}~€‚‚‚‚‚€€€€€€€€„“¡­··±¬¤—wmffhkqv{ƒ‰”—–•’Ž‹†€zurppqsux|…ˆ‹ŒŒŒ‹‰†ƒ|zxwwwxz|~ƒ……£­³·­¦¦Ÿ™“ƒunihlllou|†Ž‘’“’‘‘‡{wutssstx}„‡ˆ‰ŠŠŠˆ…‚}{zyy{|‚ƒ„„…ƒ…µ¶º³™’}vgekt~ŠŽ‘“‘‘Œzvrsvwy}…ŠŒŠˆ†‚€~{yyxz}€‚„…………ƒ€~|||}~‚Œ«º»¿¬–”Š}zmadlvƒ••“‘‰}zyy„„†‰ˆˆ‡|zz{ƒ…„„ƒ}}|}€€‚‚‚‚~~~~€›ËÕÏÃ’txlitms¡¨¨˜uuqotsxŠ”••Š|zyuwxw}‡ŒŒ‹„}||y{{{€…‡‡†~~}|}~€‚…„‚€„®ØÑ¿¤xmxvuz‘¢ª„vpnx}z‹“Žvsv{~‚„ŠŠ…€zwz~€‚ƒ„…ƒ|{|~‚‚‚~}“ÇÝ˺“mpupu}ˆš©¨“}slpz{~‹’’Œyvyzz~ƒˆŠ‡}||||~„…„~~~~€‚‚‚€€~€ƒ«Î¸š‡ux{tpz‘žš{~{vuz…‡}zy|††„€}|}€‚ƒ‚€€~~~€€€¾Î­’€uzzsn€š¡˜‹}z~{tr}ŠŽ†€}xw|ƒˆ‡ƒ€€|z}„„€€~}~€‚‚€€~~€ŸÌÄ ‹yv{xpr‹ ž“…|}~yrs~‰ŽŒ…‚~xw{……ƒ‚ƒƒ€}{|‚‚‚~~€€€€‚€€~€‡´Éª’ƒy|zsmv™—„~wqv€ˆ‹ˆ„ƒƒ‚}xy|„ƒ‚‚ƒ‚€}|}€€€‚‚~€€€€€€€~—Á»‚€yor†’“†„…ƒ{ux~„†„ƒ„…‚~{|~€‚ƒ‚€~~€€€€€€€€€€€€€€€€ƒªÆ®–‰€skxŠŒ‡€‚…zz}€…„€€‚‚€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€‹­¸«Ÿ’‰‰‡}yƒ‰Œ‡ƒ„†~~~„ƒ€‚€~€€€€€€€€€€€€€€€€€€€€€€€€€€‹¢¬©§¢˜‰Œ—žŸžœ™•……ŠŽ‘‘‘Šƒƒ…†ˆ‰‹Š‡ƒ€€‚„†‡…ƒ€€€€ƒ„„‚€€€€‚‚„•¨¬¨¤Ÿš–‘‘˜œœ›˜•’’“’“””’’ŽŽŒŒŒ‹ŠŠ‰‰‰‰ˆˆˆ‡‡‡††††……………„„„„„„ƒ„ƒ†“˜—š›˜–”‘“–••——””’‘‘‘ŒŒ‹‹‹ŠŠŠ‰‰‰ˆˆ‡†‡……†ƒƒƒ‚‚ƒƒƒƒ‚ƒ‚ƒ€‚€‚‚€ƒ‚‚‚‚€€€‚‚‚ƒ„‚ƒ„‚ƒ‚ƒ‚€‚~ƒ€€‚‚€ƒ„€„†ƒƒ„ƒ‚ƒ„€‚„ƒ~‚€‚€‚€~€€‚ƒ€€€€€~‚‚~€€‚‚~ƒ€€„}‚‚~ƒƒ~‚€ƒ€€‚€€€€~ƒ}€„}€ƒ€‚€€‚‚‚~‚~€€~€€~‚}€ƒ{‚~‚€}‚€€€‚€‚~ƒ€€€ƒ~‚}„~„}€‚~€€‚€}‚~ƒ}‚~‚‚~~‚|ƒ|„€‚~‚€€ƒ}‚|ƒƒ|€‚~…~|‡~z†z„‚{„|„{ƒ‚|‚‚}‚~€„{€…y€…}ƒ€}‚€~ƒ|€…y‚…zƒ~ƒ|‚}‚ƒ~ƒ€€‚}‚{‚‚}~‚€€€~‚€ƒ}€ƒ|‚‚|‚€€€|ƒƒx„„x„‚{ƒ€€ƒ}ƒ€|ƒ€‚~€~„€€ƒ~„}|…}ƒ}ƒ}„ƒ€~€~€„}…~}…}„€}„{‚‚|ƒ‚|€ƒ~~„}„~ƒ}‚}€ƒ~„}„~€€€€€‚€~€€€€€€€€}€‚~€€€~€€€€€€‚~€ƒ~€ƒ‚‚ƒƒ„„€~~}|~}~~€€€}~~ƒƒ‚ƒ‚~}|€~€€€€€‚‚€‚€€ƒ€ƒ~„€~ƒ~‚‚~‚€‚€‚ƒ‚~~ƒ€€~‚€€~€€‚~~‚~‚~ƒ€€€‚~€}‚ƒ~€ƒ€ƒ€‚‚‚€~€}€€~‚€€ƒ€‚ƒ€‚€}€~€€€€€€€‚~€‚€‚ƒ€~€~~€€€ƒ€‚ƒ€ƒ‚~€€€~}}||}}|}~~€€‚„’œ£¬¬¨©§¢ž—Œƒ}uqpmkmosx~‚†ŠŒŽŒ‰…ƒ|zxvvvwy{}ƒ…†‡‡‡†…„‚€~}|}|Ÿª´´­©¤ž—Œ}phdeilou|…–™™—“‹…~wqmmnqtx|‚‡‹Ž‘ŽŠ‡‚}zwtsrrsux{‚‘¦­¶¾²±µª§¢Ž‚zmjicacdhs{€ˆ–™˜™–Ž‹‡~{vssqrvwy}~…†ˆ‰‰‡‡†„ƒ~~|{{~¡®¼À¼½»¶µ­‘ƒwrojhfcfms|„‡Œ“”“Œ†‚{ywutttwz|‚ƒ…‡‡ˆˆ‡…„‚€}}{„˜£²Á½º¹¯­¬ —‹{qmiikjkosz„‰‘‘‘’Ž‹†€}zxyyz|~‚„…††…„ƒ€~}}}}~€“­¹Ëн·«—”Œ{ulbelq{„‡‹‘”Їzzwvxxx|~€„††‡†„„ƒ€~||||}€‚‚ƒ†Ÿ±½Îƶ±žŽrqjgu€Š›¡œ”…€{qqqms{~ˆ‘‘’‘ˆ~wtvtu{~ˆŠŠŒˆƒ|xxxw|}…¨ÉÞöëĤzUONPbouˆš¤´»®ŸŒo_ZU]lt€”š¢ž–qjdcls{†•”Œ…{uqloux‚ˆ±Ñáó纒c60:Ks’Ÿ¯°¥¤Ÿ’Œ~g\SO_t‡Ÿ«©¤—„ypijmmsy~‰’–™–Œ‚xnklpx€…‰Œ‹­ÉÙëÞ³_87BW~˜¢¬©œ˜ŽŠ~j`XUdwŠŸ©¥Ÿ‘vpknqqv{ˆ”–“Š€wnlos{‚…‰‹Œ­ÑÌÄ·ˆa][^s†‰–š˜˜”…tnihr…ŠŠ‰†€zxutx~‚†‰‰†„‚~|{{z|ƒ„…„‚‚~‘¾ÍÅŦvfd^h|ƒ„Œ–—˜š‘tnilx€„‹Ž‹Š‰…{xuuz~‚†ˆ‡…„~}|{{}ƒ„„ƒƒ€…­ÍÇÆ·†he_bu‚ƒˆ’–—š—ˆzrjir{ˆŒŒŠŠ‡ƒ{wuw{ƒ‡‡‡…ƒ€}|{|}ƒ„„ƒ‚€›ÄÊÈÄ›rf^]n~ƒ‡Ž“•˜šwnhmw~…‹ŒŠŠˆ…}yuvy|†‡‡†„~||||~€‚„ƒ„‚ˆ¯ËÈÉ·‡jc[bu…Š‘”–š—‰|sjhqzˆŒŒŠ‰‡ƒ{wuwz~ƒ‡ˆ‡†„‚€~|{{|}€‚‚„‚¹ÈÁǯ„vnchrw{‚Ž•–›˜Š{qosvz„‡‰‹‹‡ƒ€{xyy{~‚„……„‚}}}|~€‚–ÁÈÃǧ€vkairw{ƒ•—œ–ˆ€yposvz€…ˆŠŒ‹†ƒzxyy{~ƒ„……„‚}}||~‚‚ŸÆÆÅÄ|thbksx}†’–˜“†woortw{€„‡Œ‰‡ƒ~{zzz{}~€‚………„‚€~~}~~~›ÄËÌʨ†zroprrmpŒ• Ÿ’ˆzxxywtw{‡ŒŒŠ†‚}~}{{{{~‚„……„‚€€~~}€£ÈÊÍÆ ‚xqoqsrlsƒ—¡œ†yxyyvtx{€ˆŒ‰†~~~}{{{|‚„……ƒ€€€~~|‰³ËÍнœ‡€ƒ‚|ym`gv…“š—ƒƒ†‡Š‡|rorzˆˆ‚€…‰ˆ„}yy{ƒƒ€~|~„†„~}—ÁÎÐË­€„‚}xg`l|Œ™›“†ƒ†‰‹ƒwpou~…І€}~‚‡Š‡{xy|‚„ƒ}|~‚…†‚€|‚ªÊÎÑÁŸ‡}…{o^^ix‡ŽŠƒ‰‘†}uuz}|zy|‚†ˆ†‚~‚ƒƒ€}||~€‚€~°ÁÆÆ·¤–’–‡€qfhp{‚…†‚€†ŠŽ‹…~z|~€~{zz‚„…ƒ€€€‚ƒƒ‚}}~~…¤½Ãƽ«œ“•”‰‚wigmv}~~|y~‡’Œ‡ƒ…ˆ‰ˆƒ}yxz~€}zz|€ƒ„ƒ„…„‚~~€Œž§ªª¥¡ž¡£ž–‚{yz|zvsqsx~‚„ƒ‚‚„‡ŠŠˆ„€€‚~|{{}€€~~€ƒƒ‚€€Š›¥©«¨£Ÿ™“Œƒ|xtsqonlmorvy|~€‚…ˆ‰ŠŠ‰‰ˆ‡†„ƒ~}||{{{{||}~€€ƒ‹—¡ª¯±±°°°®ª£›“Œ†|xspmmmoqsvx{‚…‡ˆ‰ŠŠŠŠ‰ˆ†„ƒ€~}||{{{{||}}~€…•¤ª®°²³±¯«¦ ›•‰„{xutssstvwy{~ƒ„…†††††…„ƒƒ‚€~~~~~~~~€„Œ”œ£©¬¯±²±¯­ª¦¢ž™”‹‡ƒ|ywusrqqqqqrsuvwyz|}~€‚ƒ„„„„…„„„„ƒƒƒ‚‚„‡Š‘”—™›œžžžœ™˜–“’ŽŒŠ‰ˆ††…„ƒ‚‚€€€€€€€€€€€€€€€€€€€‚„†ˆŠŠ‹‹‹‹‹‹‹‹ŠŠŠ‰‰ˆˆˆ‡‡†††………„„„„ƒƒƒƒƒ‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚‚€~€€€€€€€€‚€‚‚€€€€‚‚€‚‚~€‚‚€€€~~€€€€€€€‚‚‚€€€€€€€€€€€€€€€€€€€€€‚‚€‚€€~~€~€€€€€€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~~~~~~~~~€€€€€~~€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€~€€€€€€‚€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€~~~€€€‚€€€~€€€€€€€€€€‚‚‚‚€€€€€€€€€€‚‚€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€‚€‚‚€‚€€‚‚€‚€€‚€€€€€‚‚„ƒ„…ƒ„ƒ‚‚€€~~}}}|}|}|}}{~}}~|~~~€€€€€~~€€€€€€‚ƒƒ„ƒ„Ž˜¢¯µ¶¶°¨¡™ˆzwtstvy}€ƒ†ˆ‰‰‰ˆ†…ƒ~}}|}}~€‚‚‚‚€€€€žª¶¸²®§Ÿ™ƒyofegiouyˆŽ”—–•‘Œˆƒ|wrnmnoruy}‚†ŠŽŒ‹ˆ…‚~{xvvvvxy~¤­·¸¯®­¥Ÿ”umgghfgkr{†Ž‘”••–•‰‚{wurqpprw{€„‡ˆŠŒŒ‹‰†‚€}{zxwwyz~£«µ·ª¢›ƒ{nghls}…Š”””‘‰‚|vsssuy}†Š‹‹‰†ƒ}zyxy{}‚„……†„ƒ~|}{‚Ÿµ¸¿´œ˜‘ƒ~scbhq}‰Ž“•””Ž‚{uqruuw|€…‹‹Š‡ƒ~{yxy~‚…†…ƒ‚€}|{}„ƒŽºÕÏÊ¥wurhsso…œ¦©Ÿˆvtsptuuƒ’”•€yyvvyx{„‹ŒŒ‡||zz|{~„†‡‡ƒ~~}|}}~•ÆØÑÈ›uwngrmp‹ ©ªœ„vttrw}‚™“Šwtwz{~„ˆ‹‹…}zyz}€‚…†…‚~{{}€‚‚„ƒœÍ×IJˆktwty€‹œ¨¤zrms}|~ˆŽ’‘†zsuy|€‚ƒˆŠ‡‚|xx|‚ƒ„„„}{|}€ƒ‚‚‚§Ë¶š‡vz~vqzœ™|~}zw|†ŒŽˆ€~|z}…†„€€}|~€‚ƒ‚€€€~~€€€€~½Êª“u|zrr‚˜–Š}|~zuv~‰Ž‹„€€|yy}ƒ‡†‚€~|{~ƒƒ~}~€€€€~žÌÄ ‹zw|xoqŠ ž“…{}xqu‚‹‚~€€{wx†‰†€~{{~ƒ„ƒ€}}‚€€€~…³Éª’ƒy}{tlvŽ™—„€xquˆ‹ˆ„ƒƒ‚}yx|„ƒ‚‚ƒƒ€}|}‚‚~~€€€‚•ÿ‹|y}yqn€–™”Š€|urzƒŠŠ†ƒƒƒ€{x{‚ƒ‚‚ƒƒ~}}€€€‚‚€€€€€€€€ƒªÆ­–‰uny”’‹„„…€xuz††ƒƒ„„}{|€ƒƒ~€€€€€€€€€€€€~¼À¦›…Їyv†ŒŽ†…‡€|~‚†‚ƒ€~‚€€€€€€€€€€€€€€€€€€€€€€€€€˜¶³¦š‰Š„y|†Š‹…ƒ†…~~ƒ„‚€‚‚~€€€€€€~€€€€€€€€€€€€€€€€„™ª«¨¤Ÿš“‹‰“œŸŸš—‘ˆ„ˆŒ‘‘‘‘Œ†‚‚„†‡‰Š‹‰…€€‚ƒ…‡†„‚€€€‚ƒ„ƒ‚€‹£®¬¨£˜ˆ‹˜žž¡¡žš•’”“”——•”‘ŽŽŽŽŽŒ‹‹Š‰ŠŠ‰‰‰ˆˆˆ‡‡‡††††…………„…„†‘™˜šœ™—•’“––•˜˜••“‘‘‘‘ŽŒ‹ŒŒ‹ŠŠ‰‰‰ˆˆˆ‡‡‡‡††††…„†„„†ƒ…†ƒ†…„†„…„„†„…†ƒƒƒƒ‚‚ƒ‚‚‚‚‚‚‚‚ƒƒ€„„€‚ƒ‚ƒƒ„‚ƒƒ‚„ƒƒ‚€ƒ€ƒ~‚‚‚ƒ‚‚€‚€€€~‚~~‚~~€‚€€ƒ}‚}‚€€€‚€‚}€‚~€~ƒ~~~~€€€~€€~‚}‚€€€‚~€‚~€€€~€ƒ}„}€ƒ}€‚€}‚}‚€€€}ƒ€~‚€€€~„~ƒ{ƒ‚|ƒ‚€ƒ~‚‚€~‚‚{ƒƒy„‚|ƒ‚~ƒ}…|~„|…~~„|ƒ|ƒ|ƒ€~„~}„|…€{†€|„€~‚~„|ƒ|„|ƒ|ƒ}~ƒ}‚~€~‚€}„~}†|~ƒ}‚zƒ‚|€‚€~ƒ}†|}ˆ{}‡~}„}‚ƒ}€ƒ~ƒ~}„|‚€}€‚~€‚}€‚}€ƒ|‚€€€€‚~‚~€‚}‚}€~‚~‚‚}ƒ~„}€ƒ}ƒ~…}€~ƒ~„~ƒ}€ƒ~€€€‚€~€‚~€€€€€€€‚€~€~‚€‚€‚ƒ~€~€‚€€~€€€€€‚€€‚€€€‚~‚€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒƒƒ‚€‚€‚€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€~€}€€}€}€~€}€}€~}€~|}}~}}}}}~€~€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€~€€€€€€€€€€€€€€~€€€€‚€€ƒ€‚€€€€~€~€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚ƒ„……„ƒƒ‚€~}}|}}}}~~~}}~~~‚‚ƒƒ‚€€€€€}~~}}}~}}}}~|~€‚ƒ…ƒ„‡‡„ƒ…‡ˆ†‚…ˆ‡…„„†ˆ‡…†‰Š‰‰‡ˆŠˆ†„…†…ƒ‚‚‚€€€€€€€€}€‚~}€€€€‚„ƒ~…€€ƒƒ€€‚ƒ€‚€€ƒ‚ƒ„‚ƒ„‚‚‚‚‚}€ƒ~‚„„‚‚‚‚€~€}€}~}~€„‚„„ƒ‚~€~}€€‚‚€€€€€‘ˆš”‘Žˆ€~€{tvzxxz~‚‚‚†‰ˆ…†‡„~|z{}|{~€‚ƒ„ƒƒƒƒ‚€Š’ˆ‹–’ŽŒŒ‰~~ww{zz{~‚ƒ„ˆ‡„…†„}{|}}|}€ƒƒƒ‚‚„€‰¡™¨ªŸŸ›˜”ˆ}~~qkstrty€…„†Ž‹‰ŒŠ…€~~{wvyzxz~‚…ˆˆ‡ˆŠˆ‡—ž’œ©¢£¡ž¢™Ž‹‚zwxtnorutu|ƒˆŒŒŠ‹‹‡……ƒ||{ywxzyy{†š™–ª®©­©©¨š“’ˆ}vsoifgjkkqx{~„‰Ž’’ŽŠ…‚}ywvvtuuxzz‹˜Ž›®¥©¯§­¦—›–†|vrkiljhlruv{„†ˆŒŒ‹Œˆ†…ƒzz~ywzz{|‹–Œ›¬£ª®¨°§›¢šŒŠ„zrqrnlosrrx|~€‡‰†‰‹‰ˆ‡‡‡ƒ‚€}}|}z~އ…š•• —Ÿ¢“›œ‘‡ˆ|~yvvvuuvwyz{€ƒ„…†…†‡………„‚€|ƒŠ‡“‹”–“Ž“ŠŠ‰„‚€||zvyxuxxx{{}€€„„„††††………ƒ‚‚€}|}‚‚„„†ˆ‡ˆŠ‰Š‹Š‹‹‰ŠŠˆˆ‡††…ƒ„‚€~~}}~}}}}}~}~~~‚ƒƒ‡ˆ‰‹‹Ž‘ŽŒ‹Š‰ˆˆ‡††…„„ƒƒ‚‚‚€€€€€€€€€€€‚‚‚„„„†…††††††††……………„„„ƒƒƒ‚‚‚‚‚€€€€€€€€€€€€€€ƒ‚ƒ„„………………„„„ƒƒƒ‚€€€€~€€€€‚‚‚‚€€€€~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ‡‹‘ŽŒ‹Š‰ˆ‰‰ŠŠ‰‰ˆˆ‡‡†………„……„„ƒƒƒ‚‚€€€€€€€€€‚€€€~€~€€€€€€€€€€€€€€€€€€€€€€€€‚€€‚‚€€€€€~‚€~ƒ‚€€€‚~€‚~€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒƒ„„€€€€‚}}{~}~}|~€‚ƒ‚€‚€|~}€‚‚„ƒ‚„‚~}zzyz{zz|~~}‚~|}~}~}}€~|}€~|‚ƒ…ˆŠ‰‡‰Š‡„€€|x{{xz{{€~†‡†ˆŠˆ‡‡„‚}}~~€‚ƒƒƒƒ„ƒ‚€~~~~~~€‚”¦žª­«¥˜’“Šxqrpnkkt~‡“‘ŽŽ„}}|xsqtxyy|‚†‡†ˆŠŠ‡ƒ‚‚|x˜Ÿ”ž«­¬¡—˜—‡uruqlkp|„„…˜–‘‹„ysuupnry‚ˆŒ‰‰ˆƒ}xwxusuz”²¨¥½Ã¹¬œ‹eWad^al|”“›¨§š‘Œ†}oddiifmz…‹Ž’™œ–Œˆ…~tmjmpnryºº¦¿Ì¾±™†‚z`IQa_bn}–¤Ÿ ¬¯ Žƒ|uiYVbijo}Ž˜›™œ¡›Š}xurmjq~†ˆ‰’ Âº™¡¤’‡vdiyvjwŒ“—•Œ–‰vruutrq|ŠŒ‡Š‹ƒ{{}xrtz~‚‚ƒˆŒˆ„‚€|zvˆ³±™¨¯¥ž‰rs{n_jx€‹‹Š– ˜Š†ƒ|rjqz{z~…‹‹…‡‰„}xwy|zx}ƒ……„„††„}а²¡¥£¡Žvryjls}‹ŠƒŠ—–‹„€ƒzpt}~||„‰„~‚ƒ{z€ƒ|}„ƒ~}‚ƒ~}Š¡§£§«®«Žˆ|~…‰„‡Œ‹†……{~‚ƒ€}„…~€‚ƒ€}~‚‚€~‚‚€‚‚‚‚€€€€€€€€€€‚ƒ„ƒƒ††…ƒƒƒ„…ƒ‚ƒ‚ƒ„‚‚‚ƒƒ„††…††„ƒ‚€€~~||}|||||||~~}€€‚ƒ‚„…†‡‡‡‡‡‡…„„‚€~{|}{||z{|{{|{{|||}||}}}~}}~~~~~€€€€€€€‚‚€€‚ƒƒ‚‚€€~~€~~~€~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚~€€€€€€€€€€€€€€€€€‚€€€€€~€~€€€~€€€€€€~€~€‚€‚€€€€‚€€€€€~€~€€€€€€€€€€€€€€€€€‚€€‚€‚€ƒ€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€ƒƒ‚‚‚…‡‡‰‰Š‹‹‰ˆˆˆ‰‰‹‹‹‹‰ŠŠŠŠŠˆ‡‰ŠŠ‰‡…†ˆ†…‡…„††…ˆŠ‹’’”“Œ‰‡‡„ƒƒ‚ƒ‚‚ƒ‚€‚€€‚‚ƒ‚~€~€‚ƒ€~€€‚€€‚€‚~€€ƒ‚~~€€‚}ƒ‚€‚ƒ~€€€ƒƒ€~||ƒ‚ƒ‚~~€€‚ƒƒ‚}}€‚‚‚‚€~|||ƒƒ~||„„‚€~~~}|~€‚‚€€™¶¾²›†~~€}}„˜–‹z{~~€„‰Š†||~€€ƒ„ƒ€~}€€€€‚‚€€€€€€€­¿¸¤€~|‹–˜ƒ{z~~~‚‡Šˆ‚}|~€~~„…„€~~~~‚ƒ‚€€€€~€€‚€ˆ²Æ«—„swzslt‡–˜Š€}xsqw‚‹Ž‹†„‚{vvz€…†…„„ƒ€}zz|€‚ƒƒƒƒ‚€~|}~ Ç¸›Štr{wop‚•›}{|zurvŒ‘‹„€~|xw{‚‡ˆ…‚}z{~‚„„‚~|}€ƒ€½Æ¥‘{nx{snyœž”‚z|{wst|‰†}ywz€†‡…‚€}{{~ƒƒ‚~}~€€‚„«É¯”…sw}wpuŠ˜™”†|}~yuv}†ŒŒ†€~{y{€„†„ƒ‚€~|}~‚‚€~~€ Â²šŒ}|}vpuˆ“”‡‚‚yux~„ˆ†„„ƒ~{{}€‚‚‚‚‚€~~€€€€€€€€€Œ¯»©š…„xuƒŽˆƒ„„z|€ƒ…„‚ƒ‚~~€€€€€€€€€€€€€€€€€€€’¨¯ª¦¡›–Œ„‰”šš™—•’‰€€…ˆŠ‹‹‡€~‚‚„‡ˆ†‚€‚…„‚€€~~€‚‚‚£­ª§£˜Ž†‡†‚‚€€~}}}}}}}}}}}~~~~~~~€€€€€€€€€€€€€€€‡ŒŠ‹‹‹ŒŒŠŠŠŠ‰‰ˆˆ‡†††……„„„ƒƒƒƒ‚‚‚‚‚€€€€‚ƒ‚‚€€€€€€€€€€€~~~~~~~€€‚ƒ‚‚ƒ‚‚‚‚€€€€€€€€€€‚‚‚€€€€€€€€€€€€€€€€€€€€€€‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€‚‚~‚€~ƒ‚‚€€€€€€€~€€ƒ‚€‚€‚€€‚‚€€€€€€€€€€‚€~‚~‚€‚‚ƒ‚~€‚‚€}ƒ€|‚€‚€~‚}‚~‚€€€}ƒ|€„~„€„}ƒ}}€‚|ƒ~}ƒ}‚~‚€€€€€€‚€€€‚}}ƒ~„‚~€~„}€„}‚~‚~‚‚‚|ƒ{„‚}ƒ~…~~„~~€~€~~€}€‚~€€€~€~€€€~€€|‚~€‚~„~€€€~‚‚~~€€€€€ƒ€~ƒ~€‚‚~€ƒ~~€€€‚€~ƒ‚€‚‚}‚‚}€‚€ƒ€ƒ€~‚~€~€‚‚€€€€€€…Ž”—›œš•‘މ…‚}}}}~€€‚ƒƒƒ„ƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€ƒ“•›œš“‹‡{xtrtwz}„ˆ‹ŒŠŠˆ…ƒ€|zyyyz{}€‚ƒ„…………ƒ€~}|||~~€€‚‚…«¡¡¡ œŒ{yytsnjsƒƒ†‰”’‰…„‚€|urvyxxy{…„ƒ„…††ƒ€€€~}{|~~€‚–§¢£§¢¥¦™Š†„}zvmpyyz}€‚ŠˆˆŠ‡‡†€|~~{{{z}€€€€ƒ‚€€}~~~€‚‡™¨±¶¯¥Ÿ˜Œuiehmt}ƒ‰’˜™˜“Šƒ}vromotz€†ŠŒŒ‰…{xuuvwz~‚…‡‰ˆˆ†ƒ~§±±«¨¥œ‘…vnllotx~ˆ”—•Œ‡|wqprty~‚…ŠŒŒŒ‰…~zxwuvy{~‚„†ˆˆˆ†„‹–›ŸŸ™•“ˆ‚ytssuy|~…‰‹ŽŽ‹‰†~|wvwwy}~…†‡‰‡…„~}{zzz{}€‚„„……ƒˆ“› £ž™–‰…}wussw{~„ˆ‰ŒŽ‹Šˆ‚}yxxxy|~€„…†‡‡…„‚~}{{|{}€ƒƒƒ„ƒ‚„‰’”’‰…‚~zyxxz|~‚„…ˆˆ‡†…‚€~|{{{|}~€‚ƒ„…„ƒƒ€~}}}~€€€€~~}}}}}}}}}}}~~~~~}~}}~~}~~~~~~~}}~~~~~~~€€€€€€€€~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€‚€€€€‚‚€€€€€€€€€€~~€~€€€€~€€‚€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€‚€€€€€€€€€€~‚€~‚€€ƒ€‚‚‚ƒ‚‚‚‚‚‚ƒ‚€‚‚ƒ‚„ƒ‚„‚ƒ‚€‚€€~~~}~€€€ƒ‚ƒ„ƒ„ƒ‚ƒ‚~~}}}|}|||{|{{{{|{{||}|}||}}~~€€€€€€€€€€€€€€€€€€€€€€€€€€‡’œ©³¶·³¬¥”‹„}xursuw{~…‡ˆ‰‰ˆ‡†„‚€~}|{{|}~€‚ƒƒ„„„ƒ‚€~~}}~~…•£¯¸µ°¯ª¦¡”…xmhggffioxƒŒ‘”•–˜—”ކ~yusqonpsx~‚…ˆŠŒ‹ˆ„~|zxwvyЦ±³ª«¬¦¢˜†zrlkkhgjpyƒŠŽ’“••‹„~zwusqqrvzƒ…†††…ƒ€}{zzz{}~€‚„™¶¼¾»¡“‘‚{uf`gp{ˆ’–”’ƒzupptvw|…ŠŒŠ‡ƒ€~{xxwy|‚„……†…„‚€}||{‹«¶º¾©˜˜Œ|ladlu‚‹Œ”•’Œtqty€„…‡‹‹‰„}wwy|€‚ƒ…††„}{{|~€ƒ„ƒƒ‰µÒÌʧzyvjtrm‚š¤¨Ÿ‰xvuqtus‚‘“•€z{wwywzƒŠ‹‹‡|}{z|{}ƒ††‡ƒ~}}¢ÔØÇ°jssqx¡¬¤‹xpkt|zŠ”‘…xrty|€‚„‰‹‡{wx|‚ƒ„…„€|{|~€‚‚ƒ‚œÎØÄ±‡ktwsy€‹©£Œzrms}|~ˆ’‘†ysuy|€‚ƒˆ‹‡|z|~„…„~}~~€‚‚ƒ€•ÄÄ£Žzu}yrt‡šœ”†{}~yuwŠŠ‚~|zz„†…‚€€€~|}‚ƒ‚€€~~€¼É©“u|zrr‚˜œ–Š|{~zuu~‰ŽŒ„€}yx}ƒ‡†‚€€€|{}„ƒ€€~}~€‚€ƒ©Îº™‡yx|vov‘ ›‚z}~wqx…މ€~€zwz‡ˆ„€€€}{|ƒ„‚€€}}€‚ŸÇ·—‰{{}wpp†˜˜’‡€€{ss|…Љ…ƒƒƒzx{ƒ„ƒ‚ƒƒ~||~€‚‚€~~€€€‚€—Ä¿œ‹|y}xqn–™”Š€€|trz„ŠŠ†„„ƒzy{€ƒƒ‚‚ƒƒ~}~€€€‚‚€€€€€‚»À¡‘ƒ~€{qp‚’“ˆƒ„ƒ|uw}ƒ†…ƒƒ…ƒ|{~€‚ƒ‚€~~€€€€€€€€€€„ªÆº«œ‹‹vŠ‘Œ„„‡„~~~€……ƒ‚~€€€€€€€€€€€€€€€€€€€€€€€€˜¶³¦š‰Š„y|†ŠŒ…ƒ†…~~ƒ„‚€‚‚~€€€€€€€€€€€€€€€€€€€€¥¬©¦¡œ—ŽˆŽ™žŸž›™”‹…†‹Ž‘‘‘Žˆƒƒ…‡ˆ‰‹Š†‚€€‚‚„†‡…‚€€€ƒ„„‚€Š «ª©¤ž™‘‰Œ–ŸŸš–Œ‘’’‘Œ‹ŠŠŠŠ‹‹‹Š‰ˆˆ‡‡‡‡‡‡†††………„„„„„„„ƒƒƒƒ‹—˜—›š–•“‘”–”–˜–””‘‘ŽŒŒ‹‹‹‹ŠŠŠ‰‰ˆˆˆˆ‡‡‡†††…………………„„…„„ƒ‚„„‚„‚ƒƒ‚‚‚ƒ‚‚€ƒƒƒ‚ƒ„ƒ…‡„„…ƒ‚ƒ€‚€~~|}~~~}||~}{}z}~}~€€€‚€€€}~~}€~€}ƒ~ƒ~ƒ~„€‚€‚‚‚~‚‚~ƒ‚€‚€ƒ‚„‚€€~€€~‚€~€€€‚~~‚~€€‚‚~€„|‚}„€‚~€€‚~€‚€€~‚‚}‚~ƒ~€€€€‚|‚ƒ{ƒ}‚€€€€€~€€€~€‚~€€ƒ|‚{„€}„€~ƒ~ƒ}ƒ‚€|ƒ‚z‚ƒ|€„~€ƒ}‚~‚~~‚‚€€ƒ}~„~}ƒ€}‚€}ƒ€‚~€}‚‚~~ƒy…‚x†|„~€„|†z€„|‚~ƒ{„€{…~}ƒ€}ƒ|€‚~‚~ƒ‚€€€‚~„|€„|‚~‚€‚}€~~~€€€~ƒ~‚~ƒ~„~‚€‚~‚~€€‚€€€€€€€€‚‚~€€€€~ƒ}ƒ}‚€€€‚~‚€~‚€ƒ~€€€€€~‚~‚‚~ƒ€€€€€€€€~€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€~€}~}~€~€~€~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€€€€€~€€€€€€€€€€€€€€€‚‚‚€‚€‚€€€€€~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€ƒƒ‚‚‚ƒƒ‚‚€€€€€€€‚‚‚ƒ‚‚‚€€€€~}~}}}}~}|~~}‚‚ƒ„„……„„…„ƒƒ‚‚ƒ€‚€€‚ƒ‚ƒ…„…†„ƒ…„ƒ‚‚‚‚~~~~{}€|z~€~~‚}‚}|~€}€‚~~€}~‚ƒ‚€€€ƒ€€|~}€~€‚€~‚„‚ƒ‚ƒ‚…~‚}~}~~~~€‚‚‚€€€€€€€€€€€€€€‡’‹‹˜–‘‘ŽŠƒ~€~vuyyxy}ƒ‚„ˆ‰††‡…‚€}z{||{}€ƒ„„ƒƒƒ‚€€€~}~~~~€€‚‡Ÿž‘¦°¢ š–Š}|~riptqsx€†…‡Ž’ŠŒ‹†€~}{vuxyxy}‚‚„‡ˆ†…†…‚}{{|||}€ƒ„…œ£“¦·©¬­¨¬ž”Žvttmfinpnq|€…ŒŽ“މˆˆƒ}z{yusvxvvz~‚†‡†‡ˆˆ†„…„~~{…•ޤ£¢¨¤¨§š™™Ž†‚}yrmoolmrvwz„†ˆ‹ŽŽŠ‡…ƒ}{zywwwxyz|~€‚„……†††…„„ƒˆ—‘¨¢Ÿª¥¨§™ž‰ˆ‚}utwroquwux€€€„‡Šˆ‡‹‹‡‡‡†ƒ€~||}|z|}}}}€€‚‚‚‚ƒƒ‚ƒ‰•‰¡•™ —¡›•ŠŽˆ„ƒ{{|vuvwvvxz{|~‚‚ƒ…†‡‡‡‡‡……„ƒ€~}||{|||}}~€‚‚‚ƒ‚ˆˆŽ˜”—’—“ޒއ‡…€{wxtpspmomnpmorprutwyx{}|€‚ƒƒ……„†……†………„„„ƒ‚ƒ‚€€€ƒ‚ƒ‡†ˆŠŠŒŒŽŽŽŽŒŒ‹ŠŠ‰ˆˆ‡††……„„ƒƒ‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ‚ƒ…„…†…††††††††……………„„„ƒƒƒ‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚€€‚‚€ƒ~€‚€‚‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ‰”šœž¡£¤¤¢Ÿœ™•’‹‡„‚€~}|{{{||}~~€‚‚‚‚‚‚‚€€€€€€€€€€€€€€€€€€€€€€€€ƒ‡‰’“““’’‘ŽŽŒ‹ŠŠ‰ˆˆ‡‡††……„„ƒƒƒƒ‚‚‚‚‚ƒ‚‚€‚~€‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€}‚ƒ…‚‚ƒ‚…†…‚€‚€{~‚~}€‚€~€~‚‚}~ƒ}€€‚„…‚€„‚|ƒ€‚‚€ƒ‚~}}}}}|~€€‚‚‚€€~~„š¢ž¢¢¢¤ž…|vrlkrwy}‚‡‘‹ˆƒ~zxwvuvx|‚ƒ†ˆ‰ˆ‡…ƒ}{zz{{|}‚ƒ„„„„ƒ~~ ŸŸ”’“‰}urqu||}„‰ˆƒ‚€}zwvy}€‚ƒ„…‡†„}}}||}~€‚ƒƒ‚‚‚‚~~~~€‚‚‚€‚³»­¬‘•~kfio}ƒ~ƒ”˜•Œutuvxxy†ŒŽˆ}|zyxxy}‚‡‰ˆ†ƒ€~|zyz}€ƒ„„„ƒƒ‚€~|||~šÂËÆ»™zvofcck„š£¥ž’‰…ukffn|ˆ”‘Š…}yvsru{‚‰Š…€|zyxxz}€…ˆˆ‡…~|{{{}~€ƒƒµÏÓÓ·ˆj[U]ny~ˆ–ž¦¬ŸŠxf\`jv„ކƒ|zyvvz|‚‡‰‰ˆƒ|yy|}‚‚ƒƒ‚‚€~~}~€‚‚‚”´Íçò×µ‹ZEDLj‡˜§©Ÿ™‘†{sonnu‡”‘†~xvuw{~„„…†…ƒ}|{|~‚‚‚‚€€€€‹©¿Ôâα–o^ads…‰‹ŽŒŒ‘‘‹‚yxvw}€ƒ‚€‚‚€€~€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ž¢¯Â¿¸È¼¬±¨ ™”–ŽŠŠ‡Œ‰ˆˆ‡ˆ†††ƒ……€}ƒ~‚‚ƒ……‚ƒ…€€}€~}€~}€€~~~~}€}‚~‚€‚€ƒ‚ƒ‚‚‚‚‚‚‚€‚ƒ‚‚ƒ‚‚‚‚‚‚‚‚‚€€€€€€~~~€€€€€~~€~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€€€€€€€~~~~~~~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚‚€‚‚~~€€€€‚€€€€‚‚€‚€€‚€€€€€€‚€‚‚€€€~~~}}}||{|{{{{{z{{z{{z{{{{{||||||||||||||||||}||}}|}~}~~~€€€€€€€€|zxvvtssqrqprsswz|€‚ƒƒ~}zxvsqqsvy|~€„†‡‹ŒŒ‹ˆˆˆ‡‡‰‰ˆˆ†‚‚€}~€‚…„ƒƒ€~~}€}{zwxz{~~}~}}~}}€€~€ƒ…ˆ‰‰Š‰ˆ‰‡…„€~}|{zyy{{}‚ƒ£©°¶«ª®¥¡œ‰|ukggb_adkv†’–œŸžœ—‰ƒ|wqkgghkosx~„Š“••”’‹†|wsponopsw{‡Ÿ«µÁ»·¼´­ª—…{mdc]XZ\`lw‰‘•œ¡¡¡ž–‰{unigegkotz…‹’””“‘ŽŠ…€{wtrqqqsuz£«¹¼´¹¸°¯¤‘†znkg`]^_epx~‡Œ˜š›œ˜‘މ‚~yspnlnqrvz}‚‡‰‹ŽŒŠˆ…‚~|zxwvvw~“£®»º¶»¸³³§–Œusohgfdksw…†‹‘“•Š…‚}yxutvwx{|}ƒ„†‡†††„„ƒ€}||||…˜¨¶Â¿¼¾¸µ³¥—‹|sqlhgeelrzƒˆ‹‘’•”‘މƒ|ywusttvy|~ƒ…‡ˆˆˆ‡†„‚€~||{{{|‰«¼ÄÀ¾¹±°©‘‚tlgefhgjpu~‡Œ‘”“““‘‹†€|xvuttuuw{}ƒ„……„ƒƒ€~}|||}~€€“­¹Ëн¶ª–”Œ{ulbelr|„‡‹‘”Їzzwvxxx|~€„††‡†„„ƒ€~||||}€‚ƒ‚‚‚€¨´ÄϾ´¬˜“xpeflr~‹”–’Œ‰zwrnrty‚‡‹ŽŠˆƒ}{xuvxy~ƒ…ˆŠˆ†„€}|yyz{}޲Íâôß¹šnQPOUiszŽœ¦µ¶¨š„i^YWcpx…‘”œ š”‹{oidfov~‰•’Š‚ytpmqv{‚ˆ‰Ž«ÇÔçܱŽc<:FW}—Ÿª¨››—ŠlbZVdwˆ§¤ž‘€wqlorqv{~‡’•“‰xomps{‚…‰Š‰‰‡“´ÊÚæÌ¤‚U #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "spd_audio.h" int log_level; AudioID *module_audio_id; SPDMsgSettings msg_settings; SPDMsgSettings msg_settings_old; int current_index_mark; int Debug; FILE *CustomDebugFile; configfile_t *configfile; configoption_t *module_dc_options; int module_num_dc_options; #define CLEAN_OLD_SETTINGS_TABLE()\ msg_settings_old.rate = -101;\ msg_settings_old.pitch = -101;\ msg_settings_old.volume = -101;\ msg_settings_old.punctuation_mode = -1;\ msg_settings_old.spelling_mode = -1;\ msg_settings_old.cap_let_recogn = -1;\ msg_settings_old.voice_type = -1;\ msg_settings_old.voice.name = NULL;\ msg_settings_old.voice.language = NULL; #define INIT_SETTINGS_TABLES()\ module_dc_options = NULL;\ msg_settings.rate = 0;\ msg_settings.pitch = 0;\ msg_settings.volume = 0;\ msg_settings.punctuation_mode = SPD_PUNCT_NONE;\ msg_settings.spelling_mode = SPD_SPELL_OFF;\ msg_settings.cap_let_recogn = SPD_CAP_NONE;\ msg_settings.voice_type = SPD_MALE1;\ msg_settings.voice.name = NULL;\ msg_settings.voice.language = NULL;\ CLEAN_OLD_SETTINGS_TABLE() #define DBG(arg...) \ if (Debug){ \ time_t t; \ struct timeval tv; \ char *tstr; \ t = time(NULL); \ tstr = g_strdup(ctime(&t)); \ tstr[strlen(tstr)-1] = 0; \ gettimeofday(&tv,NULL); \ fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \ fprintf(stderr, ": "); \ fprintf(stderr, arg); \ fprintf(stderr, "\n"); \ fflush(stderr); \ if ((Debug==2) || (Debug==3)){ \ fprintf(CustomDebugFile," %s [%d]",tstr, (int) tv.tv_usec); \ fprintf(CustomDebugFile, ": "); \ fprintf(CustomDebugFile, arg); \ fprintf(CustomDebugFile, "\n"); \ fflush(CustomDebugFile); \ } \ g_free(tstr); \ } #define FATAL(msg) { \ fprintf(stderr, "FATAL ERROR in output module [%s:%d]:\n "msg, \ __FILE__, __LINE__); \ if (Debug > 1) \ fprintf(CustomDebugFile, "FATAL ERROR in output module [%s:%d]:\n "msg, \ __FILE__, __LINE__); \ exit(EXIT_FAILURE); \ } int module_load(void); int module_init(char **status_info); SPDVoice **module_list_voices(void); int module_speak(char *data, size_t bytes, SPDMessageType msgtype); int module_stop(void); SPDVoice **module_get_voices(void); int module_tts_output(AudioTrack track, AudioFormat format); int module_play_file(const char *filename); size_t module_pause(void); char *module_is_speaking(void); int module_close(void); #define UPDATE_PARAMETER(value, setter) \ if (msg_settings_old.value != msg_settings.value) \ { \ msg_settings_old.value = msg_settings.value; \ setter (msg_settings.value); \ } #define UPDATE_STRING_PARAMETER(value, setter) \ if (msg_settings_old.value == NULL || msg_settings.value == NULL \ || strcmp (msg_settings_old.value, msg_settings.value)) \ { \ if (msg_settings_old.value != NULL) \ { \ g_free (msg_settings_old.value); \ msg_settings_old.value = NULL; \ } \ if (msg_settings.value != NULL) \ { \ msg_settings_old.value = g_strdup (msg_settings.value); \ setter (msg_settings.value); \ } \ } #define CHILD_SAMPLE_BUF_SIZE 16384 typedef struct { int pc[2]; int cp[2]; } TModuleDoublePipe; int module_get_message_part(const char *message, char *part, unsigned int *pos, size_t maxlen, const char *dividers); void set_speaking_thread_parameters(); void module_parent_dp_init(TModuleDoublePipe dpipe); void module_child_dp_init(TModuleDoublePipe dpipe); void module_parent_dp_close(TModuleDoublePipe dpipe); void module_child_dp_close(TModuleDoublePipe dpipe); void module_child_dp_write(TModuleDoublePipe dpipe, const char *msg, size_t bytes); int module_parent_dp_write(TModuleDoublePipe dpipe, const char *msg, size_t bytes); int module_parent_dp_read(TModuleDoublePipe dpipe, char *msg, size_t maxlen); int module_child_dp_read(TModuleDoublePipe dpipe, char *msg, size_t maxlen); void module_signal_end(void); void module_strip_punctuation_default(char *buf); void module_strip_punctuation_some(char *buf, char *punct_some); char *module_strip_ssml(char *buf); void module_sigblockall(void); void module_sigblockusr(sigset_t * signal_set); void module_sigunblockusr(sigset_t * signal_set); char *do_message(SPDMessageType msgtype); char *do_speak(void); char *do_sound_icon(void); char *do_char(void); char *do_key(void); void do_stop(void); void do_pause(void); char *do_list_voices(void); char *do_set(void); char *do_audio(void); char *do_loglevel(void); char *do_debug(char *cmd_buf); void do_quit(void); size_t module_parent_wfork(TModuleDoublePipe dpipe, const char *message, SPDMessageType msgtype, const size_t maxlen, const char *dividers, int *pause_requested); int module_parent_wait_continue(TModuleDoublePipe dpipe); void set_speaking_thread_parameters(); int module_terminate_thread(pthread_t thread); char *module_recode_to_iso(char *data, int bytes, char *language, char *fallback); void module_signal_end(void); configoption_t *module_add_config_option(configoption_t * options, int *num_options, char *name, int type, dotconf_callback_t callback, info_t * info, unsigned long context); void *module_get_ht_option(GHashTable * hash_table, const char *key); configoption_t *add_config_option(configoption_t * options, int *num_config_options, char *name, int type, dotconf_callback_t callback, info_t * info, unsigned long context); /* --- MODULE DOTCONF OPTIONS DEFINITION AND REGISTRATION --- */ #define MOD_OPTION_1_STR(name) \ static char *name = NULL; \ DOTCONF_CB(name ## _cb) \ { \ g_free(name); \ if (cmd->data.str != NULL) \ name = g_strdup(cmd->data.str); \ return NULL; \ } #define MOD_OPTION_1_INT(name) \ static int name; \ DOTCONF_CB(name ## _cb) \ { \ name = cmd->data.value; \ return NULL; \ } /* TODO: Switch this to real float, not /100 integer, as soon as DotConf supports floats */ #define MOD_OPTION_1_FLOAT(name) \ static float name; \ DOTCONF_CB(name ## _cb) \ { \ name = ((float) cmd->data.value) / ((float) 100); \ return NULL; \ } #define MOD_OPTION_2(name, arg1, arg2) \ typedef struct{ \ char* arg1; \ char* arg2; \ }T ## name; \ T ## name name; \ \ DOTCONF_CB(name ## _cb) \ { \ if (cmd->data.list[0] != NULL) \ name.arg1 = g_strdup(cmd->data.list[0]); \ if (cmd->data.list[1] != NULL) \ name.arg2 = g_strdup(cmd->data.list[1]); \ return NULL; \ } #define MOD_OPTION_2_HT(name, arg1, arg2) \ typedef struct{ \ char* arg1; \ char* arg2; \ }T ## name; \ GHashTable *name; \ \ DOTCONF_CB(name ## _cb) \ { \ T ## name *new_item; \ char* new_key; \ new_item = (T ## name *) g_malloc(sizeof(T ## name)); \ if (cmd->data.list[0] == NULL) return NULL; \ new_item->arg1 = g_strdup(cmd->data.list[0]); \ new_key = g_strdup(cmd->data.list[0]); \ if (cmd->data.list[1] != NULL) \ new_item->arg2 = g_strdup(cmd->data.list[1]); \ else \ new_item->arg2 = NULL; \ g_hash_table_insert(name, new_key, new_item); \ return NULL; \ } #define MOD_OPTION_3_HT(name, arg1, arg2, arg3) \ typedef struct{ \ char* arg1; \ char* arg2; \ char *arg3; \ }T ## name; \ GHashTable *name; \ \ DOTCONF_CB(name ## _cb) \ { \ T ## name *new_item; \ char* new_key; \ new_item = (T ## name *) g_malloc(sizeof(T ## name)); \ if (cmd->data.list[0] == NULL) return NULL; \ new_item->arg1 = g_strdup(cmd->data.list[0]); \ new_key = g_strdup(cmd->data.list[0]); \ if (cmd->data.list[1] != NULL) \ new_item->arg2 = g_strdup(cmd->data.list[1]); \ else \ new_item->arg2 = NULL; \ if (cmd->data.list[2] != NULL) \ new_item->arg3 = g_strdup(cmd->data.list[2]); \ else \ new_item->arg3 = NULL; \ g_hash_table_insert(name, new_key, new_item); \ return NULL; \ } #define MOD_OPTION_1_STR_REG(name, default) \ if (default != NULL) name = g_strdup(default); \ else name = NULL; \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_STR, name ## _cb, NULL, 0); #define MOD_OPTION_1_INT_REG(name, default) \ name = default; \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_INT, name ## _cb, NULL, 0); /* TODO: Switch this to real float, not /100 integer, as soon as DotConf supports floats */ #define MOD_OPTION_1_FLOAT_REG(name, default) \ name = default; \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_INT, name ## _cb, NULL, 0); #define MOD_OPTION_MORE_REG(name) \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_LIST, name ## _cb, NULL, 0); #define MOD_OPTION_HT_REG(name) \ name = g_hash_table_new(g_str_hash, g_str_equal); \ module_dc_options = module_add_config_option(module_dc_options, \ &module_num_dc_options, #name, \ ARG_LIST, name ## _cb, NULL, 0); /* --- DEBUGGING SUPPORT ---*/ #define DECLARE_DEBUG() \ DOTCONF_CB(Debug ## _cb) \ { \ Debug = cmd->data.value; \ return NULL; \ } #define REGISTER_DEBUG() \ MOD_OPTION_1_INT_REG(Debug, 0); \ /* --- INDEX MARKING --- */ #define INDEX_MARK_BODY_LEN 6 #define INDEX_MARK_BODY "__spd_" char *module_index_mark; /* This macro must be placed at the initialization of the module so that the later functions are possible to use */ #define INIT_INDEX_MARKING() module_index_mark = NULL; void module_report_index_mark(char *mark); void module_report_event_begin(void); void module_report_event_end(void); void module_report_event_stop(void); void module_report_event_pause(void); extern pthread_mutex_t module_stdout_mutex; int module_utils_init(void); int module_audio_init(char **status_info); /* Prototypes from module_utils_addvoice.c */ void module_register_settings_voices(void); char *module_getvoice(char *language, SPDVoiceType voice); #endif /* #ifndef __MODULE_UTILS_H */ speech-dispatcher-0.8.3/src/modules/ivona_client.c0000664000175000017500000001325312522771346017132 00000000000000 /* * ivona_client.c - Speech Dispatcher backend for Ivona (IVO Software) * * Copyright (C) Bohdan R. Rau 2008 * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "module_utils.h" #include "ivona_client.h" static struct sockaddr_in sinadr; char *ivona_get_wave_from_cache(char *to_say, int *nsamples); void ivona_store_wave_in_cache(char *to_say, char *wave, int nsamples); int ivona_init_sock(char *host, int port) { if (!inet_aton(host, &sinadr.sin_addr)) { struct hostent *h = gethostbyname(host); if (!h) return -1; memcpy(&sinadr.sin_addr, h->h_addr, sizeof(struct in_addr)); endhostent(); } sinadr.sin_family = AF_INET; sinadr.sin_port = htons(port); return 0; } #define BASE_WAVE_SIZE 65536 #define STEP_WAVE_SIZE 32768 int ivona_send_string(char *to_say) { int fd; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) return -1; if (connect(fd, (struct sockaddr *)&sinadr, sizeof(sinadr)) < 0) { close(fd); return -1; } write(fd, to_say, strlen(to_say)); write(fd, "\n", 1); return fd; } char *ivona_get_wave_fd(int fd, int *nsamples, int *offset) { int got, i; char *ivona_wave; int wave_size; int wave_length; short *w; wave_size = BASE_WAVE_SIZE; wave_length = 0; ivona_wave = g_malloc(wave_size); for (;;) { if (wave_size < wave_length + 8192) { ivona_wave = g_realloc(ivona_wave, wave_size + STEP_WAVE_SIZE); wave_size += STEP_WAVE_SIZE; } DBG("Have place for %d bytes", wave_size - wave_length); got = read(fd, ivona_wave + wave_length, wave_size - wave_length); DBG("Wave part at %d size %d", wave_length, got); if (got <= 0) break; wave_length += got; } close(fd); w = (short *)ivona_wave; for (i = wave_length / 2 - 1; i >= 0; i--) if (w[i]) break; if (i < 100) { g_free(ivona_wave); return NULL; } DBG("Trimmed %d samples at end", wave_length / 2 - i - 1); *nsamples = i + 1; for (i = 0; i < *nsamples; i++) if (w[i]) break; DBG("Should trim %d bytes at start", i); *offset = i; (*nsamples) -= i; return ivona_wave; } /* static char *ivona_get_wave_from_cache(char *to_say,int *nsamples); void ivona_store_wave_in_cache(char *to_say,char *wave,int nsamples); */ char *ivona_get_wave(char *to_say, int *nsamples, int *offset) { int fd; char *s; s = ivona_get_wave_from_cache(to_say, nsamples); if (s) { *offset = 0; return s; } fd = ivona_send_string(to_say); if (fd < 0) return NULL; s = ivona_get_wave_fd(fd, nsamples, offset); if (s) ivona_store_wave_in_cache(to_say, s + 2 * (*offset), *nsamples); return s; } /* Plays the specified audio file - from ibmtts/espeak module */ void play_icon(char *path, char *name) { char *buf = g_strdup_printf("%s/%s", path, name); module_play_file(buf); g_free(buf); } #define IVONA_CACHE_SIZE 256 #define IVONA_CACHE_MAX_SAMPLES 65536 static int ivona_cache_count; static struct ivona_cache { struct ivona_cache *succ, *pred; int count; char str[16]; int samples; char *wave; } ica_head, ica_tail, icas[IVONA_CACHE_SIZE]; void ivona_init_cache(void) { ica_head.pred = &ica_tail; ica_tail.succ = &ica_head; } void ica_tohead(struct ivona_cache *ica) { if (ica->pred) ica->pred->succ = ica->succ; if (ica->succ) ica->succ->pred = ica->pred; ica->pred = ica_head.pred; ica->pred->succ = ica; ica->succ = &ica_head; ica_head.pred = ica; } static struct ivona_cache *find_min_count(void) { int cnt = 0x7fffffff; struct ivona_cache *ica, *found; found = NULL; int i; for (ica = ica_tail.succ, i = 0; i < IVONA_CACHE_SIZE / 2 && ica->samples; ica = ica->succ) { if (ica->count < cnt) { cnt = ica->count; found = ica; } } if (found) { for (ica = ica_tail.succ; ica->samples; ica = ica->succ) { if (ica->count > 1) ica->count--; } } return found; } void ivona_store_wave_in_cache(char *str, char *wave, int samples) { struct ivona_cache *ica; if (strlen(str) > IVONA_CACHE_MAX_STRLEN) return; if (ivona_cache_count < IVONA_CACHE_SIZE) { ica = &icas[ivona_cache_count++]; } else { ica = find_min_count(); if (!ica) return; g_free(ica->wave); } ica->count = 1; ica->wave = g_malloc(samples * 2); memcpy(ica->wave, wave, samples * 2); ica->samples = samples; strcpy(ica->str, str); ica_tohead(ica); DBG("Stored cache %s", str); } char *ivona_get_wave_from_cache(char *to_say, int *samples) { struct ivona_cache *ica; if (strlen(to_say) > IVONA_CACHE_MAX_STRLEN) return NULL; for (ica = ica_tail.succ; ica && ica->samples; ica = ica->succ) { DBG("Cache cmp '%s'='%s'", ica->str, to_say); if (!strcmp(ica->str, to_say)) { char *wave = g_malloc(ica->samples * 2); memcpy(wave, ica->wave, ica->samples * 2); *samples = ica->samples; ica->count++; ica_tohead(ica); return wave; } } return NULL; } speech-dispatcher-0.8.3/src/modules/flite.c0000664000175000017500000002212312522771346015557 00000000000000 /* * flite.c - Speech Dispatcher backend for Flite (Festival Lite) * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: flite.c,v 1.59 2008-06-09 10:38:02 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "spd_audio.h" #include #include "module_utils.h" #define MODULE_NAME "flite" #define MODULE_VERSION "0.5" #define DEBUG_MODULE 1 DECLARE_DEBUG(); /* Thread and process control */ static int flite_speaking = 0; static pthread_t flite_speak_thread; static sem_t flite_semaphore; static char **flite_message; static SPDMessageType flite_message_type; static int flite_position = 0; static int flite_pause_requested = 0; signed int flite_volume = 0; /* Internal functions prototypes */ static void flite_set_rate(signed int rate); static void flite_set_pitch(signed int pitch); static void flite_set_volume(signed int pitch); static void flite_strip_silence(AudioTrack *); static void *_flite_speak(void *); /* Voice */ cst_voice *flite_voice; int flite_stop = 0; MOD_OPTION_1_INT(FliteMaxChunkLength); MOD_OPTION_1_STR(FliteDelimiters); /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); MOD_OPTION_1_INT_REG(FliteMaxChunkLength, 300); MOD_OPTION_1_STR_REG(FliteDelimiters, "."); return 0; } #define ABORT(msg) g_string_append(info, msg); \ DBG("FATAL ERROR:", info->str); \ *status_info = info->str; \ g_string_free(info, 0); \ return -1; int module_init(char **status_info) { int ret; GString *info; DBG("Module init"); INIT_INDEX_MARKING(); *status_info = NULL; info = g_string_new(""); /* Init flite and register a new voice */ flite_init(); #ifdef HAVE_REGISTER_CMU_US_KAL16 cst_voice *register_cmu_us_kal16(); /* This isn't declared in any headers. */ flite_voice = register_cmu_us_kal16(); #else cst_voice *register_cmu_us_kal(); flite_voice = register_cmu_us_kal(); #endif /* HAVE_REGISTER_CMU_US_KAL16 */ if (flite_voice == NULL) { DBG("Couldn't register the basic kal voice.\n"); *status_info = g_strdup("Can't register the basic kal voice. " "Currently only kal is supported. Seems your FLite " "installation is incomplete."); return -1; } DBG("FliteMaxChunkLength = %d\n", FliteMaxChunkLength); DBG("FliteDelimiters = %s\n", FliteDelimiters); flite_message = g_malloc(sizeof(char *)); *flite_message = NULL; sem_init(&flite_semaphore, 0, 0); DBG("Flite: creating new thread for flite_speak\n"); flite_speaking = 0; ret = pthread_create(&flite_speak_thread, NULL, _flite_speak, NULL); if (ret != 0) { DBG("Flite: thread failed\n"); *status_info = g_strdup("The module couldn't initialize threads " "This could be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return -1; } *status_info = g_strdup("Flite initialized successfully."); return 0; } #undef ABORT SPDVoice **module_list_voices(void) { return NULL; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { DBG("write()\n"); if (flite_speaking) { DBG("Speaking when requested to write"); return 0; } DBG("Requested data: |%s|\n", data); if (*flite_message != NULL) { g_free(*flite_message); *flite_message = NULL; } *flite_message = module_strip_ssml(data); flite_message_type = SPD_MSGTYPE_TEXT; /* Setting voice */ UPDATE_PARAMETER(rate, flite_set_rate); UPDATE_PARAMETER(volume, flite_set_volume); UPDATE_PARAMETER(pitch, flite_set_pitch); /* Send semaphore signal to the speaking thread */ flite_speaking = 1; sem_post(&flite_semaphore); DBG("Flite: leaving write() normally\n\r"); return bytes; } int module_stop(void) { int ret; DBG("flite: stop()\n"); flite_stop = 1; if (module_audio_id) { DBG("Stopping audio"); ret = spd_audio_stop(module_audio_id); if (ret != 0) DBG("WARNING: Non 0 value from spd_audio_stop: %d", ret); } return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (flite_speaking) { DBG("Flite doesn't support pause, stopping\n"); module_stop(); return -1; } else { return 0; } } int module_close(void) { DBG("flite: close()\n"); DBG("Stopping speech"); if (flite_speaking) { module_stop(); } DBG("Terminating threads"); if (module_terminate_thread(flite_speak_thread) != 0) return -1; g_free(flite_voice); sem_destroy(&flite_semaphore); return 0; } /* Internal functions */ void flite_strip_silence(AudioTrack * track) { int playlen, skip; float stretch = get_param_float(flite_voice->features, "duration_stretch", 1.); int speed = (int)(1000. / stretch); skip = (187 * track->sample_rate) / speed; playlen = track->num_samples - skip * 2; if (playlen > 0 && playlen < 500) playlen += (skip * 2) / 3; if (playlen < 0) playlen = 0; track->num_samples = playlen; assert(track->bits == 16); track->samples += skip * track->num_channels; } void *_flite_speak(void *nothing) { AudioTrack track; #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) AudioFormat format = SPD_AUDIO_BE; #else AudioFormat format = SPD_AUDIO_LE; #endif cst_wave *wav; unsigned int pos; char *buf; int bytes; int ret; DBG("flite: speaking thread starting.......\n"); set_speaking_thread_parameters(); while (1) { sem_wait(&flite_semaphore); DBG("Semaphore on\n"); flite_stop = 0; flite_speaking = 1; /* TODO: free(buf) */ buf = (char *)g_malloc((FliteMaxChunkLength + 1) * sizeof(char)); pos = 0; module_report_event_begin(); while (1) { if (flite_stop) { DBG("Stop in child, terminating"); flite_speaking = 0; module_report_event_stop(); break; } bytes = module_get_message_part(*flite_message, buf, &pos, FliteMaxChunkLength, FliteDelimiters); if (bytes < 0) { DBG("End of message"); flite_speaking = 0; module_report_event_end(); break; } buf[bytes] = 0; DBG("Returned %d bytes from get_part\n", bytes); DBG("Text to synthesize is '%s'\n", buf); if (flite_pause_requested && (current_index_mark != -1)) { DBG("Pause requested in parent, position %d\n", current_index_mark); flite_pause_requested = 0; flite_position = current_index_mark; break; } if (bytes > 0) { DBG("Speaking in child..."); DBG("Trying to synthesize text"); wav = flite_text_to_wave(buf, flite_voice); if (wav == NULL) { DBG("Stop in child, terminating"); flite_speaking = 0; module_report_event_stop(); break; } track.num_samples = wav->num_samples; track.num_channels = wav->num_channels; track.sample_rate = wav->sample_rate; track.bits = 16; track.samples = wav->samples; flite_strip_silence(&track); DBG("Got %d samples", track.num_samples); if (track.samples != NULL) { if (flite_stop) { DBG("Stop in child, terminating"); flite_speaking = 0; module_report_event_stop(); delete_wave(wav); break; } DBG("Playing part of the message"); ret = module_tts_output(track, format); if (ret < 0) DBG("ERROR: failed to play the track"); if (flite_stop) { DBG("Stop in child, terminating (s)"); flite_speaking = 0; module_report_event_stop(); delete_wave(wav); break; } } delete_wave(wav); } else if (bytes == -1) { DBG("End of data in speaking thread"); flite_speaking = 0; module_report_event_end(); break; } else { flite_speaking = 0; module_report_event_end(); break; } if (flite_stop) { DBG("Stop in child, terminating"); flite_speaking = 0; module_report_event_stop(); break; } } flite_stop = 0; g_free(buf); } flite_speaking = 0; DBG("flite: speaking thread ended.......\n"); pthread_exit(NULL); } static void flite_set_rate(signed int rate) { float stretch = 1; assert(rate >= -100 && rate <= +100); if (rate < 0) stretch -= ((float)rate) / 50; if (rate > 0) stretch -= ((float)rate) / 175; feat_set_float(flite_voice->features, "duration_stretch", stretch); } static void flite_set_volume(signed int volume) { assert(volume >= -100 && volume <= +100); flite_volume = volume; } static void flite_set_pitch(signed int pitch) { float f0; assert(pitch >= -100 && pitch <= +100); f0 = (((float)pitch) * 0.8) + 100; feat_set_float(flite_voice->features, "int_f0_target_mean", f0); } speech-dispatcher-0.8.3/src/modules/generic.c0000664000175000017500000004015612536417045016074 00000000000000 /* * generic.c - Speech Dispatcher generic output module * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: generic.c,v 1.30 2008-07-30 09:15:51 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "module_utils.h" #define MODULE_NAME "generic" #define MODULE_VERSION "0.2" DECLARE_DEBUG() /* Thread and process control */ static int generic_speaking = 0; static pthread_t generic_speak_thread; static pid_t generic_pid; static sem_t generic_semaphore; static char **generic_message; static SPDMessageType generic_message_type; static int generic_position = 0; static int generic_pause_requested = 0; static char *execute_synth_str1; static char *execute_synth_str2; /* Internal functions prototypes */ static void *_generic_speak(void *); static void _generic_child(TModuleDoublePipe dpipe, const size_t maxlen); static void generic_child_close(TModuleDoublePipe dpipe); void generic_set_rate(signed int rate); void generic_set_pitch(signed int pitch); void generic_set_voice(SPDVoiceType voice); void generic_set_language(char *language); void generic_set_volume(signed int volume); void generic_set_punct(SPDPunctuation punct); /* Fill the module_info structure with pointers to this modules functions */ MOD_OPTION_1_STR(GenericExecuteSynth) MOD_OPTION_1_INT(GenericMaxChunkLength) MOD_OPTION_1_STR(GenericDelimiters) MOD_OPTION_1_STR(GenericPunctNone) MOD_OPTION_1_STR(GenericPunctSome) MOD_OPTION_1_STR(GenericPunctAll) MOD_OPTION_1_STR(GenericStripPunctChars) MOD_OPTION_1_STR(GenericRecodeFallback) MOD_OPTION_1_INT(GenericRateAdd) MOD_OPTION_1_FLOAT(GenericRateMultiply) MOD_OPTION_1_INT(GenericRateForceInteger) MOD_OPTION_1_INT(GenericPitchAdd) MOD_OPTION_1_FLOAT(GenericPitchMultiply) MOD_OPTION_1_INT(GenericPitchForceInteger) MOD_OPTION_1_INT(GenericVolumeAdd) MOD_OPTION_1_FLOAT(GenericVolumeMultiply) MOD_OPTION_1_INT(GenericVolumeForceInteger) MOD_OPTION_3_HT(GenericLanguage, code, name, charset) static char generic_msg_pitch_str[16]; static char generic_msg_rate_str[16]; static char generic_msg_volume_str[16]; static char *generic_msg_voice_str = NULL; static TGenericLanguage *generic_msg_language = NULL; static char *generic_msg_punct_str; /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); MOD_OPTION_1_STR_REG(GenericExecuteSynth, ""); REGISTER_DEBUG(); MOD_OPTION_1_INT_REG(GenericMaxChunkLength, 300); MOD_OPTION_1_STR_REG(GenericDelimiters, "."); MOD_OPTION_1_STR_REG(GenericStripPunctChars, ""); MOD_OPTION_1_STR_REG(GenericRecodeFallback, "?"); MOD_OPTION_1_INT_REG(GenericRateAdd, 0); MOD_OPTION_1_FLOAT_REG(GenericRateMultiply, 1); MOD_OPTION_1_INT_REG(GenericRateForceInteger, 0); MOD_OPTION_1_INT_REG(GenericPitchAdd, 0); MOD_OPTION_1_FLOAT_REG(GenericPitchMultiply, 1); MOD_OPTION_1_INT_REG(GenericPitchForceInteger, 0); MOD_OPTION_1_INT_REG(GenericVolumeAdd, 0); MOD_OPTION_1_FLOAT_REG(GenericVolumeMultiply, 1); MOD_OPTION_1_INT_REG(GenericVolumeForceInteger, 0); MOD_OPTION_HT_REG(GenericLanguage); MOD_OPTION_1_STR_REG(GenericPunctNone, "--punct-none"); MOD_OPTION_1_STR_REG(GenericPunctSome, "--punct-some"); MOD_OPTION_1_STR_REG(GenericPunctAll, "--punct-all"); module_register_settings_voices(); return 0; } int module_init(char **status_info) { int ret; *status_info = NULL; DBG("GenericMaxChunkLength = %d\n", GenericMaxChunkLength); DBG("GenericDelimiters = %s\n", GenericDelimiters); DBG("GenericExecuteSynth = %s\n", GenericExecuteSynth); generic_msg_language = (TGenericLanguage *) g_malloc(sizeof(TGenericLanguage)); generic_msg_language->code = g_strdup("en"); generic_msg_language->charset = g_strdup("iso-8859-1"); generic_msg_language->name = g_strdup("english"); generic_message = g_malloc(sizeof(char *)); sem_init(&generic_semaphore, 0, 0); DBG("Generic: creating new thread for generic_speak\n"); generic_speaking = 0; ret = pthread_create(&generic_speak_thread, NULL, _generic_speak, NULL); if (ret != 0) { DBG("Generic: thread failed\n"); *status_info = g_strdup("The module couldn't initialize threads" "This can be either an internal problem or an" "architecture problem. If you are sure your architecture" "supports threads, please report a bug."); return -1; } *status_info = g_strdup("Everything ok so far."); return 0; } SPDVoice **module_list_voices(void) { return NULL; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { char *tmp; DBG("speak()\n"); if (generic_speaking) { DBG("Speaking when requested to write"); return 0; } UPDATE_STRING_PARAMETER(voice.language, generic_set_language); UPDATE_PARAMETER(voice_type, generic_set_voice); UPDATE_PARAMETER(punctuation_mode, generic_set_punct); UPDATE_PARAMETER(pitch, generic_set_pitch); UPDATE_PARAMETER(rate, generic_set_rate); UPDATE_PARAMETER(volume, generic_set_volume); /* Set the appropriate charset */ assert(generic_msg_language != NULL); if (generic_msg_language->charset != NULL) { DBG("Recoding from UTF-8 to %s...", generic_msg_language->charset); tmp = (char *)g_convert_with_fallback(data, bytes, generic_msg_language->charset, "UTF-8", GenericRecodeFallback, NULL, NULL, NULL); } else { DBG("Warning: Preferred charset not specified, recoding to iso-8859-1"); tmp = (char *)g_convert_with_fallback(data, bytes, "iso-8859-2", "UTF-8", GenericRecodeFallback, NULL, NULL, NULL); } if (tmp == NULL) return -1; if (msgtype == SPD_MSGTYPE_TEXT) *generic_message = module_strip_ssml(tmp); else *generic_message = g_strdup(tmp); g_free(tmp); module_strip_punctuation_some(*generic_message, GenericStripPunctChars); generic_message_type = SPD_MSGTYPE_TEXT; DBG("Requested data: |%s|\n", data); /* Send semaphore signal to the speaking thread */ generic_speaking = 1; sem_post(&generic_semaphore); DBG("Generic: leaving write() normaly\n\r"); return bytes; } int module_stop(void) { DBG("generic: stop()\n"); if (generic_speaking && generic_pid != 0) { DBG("generic: stopping process group pid %d\n", generic_pid); kill(-generic_pid, SIGKILL); } return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (generic_speaking) { DBG("Sending request to pause to child\n"); generic_pause_requested = 1; DBG("paused at byte: %d", generic_position); return 0; } else { return -1; } } char *module_is_speaking(void) { return NULL; } int module_close(void) { DBG("generic: close()\n"); if (generic_speaking) { module_stop(); } if (module_terminate_thread(generic_speak_thread) != 0) return -1; sem_destroy(&generic_semaphore); return 0; } /* Internal functions */ /* Replace all occurances of 'token' in 'sting' with 'data' */ char *string_replace(char *string, const char *token, const char *data) { char *p; char *str1; char *str2; char *new; char *mstring; mstring = g_strdup(string); while (1) { /* Split the string in two parts, ommit the token */ p = strstr(mstring, token); if (p == NULL) { return mstring; } *p = 0; str1 = mstring; str2 = p + (strlen(token)); /* Put it together, replacing token with data */ new = g_strdup_printf("%s%s%s", str1, data, str2); g_free(mstring); mstring = new; } } void *_generic_speak(void *nothing) { TModuleDoublePipe module_pipe; int ret; int status; DBG("generic: speaking thread starting.......\n"); set_speaking_thread_parameters(); while (1) { sem_wait(&generic_semaphore); DBG("Semaphore on\n"); ret = pipe(module_pipe.pc); if (ret != 0) { DBG("Can't create pipe pc\n"); generic_speaking = 0; continue; } ret = pipe(module_pipe.cp); if (ret != 0) { DBG("Can't create pipe cp\n"); close(module_pipe.pc[0]); close(module_pipe.pc[1]); generic_speaking = 0; continue; } module_report_event_begin(); /* Create a new process so that we could send it signals */ generic_pid = fork(); switch (generic_pid) { case -1: DBG("Can't say the message. fork() failed!\n"); close(module_pipe.pc[0]); close(module_pipe.pc[1]); close(module_pipe.cp[0]); close(module_pipe.cp[1]); generic_speaking = 0; continue; case 0:{ char *e_string; char *p; char *tmpdir, *homedir; const char *helper; const char *play_command = NULL; helper = getenv("TMPDIR"); if (helper) tmpdir = g_strdup(helper); else tmpdir = g_strdup("/tmp"); helper = g_get_home_dir(); if (helper) homedir = g_strdup(helper); else homedir = g_strdup("UNKNOWN_HOME_DIRECTORY"); play_command = spd_audio_get_playcmd(module_audio_id); if (play_command == NULL) { DBG("This audio backend has no default play command; using \"play\"\n"); play_command = "play"; } /* Set this process as a process group leader (so that SIGKILL is also delivered to the child processes created by system()) */ if (setpgid(0, 0) == -1) DBG("Can't set myself as project group leader!"); e_string = g_strdup(GenericExecuteSynth); e_string = string_replace(e_string, "$PLAY_COMMAND", play_command); e_string = string_replace(e_string, "$TMPDIR", tmpdir); g_free(tmpdir); e_string = string_replace(e_string, "$HOMEDIR", homedir); g_free(homedir); e_string = string_replace(e_string, "$PITCH", generic_msg_pitch_str); e_string = string_replace(e_string, "$RATE", generic_msg_rate_str); e_string = string_replace(e_string, "$VOLUME", generic_msg_volume_str); e_string = string_replace(e_string, "$LANGUAGE", generic_msg_language->name); e_string = string_replace(e_string, "$PUNCT", generic_msg_punct_str); if (generic_msg_voice_str != NULL) e_string = string_replace(e_string, "$VOICE", generic_msg_voice_str); else e_string = string_replace(e_string, "$VOICE", "no_voice"); /* Cut it into two strings */ p = strstr(e_string, "$DATA"); if (p == NULL) exit(1); *p = 0; execute_synth_str1 = g_strdup(e_string); execute_synth_str2 = g_strdup(p + (strlen("$DATA"))); g_free(e_string); /* execute_synth_str1 se sem musi nejak dostat */ DBG("Starting child...\n"); _generic_child(module_pipe, GenericMaxChunkLength); } break; default: /* This is the parent. Send data to the child. */ generic_position = module_parent_wfork(module_pipe, *generic_message, generic_message_type, GenericMaxChunkLength, GenericDelimiters, &generic_pause_requested); DBG("Waiting for child..."); waitpid(generic_pid, &status, 0); generic_speaking = 0; // Report CANCEL if the process was signal-terminated // and END if it terminated normally if (WIFSIGNALED(status)) module_report_event_stop(); else module_report_event_end(); DBG("child terminated -: status:%d signal?:%d signal number:%d.\n", WIFEXITED(status), WIFSIGNALED(status), WTERMSIG(status)); } } generic_speaking = 0; DBG("generic: speaking thread ended.......\n"); pthread_exit(NULL); } void _generic_child(TModuleDoublePipe dpipe, const size_t maxlen) { char *text; sigset_t some_signals; int bytes; char *command; GString *message; int i; int ret; sigfillset(&some_signals); module_sigunblockusr(&some_signals); module_child_dp_init(dpipe); DBG("Entering child loop\n"); while (1) { /* Read the waiting data */ text = g_malloc((maxlen + 1) * sizeof(char)); bytes = module_child_dp_read(dpipe, text, maxlen); DBG("read %d bytes in child", bytes); if (bytes == 0) { g_free(text); generic_child_close(dpipe); } text[bytes] = 0; DBG("text read is: |%s|\n", text); /* Escape any quotes */ message = g_string_new(""); for (i = 0; i <= bytes - 1; i++) { if (text[i] == '\'') message = g_string_append(message, "'\\''"); else { g_string_append_printf(message, "%c", text[i]); } } DBG("child: escaped text is |%s|", message->str); command = g_malloc((strlen(message->str) + strlen(execute_synth_str1) + strlen(execute_synth_str2) + 8) * sizeof(char)); if (strlen(message->str) != 0) { sprintf(command, "%s%s%s", execute_synth_str1, message->str, execute_synth_str2); DBG("child: synth command = |%s|", command); DBG("Speaking in child..."); module_sigblockusr(&some_signals); { ret = system(command); DBG("Executed shell command returned with %d", ret); } } module_sigunblockusr(&some_signals); g_free(command); g_free(text); g_string_free(message, 1); DBG("child->parent: ok, send more data"); module_child_dp_write(dpipe, "C", 1); } } static void generic_child_close(TModuleDoublePipe dpipe) { DBG("child: Pipe closed, exiting, closing pipes..\n"); module_child_dp_close(dpipe); DBG("Child ended...\n"); exit(0); } void generic_set_pitch(int pitch) { float hpitch; hpitch = ((float)pitch) * GenericPitchMultiply + GenericPitchAdd; if (!GenericPitchForceInteger) { snprintf(generic_msg_pitch_str, 15, "%.2f", hpitch); } else { snprintf(generic_msg_pitch_str, 15, "%d", (int)hpitch); } } void generic_set_rate(int rate) { float hrate; hrate = ((float)rate) * GenericRateMultiply + GenericRateAdd; if (!GenericRateForceInteger) { snprintf(generic_msg_rate_str, 15, "%.2f", hrate); } else { snprintf(generic_msg_rate_str, 15, "%d", (int)hrate); } } void generic_set_volume(int volume) { float hvolume; DBG("Volume: %d", volume); hvolume = ((float)volume) * GenericVolumeMultiply + GenericVolumeAdd; DBG("HVolume: %f", hvolume); if (!GenericVolumeForceInteger) { snprintf(generic_msg_volume_str, 15, "%.2f", hvolume); } else { snprintf(generic_msg_volume_str, 15, "%d", (int)hvolume); } } void generic_set_language(char *lang) { generic_msg_language = (TGenericLanguage *) module_get_ht_option(GenericLanguage, lang); if (generic_msg_language == NULL) { DBG("Language %s not found in the configuration file, using defaults.", lang); generic_msg_language = (TGenericLanguage *) g_malloc(sizeof(TGenericLanguage)); generic_msg_language->code = g_strdup(lang); generic_msg_language->charset = NULL; generic_msg_language->name = g_strdup(lang); } if (generic_msg_language->name == NULL) { DBG("Language name for %s not found in the configuration file.", lang); generic_msg_language = (TGenericLanguage *) g_malloc(sizeof(TGenericLanguage)); generic_msg_language->code = g_strdup("en"); generic_msg_language->charset = g_strdup("iso-8859-1"); generic_msg_language->name = g_strdup("english"); } generic_set_voice(msg_settings.voice_type); } void generic_set_voice(SPDVoiceType voice) { assert(generic_msg_language); generic_msg_voice_str = module_getvoice(generic_msg_language->code, voice); if (generic_msg_voice_str == NULL) { DBG("Invalid voice type specified or no voice available!"); } } void generic_set_punct(SPDPunctuation punct) { if (punct == SPD_PUNCT_NONE) { generic_msg_punct_str = g_strdup((char *)GenericPunctNone); return; } else if (punct == SPD_PUNCT_SOME) { generic_msg_punct_str = g_strdup((char *)GenericPunctSome); return; } else if (punct == SPD_PUNCT_ALL) { generic_msg_punct_str = g_strdup((char *)GenericPunctAll); return; } else { DBG("ERROR: Unknown punctuation setting, ignored"); } } speech-dispatcher-0.8.3/src/modules/espeak.c0000664000175000017500000010466312536417045015734 00000000000000 /* * espeak.c - Speech Dispatcher backend for espeak * * Copyright (C) 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * @author Lukas Loehrer * Based on ibmtts.c. * * $Id: espeak.c,v 1.11 2008-10-15 17:04:36 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif /* < Includes*/ /* System includes. */ #include #include #include /* espeak header file */ #include #ifndef ESPEAK_API_REVISION #define ESPEAK_API_REVISION 1 #endif /* Speech Dispatcher includes. */ #include "spd_audio.h" #include #include "module_utils.h" /* > */ /* < Basic definitions*/ #define MODULE_NAME "espeak" #define MODULE_VERSION "0.1" #define DEBUG_MODULE 1 DECLARE_DEBUG() #define DBG_WARN(e, msg) \ if (Debug && !(e)) { \ DBG("Espeak: Warning: " msg); \ } typedef enum { FATAL_ERROR = -1, OK = 0, ERROR = 1 } TEspeakSuccess; typedef enum { IDLE, BEFORE_SYNTH, BEFORE_PLAY, SPEAKING } TEspeakState; typedef enum { ESPEAK_PAUSE_OFF, ESPEAK_PAUSE_REQUESTED, ESPEAK_PAUSE_MARK_REPORTED } TEspeakPauseState; /* > */ /* < Thread and process control. */ static TEspeakState espeak_state = IDLE; static pthread_mutex_t espeak_state_mutex; static pthread_t espeak_play_thread; static pthread_t espeak_stop_or_pause_thread; static sem_t espeak_stop_or_pause_semaphore; static pthread_mutex_t espeak_stop_or_pause_suspended_mutex; static sem_t espeak_play_semaphore; static pthread_mutex_t espeak_play_suspended_mutex; static gboolean espeak_close_requested = FALSE; static TEspeakPauseState espeak_pause_state = ESPEAK_PAUSE_OFF; static gboolean espeak_stop_requested = FALSE; /* > */ static int espeak_sample_rate = 0; static SPDVoice **espeak_voice_list = NULL; /* < The playback queue. */ typedef enum { ESPEAK_QET_AUDIO, /* Chunk of audio. */ ESPEAK_QET_INDEX_MARK, /* Index mark event. */ ESPEAK_QET_SOUND_ICON, /* A Sound Icon */ ESPEAK_QET_BEGIN, /* Beginning of speech. */ ESPEAK_QET_END /* Speech completed. */ } EPlaybackQueueEntryType; typedef struct { long num_samples; short *audio_chunk; } TPlaybackQueueAudioChunk; typedef struct { EPlaybackQueueEntryType type; union { char *markId; TPlaybackQueueAudioChunk audio; char *sound_icon_filename; } data; } TPlaybackQueueEntry; static GSList *playback_queue = NULL; static int playback_queue_size = 0; /* Number of audio frames currently in queue */ static pthread_mutex_t playback_queue_mutex; pthread_cond_t playback_queue_condition; /* When a voice is set, this is the baseline pitch of the voice. SSIP PITCH commands then adjust relative to this. */ static int espeak_voice_pitch_baseline = 50; /* */ /* < Module configuration options*/ MOD_OPTION_1_STR(EspeakPunctuationList) MOD_OPTION_1_INT(EspeakCapitalPitchRise) MOD_OPTION_1_INT(EspeakMinRate) MOD_OPTION_1_INT(EspeakNormalRate) MOD_OPTION_1_INT(EspeakMaxRate) MOD_OPTION_1_INT(EspeakListVoiceVariants) MOD_OPTION_1_INT(EspeakAudioChunkSize) MOD_OPTION_1_INT(EspeakAudioQueueMaxSize) MOD_OPTION_1_STR(EspeakSoundIconFolder) MOD_OPTION_1_INT(EspeakSoundIconVolume) /* > */ /* < Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); /* Options */ MOD_OPTION_1_INT_REG(EspeakAudioChunkSize, 2000); MOD_OPTION_1_INT_REG(EspeakAudioQueueMaxSize, 20 * 22050); MOD_OPTION_1_STR_REG(EspeakSoundIconFolder, "/usr/share/sounds/sound-icons/"); MOD_OPTION_1_INT_REG(EspeakSoundIconVolume, 0); MOD_OPTION_1_INT_REG(EspeakMinRate, 80); MOD_OPTION_1_INT_REG(EspeakNormalRate, 170); MOD_OPTION_1_INT_REG(EspeakMaxRate, 390); MOD_OPTION_1_STR_REG(EspeakPunctuationList, "@/+-_"); MOD_OPTION_1_INT_REG(EspeakCapitalPitchRise, 800); MOD_OPTION_1_INT_REG(EspeakListVoiceVariants, 0); if (EspeakCapitalPitchRise == 1 || EspeakCapitalPitchRise == 2) { EspeakCapitalPitchRise = 0; } return OK; } int module_init(char **status_info) { int ret; const char *espeak_version; DBG("Espeak: Module init()."); INIT_INDEX_MARKING(); /* Make sure the glib functions are thread safe. */ if (!g_thread_supported()) g_thread_init(NULL); *status_info = NULL; /* Report versions. */ espeak_version = espeak_Info(NULL); DBG("Espeak: espeak Output Module version %s, espeak Engine version %s", MODULE_VERSION, espeak_version); /* %s", EspeakSoundIconFolder, data, data); result = espeak_Synth(msg, strlen(msg) + 1, 0, POS_CHARACTER, 0, flags, NULL, NULL); g_free(msg); break; } case SPD_MSGTYPE_CHAR:{ wchar_t wc = 0; if (bytes == 1) { // ASCII wc = (wchar_t) data[0]; } else if (bytes == 5 && (0 == strncmp(data, "space", bytes))) { wc = (wchar_t) 0x20; } else { gsize bytes_out; gchar *tmp = g_convert(data, -1, "wchar_t", "utf-8", NULL, &bytes_out, NULL); if (tmp != NULL && bytes_out == sizeof(wchar_t)) { wchar_t *wc_ptr = (wchar_t *) tmp; wc = wc_ptr[0]; } else { DBG("Espeak: Failed to convert utf-8 to wchar_t, or not exactly one utf-8 character given."); } g_free(tmp); } char *msg = g_strdup_printf ("&#%ld;", (long)wc); result = espeak_Synth(msg, strlen(msg) + 1, 0, POS_CHARACTER, 0, flags, NULL, NULL); g_free(msg); break; } case SPD_MSGTYPE_KEY:{ /* TODO: Convert unspeakable keys to speakable form */ char *msg = g_strdup_printf ("%s", data); result = espeak_Synth(msg, strlen(msg) + 1, 0, POS_CHARACTER, 0, flags, NULL, NULL); g_free(msg); break; } case SPD_MSGTYPE_SPELL: /* TODO: Not sure what to do here... */ break; } pthread_mutex_unlock(&espeak_state_mutex); if (result != EE_OK) { return FALSE; } DBG("Espeak: Leaving module_speak() normally."); return bytes; } int module_stop(void) { DBG("Espeak: module_stop()."); pthread_mutex_lock(&espeak_state_mutex); if (espeak_state != IDLE && !espeak_stop_requested && !is_thread_busy(&espeak_stop_or_pause_suspended_mutex)) { DBG("Espeak: stopping..."); espeak_stop_requested = TRUE; /* Wake the stop_or_pause thread. */ sem_post(&espeak_stop_or_pause_semaphore); } else { DBG("Espeak: Cannot stop now."); } pthread_mutex_unlock(&espeak_state_mutex); return OK; } size_t module_pause(void) { DBG("Espeak: module_pause()."); pthread_mutex_lock(&espeak_state_mutex); if (espeak_pause_state == ESPEAK_PAUSE_OFF && !espeak_stop_requested) { espeak_pause_state = ESPEAK_PAUSE_REQUESTED; } pthread_mutex_unlock(&espeak_state_mutex); return OK; } int module_close(void) { 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("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); return 0; } /* > */ /* < Internal functions */ /* Return true if the thread is busy, i.e., suspended mutex is not locked. */ static gboolean is_thread_busy(pthread_mutex_t * suspended_mutex) { if (EBUSY == pthread_mutex_trylock(suspended_mutex)) return FALSE; else { pthread_mutex_unlock(suspended_mutex); return TRUE; } } static void espeak_state_reset() { espeak_state = IDLE; espeak_pause_state = ESPEAK_PAUSE_OFF; espeak_stop_requested = FALSE; } /* Stop or Pause thread. */ static void *_espeak_stop_or_pause(void *nothing) { int ret; DBG("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); } DBG("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. */ DBG("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) { DBG("Espeak: Stopping audio."); ret = spd_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 = spd_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); } } DBG("Espeak: Waiting for synthesis to stop."); ret = espeak_Cancel(); DBG_WARN(ret == EE_OK, "Espeak: error in espeak_Cancel()."); DBG("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(); } DBG("Espeak: Stop or pause thread ended.......\n") } pthread_exit(NULL); } static void espeak_set_rate(signed int rate) { assert(rate >= -100 && rate <= +100); int speed; int normal_rate = EspeakNormalRate, max_rate = EspeakMaxRate, min_rate = EspeakMinRate; if (rate < 0) speed = normal_rate + (normal_rate - min_rate) * rate / 100; else speed = normal_rate + (max_rate - normal_rate) * rate / 100; espeak_ERROR ret = espeak_SetParameter(espeakRATE, speed, 0); if (ret != EE_OK) { DBG("Espeak: Error setting rate %i.", speed); } else { DBG("Espeak: Rate set to %i.", speed); } } static void espeak_set_volume(signed int volume) { assert(volume >= -100 && volume <= +100); int vol; vol = volume + 100; espeak_ERROR ret = espeak_SetParameter(espeakVOLUME, vol, 0); if (ret != EE_OK) { DBG("Espeak: Error setting volume %i.", vol); } else { DBG("Espeak: Volume set to %i.", vol); } } static void espeak_set_pitch(signed int pitch) { assert(pitch >= -100 && pitch <= +100); int pitchBaseline; /* Possible range 0 to 100. */ if (pitch < 0) { pitchBaseline = ((float)(pitch + 100) * espeak_voice_pitch_baseline) / (float)100; } else { pitchBaseline = (((float)pitch * (100 - espeak_voice_pitch_baseline)) / (float)100) + espeak_voice_pitch_baseline; } assert(pitchBaseline >= 0 && pitchBaseline <= 100); espeak_ERROR ret = espeak_SetParameter(espeakPITCH, pitchBaseline, 0); if (ret != EE_OK) { DBG("Espeak: Error setting pitch %i.", pitchBaseline); } else { DBG("Espeak: Pitch set to %i.", pitchBaseline); } } static void espeak_set_punctuation_mode(SPDPunctuation punct_mode) { espeak_PUNCT_TYPE espeak_punct_mode = espeakPUNCT_SOME; switch (punct_mode) { case SPD_PUNCT_ALL: espeak_punct_mode = espeakPUNCT_ALL; break; case SPD_PUNCT_SOME: espeak_punct_mode = espeakPUNCT_SOME; break; case SPD_PUNCT_NONE: espeak_punct_mode = espeakPUNCT_NONE; break; } espeak_ERROR ret = espeak_SetParameter(espeakPUNCTUATION, espeak_punct_mode, 0); if (ret != EE_OK) { DBG("Espeak: Failed to set punctuation mode."); } else { DBG("Set punctuation mode."); } } static void espeak_set_cap_let_recogn(SPDCapitalLetters cap_mode) { int espeak_cap_mode = 0; switch (cap_mode) { case SPD_CAP_NONE: espeak_cap_mode = EspeakCapitalPitchRise; break; case SPD_CAP_SPELL: espeak_cap_mode = 2; break; case SPD_CAP_ICON: espeak_cap_mode = 1; break; } espeak_ERROR ret = espeak_SetParameter(espeakCAPITALS, espeak_cap_mode, 1); if (ret != EE_OK) { DBG("Espeak: Failed to set capitals mode."); } else { DBG("Set capitals mode."); } } /* Given a language code and SD voice code, sets the espeak voice. */ static void espeak_set_language_and_voice(char *lang, SPDVoiceType voice_code) { DBG("Espeak: set_language_and_voice %s %d", lang, voice_code); espeak_ERROR ret; unsigned char overlay = 0; switch (voice_code) { case SPD_MALE1: overlay = 0; break; case SPD_MALE2: overlay = 1; break; case SPD_MALE3: overlay = 2; break; case SPD_FEMALE1: overlay = 11; break; case SPD_FEMALE2: overlay = 12; break; case SPD_FEMALE3: overlay = 13; break; case SPD_CHILD_MALE: overlay = 4; break; case SPD_CHILD_FEMALE: overlay = 14; break; default: overlay = 0; break; } char *name = g_strdup_printf("%s+%d", lang, overlay); DBG("Espeak: set_language_and_voice name=%s", name); ret = espeak_SetVoiceByName(name); if (ret != EE_OK) { DBG("Espeak: Error selecting language %s", name); } else { DBG("Espeak: Successfully set voice to \"%s\"", name); } g_free(name); } static void espeak_set_voice(SPDVoiceType voice) { assert(msg_settings.voice.language); espeak_set_language_and_voice(msg_settings.voice.language, voice); } static void espeak_set_language(char *lang) { espeak_set_language_and_voice(lang, msg_settings.voice_type); } static void espeak_set_synthesis_voice(char *synthesis_voice) { if (synthesis_voice != NULL) { espeak_ERROR ret = espeak_SetVoiceByName(synthesis_voice); if (ret != EE_OK) { DBG("Espeak: Failed to set synthesis voice to %s.", synthesis_voice); } } } /* Callbacks */ static gboolean espeak_send_audio_upto(short *wav, int *sent, int upto) { assert(*sent >= 0); assert(upto >= 0); int numsamples = upto - (*sent); if (wav == NULL || numsamples == 0) { return TRUE; } short *start = wav + (*sent); gboolean result = espeak_add_audio_to_playback_queue(start, numsamples); *sent = upto; return result; } static int synth_callback(short *wav, int numsamples, espeak_EVENT * events) { /* Number of samples sent in current message. */ static int numsamples_sent_msg = 0; /* Number of samples already sent during this call to the callback. */ int numsamples_sent = 0; gboolean result = FALSE; pthread_mutex_lock(&espeak_state_mutex); if (espeak_state == BEFORE_SYNTH) { numsamples_sent_msg = 0; espeak_state = BEFORE_PLAY; espeak_add_flag_to_playback_queue(ESPEAK_QET_BEGIN); /* Wake up playback thread */ sem_post(&espeak_play_semaphore); } pthread_mutex_unlock(&espeak_state_mutex); if (espeak_stop_requested) { return 1; } /* Process events and audio data */ while (events->type != espeakEVENT_LIST_TERMINATED) { /* Enqueue audio upto event */ switch (events->type) { case espeakEVENT_MARK: case espeakEVENT_PLAY:{ /* Convert ms position to samples */ gint64 pos_msg = events->audio_position; pos_msg = pos_msg * espeak_sample_rate / 1000; /* Convert position in message to position in current chunk */ int upto = (int)CLAMP(pos_msg - numsamples_sent_msg, 0, numsamples); /* This is just for safety */ espeak_send_audio_upto(wav, &numsamples_sent, upto); break; } default: break; } /* Process actual event */ switch (events->type) { case espeakEVENT_MARK: result = espeak_add_mark_to_playback_queue(events->id.name); break; case espeakEVENT_PLAY: result = espeak_add_sound_icon_to_playback_queue(events-> id.name); break; case espeakEVENT_MSG_TERMINATED: // This event never has any audio in the same callback result = espeak_add_flag_to_playback_queue(ESPEAK_QET_END); break; default: break; } if (espeak_stop_requested) { return 1; } events++; } espeak_send_audio_upto(wav, &numsamples_sent, numsamples); numsamples_sent_msg += numsamples; return 0; } static int uri_callback(int type, const char *uri, const char *base) { int result = 1; if (type == 1) { /* Audio icon */ if (g_file_test(uri, G_FILE_TEST_EXISTS)) { result = 0; } } return result; } static TPlaybackQueueEntry *playback_queue_pop() { TPlaybackQueueEntry *result = NULL; pthread_mutex_lock(&playback_queue_mutex); while (!espeak_stop_requested && playback_queue == NULL) { pthread_cond_wait(&playback_queue_condition, &playback_queue_mutex); } if (!espeak_stop_requested) { result = (TPlaybackQueueEntry *) playback_queue->data; playback_queue = g_slist_remove(playback_queue, playback_queue->data); if (result->type == ESPEAK_QET_AUDIO) { playback_queue_size -= result->data.audio.num_samples; pthread_cond_signal(&playback_queue_condition); } } pthread_mutex_unlock(&playback_queue_mutex); return result; } static gboolean playback_queue_push(TPlaybackQueueEntry * entry) { pthread_mutex_lock(&playback_queue_mutex); playback_queue = g_slist_append(playback_queue, entry); if (entry->type == ESPEAK_QET_AUDIO) { playback_queue_size += entry->data.audio.num_samples; } pthread_cond_signal(&playback_queue_condition); pthread_mutex_unlock(&playback_queue_mutex); return TRUE; } /* Adds a chunk of pcm audio to the audio playback queue. Waits until there is enough space in the queue. */ static gboolean espeak_add_audio_to_playback_queue(short *audio_chunk, int num_samples) { pthread_mutex_lock(&playback_queue_mutex); while (!espeak_stop_requested && playback_queue_size > EspeakAudioQueueMaxSize) { pthread_cond_wait(&playback_queue_condition, &playback_queue_mutex); } pthread_mutex_unlock(&playback_queue_mutex); if (espeak_stop_requested) { return FALSE; } TPlaybackQueueEntry *playback_queue_entry = g_new(TPlaybackQueueEntry, 1); playback_queue_entry->type = ESPEAK_QET_AUDIO; playback_queue_entry->data.audio.num_samples = num_samples; gint nbytes = sizeof(short) * num_samples; playback_queue_entry->data.audio.audio_chunk = (short *)g_memdup((gconstpointer) audio_chunk, nbytes); playback_queue_push(playback_queue_entry); return TRUE; } /* Adds an Index Mark to the audio playback queue. */ static gboolean espeak_add_mark_to_playback_queue(const char *markId) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); playback_queue_entry->type = ESPEAK_QET_INDEX_MARK; playback_queue_entry->data.markId = g_strdup(markId); return playback_queue_push(playback_queue_entry); } /* Adds a begin or end flag to the playback queue. */ static gboolean espeak_add_flag_to_playback_queue(EPlaybackQueueEntryType type) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); playback_queue_entry->type = type; return playback_queue_push(playback_queue_entry); } /* Add a sound icon to the playback queue. */ static gboolean espeak_add_sound_icon_to_playback_queue(const char *filename) { TPlaybackQueueEntry *playback_queue_entry = (TPlaybackQueueEntry *) g_malloc(sizeof(TPlaybackQueueEntry)); playback_queue_entry->type = ESPEAK_QET_SOUND_ICON; playback_queue_entry->data.sound_icon_filename = g_strdup(filename); return playback_queue_push(playback_queue_entry); } /* Deletes an entry from the playback audio queue, freeing memory. */ static void espeak_delete_playback_queue_entry(TPlaybackQueueEntry * playback_queue_entry) { switch (playback_queue_entry->type) { case ESPEAK_QET_AUDIO: g_free(playback_queue_entry->data.audio.audio_chunk); break; case ESPEAK_QET_INDEX_MARK: g_free(playback_queue_entry->data.markId); break; case ESPEAK_QET_SOUND_ICON: g_free(playback_queue_entry->data.sound_icon_filename); break; default: break; } g_free(playback_queue_entry); } /* Erases the entire playback queue, freeing memory. */ static void espeak_clear_playback_queue() { pthread_mutex_lock(&playback_queue_mutex); while (NULL != playback_queue) { TPlaybackQueueEntry *playback_queue_entry = playback_queue->data; espeak_delete_playback_queue_entry(playback_queue_entry); playback_queue = g_slist_remove(playback_queue, playback_queue->data); } playback_queue = NULL; playback_queue_size = 0; pthread_mutex_unlock(&playback_queue_mutex); } /* Sends a chunk of audio to the audio player and waits for completion or error. */ static gboolean espeak_send_to_audio(TPlaybackQueueEntry * playback_queue_entry) { int ret = 0; AudioTrack track; track.num_samples = playback_queue_entry->data.audio.num_samples; track.num_channels = 1; track.sample_rate = espeak_sample_rate; track.bits = 16; track.samples = playback_queue_entry->data.audio.audio_chunk; DBG("Espeak: Sending %i samples to audio.", track.num_samples); ret = module_tts_output(track, SPD_AUDIO_LE); if (ret < 0) { DBG("ERROR: Can't play track for unknown reason."); return FALSE; } DBG("Espeak: Sent to audio."); return TRUE; } /* Playback thread. */ static void *_espeak_play(void *nothing) { char *markId; TPlaybackQueueEntry *playback_queue_entry = NULL; DBG("Espeak: Playback 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_play_semaphore)) { pthread_mutex_lock(&espeak_play_suspended_mutex); sem_wait(&espeak_play_semaphore); pthread_mutex_unlock(&espeak_play_suspended_mutex); } DBG("Espeak: Playback semaphore on."); if (espeak_close_requested) break; if (espeak_state < BEFORE_PLAY) { /* This can happen after wake-up from suspend-to-disk */ DBG("Espeak: Warning: Spurious wake of of playback thread."); continue; } while (1) { gboolean finished = FALSE; playback_queue_entry = playback_queue_pop(); if (playback_queue_entry == NULL) { DBG("Espeak: playback thread detected stop."); break; } switch (playback_queue_entry->type) { case ESPEAK_QET_AUDIO: espeak_send_to_audio(playback_queue_entry); break; case ESPEAK_QET_INDEX_MARK: markId = playback_queue_entry->data.markId; DBG("Espeak: reporting index mark |%s|.", markId); module_report_index_mark(markId); DBG("Espeak: index mark reported."); pthread_mutex_lock(&espeak_state_mutex); if (espeak_state == SPEAKING && espeak_pause_state == ESPEAK_PAUSE_REQUESTED && !is_thread_busy (&espeak_stop_or_pause_suspended_mutex) && g_str_has_prefix(markId, "__spd_")) { DBG("Espeak: Pause requested in playback thread. Stopping."); espeak_stop_requested = TRUE; espeak_pause_state = ESPEAK_PAUSE_MARK_REPORTED; sem_post (&espeak_stop_or_pause_semaphore); finished = TRUE; } pthread_mutex_unlock(&espeak_state_mutex); break; case ESPEAK_QET_SOUND_ICON: module_play_file(playback_queue_entry-> data.sound_icon_filename); break; case ESPEAK_QET_BEGIN:{ gboolean report_begin = FALSE; pthread_mutex_lock(&espeak_state_mutex); if (espeak_state == BEFORE_PLAY) { espeak_state = SPEAKING; report_begin = TRUE; } pthread_mutex_unlock (&espeak_state_mutex); if (report_begin) module_report_event_begin(); break; } case ESPEAK_QET_END: pthread_mutex_lock(&espeak_state_mutex); DBG("Espeak: playback thread got END from queue."); if (espeak_state == SPEAKING) { if (!espeak_stop_requested) { DBG("Espeak: playback thread reporting end."); espeak_state = IDLE; espeak_pause_state = ESPEAK_PAUSE_OFF; } finished = TRUE; } pthread_mutex_unlock(&espeak_state_mutex); if (finished) module_report_event_end(); break; } espeak_delete_playback_queue_entry (playback_queue_entry); if (finished) break; } } DBG("Espeak: Playback thread ended......."); return 0; } static SPDVoice **espeak_list_synthesis_voices() { SPDVoice **result = NULL; SPDVoice *voice = NULL; SPDVoice *vo = NULL; const espeak_VOICE **espeak_voices = NULL; const espeak_VOICE **espeak_variants = NULL; espeak_VOICE *variant_spec = NULL; const espeak_VOICE *v = NULL; GQueue *voice_list = NULL; GQueue *variant_list = NULL; GList *voice_list_iter = NULL; GList *variant_list_iter = NULL; const gchar *first_lang = NULL; gchar *lang = NULL; gchar *variant = NULL; gchar *dash = NULL; gchar *vname = NULL; int numvoices = 0; int numvariants = 0; int totalvoices = 0; int i = 0; espeak_voices = espeak_ListVoices(NULL); voice_list = g_queue_new(); for (i = 0; espeak_voices[i] != NULL; i++) { v = espeak_voices[i]; if (!g_str_has_prefix(v->identifier, "mb/")) { /* Not an mbrola voice */ voice = g_new0(SPDVoice, 1); voice->name = g_strdup(v->name); first_lang = v->languages + 1; lang = NULL; variant = NULL; if (g_utf8_validate(first_lang, -1, NULL)) { dash = g_utf8_strchr(first_lang, -1, '-'); if (dash != NULL) { /* There is probably a variant string (like en-uk) */ lang = g_strndup(first_lang, dash - first_lang); variant = g_strdup(g_utf8_next_char(dash)); } else { lang = g_strdup(first_lang); } } else { DBG("Espeak: Not a valid utf8 string: %s", first_lang);; } voice->language = lang; voice->variant = variant; g_queue_push_tail(voice_list, voice); } } numvoices = g_queue_get_length(voice_list); DBG("Espeak: %d voices total.", numvoices) if (EspeakListVoiceVariants) { variant_spec = g_new0(espeak_VOICE, 1); variant_spec->languages = "variant"; espeak_variants = espeak_ListVoices(variant_spec); variant_list = g_queue_new(); for (i = 0; espeak_variants[i] != NULL; i++) { v = espeak_variants[i]; vname = g_strdup(v->name); g_queue_push_tail(variant_list, vname); } numvariants = g_queue_get_length(variant_list); DBG("Espeak: %d variants total.", numvariants) } totalvoices = (numvoices * numvariants) + numvoices; result = g_new0(SPDVoice *, totalvoices + 1); voice_list_iter = g_queue_peek_head_link(voice_list); for (i = 0; i < totalvoices; i++) { result[i] = voice_list_iter->data; if (!g_queue_is_empty(variant_list)) { vo = voice_list_iter->data; variant_list_iter = g_queue_peek_head_link(variant_list); while (variant_list_iter != NULL && variant_list_iter->data != NULL) { voice = g_new0(SPDVoice, 1); voice->name = g_strdup_printf("%s+%s", vo->name, variant_list_iter->data); voice->language = g_strdup(vo->language); voice->variant = g_strdup(vo->variant); result[++i] = voice; variant_list_iter = variant_list_iter->next; } } voice_list_iter = voice_list_iter->next; } if (voice_list != NULL) g_queue_free(voice_list); if (variant_list != NULL) g_queue_free_full(variant_list, (GDestroyNotify)g_free); if (variant_spec != NULL) g_free(variant_spec); result[i] = NULL; DBG("Espeak: %d usable voices.", totalvoices); return result; } static void espeak_free_voice_list() { if (espeak_voice_list != NULL) { int i; for (i = 0; espeak_voice_list[i] != NULL; i++) { g_free(espeak_voice_list[i]->name); g_free(espeak_voice_list[i]->language); g_free(espeak_voice_list[i]->variant); g_free(espeak_voice_list[i]); } g_free(espeak_voice_list); espeak_voice_list = NULL; } } static TEspeakSuccess espeak_set_punctuation_list_from_utf8(const gchar * punct) { TEspeakSuccess result = ERROR; wchar_t *wc_punct = (wchar_t *) g_convert(punct, -1, "wchar_t", "utf-8", NULL, NULL, NULL); if (wc_punct != NULL) { espeak_ERROR ret = espeak_SetPunctuationList(wc_punct); if (ret == EE_OK) result = OK; g_free(wc_punct); } return result; } /* > */ /* local variables: */ /* folded-file: t */ /* c-basic-offset: 4 */ /* end: */ speech-dispatcher-0.8.3/src/modules/module_utils_addvoice.c0000664000175000017500000001047012522771346021021 00000000000000/* * module_utils_addvoice.c - Functionality for the DotConf AddVoice feature * * Copyright (C) 2001, 2002, 2003, 2006, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: module_utils_addvoice.c,v 1.5 2007-07-29 23:43:33 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "module_utils.h" GHashTable *module_voice_table = NULL; typedef struct { char *male1; char *male2; char *male3; char *female1; char *female2; char *female3; char *child_male; char *child_female; } SPDVoiceDef; DOTCONF_CB(AddVoice_cb) { SPDVoiceDef *voices; char *language = cmd->data.list[0]; char *symbolic; char *voicename = cmd->data.list[2]; char *key; SPDVoiceDef *value; if (language == NULL) { DBG("Missing language.\n"); return NULL; } if (cmd->data.list[1] == NULL) { DBG("Missing symbolic name.\n"); return NULL; } if (voicename == NULL) { DBG("Missing voice name for %s\n", cmd->data.list[0]); return NULL; } if (module_voice_table == NULL) { return NULL; } symbolic = (char *)g_ascii_strup(cmd->data.list[1], strlen(cmd->data.list[1])); voices = g_hash_table_lookup(module_voice_table, language); if (voices == NULL) { key = (char *)g_strdup(language); value = (SPDVoiceDef *) g_malloc(sizeof(SPDVoiceDef)); value->male1 = NULL; value->male2 = NULL; value->male3 = NULL; value->female1 = NULL; value->female2 = NULL; value->female3 = NULL; value->child_male = NULL; value->child_female = NULL; g_hash_table_insert(module_voice_table, key, value); voices = value; } if (!strcmp(symbolic, "MALE1")) voices->male1 = g_strdup(voicename); else if (!strcmp(symbolic, "MALE2")) voices->male2 = g_strdup(voicename); else if (!strcmp(symbolic, "MALE3")) voices->male3 = g_strdup(voicename); else if (!strcmp(symbolic, "FEMALE1")) voices->female1 = g_strdup(voicename); else if (!strcmp(symbolic, "FEMALE2")) voices->female2 = g_strdup(voicename); else if (!strcmp(symbolic, "FEMALE3")) voices->female3 = g_strdup(voicename); else if (!strcmp(symbolic, "CHILD_MALE")) voices->child_male = g_strdup(voicename); else if (!strcmp(symbolic, "CHILD_FEMALE")) voices->child_female = g_strdup(voicename); else { DBG("Unrecognized voice name in configuration\n"); return NULL; } return NULL; } void module_register_settings_voices(void) { module_voice_table = g_hash_table_new(g_str_hash, g_str_equal); module_dc_options = module_add_config_option(module_dc_options, &module_num_dc_options, "AddVoice", ARG_LIST, AddVoice_cb, NULL, 0); } char *module_getvoice(char *language, SPDVoiceType voice) { SPDVoiceDef *voices; char *ret; if (module_voice_table == NULL) { DBG("Can't get voice because voicetable is NULL\n"); return NULL; } voices = g_hash_table_lookup(module_voice_table, language); if (voices == NULL) { DBG("There are no voices in the table for language=%s\n", language); return NULL; } switch (voice) { case SPD_MALE1: ret = voices->male1; break; case SPD_MALE2: ret = voices->male2; break; case SPD_MALE3: ret = voices->male3; break; case SPD_FEMALE1: ret = voices->female1; break; case SPD_FEMALE2: ret = voices->female2; break; case SPD_FEMALE3: ret = voices->female3; break; case SPD_CHILD_MALE: ret = voices->child_male; break; case SPD_CHILD_FEMALE: ret = voices->child_female; break; default: printf("Unknown voice"); return NULL; } if (ret == NULL) ret = voices->male1; if (ret == NULL) fprintf(stderr, "No voice available for this output module!"); return ret; } speech-dispatcher-0.8.3/src/modules/cicero.c0000664000175000017500000002316312522771346015725 00000000000000/* * cicero.c - Speech Dispatcher backend for Cicero French TTS engine * * Copyright (C) 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * @author: Olivier BERT */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "module_utils.h" #define MODULE_NAME "cicero" #define MODULE_VERSION "0.3" // #define DEBUG_MODULE 1 DECLARE_DEBUG() /* Thread and process control */ static int cicero_speaking = 0; static pthread_t cicero_speaking_thread; static sem_t cicero_semaphore; static char **cicero_message; static SPDMessageType cicero_message_type; static int cicero_position = 0; static int cicero_pause_requested = 0; signed int cicero_volume = 0; static unsigned int CiceroMaxChunkLength = 500; /* Internal functions prototypes */ static void cicero_set_rate(signed int rate); static void *_cicero_speak(void *); int cicero_stop = 0; /* ** Config file options */ //MOD_OPTION_1_STR(CiceroWrapper); MOD_OPTION_1_STR(CiceroExecutable) MOD_OPTION_1_STR(CiceroExecutableLog) /* ** Pipes to cicero */ static int fd1[2], fd2[2]; /* ** Some internal functions */ static long int millisecondsBetween(const struct timeval *from, const struct timeval *to) { return ((to->tv_sec - from->tv_sec) * 1000) + ((to->tv_usec - from->tv_usec) / 1000); } long int millisecondsSince(const struct timeval *from) { struct timeval now; gettimeofday(&now, NULL); return millisecondsBetween(from, &now); } static int hasTimedOut(int milliseconds) { static struct timeval start = { 0, 0 }; if (milliseconds) return millisecondsSince(&start) >= milliseconds; gettimeofday(&start, NULL); return 1; } static void mywrite(int fd, const void *buf, int len) { char *pos = (char *)buf; int w; if (fd < 0) return; hasTimedOut(0); do { if ((w = write(fd, pos, len)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; else if (errno == EPIPE) { DBG("Broken pipe\n"); } else perror("Pipe write"); return; } pos += w; len -= w; } while (len && !hasTimedOut(600)); if (len) fprintf(stderr, "Pipe write timed out"); } /* Public functions */ int module_load(void) { INIT_SETTINGS_TABLES(); REGISTER_DEBUG(); MOD_OPTION_1_STR_REG(CiceroExecutable, "/usr/bin/cicero"); MOD_OPTION_1_STR_REG(CiceroExecutableLog, "/var/log/speech-dispatcher/cicero-executable.log"); return 0; } int module_init(char **status_info) { int ret; int stderr_redirect; DBG("Module init\n"); (void)signal(SIGPIPE, SIG_IGN); DBG("call the pipe system call\n"); if (pipe(fd1) < 0 || pipe(fd2) < 0) { DBG("Error pipe()\n"); return -1; } DBG("Call fork system call\n"); stderr_redirect = open(CiceroExecutableLog, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (stderr_redirect == -1) { DBG("ERROR: Openning debug file for Cicero binary failed: (error=%d) %s", stderr_redirect, strerror(errno)); } else { DBG("Cicero synthesizer logging to file %s", CiceroExecutableLog); } switch (fork()) { case -1:{ DBG("Error fork()\n"); return -1; } case 0:{ if (dup2(fd2[0], 0) < 0 /* stdin */ || dup2(fd1[1], 1) < 0) { /* stdout */ DBG("Error dup2()\n"); exit(1); } if (stderr_redirect >= 0) { if (dup2(stderr_redirect, 2) < 0) DBG("ERROR: Couldn't redirect stderr, not logging for Cicero synthesizer."); } /*close(2); close(fd2[1]); close(fd1[0]); */ int i = 0; for (i = 3; i < 256; i++) close(i); (void)signal(SIGPIPE, SIG_IGN); execl(CiceroExecutable, CiceroExecutable, (void *)NULL); DBG("Error execl()\n"); exit(1); } default:{ close(fd1[1]); close(fd2[0]); if (fcntl(fd2[1], F_SETFL, O_NDELAY) < 0 || fcntl(fd1[0], F_SETFL, O_NDELAY) < 0) { DBG("Error fcntl()\n"); return -1; } } } cicero_message = g_malloc(sizeof(char *)); *cicero_message = NULL; sem_init(&cicero_semaphore, 0, 0); DBG("Cicero: creating new thread for cicero_tracking\n"); cicero_speaking = 0; ret = pthread_create(&cicero_speaking_thread, NULL, _cicero_speak, NULL); if (ret != 0) { DBG("Cicero: thread failed\n"); *status_info = g_strdup("The module couldn't initialize threads " "This can be either an internal problem or an " "architecture problem. If you are sure your architecture " "supports threads, please report a bug."); return -1; } *status_info = g_strdup("Cicero initialized successfully."); return 0; } SPDVoice **module_list_voices(void) { return NULL; } int module_speak(gchar * data, size_t bytes, SPDMessageType msgtype) { DBG("Module speak\n"); /* The following should not happen */ if (cicero_speaking) { DBG("Speaking when requested to write"); return 0; } DBG("Requested data: |%s|\n", data); if (*cicero_message != NULL) { g_free(*cicero_message); *cicero_message = NULL; } *cicero_message = module_strip_ssml(data); cicero_message_type = SPD_MSGTYPE_TEXT; /* Setting voice */ /* UPDATE_PARAMETER(voice, cicero_set_voice); */ UPDATE_PARAMETER(rate, cicero_set_rate); /* UPDATE_PARAMETER(pitch, cicero_set_pitch); */ /* Send semaphore signal to the speaking thread */ cicero_speaking = 1; sem_post(&cicero_semaphore); DBG("Cicero: leaving module_speak() normaly\n\r"); return bytes; } int module_stop(void) { unsigned char c = 1; DBG("cicero: stop()\n"); cicero_stop = 1; mywrite(fd2[1], &c, 1); return 0; } size_t module_pause(void) { DBG("pause requested\n"); if (cicero_speaking) { DBG("Pause not supported by cicero\n"); cicero_pause_requested = 1; module_stop(); return -1; } cicero_pause_requested = 0; return 0; } int module_close(void) { DBG("cicero: close()\n"); if (cicero_speaking) { module_stop(); } if (module_terminate_thread(cicero_speaking_thread) != 0) return -1; sem_destroy(&cicero_semaphore); return 0; } /* Internal functions */ void *_cicero_speak(void *nothing) { char stop_code = 1; unsigned int pos = 0, inx = 0, len = 0; int flag = 0; int bytes; int ret; char buf[CiceroMaxChunkLength], l[5], b[2]; struct pollfd ufds = { fd1[0], POLLIN | POLLPRI, 0 }; DBG("cicero: speaking thread starting.......\n"); set_speaking_thread_parameters(); while (1) { sem_wait(&cicero_semaphore); DBG("Semaphore on\n"); len = strlen(*cicero_message); cicero_stop = 0; cicero_speaking = 1; cicero_position = 0; pos = 0; module_report_event_begin(); while (1) { flag = 0; if (cicero_stop) { DBG("Stop in thread, terminating"); cicero_speaking = 0; module_report_event_stop(); break; } if (pos >= len) { /* end of text */ DBG("End of text in speaking thread\n"); module_report_event_end(); cicero_speaking = 0; break; } DBG("Call get_parts: pos=%d, msg=\"%s\" \n", pos, *cicero_message); bytes = module_get_message_part(*cicero_message, buf, &pos, CiceroMaxChunkLength, ".;?!"); DBG("Returned %d bytes from get_part\n", bytes); if (bytes < 0) { DBG("ERROR: Can't get message part, terminating"); cicero_speaking = 0; module_report_event_stop(); break; } buf[bytes] = 0; DBG("Text to synthesize is '%s'\n", buf); if (bytes > 0) { DBG("Speaking ..."); DBG("Trying to synthesize text"); l[0] = 4; /* say code for UTF-8 data */ l[1] = bytes >> 8; l[2] = bytes & 0xFF; l[3] = 0, l[4] = 0; mywrite(fd2[1], &stop_code, 1); mywrite(fd2[1], l, 5); mywrite(fd2[1], buf, bytes); cicero_position = 0; while (1) { ret = poll(&ufds, 1, 60); if (ret) DBG("poll() system call returned %d, events=%d\n", ret, ufds.events); if (ret < 0) { perror("poll"); module_report_event_stop(); flag = 1; cicero_speaking = 0; break; } if (ret > 0) safe_read(fd1[0], b, 2); if (cicero_stop) { cicero_speaking = 0; module_report_event_stop(); flag = 1; break; } if (ret == 0) continue; inx = (b[0] << 8 | b[1]); DBG("Tracking: index=%u, bytes=%d\n", inx, bytes); if (inx == bytes) { cicero_speaking = 0; break; } else { if (inx) cicero_position = inx; } } } else { cicero_speaking = 0; break; } if (flag) break; } cicero_stop = 0; } cicero_speaking = 0; DBG("cicero: tracking thread ended.......\n"); pthread_exit(NULL); } static void cicero_set_rate(signed int rate) { const float spkRateTable[] = { 0.3333, 0.3720, 0.4152, 0.4635, 0.5173, 0.5774, 0.6444, 0.7192, 0.8027, 0.8960, 1.0000, 1.1161, 1.2457, 1.3904, 1.5518, 1.7320, 1.9332, 2.1577, 2.4082, 2.6879, 3.0000 }; float expand; rate -= 100; rate = abs(rate); rate /= 10; expand = spkRateTable[rate]; unsigned char *p = (unsigned char *)&expand; unsigned char l[5]; l[0] = 3; l[1] = p[3]; l[2] = p[2]; l[3] = p[1]; l[4] = p[0]; mywrite(fd2[1], l, 5); } speech-dispatcher-0.8.3/src/modules/spd_audio.h0000644000175000017500000000261012233560613016415 00000000000000 /* * spd_audio.h -- The SPD Audio Library Header * * Copyright (C) 2004 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: spd_audio.h,v 1.21 2008-10-15 17:28:17 hanke Exp $ */ #ifndef __SPD_AUDIO_H #define __SPD_AUDIO_H #include #define SPD_AUDIO_LIB_PREFIX "spd_" AudioID *spd_audio_open(char *name, void **pars, char **error); int spd_audio_play(AudioID * id, AudioTrack track, AudioFormat format); int spd_audio_stop(AudioID * id); int spd_audio_close(AudioID * id); int spd_audio_set_volume(AudioID * id, int volume); void spd_audio_set_loglevel(AudioID * id, int level); char const *spd_audio_get_playcmd(AudioID * id); #endif /* ifndef #__SPD_AUDIO_H */ speech-dispatcher-0.8.3/src/modules/module_main.c0000664000175000017500000001143512536417045016747 00000000000000/* * module_main.c - One way of doing main() in output modules. * * Copyright (C) 2001, 2002, 2003, 2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: module_main.c,v 1.17 2008-10-15 17:05:37 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "module_utils.h" #define PROCESS_CMD(command, function) \ if (!strcmp(cmd_buf, #command"\n")){ \ char *msg; \ pthread_mutex_lock(&module_stdout_mutex); \ if (printf("%s\n", msg = (char*) function()) < 0){ \ DBG("Broken pipe, exiting...\n"); \ ret = 2; \ break; \ } \ fflush(stdout); \ pthread_mutex_unlock(&module_stdout_mutex);\ g_free(msg); \ } #define PROCESS_CMD_W_ARGS(command, function) \ if (!strncmp(cmd_buf, #command, strlen(#command))){ \ char *msg; \ pthread_mutex_lock(&module_stdout_mutex); \ if (printf("%s\n", msg = (char*) function(cmd_buf)) < 0){ \ DBG("Broken pipe, exiting...\n"); \ ret = 2; \ break; \ } \ fflush(stdout); \ pthread_mutex_unlock(&module_stdout_mutex);\ g_free(msg); \ } #define PROCESS_CMD_NRP(command, function) \ if (!strcmp(cmd_buf, #command"\n")){ \ function(); \ } int main(int argc, char *argv[]) { char *cmd_buf; int ret; size_t n; char *configfilename = NULL; char *status_info = NULL; g_thread_init(NULL); /* Initialize ltdl's list of preloaded audio backends. */ LTDL_SET_PRELOADED_SYMBOLS(); module_num_dc_options = 0; module_audio_id = 0; if (argc >= 2) { configfilename = g_strdup(argv[1]); } ret = module_load(); if (ret == -1) { module_close(); exit(1); } if (configfilename != NULL) { /* Add the LAST option */ module_dc_options = module_add_config_option(module_dc_options, &module_num_dc_options, "", 0, NULL, NULL, 0); configfile = dotconf_create(configfilename, module_dc_options, 0, CASE_INSENSITIVE); if (configfile) { if (dotconf_command_loop(configfile) == 0) { DBG("Error reading config file\n"); module_close(); exit(1); } dotconf_cleanup(configfile); DBG("Configuration (pre) has been read from \"%s\"\n", configfilename); g_free(configfilename); } else { DBG("Can't read specified config file!\n"); } } else { DBG("No config file specified, using defaults...\n"); } cmd_buf = NULL; n = 0; ret = spd_getline(&cmd_buf, &n, stdin); if (ret == -1) { DBG("Broken pipe when reading INIT, exiting... \n"); module_close(); exit(2); } if (strcmp(cmd_buf, "INIT\n")) { DBG("ERROR: Wrong communication from module client: didn't call INIT\n"); module_close(); exit(3); } ret = module_init(&status_info); if (status_info == NULL) { status_info = g_strdup("unknown, was not set by module"); } if (ret != 0) { printf("399-%s\n", status_info); printf("%s\n", "399 ERR CANT INIT MODULE"); g_free(status_info); module_close(); exit(1); } printf("299-%s\n", status_info); ret = printf("%s\n", "299 OK LOADED SUCCESSFULLY"); if (ret < 0) { DBG("Broken pipe, exiting...\n"); module_close(); exit(2); } fflush(stdout); g_free(status_info); g_free(cmd_buf); while (1) { cmd_buf = NULL; n = 0; ret = spd_getline(&cmd_buf, &n, stdin); if (ret == -1) { DBG("Broken pipe, exiting... \n"); ret = 2; break; } DBG("CMD: <%s>", cmd_buf); PROCESS_CMD(SPEAK, do_speak) else PROCESS_CMD(SOUND_ICON, do_sound_icon) else PROCESS_CMD(CHAR, do_char) else PROCESS_CMD(KEY, do_key) else PROCESS_CMD_NRP(STOP, do_stop) else PROCESS_CMD_NRP(PAUSE, do_pause) else PROCESS_CMD(LIST VOICES, do_list_voices) else PROCESS_CMD(SET, do_set) else PROCESS_CMD(AUDIO, do_audio) else PROCESS_CMD(LOGLEVEL, do_loglevel) else PROCESS_CMD_W_ARGS(DEBUG, do_debug) else if (!strcmp(cmd_buf, "QUIT\n")) { do_quit(); exit(0); } else { printf("300 ERR UNKNOWN COMMAND\n"); fflush(stdout); } g_free(cmd_buf); } module_close(); exit(ret); } #undef PROCESS_CMD speech-dispatcher-0.8.3/src/clients/0000775000175000017500000000000012536424375014363 500000000000000speech-dispatcher-0.8.3/src/clients/spdsend/0000775000175000017500000000000012536424375016023 500000000000000speech-dispatcher-0.8.3/src/clients/spdsend/README0000644000175000017500000000151512233560613016611 00000000000000This is a simple command line client to Speech Dispatcher. It may be useful in programs, which don't want to use direct socket communication with Speech Dispatcher for some reason. To compile the program, just run `make'. To install it, run `make install'. The following operations are supported: $ spdsend --open HOST PORT Open new connection to Speech Dispatcher running at HOST:PORT and print the connection identifier on the standard output. $ spdsend --close CONNECTION Close the given Speech Dispatcher CONNECTION. $ spdsend --send CONNECTION Read an SSIP command from standard input, forward it to Speech Dispatcher CONNECTION and print the answer on the standard output. You can send your bug reports, patches, suggestions, etc. to the mailing list speechd@lists.freebsoft.org. -- Milan Zamazal speech-dispatcher-0.8.3/src/clients/spdsend/common.c0000644000175000017500000000364512233560613017373 00000000000000/* common.c -- Common parts of the client and the server Author: Milan Zamazal */ /* Copyright (C) 2004 Brailcom, o.p.s. COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "spdsend.h" const long CONNECTION_ID_MIN = 1; const long CONNECTION_ID_MAX = 1000; const int EXIT_OK = 0; const int EXIT_ERROR = 1; extern Success write_data(Stream s, const void *buffer, size_t size) { int written; for (; size > 0; size -= written, buffer += written) { written = write(s, buffer, size); if (written < 0) return ERROR; } return OK; } extern int read_data(Stream s, void *buffer, size_t max_size) { size_t nread = 0, n; while (nread < max_size) { n = read(s, buffer, max_size); if (n < 0) return NONE; if (n == 0) break; nread += n; buffer += n; max_size -= n; } return nread; } extern Success forward_data(Stream from, Stream to, bool closep) { const size_t buffer_size = 4096; char buffer[buffer_size]; ssize_t n; while ((n = read(from, buffer, buffer_size)) > 0) { if (write_data(to, buffer, n) == ERROR) return ERROR; } if (closep) shutdown(to, SHUT_WR); return (n == NONE ? ERROR : OK); } speech-dispatcher-0.8.3/src/clients/spdsend/spdsend.h0000644000175000017500000000345612233560613017550 00000000000000/* Declarations for spdsend Author: Milan Zamazal */ /* Copyright (C) 2004 Brailcom, o.p.s. COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __SPDSEND_H #define __SPDSEND_H #define _GNU_SOURCE #include /* Configuration */ #ifndef LISTEN_QUEUE_LENGTH #define LISTEN_QUEUE_LENGTH 100 #endif /* Types */ typedef enum { FALSE, TRUE } bool; typedef int Stream; typedef int Connection_Id; typedef enum { OK, ERROR } Success; #define NONE -1 /* common.c */ extern Success write_data(Stream s, const void *buffer, size_t size); extern int read_data(Stream s, void *buffer, size_t max_size); extern Success forward_data(Stream from, Stream to, bool closep); typedef enum { A_OPEN, A_CLOSE, A_DATA } Action; typedef enum { OK_CODE, ER_CODE } Result; extern const long CONNECTION_ID_MIN; extern const long CONNECTION_ID_MAX; extern const int EXIT_OK; extern const int EXIT_ERROR; /* server.c */ extern Stream open_server(); /* client.c */ extern Success open_connection(Stream server, const char *host, int port); extern Success close_connection(Stream server, Connection_Id id); extern Success send_command(Stream server, Connection_Id id); #endif speech-dispatcher-0.8.3/src/clients/spdsend/server.c0000664000175000017500000002230612522771346017416 00000000000000/* server.c -- Server part of spdsend Author: Milan Zamazal */ /* Copyright (C) 2004 Brailcom, o.p.s. COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "spdsend.h" #ifndef USE_THREADS #define USE_THREADS 1 #endif #include #include #include #include #if USE_THREADS #include #endif #include #include #include #include #include #include #include #include #include #if !(defined(__GLIBC__) && defined(_GNU_SOURCE)) /* Added by Willie Walker - TEMP_FAILURE_RETRY, strndup, and getline * are gcc-isms */ ssize_t getline(char **lineptr, size_t * n, FILE * f); #endif /* Utilities */ static void system_error(const char *message) { perror(message); exit(1); } /* Connection management */ Stream *connections; #if USE_THREADS pthread_mutex_t connections_mutex = PTHREAD_MUTEX_INITIALIZER; #endif static Stream get_connection(Connection_Id id) { return connections[id]; } static void set_connection(Connection_Id id, Stream s) { #if USE_THREADS pthread_mutex_lock(&connections_mutex); #endif connections[id] = s; #if USE_THREADS pthread_mutex_unlock(&connections_mutex); #endif } static Connection_Id new_connection(Stream s) { #if USE_THREADS pthread_mutex_lock(&connections_mutex); #endif int id; for (id = CONNECTION_ID_MIN; id < CONNECTION_ID_MAX && connections[id] != NONE; id++) ; if (id >= CONNECTION_ID_MAX) return NONE; connections[id] = s; #if USE_THREADS pthread_mutex_unlock(&connections_mutex); #endif return id; } static Connection_Id do_open_connection(const char *host, int port) { int sock = socket(AF_INET, SOCK_STREAM, 0); { struct sockaddr_in name; name.sin_family = AF_INET; name.sin_port = htons(port); { struct hostent *hostinfo; hostinfo = gethostbyname(host); if (hostinfo == NULL) return NONE; name.sin_addr = *(struct in_addr *)hostinfo->h_addr; } if (connect(sock, (struct sockaddr *)&name, sizeof(name)) < 0) return NONE; { int arg = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &arg, sizeof(int)); } } { Connection_Id id = new_connection(sock); if (id == NONE) close(sock); return id; } } static Success do_close_connection(Connection_Id id) { Stream c = get_connection(id); if (c == NONE) return ERROR; close(c); set_connection(id, NONE); return OK; } static Success do_send_data(Connection_Id id, Stream from, Stream to, Success(*forwarder) (Stream, Stream, bool)) { int sock = get_connection(id); if (sock == NONE) return ERROR; if (from == NONE) from = sock; else if (to == NONE) to = sock; { Success result = ((*forwarder) (from, to, FALSE)); if (result != OK) do_close_connection(id); return result; } } /* Processing requests */ /* Protocol: Client request: First comes the action code, of the type Action. If Action is A_OPEN, the following data follows: int port, int strlen(hostname), hostname Else: Connection_Id Then, if Action is A_DATA, the SSIP lines follow. Server answer: The result code, of the type Result. If Result is OK, Connection_Id follows. Additionally, if Action is A_DATA, SSIP reply follows. */ static Success report(Stream s, Result code) { return write_data(s, &code, sizeof(Result)); } static Success report_ok(Stream s, Connection_Id id) { if (report(s, OK_CODE) == OK && write_data(s, &id, sizeof(Connection_Id)) == OK) return OK; else return ERROR; } static Success report_error(Stream s) { return report(s, ER_CODE); } static Connection_Id read_id(Stream s) { Connection_Id id; if (read_data(s, &id, sizeof(Connection_Id)) == ERROR) return NONE; return id; } static Success forward_ssip_answer(Stream from, Stream to, bool _closep) { int result = OK; FILE *f = fdopen(from, "r"); size_t line_size = 256; char *line = malloc(line_size); if (line == NULL) system_error("memory allocation"); while (1) { int n = getline(&line, &line_size, f); if (n < 0 || write_data(to, line, n) == ERROR) { result = ERROR; break; } if (n > 3 && line[3] == ' ') break; } free(line); return result; } static void process_open(Stream s) { Connection_Id id; int port; int hostlen; if (read_data(s, &port, sizeof(int)) != sizeof(int)) { report_error(s); return; } if (read_data(s, &hostlen, sizeof(int)) != sizeof(int)) { report_error(s); return; } { char *host = malloc(hostlen + 1); if (host == NULL) system_error("memory allocation"); if (read_data(s, host, hostlen) != hostlen) { free(host); report_error(s); return; } host[hostlen] = '\0'; id = do_open_connection(host, port); free(host); } if (id == NONE) report_error(s); else report_ok(s, id); } static void process_close(Stream s) { Connection_Id id = read_id(s); if (id != NONE && do_close_connection(id) == OK) report_ok(s, id); else report_error(s); } static void process_data(Stream s) { Connection_Id id = read_id(s); if (id != NONE) report_ok(s, id); else report_error(s); if (do_send_data(id, s, NONE, forward_data) == OK) do_send_data(id, NONE, s, forward_ssip_answer); } static void process_request(Stream s) { Action action; if (read_data(s, &action, sizeof(Action)) == NONE) return; if (action == A_OPEN) process_open(s); else if (action == A_CLOSE) process_close(s); else if (action == A_DATA) process_data(s); else report_error(s); close(s); } #if USE_THREADS static void *process_request_thread(void *s) { Stream s_deref = *((Stream *) s); free(s); pthread_detach(pthread_self()); process_request(s_deref); return NULL; } #endif /* Starting the server */ static const char *login_name() { return getpwuid(getuid())->pw_name; } static const char *server_socket_name() { char *name; if (asprintf(&name, "/tmp/spdsend-server.%s", login_name()) < 0) system_error("memory allocation"); return name; } static void serve() { struct sockaddr_un name; int sock; size_t size; const char *filename = server_socket_name(); sock = socket(PF_LOCAL, SOCK_STREAM, 0); if (sock < 0) system_error("socket creation"); name.sun_family = AF_LOCAL; strncpy(name.sun_path, filename, sizeof(name.sun_path)); name.sun_path[sizeof(name.sun_path) - 1] = '\0'; size = (offsetof(struct sockaddr_un, sun_path) + strlen(name.sun_path) + 1); if (bind(sock, (struct sockaddr *)&name, size) < 0) system_error("bind"); if (listen(sock, LISTEN_QUEUE_LENGTH) < 0) system_error("listen"); while (1) { struct sockaddr_un client_address; socklen_t client_address_len = sizeof(client_address); Stream *s = malloc(sizeof(Stream)); if (s == NULL) system_error("memory allocation"); *s = accept(sock, (struct sockaddr *)&client_address, &client_address_len); if (*s < 0) break; { #if USE_THREADS pthread_t tid; #endif #if USE_THREADS pthread_create(&tid, NULL, &process_request_thread, s); #else process_request(*s); #endif } } } static void daemonize() { int ret = 0; if (fork() != 0) exit(0); setsid(); signal(SIGHUP, SIG_IGN); if (fork() != 0) exit(0); if ((ret = chdir("/")) != 0) fputs("server.c:daemonize: could not chdir", stderr); exit(1); umask(0); { int i; for (i = 0; i < 4; i++) close(i); } } static void init_connections() { connections = malloc(CONNECTION_ID_MAX * sizeof(Connection_Id)); if (connections == NULL) system_error("memory allocation"); { int i; for (i = CONNECTION_ID_MIN; i < CONNECTION_ID_MAX; i++) connections[i] = NONE; } #if USE_THREADS pthread_mutex_init(&connections_mutex, NULL); #endif } static void start_server() { const char *socket_name = server_socket_name(); unlink(socket_name); { int pid = fork(); if (pid == -1) system_error("fork"); if (pid == 0) { daemonize(); init_connections(); serve(); unlink(socket_name); exit(0); } else sleep(1); } } static int connect_server() { struct sockaddr_un name; int sock = socket(AF_LOCAL, SOCK_STREAM, 0); int name_size; name.sun_family = AF_LOCAL; strncpy(name.sun_path, server_socket_name(), sizeof(name.sun_path)); name.sun_path[sizeof(name.sun_path) - 1] = '\0'; name_size = (offsetof(struct sockaddr_un, sun_path) + strlen(name.sun_path) + 1); if (connect(sock, (struct sockaddr *)&name, name_size) < 0) return NONE; else return sock; } /* External functions */ Stream open_server() { Stream s; s = connect_server(); if (s == NONE) { start_server(); s = connect_server(); } if (s == NONE) return NONE; return s; } speech-dispatcher-0.8.3/src/clients/spdsend/spdsend.c0000644000175000017500000000663112233560613017541 00000000000000/* spdsend.c -- Send SSIP commands to Speech Dispatcher Author: Milan Zamazal */ /* Copyright (C) 2004 Brailcom, o.p.s. COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "spdsend.h" const char *const SPDSEND_VERSION = "0.0.0"; #if !(defined(__GLIBC__) && defined(_GNU_SOURCE)) /* Added by Willie Walker - getline is a gcc-ism */ #define BUFFER_LEN 256 ssize_t getline(char **lineptr, size_t * n, FILE * f) { char ch; size_t m = 0; ssize_t buf_len = 0; char *buf = NULL; char *p = NULL; if (errno != 0) { errno = 0; } while ((ch = getc(f)) != EOF) { if (errno != 0) return -1; if (m++ >= buf_len) { buf_len += BUFFER_LEN; buf = (char *)realloc(buf, buf_len + 1); if (buf == NULL) { return -1; } p = buf + buf_len - BUFFER_LEN; } *p = ch; p++; if (ch == '\n') break; } if (m == 0) { return -1; } else { *p = '\0'; *lineptr = buf; *n = m; return m; } } #endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */ static void usage(const char *const message) { if (message != NULL) fprintf(stderr, "spdsend: %s\n", message); fprintf(stderr, "usage: spdsend { --open SERVER PORT | --close ID | --send ID }\n"); exit(EXIT_ERROR); } static long string_to_number(const char *string, long low_limit, long high_limit) { char *tailptr; errno = 0; long int number = strtol(string, &tailptr, 0); if (errno || *tailptr || number < low_limit || number > high_limit) usage("Invalid parameter"); return number; } int main(int argc, char **argv) { if (argc < 2) usage("Invalid number of arguments"); { const char *const action = argv[1]; Success(*function) (Stream, Connection_Id); Connection_Id conn_id; char *host; int port; if (!strcmp(action, "--version")) { printf("spdsend %s\n", SPDSEND_VERSION); exit(EXIT_OK); } const int action_is_open = strcmp(action, "--open") == 0; if (action_is_open) { if (argc != 4) usage("Invalid number of arguments"); host = argv[2]; port = string_to_number(argv[3], 0, 65535); } else { if (argc != 3) usage("Invalid number of arguments"); conn_id = string_to_number(argv[2], CONNECTION_ID_MIN, CONNECTION_ID_MAX); if (!strcmp(action, "--close")) function = close_connection; else if (!strcmp(action, "--send")) function = send_command; else usage("Invalid option"); } { Stream server = open_server(); if (server == NONE) return EXIT_ERROR; { int result = (action_is_open ? open_connection(server, host, port) : function(server, conn_id)); return (result == OK ? EXIT_OK : EXIT_ERROR); } } } } speech-dispatcher-0.8.3/src/clients/spdsend/ChangeLog0000644000175000017500000000041012233560613017474 000000000000002008-02-01 Hynek Hanke * server.c (serve): Correct type for client_address_len. 2006-07-25 root * README: speechd 2004-09-08 Milan Zamazal * server.c (do_send_data): Close the connection on error. speech-dispatcher-0.8.3/src/clients/spdsend/Makefile.in0000664000175000017500000005262412536424263020015 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = spdsend$(EXEEXT) subdir = src/clients/spdsend DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ChangeLog README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_spdsend_OBJECTS = spdsend.$(OBJEXT) server.$(OBJEXT) \ client.$(OBJEXT) common.$(OBJEXT) spdsend_OBJECTS = $(am_spdsend_OBJECTS) am__DEPENDENCIES_1 = spdsend_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(spdsend_SOURCES) DIST_SOURCES = $(spdsend_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ spdsend_SOURCES = spdsend.h spdsend.c server.c client.c common.c spdsend_LDADD = $(EXTRA_SOCKET_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/clients/spdsend/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/clients/spdsend/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list spdsend$(EXEEXT): $(spdsend_OBJECTS) $(spdsend_DEPENDENCIES) $(EXTRA_spdsend_DEPENDENCIES) @rm -f spdsend$(EXEEXT) $(AM_V_CCLD)$(LINK) $(spdsend_OBJECTS) $(spdsend_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spdsend.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/clients/spdsend/client.c0000664000175000017500000000505412522771346017367 00000000000000/* client.c -- Client part of spdsend Author: Milan Zamazal */ /* Copyright (C) 2004 Brailcom, o.p.s. COPYRIGHT NOTICE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "spdsend.h" #include #include #include static Success send_header(Stream s, Action action, Connection_Id id) { if (write_data(s, &action, sizeof(Action)) == OK && write_data(s, &id, sizeof(Connection_Id)) == OK) return OK; else return ERROR; } #define SEND_HEADER(action) \ if (send_header (s, action, id) == ERROR) \ return ERROR static Success send_open_header(Stream s, const char *host, int port) { int hostlen = strlen(host); Action action = A_OPEN; if (write_data(s, &action, sizeof(Action)) == OK && write_data(s, &port, sizeof(int)) == OK && write_data(s, &hostlen, sizeof(int)) == OK && write_data(s, host, hostlen) == OK) return OK; else return ERROR; } static Connection_Id read_reply(Stream s) { Result result; Connection_Id id; if (read_data(s, &result, sizeof(Result)) != sizeof(Result)) return NONE; if (result != OK_CODE) return NONE; if (read_data(s, &id, sizeof(Connection_Id)) != sizeof(Connection_Id)) return NONE; return id; } /* External functions */ extern Success open_connection(Stream s, const char *host, int port) { if (send_open_header(s, host, port) == ERROR) return ERROR; { Connection_Id id = read_reply(s); if (id == NONE) return ERROR; printf("%d\n", id); } return OK; } extern Success close_connection(Stream s, Connection_Id id) { SEND_HEADER(A_CLOSE); return (read_reply(s) == OK ? OK : ERROR); } extern Success send_command(Stream s, Connection_Id id) { SEND_HEADER(A_DATA); if (read_reply(s) == NONE) return ERROR; if (forward_data(0, s, TRUE) == OK && forward_data(s, 1, FALSE) == OK) return OK; else return ERROR; } speech-dispatcher-0.8.3/src/clients/spdsend/Makefile.am0000644000175000017500000000027212233560613017764 00000000000000## Process this file with automake to produce Makefile.in bin_PROGRAMS = spdsend spdsend_SOURCES = spdsend.h spdsend.c server.c client.c common.c spdsend_LDADD = $(EXTRA_SOCKET_LIBS) speech-dispatcher-0.8.3/src/clients/say/0000775000175000017500000000000012536424375015157 500000000000000speech-dispatcher-0.8.3/src/clients/say/options.c0000664000175000017500000001522112536417045016733 00000000000000/* * options.c - Parse and process possible command line options * * Copyright (C) 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: options.c,v 1.9 2006-07-11 16:12:26 hanke Exp $ */ /* NOTE: Be careful not to include options.h, we would get repetitive initializations warnings */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "options.h" #include void options_print_help(char *argv[]) { assert(argv); assert(argv[0]); printf(_("Usage: %s [options] \"some text\"\n"), argv[0]); printf(_("%s -- a simple client for speech synthesis %s\n\n"), "Speech Dispatcher Say", "(GNU GPL)"); printf("-r, --rate\t\t\t"); printf(_("Set the rate of the speech\n")); printf("\t\t\t\t"); printf(_("(between %+d and %+d, default: %d)\n"), -100, 100, 0); printf("-p, --pitch\t\t\t"); printf(_("Set the pitch of the speech\n")); printf("\t\t\t\t"); printf(_("(between %+d and %+d, default: %d)\n"), -100, 100, 0); printf("-i, --volume\t\t\t"); printf(_("Set the volume (intensity) of the speech\n")); printf("\t\t\t\t"); printf(_("(between %+d and %+d, default: %d)\n"), -100, 100, 0); printf("-o, --output-module\t\t"); printf(_("Set the output module\n")); printf("-O, --list-output-modules\t"); printf(_("Get the list of output modules\n")); printf("-I, --sound-icon\t\t"); printf(_("Play the sound icon\n")); printf("-l, --language\t\t\t"); printf(_("Set the language (ISO code)\n")); printf("-t, --voice-type\t\t"); printf(_("Set the preferred voice type\n")); printf("\t\t\t\t(male1, male2, male3, female1, female2\n" "\t\t\t\tfemale3, child_male, child_female)\n"); printf("-L, --list-synthesis-voices\t"); printf(_("Get the list of synthesis voices\n")); printf("-y, --synthesis-voice\t\t"); printf(_("Set the synthesis voice\n")); printf("-m, --punctuation-mode\t\t"); printf(_("Set the punctuation mode %s\n"), "(none, some, all)"); printf("-s, --spelling\t\t\t"); printf(_("Spell the message\n")); printf("-x, --ssml\t\t\t"); printf(_("Set SSML mode on (default: off)\n")); printf("\n"); printf("-e, --pipe-mode\t\t\t"); printf(_("Pipe from stdin to stdout plus Speech Dispatcher\n")); printf("-P, --priority\t\t\t"); printf(_("Set priority of the message ")); printf("(important, message,\n" "\t\t\t\ttext, notification, progress;"); printf(_("default: %s)\n"), "text"); printf("-N, --application-name\t\t"); printf(_("Set the application name used to establish\n" "%sthe connection to specified string value\n"), "\t\t\t\t"); printf("\t\t\t\t"); printf(_("(default: %s)\n"), "spd-say"); printf("-n, --connection-name\t\t"); printf(_("Set the connection name used to establish\n" "%sthe connection to specified string value\n"), "\t\t\t\t"); printf("\t\t\t\t"); printf(_("(default: %s)\n"), "main"); printf("\n"); printf("-w, --wait\t\t\t"); printf(_("Wait till the message is spoken or discarded\n")); printf("-S, --stop\t\t\t"); printf(_("Stop speaking the message being spoken\n")); printf("-C, --cancel\t\t\t"); printf(_("Cancel all messages\n")); printf("\n"); printf("-v, --version\t\t\t"); printf(_("Print version and copyright info\n")); printf("-h, --help\t\t\t"); printf(_("Print this info\n")); printf("\n"); printf(_("Copyright (C) %d-%d Brailcom, o.p.s.\n" "This is free software; you can redistribute it and/or modify it\n" "under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2, or (at your option)\n" "any later version. Please see COPYING for more details.\n\n" "Please report bugs to %s\n\n"), 2002, 2012, PACKAGE_BUGREPORT); } void options_print_version() { printf("spd-say: " VERSION "\n"); printf(_("Copyright (C) %d-%d Brailcom, o.p.s.\n" "%s comes with ABSOLUTELY NO WARRANTY.\n" "You may redistribute copies of this program\n" "under the terms of the GNU General Public License.\n" "For more information about these matters, see the file named COPYING.\n"), 2002, 2012, "spd-say"); } #define OPT_SET_INT(param) \ val = strtol(optarg, &tail_ptr, 10); \ if(tail_ptr != optarg){ \ param = val; \ }else{ \ printf(_("Syntax error or bad parameter!\n")); \ options_print_help(argv); \ exit(1); \ } #define OPT_SET_STR(param) \ if(optarg != NULL){ \ param = (char*) strdup(optarg); \ }else{ \ printf(_("Missing argument!\n")); \ options_print_help(argv); \ exit(1); \ } int options_parse(int argc, char *argv[]) { char *tail_ptr; int c_opt; int option_index; int val; assert(argc > 0); assert(argv); while (1) { option_index = 0; c_opt = getopt_long(argc, argv, short_options, long_options, &option_index); if (c_opt == -1) break; switch (c_opt) { case 'r': OPT_SET_INT(rate); break; case 'p': OPT_SET_INT(pitch); break; case 'i': OPT_SET_INT(volume); break; case 'l': OPT_SET_STR(language); break; case 'o': OPT_SET_STR(output_module); break; case 'O': list_output_modules = 1; break; case 'I': OPT_SET_STR(sound_icon); break; case 't': OPT_SET_STR(voice_type); break; case 'L': list_synthesis_voices = 1; break; case 'y': OPT_SET_STR(synthesis_voice); break; case 'm': OPT_SET_STR(punctuation_mode); break; case 's': spelling = 1; break; case 'e': pipe_mode = 1; break; case 'P': OPT_SET_STR(priority); break; case 'x': ssml_mode = SPD_DATA_SSML; break; case 'N': OPT_SET_STR(application_name); break; case 'n': OPT_SET_STR(connection_name); break; case 'w': wait_till_end = 1; break; case 'S': stop_previous = 1; break; case 'C': cancel_previous = 1; break; case 'v': options_print_version(argv); exit(0); break; case 'h': options_print_help(argv); exit(0); break; default: printf(_("Unrecognized option\n")); options_print_help(argv); exit(1); } } return 0; } #undef SPD_OPTION_SET_INT speech-dispatcher-0.8.3/src/clients/say/say.c0000664000175000017500000002006712536417045016040 00000000000000 /* * say.c - Super-simple Speech Dispatcher client * * Copyright (C) 2001, 2002, 2003, 2007 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: say.c,v 1.16 2007-05-03 09:43:12 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include /* * Since this client is built as part of the Speech Dispatcher source * tree, we must include speechd_types.h directly. * Clients built outside the speech dispatcher source tree should not do * this. */ #include #include #include "options.h" #include #define MAX_LINELEN 16384 sem_t semaphore; /* Callback for Speech Dispatcher notifications */ void end_of_speech(size_t msg_id, size_t client_id, SPDNotificationType type) { sem_post(&semaphore); } int main(int argc, char **argv) { SPDConnection *conn; SPDPriority spd_priority; int err; char *error; int msg_arg_required = 0; int ret; int option_ret; char *line; /* initialize i18n support */ i18n_init(); rate = -101; pitch = -101; volume = -101; language = NULL; voice_type = NULL; punctuation_mode = NULL; spelling = -2; ssml_mode = SPD_DATA_TEXT; wait_till_end = 0; stop_previous = 0; cancel_previous = 0; list_synthesis_voices = 0; list_output_modules = 0; synthesis_voice = NULL; pipe_mode = 0; priority = NULL; application_name = NULL; connection_name = NULL; option_ret = options_parse(argc, argv); /* Check if the text to say or options are specified in the argument */ msg_arg_required = (pipe_mode != 1) && (stop_previous != 1) && (cancel_previous != 1) && (list_synthesis_voices != 1) && (list_output_modules != 1) && (sound_icon == NULL); if ((optind >= argc) && msg_arg_required) { options_print_help(argv); return 1; } /* Open a connection to Speech Dispatcher */ conn = spd_open2(application_name ? application_name : "spd-say", connection_name ? connection_name : "main", NULL, SPD_MODE_THREADED, NULL, 1, &error); if (conn == NULL) { fprintf(stderr, "Failed to connect to Speech Dispatcher:\n%s\n", error); exit(1); } if (stop_previous) spd_stop_all(conn); if (cancel_previous) spd_cancel_all(conn); /* Set the desired parameters */ if (language != NULL) if (spd_set_language(conn, language)) printf("Invalid language!\n"); if (output_module != NULL) if (spd_set_output_module(conn, output_module)) printf("Invalid output module!\n"); if (list_output_modules) { char **list; int i; list = spd_list_modules(conn); if (list != NULL) { printf("OUTPUT MODULES\n"); for (i = 0; list[i]; i++) { printf("%s\n", list[i]); } } else { printf("Output modules not found.\n"); } } if (voice_type != NULL) { if (!strcmp(voice_type, "male1")) { if (spd_set_voice_type(conn, SPD_MALE1)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "male2")) { if (spd_set_voice_type(conn, SPD_MALE2)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "male3")) { if (spd_set_voice_type(conn, SPD_MALE3)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "female1")) { if (spd_set_voice_type(conn, SPD_FEMALE1)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "female2")) { if (spd_set_voice_type(conn, SPD_FEMALE2)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "female3")) { if (spd_set_voice_type(conn, SPD_FEMALE3)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "child_male")) { if (spd_set_voice_type(conn, SPD_CHILD_MALE)) printf("Can't set this voice!\n"); } else if (!strcmp(voice_type, "child_female")) { if (spd_set_voice_type(conn, SPD_CHILD_FEMALE)) printf("Can't set this voice!\n"); } else { printf("Invalid voice\n"); } } if (list_synthesis_voices) { SPDVoice **list; int i; list = spd_list_synthesis_voices(conn); if (list != NULL) { printf("%25s%25s%25s\n", "NAME", "LANGUAGE", "VARIANT"); for (i = 0; list[i]; i++) { printf("%25s%25s%25s\n", list[i]->name, list[i]->language, list[i]->variant); } } else { printf("Failed to get voice list.\n"); } } if (synthesis_voice != NULL) if (spd_set_synthesis_voice(conn, synthesis_voice)) printf("Failed to set synthesis voice!\n"); if (ssml_mode == SPD_DATA_SSML) if (spd_set_data_mode(conn, ssml_mode)) printf("Failed to set SSML mode.\n"); if (rate != -101) if (spd_set_voice_rate(conn, rate)) printf("Invalid rate!\n"); if (pitch != -101) if (spd_set_voice_pitch(conn, pitch)) printf("Invalid pitch!\n"); if (volume != -101) if (spd_set_volume(conn, volume)) printf("Invalid volume!\n"); if (spelling == 1) if (spd_set_spelling(conn, SPD_SPELL_ON)) printf("Can't set spelling to on!\n"); if (punctuation_mode != NULL) { if (!strcmp(punctuation_mode, "none")) { if (spd_set_punctuation(conn, SPD_PUNCT_NONE)) printf("Can't set this punctuation mode!\n"); } else if (!strcmp(punctuation_mode, "some")) { if (spd_set_punctuation(conn, SPD_PUNCT_SOME)) printf("Can't set this punctuation mode!\n"); } else if (!strcmp(punctuation_mode, "all")) { if (spd_set_punctuation(conn, SPD_PUNCT_ALL)) printf("Can't set this punctuation mode!\n"); } else { printf("Invalid punctuation mode.\n"); } } /* Set default priority... */ if (1 == pipe_mode) spd_priority = SPD_MESSAGE; else spd_priority = SPD_TEXT; /* ...and look if it wasn't overriden */ if (priority != NULL) { if (!strcmp(priority, "important")) spd_priority = SPD_IMPORTANT; else if (!strcmp(priority, "message")) spd_priority = SPD_MESSAGE; else if (!strcmp(priority, "text")) spd_priority = SPD_TEXT; else if (!strcmp(priority, "notification")) spd_priority = SPD_NOTIFICATION; else if (!strcmp(priority, "progress")) spd_priority = SPD_PROGRESS; else { printf("Invalid priority.\n"); } } if (sound_icon != NULL) if (spd_sound_icon(conn, spd_priority, sound_icon)) printf("Invalid sound_icon!\n"); if (wait_till_end) { ret = sem_init(&semaphore, 0, 0); if (ret < 0) { fprintf(stderr, "Can't initialize semaphore: %s", strerror(errno)); return 0; } /* Notify when the message is canceled or the speech terminates */ conn->callback_end = end_of_speech; conn->callback_cancel = end_of_speech; spd_set_notification_on(conn, SPD_END); spd_set_notification_on(conn, SPD_CANCEL); } /* In pipe mode, read from stdin, write to stdout, and also to Speech Dispatcher. */ if (pipe_mode == 1) { line = (char *)malloc(MAX_LINELEN); while (NULL != fgets(line, MAX_LINELEN, stdin)) { fputs(line, stdout); if (0 == strncmp(line, "!-!", 3)) { /* Remove EOL */ line[strlen(line) - 1] = 0; spd_execute_command(conn, line + 3); } else { spd_say(conn, spd_priority, line); if (wait_till_end) sem_wait(&semaphore); } } free(line); } else { /* Say the message with priority "text" */ /* Or do nothing in case of -C or -S with no message. */ if (optind < argc) { err = spd_sayf(conn, spd_priority, (char *)argv[optind]); if (err == -1) { fprintf(stderr, "Speech Dispatcher failed to say message"); exit(1); } /* Wait till the callback is called */ if (wait_till_end) sem_wait(&semaphore); } } /* Close the connection */ spd_close(conn); return 0; } speech-dispatcher-0.8.3/src/clients/say/Makefile.in0000664000175000017500000006147212536424263017152 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = spd-say$(EXEEXT) subdir = src/clients/say DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_spd_say_OBJECTS = spd_say-say.$(OBJEXT) spd_say-options.$(OBJEXT) spd_say_OBJECTS = $(am_spd_say_OBJECTS) am__DEPENDENCIES_1 = spd_say_DEPENDENCIES = $(c_api)/libspeechd.la $(am__DEPENDENCIES_1) \ $(top_builddir)/src/common/libcommon.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(spd_say_SOURCES) DIST_SOURCES = $(spd_say_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ inc_local = -I$(top_srcdir)/include -I$(top_srcdir)/src/api/c c_api = $(top_builddir)/src/api/c spd_say_CPPFLAGS = $(inc_local) $(GLIB_CFLAGS) spd_say_SOURCES = say.c options.c options.h spd_say_LDADD = $(c_api)/libspeechd.la $(EXTRA_SOCKET_LIBS) $(top_builddir)/src/common/libcommon.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/clients/say/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/clients/say/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list spd-say$(EXEEXT): $(spd_say_OBJECTS) $(spd_say_DEPENDENCIES) $(EXTRA_spd_say_DEPENDENCIES) @rm -f spd-say$(EXEEXT) $(AM_V_CCLD)$(LINK) $(spd_say_OBJECTS) $(spd_say_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spd_say-options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spd_say-say.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< spd_say-say.o: say.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spd_say-say.o -MD -MP -MF $(DEPDIR)/spd_say-say.Tpo -c -o spd_say-say.o `test -f 'say.c' || echo '$(srcdir)/'`say.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spd_say-say.Tpo $(DEPDIR)/spd_say-say.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='say.c' object='spd_say-say.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spd_say-say.o `test -f 'say.c' || echo '$(srcdir)/'`say.c spd_say-say.obj: say.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spd_say-say.obj -MD -MP -MF $(DEPDIR)/spd_say-say.Tpo -c -o spd_say-say.obj `if test -f 'say.c'; then $(CYGPATH_W) 'say.c'; else $(CYGPATH_W) '$(srcdir)/say.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spd_say-say.Tpo $(DEPDIR)/spd_say-say.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='say.c' object='spd_say-say.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spd_say-say.obj `if test -f 'say.c'; then $(CYGPATH_W) 'say.c'; else $(CYGPATH_W) '$(srcdir)/say.c'; fi` spd_say-options.o: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spd_say-options.o -MD -MP -MF $(DEPDIR)/spd_say-options.Tpo -c -o spd_say-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spd_say-options.Tpo $(DEPDIR)/spd_say-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='spd_say-options.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spd_say-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c spd_say-options.obj: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spd_say-options.obj -MD -MP -MF $(DEPDIR)/spd_say-options.Tpo -c -o spd_say-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/spd_say-options.Tpo $(DEPDIR)/spd_say-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='spd_say-options.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(spd_say_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spd_say-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/clients/say/Makefile.am0000644000175000017500000000056212233560613017122 00000000000000## Process this file with automake to produce Makefile.in inc_local = -I$(top_srcdir)/include -I$(top_srcdir)/src/api/c c_api = $(top_builddir)/src/api/c bin_PROGRAMS = spd-say spd_say_CPPFLAGS = $(inc_local) $(GLIB_CFLAGS) spd_say_SOURCES = say.c options.c options.h spd_say_LDADD = $(c_api)/libspeechd.la $(EXTRA_SOCKET_LIBS) $(top_builddir)/src/common/libcommon.la speech-dispatcher-0.8.3/src/clients/say/options.h0000664000175000017500000000430712536417045016743 00000000000000/* * options.h - Defines possible command line options * * Copyright (C) 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: options.h,v 1.10 2006-07-11 16:12:27 hanke Exp $ */ #include #include "speechd_types.h" signed int rate; signed int pitch; signed int volume; int list_output_modules; char *output_module; char *sound_icon; char *language; char *voice_type; char *punctuation_mode; char *priority; int pipe_mode; SPDDataMode ssml_mode; int spelling; int wait_till_end; int stop_previous; int cancel_previous; int list_synthesis_voices; char *synthesis_voice; char *application_name; char *connection_name; static struct option long_options[] = { {"rate", 1, 0, 'r'}, {"pitch", 1, 0, 'p'}, {"volume", 1, 0, 'i'}, {"output-module", 1, 0, 'o'}, {"list-output-modules", no_argument, 0, 'O'}, {"sound-icon", required_argument, 0, 'I'}, {"language", 1, 0, 'l'}, {"voice-type", 1, 0, 't'}, {"list-synthesis-voices", no_argument, 0, 'L'}, {"synthesis-voice", required_argument, 0, 'y'}, {"punctuation-mode", 1, 0, 'm'}, {"spelling", 0, 0, 's'}, {"ssml", 0, 0, 'x'}, {"pipe-mode", 0, 0, 'e'}, {"priority", 1, 0, 'P'}, {"application-name", 1, 0, 'N'}, {"connection-name", 1, 0, 'n'}, {"wait", 0, 0, 'w'}, {"stop", 1, 0, 'S'}, {"cancel", no_argument, 0, 'C'}, {"version", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; static char *short_options = "r:p:i:l:o:OI:t:Ly:m:sxeP:N:n:wSCvh"; int options_parse(int argc, char *argv[]); void options_print_version(); void options_print_help(char *argv[]); speech-dispatcher-0.8.3/src/clients/Makefile.in0000664000175000017500000005017212536424263016351 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/clients DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = say spdsend all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/clients/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/clients/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/clients/Makefile.am0000644000175000017500000000012212233560613016316 00000000000000## Process this file with automake to produce Makefile.in SUBDIRS= say spdsend speech-dispatcher-0.8.3/src/Makefile.in0000664000175000017500000005020412536424263014704 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = common server audio modules api clients tests all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/Makefile.am0000644000175000017500000000016212233560613014661 00000000000000## Process this file with automake to produce Makefile.in SUBDIRS=common server audio modules api clients tests speech-dispatcher-0.8.3/src/common/0000775000175000017500000000000012536424374014211 500000000000000speech-dispatcher-0.8.3/src/common/fdsetconv.c0000644000175000017500000001003612233560613016255 00000000000000 /* * fdsetconv.c - Conversion of types for Speech Dispatcher * * Copyright (C) 2001, 2002, 2003 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id: fdsetconv.c,v 1.5 2007-06-21 20:09:45 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include "fdsetconv.h" char *EVoice2str(SPDVoiceType voice) { char *str; switch (voice) { case SPD_MALE1: str = g_strdup("male1"); break; case SPD_MALE2: str = g_strdup("male2"); break; case SPD_MALE3: str = g_strdup("male3"); break; case SPD_FEMALE1: str = g_strdup("female1"); break; case SPD_FEMALE2: str = g_strdup("female2"); break; case SPD_FEMALE3: str = g_strdup("female3"); break; case SPD_CHILD_MALE: str = g_strdup("child_male"); break; case SPD_CHILD_FEMALE: str = g_strdup("child_female"); break; default: str = NULL; } return str; } SPDVoiceType str2EVoice(char *str) { SPDVoiceType voice; if (!strcmp(str, "male1")) voice = SPD_MALE1; else if (!strcmp(str, "male2")) voice = SPD_MALE2; else if (!strcmp(str, "male3")) voice = SPD_MALE3; else if (!strcmp(str, "female1")) voice = SPD_FEMALE1; else if (!strcmp(str, "female2")) voice = SPD_FEMALE2; else if (!strcmp(str, "female3")) voice = SPD_FEMALE3; else if (!strcmp(str, "child_male")) voice = SPD_CHILD_MALE; else if (!strcmp(str, "child_female")) voice = SPD_CHILD_FEMALE; else voice = -1; return voice; } char *EPunctMode2str(SPDPunctuation punct) { char *str; switch (punct) { case SPD_PUNCT_NONE: str = g_strdup("none"); break; case SPD_PUNCT_ALL: str = g_strdup("all"); break; case SPD_PUNCT_SOME: str = g_strdup("some"); break; default: str = NULL; } return str; } SPDPunctuation str2EPunctMode(char *str) { SPDPunctuation punct; if (!strcmp(str, "none")) punct = SPD_PUNCT_NONE; else if (!strcmp(str, "all")) punct = SPD_PUNCT_ALL; else if (!strcmp(str, "some")) punct = SPD_PUNCT_SOME; else punct = -1; return punct; } char *ESpellMode2str(SPDSpelling spell) { char *str; switch (spell) { case SPD_SPELL_ON: str = g_strdup("on"); break; case SPD_SPELL_OFF: str = g_strdup("off"); break; default: str = NULL; } return str; } SPDSpelling str2ESpellMode(char *str) { SPDSpelling spell; if (!strcmp(str, "on")) spell = SPD_SPELL_ON; else if (!strcmp(str, "off")) spell = SPD_SPELL_OFF; else spell = -1; return spell; } char *ECapLetRecogn2str(SPDCapitalLetters recogn) { char *str; switch (recogn) { case SPD_CAP_NONE: str = g_strdup("none"); break; case SPD_CAP_SPELL: str = g_strdup("spell"); break; case SPD_CAP_ICON: str = g_strdup("icon"); break; default: str = NULL; } return str; } SPDCapitalLetters str2ECapLetRecogn(char *str) { SPDCapitalLetters recogn; if (!strcmp(str, "none")) recogn = SPD_CAP_NONE; else if (!strcmp(str, "spell")) recogn = SPD_CAP_SPELL; else if (!strcmp(str, "icon")) recogn = SPD_CAP_ICON; else recogn = -1; return recogn; } SPDPriority str2intpriority(char *str) { SPDPriority priority; if (!strcmp(str, "important")) priority = SPD_IMPORTANT; else if (!strcmp(str, "message")) priority = SPD_MESSAGE; else if (!strcmp(str, "text")) priority = SPD_TEXT; else if (!strcmp(str, "notification")) priority = SPD_NOTIFICATION; else if (!strcmp(str, "progress")) priority = SPD_PROGRESS; else priority = -1; return priority; } speech-dispatcher-0.8.3/src/common/i18n.c0000644000175000017500000000237012233560613015043 00000000000000/* * i18n.c - internationalization support for Speech-dispatcher * * Copyright (C) 2010 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #if HAVE_CONFIG_H #include #endif #include #include /* For setlocale. */ #include #include void i18n_init(void) { if (setlocale(LC_ALL, "") == NULL) { perror("setlocale"); exit(1); } if (bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR) == NULL) { perror("bindtextdomain"); exit(1); } if (textdomain(GETTEXT_PACKAGE) == NULL) { perror("textdomain"); exit(1); } } speech-dispatcher-0.8.3/src/common/Makefile.in0000664000175000017500000005621512536424264016205 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/common DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libcommon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libcommon_la_OBJECTS = libcommon_la-fdsetconv.lo \ libcommon_la-spd_getline.lo libcommon_la-i18n.lo libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libcommon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcommon_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcommon_la_SOURCES) DIST_SOURCES = $(libcommon_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DOTCONF_CFLAGS = @DOTCONF_CFLAGS@ DOTCONF_LIBS = @DOTCONF_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ EXTRA_ESPEAK_LIBS = @EXTRA_ESPEAK_LIBS@ EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@ FGREP = @FGREP@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ GTHREAD_LIBS = @GTHREAD_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBAO_CFLAGS = @LIBAO_CFLAGS@ LIBAO_LIBS = @LIBAO_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SPD_AGE = @LIB_SPD_AGE@ LIB_SPD_CURRENT = @LIB_SPD_CURRENT@ LIB_SPD_REVISION = @LIB_SPD_REVISION@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAJOR_VERSION = @MAJOR_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MICRO_VERSION = @MICRO_VERSION@ MINOR_VERSION = @MINOR_VERSION@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ MSGMERGE = @MSGMERGE@ NAS_LIBS = @NAS_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ PULSE_CFLAGS = @PULSE_CFLAGS@ PULSE_LIBS = @PULSE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ RDYNAMIC = @RDYNAMIC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ SNDFILE_LIBS = @SNDFILE_LIBS@ STRIP = @STRIP@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ audio_dlopen_modules = @audio_dlopen_modules@ audiodir = @audiodir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ clientconfdir = @clientconfdir@ clientconforigdir = @clientconforigdir@ datadir = @datadir@ datarootdir = @datarootdir@ default_audio_method = @default_audio_method@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ flite_basic = @flite_basic@ flite_kal = @flite_kal@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ ibmtts_include = @ibmtts_include@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intltool__v_merge_options_ = @intltool__v_merge_options_@ intltool__v_merge_options_0 = @intltool__v_merge_options_0@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ modulebindir = @modulebindir@ moduleconfdir = @moduleconfdir@ moduleconforigdir = @moduleconforigdir@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ snddatadir = @snddatadir@ spdconfdir = @spdconfdir@ spdconforigdir = @spdconforigdir@ spddesktopconforigdir = @spddesktopconforigdir@ spdincludedir = @spdincludedir@ spdlibdir = @spdlibdir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libcommon.la libcommon_la_CFLAGS = $(ERROR_CFLAGS) $(GLIB_CFLAGS) \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" -DLOCALEDIR=\"$(localedir)\" libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/" $(GLIB_CFLAGS) libcommon_la_LIBADD = $(GLIB_LIBS) libcommon_la_SOURCES = fdsetconv.c spd_getline.c i18n.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/common/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/common/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES) $(AM_V_CCLD)$(libcommon_la_LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-fdsetconv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-i18n.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcommon_la-spd_getline.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libcommon_la-fdsetconv.lo: fdsetconv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-fdsetconv.lo -MD -MP -MF $(DEPDIR)/libcommon_la-fdsetconv.Tpo -c -o libcommon_la-fdsetconv.lo `test -f 'fdsetconv.c' || echo '$(srcdir)/'`fdsetconv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_la-fdsetconv.Tpo $(DEPDIR)/libcommon_la-fdsetconv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fdsetconv.c' object='libcommon_la-fdsetconv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-fdsetconv.lo `test -f 'fdsetconv.c' || echo '$(srcdir)/'`fdsetconv.c libcommon_la-spd_getline.lo: spd_getline.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-spd_getline.lo -MD -MP -MF $(DEPDIR)/libcommon_la-spd_getline.Tpo -c -o libcommon_la-spd_getline.lo `test -f 'spd_getline.c' || echo '$(srcdir)/'`spd_getline.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_la-spd_getline.Tpo $(DEPDIR)/libcommon_la-spd_getline.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spd_getline.c' object='libcommon_la-spd_getline.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-spd_getline.lo `test -f 'spd_getline.c' || echo '$(srcdir)/'`spd_getline.c libcommon_la-i18n.lo: i18n.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -MT libcommon_la-i18n.lo -MD -MP -MF $(DEPDIR)/libcommon_la-i18n.Tpo -c -o libcommon_la-i18n.lo `test -f 'i18n.c' || echo '$(srcdir)/'`i18n.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcommon_la-i18n.Tpo $(DEPDIR)/libcommon_la-i18n.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i18n.c' object='libcommon_la-i18n.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcommon_la_CPPFLAGS) $(CPPFLAGS) $(libcommon_la_CFLAGS) $(CFLAGS) -c -o libcommon_la-i18n.lo `test -f 'i18n.c' || echo '$(srcdir)/'`i18n.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: speech-dispatcher-0.8.3/src/common/Makefile.am0000644000175000017500000000057012233560613016154 00000000000000## Process this file with automake to produce Makefile.in noinst_LTLIBRARIES = libcommon.la libcommon_la_CFLAGS = $(ERROR_CFLAGS) $(GLIB_CFLAGS) \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" -DLOCALEDIR=\"$(localedir)\" libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/" $(GLIB_CFLAGS) libcommon_la_LIBADD = $(GLIB_LIBS) libcommon_la_SOURCES = fdsetconv.c spd_getline.c i18n.c speech-dispatcher-0.8.3/src/common/spd_getline.c0000644000175000017500000000626312233560613016566 00000000000000/* * spd_getline.c - portable implementation of getline * * Copyright (C) 2010 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #define INITIAL_BUF_SIZE 120 #define GETLINE_FAILURE -1 /* * A portable implementation of getline. * Originally provided by Willie Walker, and modified by Chris Brannon. * * Note: `*lineptr' must be a valid argument that could be passed to the * `g_free()' glib function, i.e. it must be g_malloc'ed, not malloc'ed. * In all other respects, this function behaves just like the POSIX version * of getline. */ ssize_t spd_getline(char **lineptr, size_t * n, FILE * f) { char ch; ssize_t buf_pos = 0; ssize_t needed = 2; /* Always buf_pos + 2 (see below). */ size_t new_length = 0; char *temp; if ((n == NULL) || (lineptr == NULL) || (f == NULL)) { errno = EINVAL; return GETLINE_FAILURE; } if (errno != 0) errno = 0; if ((*lineptr == NULL) || (*n == 0)) { *n = INITIAL_BUF_SIZE; *lineptr = g_malloc(*n * sizeof(char)); if (*lineptr == NULL) { *n = 0; return GETLINE_FAILURE; /* Out of memory. */ } } /* * For each iteration of this loop, the following holds. * We have read buf_pos bytes of the line. The buffer contains buf_pos * bytes, not including the trailing null byte at the end of the string. * When we read another character, we want to store it, and we also need * enough room for a null byte. So we need to realloc as soon as our * capacity becomes less than buf_pos + 2. * Hence the variable "needed" which always equals buf_pos + 2. */ while ((ch = getc(f)) != EOF) { if (errno != 0) return GETLINE_FAILURE; if (needed > *n) { new_length = *n * 2; if (new_length <= *n) { /* Overflow. */ errno = ENOMEM; /* We couldn't store the character, */ /* so put it back on the stream. */ ungetc(ch, f); return GETLINE_FAILURE; } temp = (char *)g_realloc(*lineptr, new_length * sizeof(char)); if (temp == NULL) { ungetc(ch, f); return GETLINE_FAILURE; } *n = new_length; *lineptr = temp; } (*lineptr)[buf_pos++] = ch; if (ch == '\n') break; if (needed == SSIZE_MAX) { /* We'll overflow ssize_t on the next round. */ errno = ENOMEM; return GETLINE_FAILURE; } needed++; } (*lineptr)[buf_pos] = '\0'; if (buf_pos == 0) { buf_pos = GETLINE_FAILURE; } return buf_pos; } speech-dispatcher-0.8.3/src/audio/0000775000175000017500000000000012536424374014022 500000000000000speech-dispatcher-0.8.3/src/audio/pulse.c0000644000175000017500000002024512233560613015226 00000000000000 /* * pulse.c -- The simple pulseaudio backend for the spd_audio library. * * Based on libao.c from Marco Skambraks * Date: 2009-12-15 * * Copied from Luke Yelavich's libao.c driver, and merged with code from * Marco's ao_pulse.c driver, by Bill Cox, Dec 21, 2009. * * Minor changes be Rui Batista to configure settings through speech-dispatcher configuration files * Date: Dec 22, 2009 * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Leser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #define SPD_AUDIO_PLUGIN_ENTRY spd_pulse_LTX_spd_audio_plugin_get #include /* Switch this on to debug, see output log location in MSG() */ //#define DEBUG_PULSE typedef struct { AudioID id; pa_simple *pa_simple; char *pa_server; int pa_min_audio_length; volatile int pa_stop_playback; int pa_current_rate; // Sample rate for currently PA connection int pa_current_bps; // Bits per sample rate for currently PA connection int pa_current_channels; // Number of channels for currently PA connection } spd_pulse_id_t; /* send a packet of XXX bytes to the sound device */ #define PULSE_SEND_BYTES 256 /* This is the smallest audio sound we are expected to play immediately without buffering. */ /* Changed to define on config file. Default is the same. */ #define DEFAULT_PA_MIN_AUDIO_LENgTH 100 static int pulse_log_level; static char const *pulse_play_cmd = "paplay"; /* Write to /tmp/speech-dispatcher-pulse.log */ #ifdef DEBUG_PULSE static FILE *pulseDebugFile = NULL; static void MSG(char *message, ...) { va_list ap; if (pulseDebugFile == NULL) { pulseDebugFile = fopen("/tmp/speech-dispatcher-pulse.log", "w"); } va_start(ap, message); vfprintf(pulseDebugFile, message, ap); va_end(ap); fflush(pulseDebugFile); } #else static void MSG(char *message, ...) { } #endif static int _pulse_open(spd_pulse_id_t * id, int sample_rate, int num_channels, int bytes_per_sample) { pa_buffer_attr buffAttr; pa_sample_spec ss; int error; ss.rate = sample_rate; ss.channels = num_channels; if (bytes_per_sample == 2) { switch (id->id.format) { case SPD_AUDIO_LE: ss.format = PA_SAMPLE_S16LE; break; case SPD_AUDIO_BE: ss.format = PA_SAMPLE_S16BE; break; } } else { ss.format = PA_SAMPLE_U8; } /* Set prebuf to one sample so that keys are spoken as soon as typed rather than delayed until the next key pressed */ buffAttr.maxlength = (uint32_t) - 1; //buffAttr.tlength = (uint32_t)-1; - this is the default, which causes key echo to not work properly. buffAttr.tlength = id->pa_min_audio_length; buffAttr.prebuf = (uint32_t) - 1; buffAttr.minreq = (uint32_t) - 1; buffAttr.fragsize = (uint32_t) - 1; /* Open new connection */ if (! (id->pa_simple = pa_simple_new(id->pa_server, "speech-dispatcher", PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &buffAttr, &error))) { fprintf(stderr, __FILE__ ": pa_simple_new() failed: %s\n", pa_strerror(error)); return 1; } return 0; } /* Close the connection to the server. Does not free the AudioID struct. */ /* Usable in pulse_play, which closes connections on failure or */ /* changes in audio parameters. */ static void pulse_connection_close(spd_pulse_id_t * pulse_id) { if (pulse_id->pa_simple != NULL) { pa_simple_free(pulse_id->pa_simple); pulse_id->pa_simple = NULL; } } static AudioID *pulse_open(void **pars) { spd_pulse_id_t *pulse_id; int ret; pulse_id = (spd_pulse_id_t *) g_malloc(sizeof(spd_pulse_id_t)); /* Select an Endianness for the initial connection. */ #if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) pulse_id->id.format = SPD_AUDIO_BE; #else pulse_id->id.format = SPD_AUDIO_LE; #endif pulse_id->pa_simple = NULL; pulse_id->pa_server = (char *)pars[3]; pulse_id->pa_min_audio_length = DEFAULT_PA_MIN_AUDIO_LENgTH; pulse_id->pa_current_rate = -1; pulse_id->pa_current_bps = -1; pulse_id->pa_current_channels = -1; if (!strcmp(pulse_id->pa_server, "default")) { pulse_id->pa_server = NULL; } if (pars[4] != NULL && atoi(pars[4]) != 0) pulse_id->pa_min_audio_length = atoi(pars[4]); pulse_id->pa_stop_playback = 0; ret = _pulse_open(pulse_id, 44100, 1, 2); if (ret) { g_free(pulse_id); pulse_id = NULL; } return (AudioID *) pulse_id; } static int pulse_play(AudioID * id, AudioTrack track) { int bytes_per_sample; int num_bytes; int outcnt = 0; signed short *output_samples; int i; int error; spd_pulse_id_t *pulse_id = (spd_pulse_id_t *) id; if (id == NULL) { return -1; } if (track.samples == NULL || track.num_samples <= 0) { return 0; } MSG("Starting playback\n"); /* Choose the correct format */ if (track.bits == 16) { bytes_per_sample = 2; } else if (track.bits == 8) { bytes_per_sample = 1; } else { MSG("ERROR: Unsupported sound data format, track.bits = %d\n", track.bits); return -1; } output_samples = track.samples; num_bytes = track.num_samples * bytes_per_sample; /* Check if the current connection has suitable parameters for this track */ if (pulse_id->pa_current_rate != track.sample_rate || pulse_id->pa_current_bps != track.bits || pulse_id->pa_current_channels != track.num_channels) { MSG("Reopenning connection due to change in track parameters sample_rate:%d bps:%d channels:%d\n", track.sample_rate, track.bits, track.num_channels); /* Close old connection if any */ pulse_connection_close(pulse_id); /* Open a new connection */ _pulse_open(pulse_id, track.sample_rate, track.num_channels, bytes_per_sample); /* Keep track of current connection parameters */ pulse_id->pa_current_rate = track.sample_rate; pulse_id->pa_current_bps = track.bits; pulse_id->pa_current_channels = track.num_channels; } MSG("bytes to play: %d, (%f secs)\n", num_bytes, (((float)(num_bytes) / 2) / (float)track.sample_rate)); pulse_id->pa_stop_playback = 0; outcnt = 0; i = 0; while ((outcnt < num_bytes) && !pulse_id->pa_stop_playback) { if ((num_bytes - outcnt) > PULSE_SEND_BYTES) { i = PULSE_SEND_BYTES; } else { i = (num_bytes - outcnt); } if (pa_simple_write (pulse_id->pa_simple, ((char *)output_samples) + outcnt, i, &error) < 0) { pa_simple_drain(pulse_id->pa_simple, NULL); pulse_connection_close(pulse_id); MSG("ERROR: Audio: pulse_play(): %s - closing device - re-open it in next run\n", pa_strerror(error)); break; } else { MSG("Pulse: wrote %u bytes\n", i); } outcnt += i; } return 0; } /* stop the pulse_play() loop */ static int pulse_stop(AudioID * id) { spd_pulse_id_t *pulse_id = (spd_pulse_id_t *) id; pulse_id->pa_stop_playback = 1; return 0; } static int pulse_close(AudioID * id) { spd_pulse_id_t *pulse_id = (spd_pulse_id_t *) id; pulse_connection_close(pulse_id); g_free(pulse_id); id = NULL; return 0; } static int pulse_set_volume(AudioID * id, int volume) { return 0; } static void pulse_set_loglevel(int level) { if (level) { pulse_log_level = level; } } static char const *pulse_get_playcmd(void) { return pulse_play_cmd; } /* Provide the pulse backend. */ static spd_audio_plugin_t pulse_functions = { "pulse", pulse_open, pulse_play, pulse_stop, pulse_close, pulse_set_volume, pulse_set_loglevel, pulse_get_playcmd }; spd_audio_plugin_t *pulse_plugin_get(void) { return &pulse_functions; } spd_audio_plugin_t *SPD_AUDIO_PLUGIN_ENTRY(void) __attribute__ ((weak, alias("pulse_plugin_get"))); speech-dispatcher-0.8.3/src/audio/oss.c0000664000175000017500000003204412522771346014714 00000000000000 /* * oss.c -- The Open Sound System backend for the spd_audio library. * * Copyright (C) 2004,2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Leser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: oss.c,v 1.13 2006-07-11 16:12:26 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include /* for open, close */ #include #include #include #include #define SPD_AUDIO_PLUGIN_ENTRY spd_oss_LTX_spd_audio_plugin_get #include typedef struct { AudioID id; int fd; char *device_name; pthread_mutex_t fd_mutex; pthread_cond_t pt_cond; pthread_mutex_t pt_mutex; } spd_oss_id_t; static int _oss_open(spd_oss_id_t * id); static int _oss_close(spd_oss_id_t * id); static int _oss_sync(spd_oss_id_t * id); /* Put a message into the logfile (stderr) */ #define MSG(level, arg...) \ if(level <= oss_log_level){ \ time_t t; \ struct timeval tv; \ char *tstr; \ t = time(NULL); \ tstr = g_strdup(ctime(&t)); \ tstr[strlen(tstr)-1] = 0; \ gettimeofday(&tv,NULL); \ fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \ fprintf(stderr," OSS: "); \ fprintf(stderr,arg); \ fprintf(stderr,"\n"); \ fflush(stderr); \ g_free(tstr); \ } #define ERR(arg...) \ { \ time_t t; \ struct timeval tv; \ char *tstr; \ t = time(NULL); \ tstr = g_strdup(ctime(&t)); \ tstr[strlen(tstr)-1] = 0; \ gettimeofday(&tv,NULL); \ fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \ fprintf(stderr," OSS ERROR: "); \ fprintf(stderr,arg); \ fprintf(stderr,"\n"); \ fflush(stderr); \ g_free(tstr); \ } static int oss_log_level; static char const *oss_play_cmd = "play"; static int _oss_open(spd_oss_id_t * id) { MSG(1, "_oss_open()") pthread_mutex_lock(&id->fd_mutex); id->fd = open(id->device_name, O_WRONLY, 0); if (id->fd < 0) { perror(id->device_name); pthread_mutex_unlock(&id->fd_mutex); id = NULL; return -1; } pthread_mutex_unlock(&id->fd_mutex); return 0; } static int _oss_close(spd_oss_id_t * id) { MSG(1, "_oss_close()") if (id == NULL) return 0; if (id->fd < 0) return 0; pthread_mutex_lock(&id->fd_mutex); close(id->fd); id->fd = -1; pthread_mutex_unlock(&id->fd_mutex); return 0; } /* Open OSS device Arguments: **pars: (char*) pars[0] -- the name of the device (e.g. "/dev/dsp") (void*) pars[1] = NULL */ static AudioID *oss_open(void **pars) { spd_oss_id_t *oss_id; int ret; if (pars[0] == NULL) return NULL; oss_id = (spd_oss_id_t *) g_malloc(sizeof(spd_oss_id_t)); oss_id->device_name = g_strdup((char *)pars[0]); pthread_mutex_init(&oss_id->fd_mutex, NULL); pthread_cond_init(&oss_id->pt_cond, NULL); pthread_mutex_init(&oss_id->pt_mutex, NULL); /* Test if it's possible to access the device */ ret = _oss_open(oss_id); if (ret) { g_free(oss_id->device_name); g_free(oss_id); return NULL; } ret = _oss_close(oss_id); if (ret) { g_free(oss_id->device_name); g_free(oss_id); return NULL; } return (AudioID *) oss_id; } /* Internal function. */ static int _oss_sync(spd_oss_id_t * id) { int ret; ret = ioctl(id->fd, SNDCTL_DSP_POST, 0); if (ret == -1) { perror("reset"); return -1; } return 0; } static int oss_play(AudioID * id, AudioTrack track) { int ret, ret2; struct timeval now; struct timespec timeout; float lenght; int r = 0; int format, oformat, channels, speed; int bytes_per_sample; int num_bytes; signed short *output_samples; float delay = 0; float DELAY = 0.1; /* in seconds */ audio_buf_info info; int bytes; float real_volume; int i; int re; spd_oss_id_t *oss_id = (spd_oss_id_t *) id; AudioTrack track_volume; if (oss_id == NULL) return -1; /* Open the sound device. This is necessary for OSS so that the application doesn't prevent others from accessing /dev/dsp when it doesn't play anything. */ ret = _oss_open(oss_id); if (ret) return -2; /* Create a copy of track with the adjusted volume */ track_volume = track; track_volume.samples = (short *)g_malloc(sizeof(short) * track.num_samples); real_volume = ((float)id->volume + 100) / (float)200; for (i = 0; i <= track.num_samples - 1; i++) track_volume.samples[i] = track.samples[i] * real_volume; /* Choose the correct format */ if (track.bits == 16) { format = AFMT_S16_NE; bytes_per_sample = 2; } else if (track.bits == 8) { bytes_per_sample = 1; format = AFMT_S8; } else { ERR("Audio: Unrecognized sound data format.\n"); _oss_close(oss_id); return -10; } oformat = format; ret = ioctl(oss_id->fd, SNDCTL_DSP_SETFMT, &format); if (ret == -1) { perror("OSS ERROR: format"); _oss_close(oss_id); return -1; } if (format != oformat) { ERR("Device doesn't support 16-bit sound format.\n"); _oss_close(oss_id); return -2; } /* Choose the correct number of channels */ channels = track.num_channels; ret = ioctl(oss_id->fd, SNDCTL_DSP_CHANNELS, &channels); if (ret == -1) { perror("OSS ERROR: channels"); _oss_close(oss_id); return -3; } if (channels != track.num_channels) { MSG(1, "Device doesn't support stereo sound.\n"); _oss_close(oss_id); return -4; } /* Choose the correct sample rate */ speed = track.sample_rate; ret = ioctl(oss_id->fd, SNDCTL_DSP_SPEED, &speed); if (ret == -1) { ERR("OSS ERROR: Can't set sample rate %d nor any similar.", track.sample_rate); _oss_close(oss_id); return -5; } if (speed != track.sample_rate) { ERR("Device doesn't support bitrate %d, using %d instead.\n", track.sample_rate, speed); } /* Is it not an empty track? */ if (track.samples == NULL) { _oss_close(oss_id); return 0; } /* Loop until all samples are played on the device. In the meantime, wait in pthread_cond_timedwait for more data or for interruption. */ MSG(4, "Starting playback"); output_samples = track_volume.samples; num_bytes = track.num_samples * bytes_per_sample; MSG(4, "bytes to play: %d, (%f secs)", num_bytes, (((float)(num_bytes) / 2) / (float)track.sample_rate)); while (num_bytes > 0) { /* OSS doesn't support non-blocking write, so lets check how much data can we write so that write() returns immediatelly */ re = ioctl(oss_id->fd, SNDCTL_DSP_GETOSPACE, &info); if (re == -1) { perror("OSS ERROR: GETOSPACE"); _oss_close(oss_id); return -5; } /* If there is not enough space for a single fragment, try later. (This shouldn't happen, it has very bad effect on synchronization!) */ if (info.fragments == 0) { MSG(4, "WARNING: There is not enough space for a single fragment, looping"); usleep(100); continue; } MSG(4, "There is space for %d more fragments, fragment size is %d bytes", info.fragments, info.fragsize); bytes = info.fragments * info.fragsize; ret = write(oss_id->fd, output_samples, num_bytes > bytes ? bytes : num_bytes); /* Handle write() errors */ if (ret <= 0) { perror("audio"); _oss_close(oss_id); return -6; } num_bytes -= ret; output_samples += ret / 2; MSG(4, "%d bytes written to OSS, %d remaining", ret, num_bytes); /* If there is some more data that is less than a full fragment, we need to write it immediatelly so that it doesn't cause buffer underruns later. */ if ((num_bytes > 0) && (num_bytes < info.fragsize) && (bytes + num_bytes < info.bytes)) { MSG(4, "Writing the rest of the data (%d bytes) to OSS, not a full fragment", num_bytes); ret2 = write(oss_id->fd, output_samples, num_bytes); num_bytes -= ret2; output_samples += ret2 / 2; ret += ret2; } /* Handle write() errors */ if (ret <= 0) { perror("audio"); _oss_close(oss_id); return -6; } /* Some timing magic... We need to wait for the time computed from the number of samples written. But this wait needs to be interruptible by oss_stop(). Furthermore, there need to be no buffer underrruns, so we actually wait a bit (DELAY) less in the first pass through the while() loop. Then our timer will be DELAY nsecs backwards. */ MSG(4, "Now we will try to wait"); pthread_mutex_lock(&oss_id->pt_mutex); lenght = (((float)(ret) / 2) / (float)track.sample_rate); if (!delay) { delay = lenght > DELAY ? DELAY : lenght; lenght -= delay; } MSG(4, "Wait for %f secs (begin: %f, delay: %f)", lenght, lenght + delay, delay) gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + (int)lenght; timeout.tv_nsec = now.tv_usec * 1000 + (lenght - (int)lenght) * 1000000000; //MSG("5, waiting till %d:%d (%d:%d | %d:%d)", timeout.tv_sec, timeout.tv_nsec, // now.tv_sec, now.tv_usec*1000, timeout.tv_sec - now.tv_sec, timeout.tv_nsec-now.tv_usec*1000); timeout.tv_sec += timeout.tv_nsec / 1000000000; timeout.tv_nsec = timeout.tv_nsec % 1000000000; // MSG("6, waiting till %d:%d (%d:%d | %d:%d)", timeout.tv_sec, timeout.tv_nsec, // now.tv_sec, now.tv_usec*1000, timeout.tv_sec - now.tv_sec, timeout.tv_nsec-now.tv_usec*1000); r = pthread_cond_timedwait(&oss_id->pt_cond, &oss_id->pt_mutex, &timeout); pthread_mutex_unlock(&oss_id->pt_mutex); MSG(4, "End of wait"); /* The pthread_cond_timedwait was interrupted by change in the condition variable? if so, terminate. */ if (r != ETIMEDOUT) { MSG(4, "Playback stopped, %d", r); break; } } /* ...one more excersise in timing magic. Wait for the resting delay secs. */ /* Ugly hack: correct for the time we spend outside timing segments */ delay -= 0.05; MSG(4, "Wait for the resting delay = %f secs", delay) if ((delay > 0) && (r == ETIMEDOUT)) { pthread_mutex_lock(&oss_id->pt_mutex); gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec; timeout.tv_nsec = now.tv_usec * 1000 + delay * 1000000000; // MSG("6, waiting till %d:%d (%d:%d | %d:%d)", timeout.tv_sec, timeout.tv_nsec, // now.tv_sec, now.tv_usec*1000, timeout.tv_sec - now.tv_sec, timeout.tv_nsec-now.tv_usec*1000); timeout.tv_sec += timeout.tv_nsec / 1000000000; timeout.tv_nsec = timeout.tv_nsec % 1000000000; // MSG("6, waiting till %d:%d (%d:%d | %d:%d)", timeout.tv_sec, timeout.tv_nsec, // now.tv_sec, now.tv_usec*1000, timeout.tv_sec - now.tv_sec, timeout.tv_nsec-now.tv_usec*1000); r = pthread_cond_timedwait(&oss_id->pt_cond, &oss_id->pt_mutex, &timeout); pthread_mutex_unlock(&oss_id->pt_mutex); } MSG(4, "End of wait"); if (track_volume.samples != NULL) g_free(track_volume.samples); /* Flush all the buffers */ _oss_sync(oss_id); /* Close the device so that we don't block other apps trying to access the device. */ _oss_close(oss_id); MSG(4, "Device closed"); return 0; } /* Stop the playback on the device and interrupt oss_play */ static int oss_stop(AudioID * id) { int ret = 0; spd_oss_id_t *oss_id = (spd_oss_id_t *) id; if (oss_id == NULL) return 0; MSG(4, "stop() called"); /* Stop the playback on /dev/dsp */ pthread_mutex_lock(&oss_id->fd_mutex); if (oss_id->fd >= 0) ret = ioctl(oss_id->fd, SNDCTL_DSP_RESET, 0); pthread_mutex_unlock(&oss_id->fd_mutex); if (ret == -1) { perror("reset"); return -1; } /* Interrupt oss_play by setting the condition variable */ pthread_mutex_lock(&oss_id->pt_mutex); pthread_cond_signal(&oss_id->pt_cond); pthread_mutex_unlock(&oss_id->pt_mutex); return 0; } /* Close the device */ static int oss_close(AudioID * id) { spd_oss_id_t *oss_id = (spd_oss_id_t *) id; /* Does nothing because the device is being automatically openned and closed in oss_play before and after playing each sample. */ g_free(oss_id->device_name); g_free(oss_id); id = NULL; return 0; } /* Set volume Comments: /dev/dsp can't set volume. We just multiply the track samples by a constant in oss_play (see oss_play() for more information). */ static int oss_set_volume(AudioID * id, int volume) { return 0; } static void oss_set_loglevel(int level) { if (level) { oss_log_level = level; } } static char const *oss_get_playcmd(void) { return oss_play_cmd; } /* Provide the OSS backend. */ static spd_audio_plugin_t oss_functions = { "oss", oss_open, oss_play, oss_stop, oss_close, oss_set_volume, oss_set_loglevel, oss_get_playcmd }; spd_audio_plugin_t *oss_plugin_get(void) { return &oss_functions; } spd_audio_plugin_t *SPD_AUDIO_PLUGIN_ENTRY(void) __attribute__ ((weak, alias("oss_plugin_get"))); #undef MSG #undef ERR speech-dispatcher-0.8.3/src/audio/nas.c0000644000175000017500000001431512233560613014660 00000000000000/* * nas.c -- The Network Audio System backend for the spd_audio library. * * Copyright (C) 2004,2006 Brailcom, o.p.s. * * This is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1, or (at your option) any later * version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this package; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: nas.c,v 1.8 2006-07-11 16:12:26 hanke Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include