| /* |
| * module_utils.h - Module utilities |
| * Functions to help writing output modules for Speech Dispatcher |
| * Copyright (C) 2003, 2004, 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 program. If not, see <https://www.gnu.org/licenses/>. |
| * |
| * $Id: module_utils.h,v 1.22 2008-06-27 12:29:21 hanke Exp $ |
| */ |
| |
| #ifndef __MODULE_UTILS_H |
| #define __MODULE_UTILS_H |
| |
| #include <dotconf.h> |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <glib.h> |
| #include <pthread.h> |
| #include <signal.h> |
| #include <sys/wait.h> |
| #include <sys/time.h> |
| #include <errno.h> |
| #include <dotconf.h> |
| |
| #include <speechd_types.h> |
| #include "common.h" |
| #include "spd_audio.h" |
| #include "spd_module_main.h" |
| |
| G_BEGIN_DECLS |
| |
| extern AudioID *module_audio_id; |
| |
| typedef struct SPDMarks { |
| unsigned num; |
| unsigned allocated; |
| unsigned *samples; |
| char **names; |
| gboolean stop; |
| } SPDMarks; |
| |
| extern int log_level; |
| |
| extern SPDMsgSettings msg_settings; |
| extern SPDMsgSettings msg_settings_old; |
| |
| extern int Debug; |
| extern FILE *CustomDebugFile; |
| |
| extern configfile_t *configfile; |
| extern configoption_t *module_dc_options; |
| extern int module_num_dc_options; |
| |
| extern const char *module_name; |
| |
| #define CLEAN_OLD_SETTINGS_TABLE() do { \ |
| msg_settings_old.rate = -101;\ |
| msg_settings_old.pitch = -101;\ |
| msg_settings_old.pitch_range = -101;\ |
| msg_settings_old.volume = -101;\ |
| msg_settings_old.punctuation_mode = (SPDPunctuation) -1;\ |
| msg_settings_old.spelling_mode = (SPDSpelling) -1;\ |
| msg_settings_old.cap_let_recogn = (SPDCapitalLetters) -1;\ |
| msg_settings_old.voice_type = (SPDVoiceType) -1;\ |
| msg_settings_old.voice.name = NULL;\ |
| msg_settings_old.voice.language = NULL; \ |
| } while (0) |
| |
| #define INIT_SETTINGS_TABLES() do { \ |
| module_name = MODULE_NAME; \ |
| module_dc_options = NULL;\ |
| msg_settings.rate = 0;\ |
| msg_settings.pitch = 0;\ |
| msg_settings.pitch_range = 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(); \ |
| } while (0) |
| |
| #define FATAL(msg, ...) do { \ |
| fprintf(stderr, "FATAL ERROR in output module [%s:%d]:\n " msg, \ |
| __FILE__, __LINE__, ## __VA_ARGS__); \ |
| if (Debug > 1) \ |
| fprintf(CustomDebugFile, "FATAL ERROR in output module [%s:%d]:\n " msg, \ |
| __FILE__, __LINE__, ## __VA_ARGS__); \ |
| exit(EXIT_FAILURE); \ |
| } while (0) |
| |
| int module_load(void); |
| SPDVoice **module_get_voices(void); |
| void module_strip_silence(AudioTrack * track); |
| void module_strip_head_silence(AudioTrack * track); |
| void module_strip_tail_silence(AudioTrack * track); |
| int module_tts_output(AudioTrack track, AudioFormat format); |
| int module_marks_init(SPDMarks *marks); |
| int module_marks_add(SPDMarks *marks, unsigned sample, const char *name); |
| int module_tts_output_marks(AudioTrack track, AudioFormat format, SPDMarks *marks); |
| int module_marks_stop(SPDMarks *marks); |
| int module_marks_clear(SPDMarks *marks); |
| char *module_is_speaking(void); |
| SPDVoice **module_list_registered_voices(void); |
| |
| #define UPDATE_PARAMETER(value, setter) do { \ |
| if (msg_settings_old.value != msg_settings.value) \ |
| { \ |
| msg_settings_old.value = msg_settings.value; \ |
| setter (msg_settings.value); \ |
| } \ |
| } while (0) |
| |
| #define UPDATE_STRING_PARAMETER(value, setter) do { \ |
| 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); \ |
| } \ |
| } \ |
| } while (0) |
| |
| #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); |
| |
| 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(const char *buf); |
| char *module_multicases_string(char *message); |
| |
| 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); |
| 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(void); |
| int module_terminate_thread(pthread_t thread); |
| char *module_recode_to_iso(const char *data, int bytes, const char *language, |
| const char *fallback); |
| void module_signal_end(void); |
| configoption_t *module_add_config_option(configoption_t * options, |
| int *num_options, const char *name, int type, |
| dotconf_callback_t callback, |
| info_t * info, unsigned long context); |
| |
| configoption_t *add_config_option(configoption_t * options, |
| int *num_config_options, const 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) \ |
| { \ |
| if (cmd->data.str != NULL) { \ |
| g_free(name); \ |
| 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; \ |
| if (cmd->data.list[0] == NULL) return NULL; \ |
| new_item = (T ## name *) g_malloc(sizeof(T ## name)); \ |
| 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) do { \ |
| 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); \ |
| } while (0) |
| |
| #define MOD_OPTION_1_INT_REG(name, default) do { \ |
| name = default; \ |
| module_dc_options = module_add_config_option(module_dc_options, \ |
| &module_num_dc_options, #name, \ |
| ARG_INT, name ## _cb, NULL, 0); \ |
| } while (0) |
| |
| /* TODO: Switch this to real float, not /100 integer, |
| as soon as DotConf supports floats */ |
| #define MOD_OPTION_1_FLOAT_REG(name, default) do { \ |
| name = default; \ |
| module_dc_options = module_add_config_option(module_dc_options, \ |
| &module_num_dc_options, #name, \ |
| ARG_INT, name ## _cb, NULL, 0); \ |
| } while (0) |
| |
| #define MOD_OPTION_MORE_REG(name) do { \ |
| module_dc_options = module_add_config_option(module_dc_options, \ |
| &module_num_dc_options, #name, \ |
| ARG_LIST, name ## _cb, NULL, 0); \ |
| } while (0) |
| |
| #define MOD_OPTION_HT_REG(name) do { \ |
| 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); \ |
| } while (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_" |
| |
| extern int current_index_mark; |
| extern char *module_index_mark; |
| |
| /* Kept only for compatibility with old modules, do not use */ |
| #define INIT_INDEX_MARKING() module_index_mark = NULL; |
| |
| /* Prototypes from module_utils_addvoice.c */ |
| void module_register_available_voices(void); |
| void module_register_settings_voices(void); |
| char *module_getvoice(const char *language, SPDVoiceType voice); |
| gboolean module_existsvoice(const char *voicename); |
| char *module_getdefaultvoice(void); |
| |
| G_END_DECLS |
| |
| #endif /* #ifndef __MODULE_UTILS_H */ |