1 /*
2 * module_utils_addvoice.c - Functionality for the DotConf AddVoice feature
3 *
4 * Copyright (C) 2001, 2002, 2003, 2006, 2007 Brailcom, o.p.s.
5 *
6 * This is free software; you can redistribute it and/or modify it under the
7 * terms of the GNU Lesser General Public License as published by the Free
8 * Software Foundation; either version 2, or (at your option) any later
9 * version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * $Id: module_utils_addvoice.c,v 1.5 2007-07-29 23:43:33 hanke Exp $
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28
29 #include <glib.h>
30 #include <dotconf.h>
31
32 #include "module_utils.h"
33
34 GHashTable *module_voice_table = NULL;
35
36 static int nbvoices=0;
37 static int nbpaths=0;
38 static SPDVoice *generic_voices;
39 static SPDVoice **generic_voices_list;
40 static char **dependency_paths;
41 typedef struct {
42 char *male1;
43 char *male2;
44 char *male3;
45 char *female1;
46 char *female2;
47 char *female3;
48 char *child_male;
49 char *child_female;
50 } SPDVoiceDef;
51
DOTCONF_CB(VoiceFileDependency_cb)52 DOTCONF_CB(VoiceFileDependency_cb)
53 {
54 dependency_paths = (char **)g_realloc(dependency_paths, (nbpaths + 1) * sizeof *dependency_paths);
55 dependency_paths[nbpaths] = g_strdup(cmd->data.str);
56 ++nbpaths;
57 return NULL;
58 }
59
DOTCONF_CB(AddVoice_cb)60 DOTCONF_CB(AddVoice_cb)
61 {
62 int i=0;
63 GRegex *regex;
64 SPDVoiceDef *voices;
65 char *language = cmd->data.list[0];
66 char *symbolic;
67 char *voicename = cmd->data.list[2];
68 char *key;
69 SPDVoiceDef *value;
70
71 if (language == NULL) {
72 DBG("Missing language.\n");
73 return NULL;
74 }
75
76 if (cmd->data.list[1] == NULL) {
77 DBG("Missing symbolic name.\n");
78 return NULL;
79 }
80
81 if (voicename == NULL) {
82 DBG("Missing voice name for %s\n", cmd->data.list[0]);
83 return NULL;
84 }
85
86 if (module_voice_table == NULL) {
87 return NULL;
88 }
89
90 symbolic =
91 (char *)g_ascii_strup(cmd->data.list[1], strlen(cmd->data.list[1]));
92
93 voices = g_hash_table_lookup(module_voice_table, language);
94 if (voices == NULL) {
95 key = (char *)g_strdup(language);
96 value = (SPDVoiceDef *) g_malloc(sizeof(SPDVoiceDef));
97
98 value->male1 = NULL;
99 value->male2 = NULL;
100 value->male3 = NULL;
101 value->female1 = NULL;
102 value->female2 = NULL;
103 value->female3 = NULL;
104 value->child_male = NULL;
105 value->child_female = NULL;
106
107 g_hash_table_insert(module_voice_table, key, value);
108 voices = value;
109 }
110
111 regex = g_regex_new("[$]VOICE", 0, 0, NULL);
112 for (i = 0; i < nbpaths; i++)
113 {
114 char *new_dependency_path = g_regex_replace_literal(regex, dependency_paths[i], -1, 0, cmd->data.list[2], 0, NULL);
115 if (! g_file_test(new_dependency_path, G_FILE_TEST_EXISTS)) {
116 g_free(new_dependency_path);
117 g_regex_unref(regex);
118 return NULL;
119 }
120 g_free(new_dependency_path);
121 }
122 g_regex_unref(regex);
123
124 if (!strcmp(symbolic, "MALE1"))
125 voices->male1 = g_strdup(voicename);
126 else if (!strcmp(symbolic, "MALE2"))
127 voices->male2 = g_strdup(voicename);
128 else if (!strcmp(symbolic, "MALE3"))
129 voices->male3 = g_strdup(voicename);
130 else if (!strcmp(symbolic, "FEMALE1"))
131 voices->female1 = g_strdup(voicename);
132 else if (!strcmp(symbolic, "FEMALE2"))
133 voices->female2 = g_strdup(voicename);
134 else if (!strcmp(symbolic, "FEMALE3"))
135 voices->female3 = g_strdup(voicename);
136 else if (!strcmp(symbolic, "CHILD_MALE"))
137 voices->child_male = g_strdup(voicename);
138 else if (!strcmp(symbolic, "CHILD_FEMALE"))
139 voices->child_female = g_strdup(voicename);
140 else {
141 DBG("Unrecognized voice name in configuration\n");
142 return NULL;
143 }
144
145 generic_voices = (SPDVoice *)g_realloc(generic_voices, (nbvoices+1) * sizeof(SPDVoice));
146 generic_voices_list = (SPDVoice **)g_realloc(generic_voices_list, (nbvoices+2) * sizeof(SPDVoice *));
147 generic_voices[nbvoices].name = g_strdup(cmd->data.list[2]);
148 generic_voices[nbvoices].language = g_strdup(cmd->data.list[0]);
149 generic_voices[nbvoices].variant = g_strdup(cmd->data.list[1]);;
150 for (i = 0; i < nbvoices+1; i++)
151 generic_voices_list[i] = &generic_voices[i];
152 generic_voices_list[nbvoices+1] = NULL;
153 ++nbvoices;
154 return NULL;
155 }
156
module_register_available_voices(void)157 void module_register_available_voices(void)
158 {
159 module_dc_options = module_add_config_option(module_dc_options,
160 &module_num_dc_options,
161 "VoiceFileDependency", ARG_STR,
162 VoiceFileDependency_cb, NULL, 0);
163 }
164
module_register_settings_voices(void)165 void module_register_settings_voices(void)
166 {
167 module_voice_table = g_hash_table_new(g_str_hash, g_str_equal);
168 module_dc_options = module_add_config_option(module_dc_options,
169 &module_num_dc_options,
170 "AddVoice", ARG_LIST,
171 AddVoice_cb, NULL, 0);
172 }
173
module_existsvoice(char * voicename)174 gboolean module_existsvoice(char *voicename)
175 {
176 int i;
177 if (!nbvoices)
178 return FALSE;
179 for (i = 0; generic_voices_list[i] != NULL; i++) {
180 if (strcasecmp(generic_voices[i].name, voicename) == 0)
181 return TRUE;
182 }
183 return FALSE;
184 }
185
module_list_registered_voices(void)186 SPDVoice **module_list_registered_voices(void) {
187 return (SPDVoice **)generic_voices_list;
188 }
189
module_getvoice(char * language,SPDVoiceType voice)190 char *module_getvoice(char *language, SPDVoiceType voice)
191 {
192 SPDVoiceDef *voices;
193 char *ret;
194
195 if (module_voice_table == NULL) {
196 DBG("Can't get voice because voicetable is NULL\n");
197 return NULL;
198 }
199
200 voices = g_hash_table_lookup(module_voice_table, language);
201 if (voices == NULL) {
202 DBG("There are no voices in the table for language=%s\n",
203 language);
204 return NULL;
205 }
206
207 switch (voice) {
208 case SPD_MALE1:
209 ret = voices->male1;
210 break;
211 case SPD_MALE2:
212 ret = voices->male2;
213 break;
214 case SPD_MALE3:
215 ret = voices->male3;
216 break;
217 case SPD_FEMALE1:
218 ret = voices->female1;
219 break;
220 case SPD_FEMALE2:
221 ret = voices->female2;
222 break;
223 case SPD_FEMALE3:
224 ret = voices->female3;
225 break;
226 case SPD_CHILD_MALE:
227 ret = voices->child_male;
228 break;
229 case SPD_CHILD_FEMALE:
230 ret = voices->child_female;
231 break;
232 default:
233 printf("Unknown voice");
234 return NULL;
235 }
236
237 if (ret == NULL)
238 ret = voices->male1;
239 if (ret == NULL)
240 ret = voices->female1;
241 if (ret == NULL)
242 ret = voices->male2;
243 if (ret == NULL)
244 ret = voices->female2;
245 if (ret == NULL)
246 ret = voices->male3;
247 if (ret == NULL)
248 ret = voices->female3;
249 if (ret == NULL)
250 ret = voices->child_male;
251 if (ret == NULL)
252 ret = voices->child_female;
253 if (ret == NULL)
254 fprintf(stderr, "No voice available for this output module!");
255
256 return ret;
257 }
258