blob: 457150972b4930cb3c79862c26e9915d7eebff67 [file] [log] [blame] [edit]
/*
* 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 */