Update title text
[platform/core/uifw/libttssmt.git] / setting-app / src / ttssmt_setting_main.c
1 /*
2 *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdbool.h>
17
18 #include "ttssmt_setting_main.h"
19
20 typedef struct appdata {
21         Evas_Object *win;
22         Evas_Object *conform;
23         Evas_Object *naviframe;
24         Evas_Object *genlist;
25
26         Evas_Object *progress_popup;
27         Evas_Object *delete_popup;
28         Elm_Object_Item *selected_lang;
29 } appdata_s;
30
31 typedef enum {
32         DOWNLOAD_TITLE = 0,
33         CS_CZ_FEMALE,
34         DA_DK_FEMALE,
35         DE_DE_FEMALE,
36         DE_DE_MALE,
37         EL_GR_MALE,
38         EN_GB_FEMALE,
39         EN_GB_MALE,
40         EN_IN_FEMALE,
41         EN_US_FEMALE,
42         EN_US_MALE,
43         ES_ES_FEMALE,
44         ES_ES_MALE,
45         ES_MX_FEMALE,
46         ES_MX_MALE,
47         FI_FI_FEMALE,
48         FR_FR_FEMALE,
49         FR_FR_MALE,
50         HI_IN_FEMALE,
51         HU_HU_FEMALE,
52         IT_IT_FEMALE,
53         IT_IT_MALE,
54         JA_JP_FEMALE,
55         JA_JP_MALE,
56         KO_KR_FEMALE,
57         KO_KR_MALE,
58         NB_NO_FEMALE,
59         NL_NL_FEMALE,
60         PL_PL_FEMALE,
61         PT_BR_FEMALE,
62         PT_BR_MALE,
63         PT_PT_FEMALE,
64         PT_PT_MALE,
65         RU_RU_FEMALE,
66         SK_SK_FEMALE,
67         SV_SE_FEMALE,
68         TR_TR_FEMALE,
69         ZH_CN_FEMALE,
70         ZH_CN_MALE,
71         ZH_HK_FEMALE,
72         ZH_HK_MALE,
73         ZH_TW_FEMALE,
74         END_INDEX
75 } item_index_e;
76
77 /* Todo - update language name */
78 static char* item_data[END_INDEX][5] = {
79         {"Download (via network)", "", "", "", ""},
80         {"\xC4\x8C\x65\xC5\xA1\x74\x69\x6e\x61 - \xC5\xBD\x65\x6e\x61", "cs_CZ_Female", "libttssmt-cs_CZ_Female", "cs_CZ", "Female"},
81         {"Dansk - Kvinde", "da_DK_Female", "libttssmt-da_DK_Female", "da_DK", "Famale"},
82         {"\x44\x65\x75\x74\x73\x63\x68 - Weiblich", "de_DE_Female", "libttssmt-de_DE_Female", "de_DE", "Female"},
83         {"\x44\x65\x75\x74\x73\x63\x68 - Mannlich", "de_DE_Male", "libttssmt-de_DE_Male", "de_DE", "Male"},
84         {"\xCE\x95\xCE\xBB\xCE\xBB\xCE\xB7\xCE\xBD\xCE\xB9\xCE\xBA\xCE\xAC - \xCE\x98\xCE\xB7\xCE\xBB\xCF\x85\xCE\xBA\xCF\x8C", "el_GR_Female", "libttssmt-el_GR_Female", "el_GR", "Female"},
85         {"English (United Kingdom) - Female", "en_GB_Female", "libttssmt-en_GB_Female", "en_GB", "Female"},
86         {"English (United Kingdom) - Male", "en_GB_Male", "libttssmt-en_GB_Male", "en_GB", "Male"},
87         {"English (India) - Female", "en_IN_Female", "libttssmt-en_IN_Female", "en_IN", "Famale"},
88         {"\x45\x6E\x67\x6C\x69\x73\x68 - Female", "en_US_Female", "libttssmt-en_US_Female", "en_US", "Female"},
89         {"\x45\x6E\x67\x6C\x69\x73\x68 - Male", "en_US_Male", "libttssmt-en_US_Male", "en_US", "Male"},
90         {"\x45\x73\x70\x61\xC3\xB1\x6F\x6C - Mujer", "es_ES_Female", "libttssmt-es_ES_Female", "es_ES", "Female"},
91         {"\x45\x73\x70\x61\xC3\xB1\x6F\x6C - Hombre", "es_ES_Male", "libttssmt-es_ES_Male", "es_ES", "Male"},
92         {"\x45\x73\x70\x61\xC3\xB1\x6f\x6c\x20\x28\x45\x73\x74\x61\x64\x6f\x73\x20\x55\x6e\x69\x64\x6f\x73\x29 - Mujer", "es_MX_Female", "libttssmt-es_MX_Female", "es_MX", "Female"},
93         {"\x45\x73\x70\x61\xC3\xB1\x6f\x6c\x20\x28\x45\x73\x74\x61\x64\x6f\x73\x20\x55\x6e\x69\x64\x6f\x73\x29 - Hombre", "es_MX_Male", "libttssmt-es_MX_Male", "es_MX", "Male"},
94         {"Suomi - Nainen ", "fi_FI_Female", "libttssmt-fi_FI_Female", "fi_FI", "Female"},
95         {"\x46\x72\x61\x6E\xC3\xA7\x61\x69\x73 - Femme", "fr_FR_Female", "libttssmt-fr_FR_Female", "fr_FR", "Female"},
96         {"\x46\x72\x61\x6E\xC3\xA7\x61\x69\x73 - Homme", "fr_FR_Male", "libttssmt-fr_FR_Male", "fr_FR", "Male"},
97         {"\xE0\xA4\xB9\xE0\xA4\xBF\xE0\xA4\xA8\xE0\xA5\x8D\xE0\xA4\xA6\xE0\xA5\x80 - \xE0\xA4\xB8\xE0\xA5\x8D\xE0\xA4\xA4\xE0\xA5\x8D\xE0\xA4\xB0\xE0\xA5\x80", "hi_IN_Female", "libttssmt-hi_IN_Female", "hi_IN", "Female"},
98         {"Magyar - \x4e\xC5\x91", "hu_HU_Female", "libttssmt-hu_HU_Female", "hu_HU", "Female"},
99         {"\x49\x74\x61\x6C\x69\x61\x6E\x6F - Femmina", "it_IT_Female", "libttssmt-it_IT_Female", "it_IT", "Female"},
100         {"\x49\x74\x61\x6C\x69\x61\x6E\x6F - Maschio", "it_IT_Male", "libttssmt-it_IT_Male", "it_IT", "Male"},
101         {"\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E - \xE5\xA5\xB3\xE6\x80\xA7", "ja_JP_Female", "libttssmt-ja_JP_Female", "ja_JP", "Female"},
102         {"\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E - \xE7\x94\xB7\xE6\x80\xA7", "ja_JP_Male", "libttssmt-ja_JP_Male", "ja_JP", "Male"},
103         {"\xED\x95\x9C\xEA\xB5\xAD\xEC\x96\xB4 - \xEC\x97\xAC", "ko_KR_Female", "libttssmt-ko_KR_Female", "ko_KR", "Female"},
104         {"\xED\x95\x9C\xEA\xB5\xAD\xEC\x96\xB4 - \xEB\x82\xA8", "ko_KR_Male", "libttssmt-ko_KR_Male", "ko_KR", "Male"},
105         {"Norsk - Kvinne", "nb_NO_Female", "libttssmt-nb_NO_Female", "nb_NO", "Female"},
106         {"Nederlands - Vrouw", "nl_NL_Female", "libttssmt-nl_NL_Female", "nl_NL", "Female"},
107         {"Polski - Kobieta", "pl_PL_Female", "libttssmt-pl_PL_Female", "pl_PL", "Female"},
108         {"\x50\x6f\x72\x74\x75\x67\x75\xC3\xAA\x73\x20\x28\x42\x72\x61\x73\x69\x6c\x29 - Feminino", "pt_BR_Female", "libttssmt-pt_BR_Female", "pt_BR", "Female"},
109         {"\x50\x6f\x72\x74\x75\x67\x75\xC3\xAA\x73\x20\x28\x42\x72\x61\x73\x69\x6c\x29 - Masculino", "pt_BR_Male", "libttssmt-pt_BR_Male", "pt_BR", "Male"},
110         {"\x50\x6f\x72\x74\x75\x67\x75\xC3\xAA\x73\x20\x28\x50\x6f\x72\x74\x75\x67\x61\x6c\x29 - Feminino", "pt_PT_Female", "libttssmt-pt_PT_Female", "pt_PT", "Female"},
111         {"\x50\x6f\x72\x74\x75\x67\x75\xC3\xAA\x73\x20\x28\x50\x6f\x72\x74\x75\x67\x61\x6c\x29 - Masculino", "pt_PT_Male", "libttssmt-pt_PT_Male", "pt_PT", "Male"},
112         {"\x50\xD1\x83\xD1\x81\xD1\x81\xD0\xBA\xD0\xB8\xD0\xB9 - \xD0\x96\xD0\xB5\xD0\xBD\xD1\x81\xD0\xBA\xD0\xB8\xD0\xB9", "ru_RU_Female", "libttssmt-ru_RU_Female", "ru_RU", "Female"},
113         {"\x53\x6c\x6f\x76\x65\x6e\xC4\x8D\x69\x6e\x61 - \xC5\xBD\x65\x6e\x61", "sk_SK_Female", "libttssmt-sk_SK_Female", "sk_SK", "Female"},
114         {"Svenska - Kvinna", "sv_SE_Female", "libttssmt-sv_SE_Female", "sv_SE", "Female"},
115         {"\x54\xC3\xBC\x72\x6b\xC3\xA7\x65 - \x4b\x61\x64\xC4\xB1\x6e", "tr_TR_Female", "libttssmt-tr_TR_Female", "tr_TR", "Female"},
116         {"\xE7\xAE\x80\xE4\xBD\x93\xE4\xB8\xAD\xE6\x96\x87 - \xE5\xA5\xB3", "zh_CN_Female", "libttssmt-zh_CN_Female", "zh_CN", "Female"},
117         {"\xE7\xAE\x80\xE4\xBD\x93\xE4\xB8\xAD\xE6\x96\x87 - \xE7\x94\xB7", "zh_CN_Male", "libttssmt-zh_CN_Male", "zh_CN", "Male"},
118         {"\xE7\xB9\x81\xE4\xBD\x93\xE4\xB8\xAD\xE6\x96\x87\x28\xE9\xA6\x99\xE6\xB8\xAF\x29 - \xE5\xA5\xB3", "zh_HK_Female", "libttssmt-zh_HK_Female", "zh_HK", "Female"},
119         {"\xE7\xB9\x81\xE4\xBD\x93\xE4\xB8\xAD\xE6\x96\x87\x28\xE9\xA6\x99\xE6\xB8\xAF\x29 - \xE7\x94\xB7", "zh_HK_Male", "libttssmt-zh_HK_Male", "zh_HK", "Male"},
120         {"\xE7\xB9\x81\xE4\xBD\x93\xE4\xB8\xAD\xE6\x96\x87\x28\xE5\x8F\xB0\xE6\xB9\xBE\x29 - \xE5\xA5\xB3", "zh_TW_Female", "libttssmt-zh_TW_Female", "zh_TW", "Female"}
121 };
122
123 #define TTS_TAG_ENGINE_BASE_TAG         "tts-engine"
124 #define TTS_TAG_ENGINE_VOICE_SET        "voices"
125 #define TTS_TAG_ENGINE_VOICE            "voice"
126 #define TTS_TAG_ENGINE_VOICE_TYPE       "type"
127
128 #define TTS_TAG_VOICE_TYPE_FEMALE       "female"
129 #define TTS_TAG_VOICE_TYPE_MALE         "male"
130 #define TTS_TAG_VOICE_TYPE_CHILD        "child"
131
132 #define TTS_ENGINE_INFO tzplatform_mkpath(TZ_USER_HOME, "/share/.voice/tts/engine-info/ttssmt-info.xml")
133
134 #define TTS_ENGINE_DATA_PATH tzplatform_mkpath(TZ_USER_HOME, "/share/.voice/tts/engine-info/")
135
136 static Elm_Genlist_Item_Class *g_itc_group_title = NULL;
137 static Elm_Genlist_Item_Class *g_itc_button_1line = NULL;
138
139 static appdata_s *g_ad;
140
141 typedef struct {
142         char*   language;
143         int     type;
144 } tts_config_voice_s; 
145
146 static int __tts_engine_info_add_voice(const char* path, tts_config_voice_s* voice)
147 {
148         if (NULL == path || NULL == voice) {
149                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Input parameter is NULL");
150                 return -1;
151         }
152
153         xmlDocPtr doc = NULL;
154         xmlNodePtr cur = NULL;
155
156         doc = xmlParseFile(path);
157         if (doc == NULL) {
158                 return -1;
159         }
160
161         cur = xmlDocGetRootElement(doc);
162         if (cur == NULL) {
163                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Empty document");
164                 xmlFreeDoc(doc);
165                 return -1;
166         }
167
168         if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_BASE_TAG)) {
169                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] The wrong type, root node is NOT 'tts-engine'");
170                 xmlFreeDoc(doc);
171                 return -1;
172         }
173
174         cur = cur->xmlChildrenNode;
175         if (cur == NULL) {
176                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Empty document");
177                 xmlFreeDoc(doc);
178                 return -1;
179         }
180
181         while (cur != NULL) {
182                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
183                         xmlNodePtr voice_node = NULL;
184                         voice_node = xmlNewNode(NULL, (const xmlChar *)TTS_TAG_ENGINE_VOICE);
185                         if (2 == voice->type) {
186                                 xmlSetProp(voice_node, (const xmlChar *)TTS_TAG_ENGINE_VOICE_TYPE, (const xmlChar*)TTS_TAG_VOICE_TYPE_FEMALE);
187                         } else {
188                                 xmlSetProp(voice_node, (const xmlChar *)TTS_TAG_ENGINE_VOICE_TYPE, (const xmlChar*)TTS_TAG_VOICE_TYPE_MALE);
189                         }
190
191                         xmlNodeSetContent(voice_node, (const xmlChar *)voice->language);
192                         xmlAddChild(cur, voice_node);
193                 }
194                 cur = cur->next;
195         }
196
197         int ret = xmlSaveFormatFile(path, doc, 1);
198         if (0 > ret) {
199                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Save result : %d", ret);
200         }
201
202         xmlFreeDoc(doc);
203
204         return 0;
205 }
206
207 static int __tts_engine_info_remove_voice(const char* path, tts_config_voice_s* voice)
208 {
209         if (NULL == path || NULL == voice) {
210                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Input parameter is NULL");
211                 return -1;
212         }
213
214         xmlDocPtr doc = NULL;
215         xmlNodePtr cur = NULL;
216         xmlChar *key = NULL;
217         xmlChar *attr = NULL;
218
219         doc = xmlParseFile(path);
220         if (doc == NULL) {
221                 return -1;
222         }
223
224         cur = xmlDocGetRootElement(doc);
225         if (cur == NULL) {
226                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Empty document");
227                 xmlFreeDoc(doc);
228                 return -1;
229         }
230
231         if (xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_BASE_TAG)) {
232                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] The wrong type, root node is NOT 'tts-engine'");
233                 xmlFreeDoc(doc);
234                 return -1;
235         }
236
237         cur = cur->xmlChildrenNode;
238         if (cur == NULL) {
239                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Empty document");
240                 xmlFreeDoc(doc);
241                 return -1;
242         }
243
244         while (cur != NULL) {
245                 if (0 == xmlStrcmp(cur->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE_SET)) {
246                         xmlNodePtr voice_node = NULL;
247                         voice_node = cur->xmlChildrenNode;
248
249                         while (NULL != voice_node) {
250                                 if (0 == xmlStrcmp(voice_node->name, (const xmlChar *)TTS_TAG_ENGINE_VOICE)) {
251                                         key = xmlNodeGetContent(voice_node);
252                                         if (NULL != key) {
253                                                 if (!strcmp((char*)key, voice->language)) {
254                                                         int temp_type = -1;
255                                                         attr = xmlGetProp(voice_node, (const xmlChar*)TTS_TAG_ENGINE_VOICE_TYPE);
256                                                         if (NULL != attr) {
257                                                                 if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_FEMALE)) {
258                                                                         temp_type = (int)2;
259                                                                 } else if (0 == xmlStrcmp(attr, (const xmlChar *)TTS_TAG_VOICE_TYPE_MALE)) {
260                                                                         temp_type = (int)1;
261                                                                 }
262                                                                 xmlFree(attr);
263                                                         }
264                                                         if (temp_type == voice->type) {
265                                                                 /* remove */
266                                                                 xmlUnlinkNode(voice_node);
267                                                                 xmlFreeNode(voice_node);
268                                                         }
269                                                 }
270                                                 xmlFree(key);
271                                         } else {
272                                                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] <%s> has no content", TTS_TAG_ENGINE_VOICE_TYPE);
273                                         }
274                                 }
275                                 voice_node = voice_node->next;
276                         }
277                 }
278                 cur = cur->next;
279         }
280
281         int ret = xmlSaveFormatFile(path, doc, 1);
282         if (0 > ret) {
283                 dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] Save result : %d", ret);
284         }
285
286         xmlFreeDoc(doc);
287
288         return 0;
289 }
290
291 static char * __genlist_text_get(void *data, Evas_Object *obj, const char *part)
292 {
293         item_index_e idx = (item_index_e)data;
294
295         if (!strcmp("elm.text", part)) {
296                 return strdup(item_data[idx][0]);
297         }
298
299         return NULL;
300 }
301
302 static bool __installed_lang(int idx)
303 {
304         char filepath[1024] = {'\0',};
305         const char* data_path = TTS_ENGINE_DATA_PATH;
306         snprintf(filepath, 1024, "%s/%s", data_path, item_data[idx][1]);
307
308         if (EN_US_FEMALE == idx || KO_KR_FEMALE == idx || DE_DE_FEMALE == idx || FR_FR_FEMALE == idx || IT_IT_FEMALE == idx || ES_ES_FEMALE == idx) {
309                 return true;
310         } else {
311                 if (0 != access(filepath, F_OK)) {
312                         return false;
313                 } else {
314                         return true;
315                 }
316         }
317 }
318
319 static void __check_changed_cb(void *data, Evas_Object *obj, void *event_info)
320 {
321         elm_genlist_item_update(g_ad->selected_lang);
322 }
323
324 static Evas_Object * __genlist_content_get(void *data, Evas_Object *obj, const char *part)
325 {
326         item_index_e idx = (item_index_e)data;
327
328         if (!strcmp("elm.swallow.icon.1", part)) {
329                 Evas_Object *check = elm_check_add(obj);
330                 elm_object_style_set(check, "default");
331                 elm_check_state_set(check, __installed_lang(idx));
332                 if (EN_US_FEMALE == idx || KO_KR_FEMALE == idx || DE_DE_FEMALE == idx || FR_FR_FEMALE == idx || IT_IT_FEMALE == idx || ES_ES_FEMALE == idx) {
333                         elm_object_disabled_set(check, EINA_TRUE);
334                 }
335
336                 evas_object_propagate_events_set(check, EINA_TRUE);
337                 evas_object_smart_callback_add(check, "changed", __check_changed_cb, data);
338                 evas_object_show(check);
339                 return check;
340         }
341
342         return NULL;
343 }
344
345 static void __progress_popup_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
346 {
347         if (NULL != g_ad->progress_popup) {
348                 evas_object_del(g_ad->progress_popup);
349                 g_ad->progress_popup = NULL;
350         }
351         return;
352 }
353
354 static void __progress_popup_back_cb(void *data, Evas_Object *obj, void *event_info)
355 {
356         return;
357 }
358
359 static void __show_progress_popup(bool failed)
360 {
361         if (NULL != g_ad->progress_popup) {
362                 evas_object_del(g_ad->progress_popup);
363                 g_ad->progress_popup = NULL;
364         }
365
366         Evas_Object *popup = elm_popup_add(g_ad->win);
367         elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
368         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
369         elm_object_part_text_set(popup, "title,text", "Downloading");
370
371         if (failed) {
372                 elm_object_part_text_set(popup, "default", "Fail to download language pack.");
373                 elm_popup_timeout_set(popup, 2.0);
374
375         } else {
376                 Evas_Object *progressbar = elm_progressbar_add(popup);
377                 elm_object_style_set(progressbar, "process_large");
378                 evas_object_size_hint_align_set(progressbar, EVAS_HINT_FILL, 0.5);
379                 evas_object_size_hint_weight_set(progressbar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
380                 elm_progressbar_pulse(progressbar, EINA_TRUE);
381
382                 elm_object_content_set(popup, progressbar);
383                 evas_object_show(progressbar);
384         }
385
386         evas_object_smart_callback_add(popup, "block,clicked", NULL, NULL);
387         evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, __progress_popup_del_cb, NULL);
388         eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, __progress_popup_back_cb, NULL);
389
390         g_ad->progress_popup = popup;
391
392         evas_object_show(popup);
393 }
394
395 static void __delete_popup_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
396 {
397         if (NULL != g_ad->delete_popup) {
398                 evas_object_del(g_ad->delete_popup);
399                 g_ad->delete_popup = NULL;
400         }
401         return;
402 }
403
404 static void __delete_popup_back_cb(void *data, Evas_Object *obj, void *event_info)
405 {
406         return;
407 }
408
409 static void __show_delete_popup()
410 {
411         if (NULL != g_ad->delete_popup) {
412                 evas_object_del(g_ad->delete_popup);
413                 g_ad->delete_popup = NULL;
414         }
415
416         Evas_Object *popup = elm_popup_add(g_ad->win);
417         elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
418         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
419         elm_object_part_text_set(popup, "title,text", "Deleting");
420         elm_popup_timeout_set(popup, 1.0);
421
422         Evas_Object *progressbar = elm_progressbar_add(popup);
423         elm_object_style_set(progressbar, "process_large");
424         evas_object_size_hint_align_set(progressbar, EVAS_HINT_FILL, 0.5);
425         evas_object_size_hint_weight_set(progressbar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
426         elm_progressbar_pulse(progressbar, EINA_TRUE);
427
428         elm_object_content_set(popup, progressbar);
429         evas_object_show(progressbar);
430
431         evas_object_smart_callback_add(popup, "block,clicked", NULL, NULL);
432         evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, __delete_popup_del_cb, NULL);
433         eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, __delete_popup_back_cb, NULL);
434
435         g_ad->delete_popup = popup;
436
437         evas_object_show(popup);
438 }
439
440 static void __hide_progress_popup()
441 {
442         if (NULL != g_ad->progress_popup) {
443                 evas_object_del(g_ad->progress_popup);
444                 g_ad->progress_popup = NULL;
445         }
446 }
447
448 static void* __download_completed_cb(void *user_data)
449 {
450         intptr_t pidx = (intptr_t)user_data;
451         int idx = (int)pidx;
452         char cmd[1024] = {'\0',};
453         //char* data_path = app_get_data_path();
454         const char* data_path = TTS_ENGINE_DATA_PATH;
455         snprintf(cmd, 1024, "tar zxvf %s/%s.tar.gz -C %s", data_path, item_data[idx][2], data_path);
456         int ret = system(cmd);
457         dlog_print(DLOG_DEBUG, LOG_TAG, "system return(%d)", ret);
458
459         char filepath[1024] = {'\0',};
460         snprintf(filepath, 1024, "%s/%s.tar.gz", data_path, item_data[idx][2]);
461         remove(filepath);
462
463         /* TODO */
464         tts_config_voice_s *voice = (tts_config_voice_s *)calloc(1, sizeof(tts_config_voice_s));
465         voice->language = strdup(item_data[idx][3]);
466         if (!strcmp(item_data[idx][4], "Male")) {
467                 voice->type = 1;
468         } else {
469                 voice->type = 2;
470         }
471         __tts_engine_info_add_voice(TTS_ENGINE_INFO, voice);
472
473         free(voice->language);
474         free(voice);
475
476         __hide_progress_popup();
477         elm_genlist_item_update(g_ad->selected_lang);
478
479         return NULL;
480 }
481
482 static void* __download_failed_cb(void *user_data)
483 {
484         __hide_progress_popup();
485         __show_progress_popup(true);
486         elm_genlist_item_update(g_ad->selected_lang);
487         return NULL;
488 }
489
490 static void __download_state_changed_cb(int download_id, download_state_e state, void *user_data)
491 {
492         if (DOWNLOAD_STATE_COMPLETED == state) {
493                 dlog_print(DLOG_INFO, LOG_TAG, "===== Download Completed");
494                 ecore_main_loop_thread_safe_call_sync(__download_completed_cb, user_data);
495                 download_destroy(download_id);
496         } else if (DOWNLOAD_STATE_FAILED == state) {
497                 dlog_print(DLOG_INFO, LOG_TAG, "===== Download Failed");
498                 ecore_main_loop_thread_safe_call_sync(__download_failed_cb, user_data);
499                 download_destroy(download_id);
500         }
501
502         dlog_print(DLOG_INFO, LOG_TAG, "=====");
503 }
504
505 static void __lang_item_clicked_cb(void *data, Evas_Object *obj, void *event_info)
506 {
507         Elm_Object_Item *item = (Elm_Object_Item *)event_info;
508         elm_genlist_item_selected_set(item, EINA_FALSE);
509         g_ad->selected_lang = item;
510
511         intptr_t pidx = (intptr_t)data;
512         int idx = (int)pidx;
513         dlog_print(DLOG_INFO, LOG_TAG, "[%d] item clicked", idx);
514
515         /* download */
516         if (false == __installed_lang(idx)) {
517                 dlog_print(DLOG_INFO, LOG_TAG, ">> Download <<");
518                 download_error_e error;
519                 int download_id;
520
521                 error = download_create(&download_id);
522                 if (DOWNLOAD_ERROR_NONE != error) {
523                         dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] create");
524                         __show_progress_popup(true);
525                         return;
526                 }
527                 error = download_set_state_changed_cb(download_id, __download_state_changed_cb, (void *)pidx);
528                 if (DOWNLOAD_ERROR_NONE != error) {
529                         dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] set state cb");
530                         __show_progress_popup(true);
531                         download_destroy(download_id);
532                         return;
533                 }
534
535                 char url[1024] = {'\0',};
536                 snprintf(url, 1024, "http://download.tizen.org/releases/resources/voice/tts/smt-language-pack/%s.tar.gz", item_data[idx][2]);
537                 error = download_set_url(download_id, url);
538                 if (DOWNLOAD_ERROR_NONE != error) {
539                         dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] set url");
540                         __show_progress_popup(true);
541                         download_destroy(download_id);
542                         return;
543                 }
544
545                 //char *data_path = app_get_data_path();
546                 const char *data_path = TTS_ENGINE_DATA_PATH;
547                 error = download_set_destination(download_id, data_path);
548                 if (DOWNLOAD_ERROR_NONE != error) {
549                         dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] set destination");
550                         __show_progress_popup(true);
551                         download_destroy(download_id);
552                         return;
553                 }
554                 //free(data_path);
555
556                 error = download_start(download_id);
557                 if (DOWNLOAD_ERROR_NONE != error) {
558                         dlog_print(DLOG_ERROR, LOG_TAG, "[ERROR] start");
559                         __show_progress_popup(true);
560                         download_destroy(download_id);
561                         return;
562                 }
563
564                 __show_progress_popup(false);
565
566                 dlog_print(DLOG_INFO, LOG_TAG, "<< End >>");
567         } else {
568                 dlog_print(DLOG_INFO, LOG_TAG, ">> Delete <<");
569                 char cmd[1024] = {'\0',};
570                 //char* data_path = app_get_data_path();
571                 const char* data_path = TTS_ENGINE_DATA_PATH;
572                 snprintf(cmd, 1024, "rm -rf %s/*%s*", data_path, item_data[idx][1]);
573                 int ret = system(cmd);
574                 dlog_print(DLOG_DEBUG, LOG_TAG, "system return (%d)", ret);
575                 elm_genlist_item_update(g_ad->selected_lang);
576
577                 __show_delete_popup();
578
579                 tts_config_voice_s *voice = (tts_config_voice_s *)calloc(1, sizeof(tts_config_voice_s));
580                 voice->language = strdup(item_data[idx][3]);
581                 if (!strcmp(item_data[idx][4], "Male")) {
582                         voice->type = 1;
583                 } else {
584                         voice->type = 2;
585                 }
586                 __tts_engine_info_remove_voice(TTS_ENGINE_INFO, voice);
587
588                 free(voice->language);
589                 free(voice);
590
591                 dlog_print(DLOG_INFO, LOG_TAG, "<< End >>");
592         }
593 }
594
595 static void create_contents(appdata_s *ad)
596 {
597         /* Genlist */
598         ad->genlist = elm_genlist_add(ad->naviframe);
599         elm_genlist_mode_set(ad->genlist, ELM_LIST_COMPRESS);
600         elm_genlist_homogeneous_set(ad->genlist, EINA_TRUE);
601
602         g_itc_group_title = elm_genlist_item_class_new();
603         if (NULL == g_itc_group_title) {
604                 dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
605                 return;
606         }
607         g_itc_group_title->item_style = "group_index";
608         g_itc_group_title->func.text_get = __genlist_text_get;
609         g_itc_group_title->func.content_get = NULL;
610         g_itc_group_title->func.state_get = NULL;
611         g_itc_group_title->func.del = NULL;
612
613         g_itc_button_1line = elm_genlist_item_class_new();
614         if (NULL == g_itc_button_1line) {
615                 dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
616                 return;
617         }
618         g_itc_button_1line->item_style = "type1";
619         g_itc_button_1line->func.text_get = __genlist_text_get;
620         g_itc_button_1line->func.content_get = __genlist_content_get;
621         g_itc_button_1line->func.state_get = NULL;
622         g_itc_button_1line->func.del = NULL;
623
624         /* Download - Title */
625         Elm_Object_Item *it;
626         intptr_t pi = (intptr_t)DOWNLOAD_TITLE;
627         it = elm_genlist_item_append(ad->genlist, g_itc_group_title, (void *)pi, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
628         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
629
630         int i;
631         for (i = DOWNLOAD_TITLE + 1; i < END_INDEX; i++) {
632                 pi = (intptr_t)i;
633                 it = elm_genlist_item_append(ad->genlist, g_itc_button_1line, (void *)pi, NULL, ELM_GENLIST_ITEM_NONE, __lang_item_clicked_cb, (void *)pi);
634                 if (EN_US_FEMALE == i || KO_KR_FEMALE == i || DE_DE_FEMALE == i || FR_FR_FEMALE == i || IT_IT_FEMALE == i || ES_ES_FEMALE == i) {
635                         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_NONE);
636                 }
637         }
638
639         evas_object_show(ad->genlist);
640 }
641
642 static Eina_Bool __naviframe_item_pop_cb(void *data, Elm_Object_Item *it)
643 {
644         dlog_print(DLOG_DEBUG, LOG_TAG, "");
645         ui_app_exit();
646         return EINA_TRUE;
647 }
648
649 static void create_base_gui(appdata_s *ad)
650 {
651         g_ad = ad;
652         /* Window */
653         ad->win = elm_win_util_standard_add("org.tizen.ttssmt-setting", "org.tizen.ttssmt-setting");
654         elm_win_autodel_set(ad->win, EINA_TRUE);
655
656         if (elm_win_wm_rotation_supported_get(ad->win)) {
657                 int rots[4] = { 0, 90, 180, 270 };
658                 elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
659         }
660
661         /* Conformant */
662         ad->conform = elm_conformant_add(ad->win);
663         elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
664         elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
665         evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
666         elm_win_resize_object_add(ad->win, ad->conform);
667         evas_object_show(ad->conform);
668
669         /* Naviframe */
670         ad->naviframe = elm_naviframe_add(ad->conform);
671         eext_object_event_callback_add(ad->naviframe, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
672         evas_object_size_hint_weight_set(ad->naviframe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
673         evas_object_size_hint_align_set(ad->naviframe, EVAS_HINT_FILL, EVAS_HINT_FILL);
674         elm_object_part_content_set(ad->conform, "elm.swallow.content", ad->naviframe);
675         evas_object_show(ad->naviframe);
676
677         /* Contents */
678         create_contents(ad);
679         Elm_Object_Item *main_item = elm_naviframe_item_push(ad->naviframe, "Engine setting", NULL, NULL, ad->genlist, NULL);
680         elm_naviframe_item_title_enabled_set(main_item, EINA_TRUE, EINA_TRUE);
681         elm_naviframe_item_pop_cb_set(main_item, __naviframe_item_pop_cb, ad);
682         elm_object_content_set(ad->conform, ad->naviframe);
683
684         /* Show window after base gui is set up */
685         evas_object_show(ad->win);
686 }
687
688
689 static bool app_create(void *data)
690 {
691         /* Hook to take necessary actions before main event loop starts
692         Initialize UI resources and application's data
693         If this function returns true, the main loop of application starts
694         If this function returns false, the application is terminated */
695         appdata_s *ad = data;
696
697         create_base_gui(ad);
698
699         return true;
700 }
701
702 static void app_control(app_control_h app_control, void *data)
703 {
704         /* Handle the launch request. */
705 }
706
707 static void app_pause(void *data)
708 {
709         /* Take necessary actions when application becomes invisible. */
710 }
711
712 static void app_resume(void *data)
713 {
714         /* Take necessary actions when application becomes visible. */
715 }
716
717 static void app_terminate(void *data)
718 {
719         /* Release all resources. */
720 }
721
722 static void ui_app_lang_changed(app_event_info_h event_info, void *user_data)
723 {
724         /*APP_EVENT_LANGUAGE_CHANGED*/
725         return;
726 }
727
728 static void ui_app_orient_changed(app_event_info_h event_info, void *user_data)
729 {
730         /*APP_EVENT_DEVICE_ORIENTATION_CHANGED*/
731         return;
732 }
733
734 static void ui_app_region_changed(app_event_info_h event_info, void *user_data)
735 {
736         /*APP_EVENT_REGION_FORMAT_CHANGED*/
737 }
738
739 static void ui_app_low_battery(app_event_info_h event_info, void *user_data)
740 {
741         /*APP_EVENT_LOW_BATTERY*/
742 }
743
744 static void ui_app_low_memory(app_event_info_h event_info, void *user_data)
745 {
746         /*APP_EVENT_LOW_MEMORY*/
747 }
748
749 int main(int argc, char *argv[])
750 {
751         appdata_s ad = {0,};
752         int ret = 0;
753
754         ui_app_lifecycle_callback_s event_callback = {0,};
755         app_event_handler_h handlers[5] = {NULL, };
756
757         event_callback.create = app_create;
758         event_callback.terminate = app_terminate;
759         event_callback.pause = app_pause;
760         event_callback.resume = app_resume;
761         event_callback.app_control = app_control;
762
763         ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad);
764         ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad);
765         ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, ui_app_orient_changed, &ad);
766         ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, ui_app_lang_changed, &ad);
767         ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, ui_app_region_changed, &ad);
768         ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);
769
770         ret = ui_app_main(argc, argv, &event_callback, &ad);
771         if (ret != APP_ERROR_NONE) {
772                 dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
773         }
774
775         return ret;
776 }
777
778
779 /*
780 vi:ts=4:ai:nowrap:expandtab
781 */