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