TTS / src /

main.c

/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */


#include "main.h"

enum {
	MAIN_LIST = 0,
	VOICE_LIST,
	TEXT_LIST
};

typedef struct appdata {
	Evas_Object *win;
	Evas_Object *conform;
	Evas_Object *naviframe;
	Evas_Object *genlist;
	Evas_Object *entry;
	Evas_Object *text_list;

	Elm_Object_Item *voice;
	Elm_Object_Item *speed;
	Elm_Object_Item *show_text;
	Elm_Object_Item *play_pause;

	int current_contents;
} appdata_s;

typedef enum {
	ADD_TEXT_TITLE = 0,
	VOICE_BUTTON,
	TEXT_ENTRY,
	ADD_TEXT_BUTTON,
	SHOW_TEXT_BUTTON,
	PLAY_TITLE,
	PLAY_PAUSE_BUTTON,
	STOP_BUTTON
} item_index_e;

static Elm_Genlist_Item_Class *g_itc_group_title = NULL;
static Elm_Genlist_Item_Class *g_itc_button_1line = NULL;
static Elm_Genlist_Item_Class *g_itc_button_2line = NULL;
static Elm_Genlist_Item_Class *g_itc_entry = NULL;

typedef struct {
	char *language;
	int voice_type;
} tts_voice_s;

typedef struct {
	char *text;
	int utt_id;
} tts_text_s;

static tts_h g_tts;
static GList *g_tts_voice_list = NULL;
static tts_voice_s *g_current_voice = NULL;
static tts_state_e g_current_state;
static GList *g_tts_text_list = NULL;

static char *
__genlist_text_get(void *data, Evas_Object *obj, const char *part)
{
	item_index_e idx = (item_index_e)data;

	if (VOICE_BUTTON == idx) {
		if (!strcmp("elm.text", part)) {
			return strdup("Select Voice");
		} else if (!strcmp("elm.text.sub", part)) {
			dlog_print(DLOG_DEBUG, LOG_TAG, "");
			if (NULL != g_current_voice) {
				if (NULL != g_current_voice->language) {
					char voice[64] = {'\0',};
					snprintf(voice, 64, "%s, %d", g_current_voice->language, g_current_voice->voice_type);
					return strdup(voice);
				}
			}
		}
	} else if (SHOW_TEXT_BUTTON == idx) {
		if (!strcmp("elm.text", part)) {
			return strdup("Show Text");
		} else if (!strcmp("elm.text.end", part)) {
			char num[8] = {'\0',};
			snprintf(num, 8, "%d", g_list_length(g_tts_text_list));
			return strdup(num);
		}
	} else if (!strcmp("elm.text", part)) {
		if (ADD_TEXT_BUTTON == idx) {
			return strdup("Add Text");
		} else if (PLAY_PAUSE_BUTTON == idx) {
			if (TTS_STATE_PLAYING == g_current_state) {
				return strdup("Pause");
			} else {
				return strdup("Play");
			}
		} else if (STOP_BUTTON == idx) {
			return strdup("Stop");
		}
	} else if (!strcmp("elm.text.main", part)) {
		if (ADD_TEXT_TITLE == idx) {
			return strdup("Add Text");
		} else if (PLAY_TITLE == idx) {
			return strdup("Play");
		}
	}

	return NULL;
}

static Evas_Object *
__genlist_content_get(void *data, Evas_Object *obj, const char *part)
{
	appdata_s *ad = (appdata_s *)data;

	ad->entry = elm_entry_add(obj);
	elm_entry_single_line_set(ad->entry, EINA_TRUE);
	elm_entry_scrollable_set(ad->entry, EINA_TRUE);
	evas_object_size_hint_weight_set(ad->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	evas_object_size_hint_align_set(ad->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
	elm_object_part_text_set(ad->entry, "elm.guide", "Tab here to input text for add");
	elm_entry_input_panel_show_on_demand_set(ad->entry, EINA_TRUE);

	return ad->entry;
}

static bool
__tts_supported_voice_cb(tts_h tts, const char* language, int voice_type, void* user_data)
{
	if (NULL != language) {
		tts_voice_s *tmp = (tts_voice_s *)calloc(1, sizeof(tts_voice_s));
		if (NULL == tmp) {
			dlog_print(DLOG_ERROR, LOG_TAG, "Fail to memory allocation");
			return false;
		}
		tmp->language = strdup(language);
		tmp->voice_type = voice_type;
		g_tts_voice_list = g_list_append(g_tts_voice_list, tmp);
		dlog_print(DLOG_DEBUG, LOG_TAG, "+ Language(%s), Type(%d)", language, voice_type);
		return true;
	}
	return false;
}

static Eina_Bool
__naviframe_sub_item_pop_cb(void *data, Elm_Object_Item *it)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "");
	appdata_s *ad = (appdata_s *)data;
	ad->current_contents = MAIN_LIST;
	return EINA_TRUE;
}

static void
__list_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = (appdata_s *)data;
	elm_naviframe_item_pop(ad->naviframe);
	elm_genlist_item_update(ad->voice);
}

static void
__voice_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *it = event_info;
	elm_list_item_selected_set(it, EINA_FALSE);

	int idx = (int)data;
	dlog_print(DLOG_DEBUG, LOG_TAG, "(%d) voice selected", idx);

	GList *iter = NULL;
	iter = g_list_nth(g_tts_voice_list, idx);
	if (NULL != iter) {
		tts_voice_s *tmp = iter->data;
		if (NULL != tmp) {
			if (NULL != tmp->language) {
				if (NULL != g_current_voice->language) {
					free(g_current_voice->language);
				}
				g_current_voice->language = strdup(tmp->language);
				g_current_voice->voice_type = tmp->voice_type;
			}
		}
	}
}

static void
__show_voice_list(appdata_s *ad)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "");
	Evas_Object *list = elm_list_add(ad->naviframe);
	elm_list_mode_set(list, ELM_LIST_COMPRESS);
	evas_object_smart_callback_add(list, "selected", __list_clicked_cb, ad);

	GList *iter = NULL;
	if (NULL != g_tts_voice_list) {
		iter = g_list_first(g_tts_voice_list);

		while (NULL != iter) {
			tts_voice_s *tmp = iter->data;
			if (NULL != tmp) {
				if (NULL != tmp->language) {
					free(tmp->language);
					tmp->language = NULL;
				}
				free(tmp);
				tmp = NULL;
			}
			g_tts_voice_list = g_list_remove_link(g_tts_voice_list, iter);
			iter = g_list_first(g_tts_voice_list);
		}
	}

	dlog_print(DLOG_DEBUG, LOG_TAG, "== Supported Voice");
	if (0 != tts_foreach_supported_voices(g_tts, __tts_supported_voice_cb, ad)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to get supported voice");
	}

	int i;
	for (i = 0; i < g_list_length(g_tts_voice_list); i++) {
			iter = g_list_nth(g_tts_voice_list, i);
			if (NULL != iter) {
				tts_voice_s *tmp = iter->data;
				if (NULL != tmp) {
					char voice[64] = {'\0',};
					snprintf(voice, 64, "%s, %d", tmp->language, tmp->voice_type);
					elm_list_item_append(list, voice, NULL, NULL, __voice_selected_cb, (void *)i);
				}
			}
	}
	elm_list_go(list);

	Elm_Object_Item *voice_item = elm_naviframe_item_push(ad->naviframe, "Voice", NULL, NULL, list, NULL);
	elm_naviframe_item_pop_cb_set(voice_item, __naviframe_sub_item_pop_cb, ad);
	ad->current_contents = VOICE_LIST;
}

static void
__voice_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *item = (Elm_Object_Item *)event_info;
	elm_genlist_item_selected_set(item, EINA_FALSE);

	appdata_s *ad = (appdata_s *)data;

	__show_voice_list(ad);

	elm_genlist_item_update(item);
	elm_object_focus_set(ad->entry, EINA_FALSE);
}

static void
__add_text_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *item = (Elm_Object_Item *)event_info;
	elm_genlist_item_selected_set(item, EINA_FALSE);

	appdata_s *ad = (appdata_s *)data;

	const char *text = elm_entry_entry_get(ad->entry);
	if (NULL != text) {
		dlog_print(DLOG_DEBUG, LOG_TAG, "Add text (%s)", text);
		int utt_id;
		if (NULL != g_current_voice) {
			if (NULL != g_current_voice->language) {
				if (0 != tts_add_text(g_tts, text, g_current_voice->language, g_current_voice->voice_type, TTS_SPEED_AUTO, &utt_id)) {
					dlog_print(DLOG_DEBUG, LOG_TAG, "Fail to add text");
				} else {
					tts_text_s *tmp = (tts_text_s *)calloc(1, sizeof(tts_text_s));
					if (NULL == tmp) {
						dlog_print(DLOG_ERROR, LOG_TAG, "Fail to memory allocation");
					} else {
						tmp->text = strdup(text);
						tmp->utt_id = utt_id;
						g_tts_text_list = g_list_append(g_tts_text_list, tmp);
					}
				}
			}
		}
	}

	elm_entry_entry_set(ad->entry, "");
	elm_genlist_item_update(item);
	elm_object_focus_set(ad->entry, EINA_FALSE);
	elm_genlist_item_update(ad->show_text);
}

static void
__show_text_list(appdata_s *ad)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "");
	ad->text_list = elm_list_add(ad->naviframe);
	elm_list_mode_set(ad->text_list, ELM_LIST_COMPRESS);
	elm_list_select_mode_set(ad->text_list, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
	evas_object_smart_callback_add(ad->text_list, "selected", __list_clicked_cb, ad);

	int i;
	GList *iter = NULL;
	for (i = 0; i < g_list_length(g_tts_text_list); i++) {
			iter = g_list_nth(g_tts_text_list, i);
			if (NULL != iter) {
				tts_text_s *tmp = iter->data;
				if (NULL != tmp) {
					if (NULL != tmp->text) {
						elm_list_item_append(ad->text_list, tmp->text, NULL, NULL, NULL, NULL);
					}
				}
			}
	}
	elm_list_go(ad->text_list);

	Elm_Object_Item *voice_item = elm_naviframe_item_push(ad->naviframe, "Text List", NULL, NULL, ad->text_list, NULL);
	elm_naviframe_item_pop_cb_set(voice_item, __naviframe_sub_item_pop_cb, ad);
	ad->current_contents = TEXT_LIST;
}

static void
__show_text_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *item = (Elm_Object_Item *)event_info;
	elm_genlist_item_selected_set(item, EINA_FALSE);

	appdata_s *ad = (appdata_s *)data;

	__show_text_list(ad);

	elm_genlist_item_update(item);
	elm_object_focus_set(ad->entry, EINA_FALSE);
}

static void
__play_pause_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *item = (Elm_Object_Item *)event_info;
	elm_genlist_item_selected_set(item, EINA_FALSE);

	appdata_s *ad = (appdata_s *)data;

	if (TTS_STATE_READY == g_current_state || TTS_STATE_PAUSED == g_current_state) {
		if (0 != tts_play(g_tts)) {
			dlog_print(DLOG_ERROR, LOG_TAG, "Fail to start");
		}
	} else if (TTS_STATE_PLAYING == g_current_state) {
		if (0 != tts_pause(g_tts)) {
			dlog_print(DLOG_ERROR, LOG_TAG, "Fail to pause");
		}
	}

	elm_genlist_item_update(item);
	elm_object_focus_set(ad->entry, EINA_FALSE);
}

static void
__stop_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *item = (Elm_Object_Item *)event_info;
	elm_genlist_item_selected_set(item, EINA_FALSE);

	appdata_s *ad = (appdata_s *)data;

	if (0 != tts_stop(g_tts)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to stop");
	}

	GList *iter = NULL;
	if (NULL != g_tts_text_list) {
		iter = g_list_first(g_tts_text_list);

		while (NULL != iter) {
			tts_text_s *tmp = iter->data;
			if (NULL != tmp) {
				if (NULL != tmp->text) {
					free(tmp->text);
					tmp->text = NULL;
				}
				free(tmp);
				tmp = NULL;
			}
			g_tts_text_list = g_list_remove_link(g_tts_text_list, iter);
			iter = g_list_first(g_tts_text_list);
		}
	}

	elm_genlist_item_update(item);
	elm_genlist_item_update(ad->play_pause);
	elm_genlist_item_update(ad->show_text);
	elm_object_focus_set(ad->entry, EINA_FALSE);
}

static void
create_contents(appdata_s *ad)
{
	/* Genlist */
	ad->genlist = elm_genlist_add(ad->naviframe);
	elm_genlist_mode_set(ad->genlist, ELM_LIST_COMPRESS);
	elm_genlist_homogeneous_set(ad->genlist, EINA_TRUE);
	
	g_itc_group_title = elm_genlist_item_class_new();
	if (NULL == g_itc_group_title) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
		return;
	}
	g_itc_group_title->item_style = "groupindex";
	g_itc_group_title->func.text_get = __genlist_text_get;
	g_itc_group_title->func.content_get = NULL;
	g_itc_group_title->func.state_get = NULL;
	g_itc_group_title->func.del = NULL;

	g_itc_button_1line = elm_genlist_item_class_new();
	if (NULL == g_itc_button_1line) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
		return;
	}
	g_itc_button_1line->item_style = "type1";
	g_itc_button_1line->func.text_get = __genlist_text_get;
	g_itc_button_1line->func.content_get = NULL;
	g_itc_button_1line->func.state_get = NULL;
	g_itc_button_1line->func.del = NULL;

	g_itc_button_2line = elm_genlist_item_class_new();
	if (NULL == g_itc_button_2line) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
		return;
	}
	g_itc_button_2line->item_style = "type1";
	g_itc_button_2line->func.text_get = __genlist_text_get;
	g_itc_button_2line->func.content_get = NULL;
	g_itc_button_2line->func.state_get = NULL;
	g_itc_button_2line->func.del = NULL;

	g_itc_entry = elm_genlist_item_class_new();
	if (NULL == g_itc_entry) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to item class new");
		return;
	}
	g_itc_entry->item_style = "full";
	g_itc_entry->func.text_get = NULL;
	g_itc_entry->func.content_get = __genlist_content_get;
	g_itc_entry->func.state_get = NULL;
	g_itc_entry->func.del = NULL;

	/* Add Text - Title */
	Elm_Object_Item *it;
	it = elm_genlist_item_append(ad->genlist, g_itc_group_title, (void *)ADD_TEXT_TITLE, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
	elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);

	/* Voice - 2line */
	ad->voice = elm_genlist_item_append(ad->genlist, g_itc_button_2line, (void *)VOICE_BUTTON, NULL, ELM_GENLIST_ITEM_NONE, __voice_item_selected_cb, ad);

	/* Text - entry */
	elm_genlist_item_append(ad->genlist, g_itc_entry, (void *)ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);

	/* Add text - button */
	elm_genlist_item_append(ad->genlist, g_itc_button_1line, (void *)ADD_TEXT_BUTTON, NULL, ELM_GENLIST_ITEM_NONE, __add_text_item_selected_cb, ad);

	/* Show text - button */
	ad->show_text = elm_genlist_item_append(ad->genlist, g_itc_button_1line, (void *)SHOW_TEXT_BUTTON, NULL, ELM_GENLIST_ITEM_NONE, __show_text_item_selected_cb, ad);

	/* Play - Title */
	it = elm_genlist_item_append(ad->genlist, g_itc_group_title, (void *)PLAY_TITLE, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
	elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);

	/* Play & Pause - button */
	ad->play_pause = elm_genlist_item_append(ad->genlist, g_itc_button_1line, (void *)PLAY_PAUSE_BUTTON, NULL, ELM_GENLIST_ITEM_NONE, __play_pause_item_selected_cb, ad);

	/* Stop - button */
	elm_genlist_item_append(ad->genlist, g_itc_button_1line, (void *)STOP_BUTTON, NULL, ELM_GENLIST_ITEM_NONE, __stop_item_selected_cb, ad);

	elm_genlist_select_mode_set(ad->genlist, ELM_OBJECT_SELECT_MODE_NONE);

	evas_object_show(ad->genlist);
}

static Eina_Bool
__naviframe_item_pop_cb(void *data, Elm_Object_Item *it)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "");
	ui_app_exit();
	return EINA_TRUE;
}

static void
create_base_gui(appdata_s *ad)
{
	/* Window */
	ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
	elm_win_autodel_set(ad->win, EINA_TRUE);

	if (elm_win_wm_rotation_supported_get(ad->win)) {
		int rots[4] = { 0, 90, 180, 270 };
		elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
	}

	/* Conformant */
	ad->conform = elm_conformant_add(ad->win);
	elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
	elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
	evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	elm_win_resize_object_add(ad->win, ad->conform);
	evas_object_show(ad->conform);

	/* Naviframe */
	ad->naviframe = elm_naviframe_add(ad->conform);
	eext_object_event_callback_add(ad->naviframe, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
	evas_object_size_hint_weight_set(ad->naviframe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	evas_object_size_hint_align_set(ad->naviframe, EVAS_HINT_FILL, EVAS_HINT_FILL);
	elm_object_part_content_set(ad->conform, "elm.swallow.content", ad->naviframe);
	evas_object_show(ad->naviframe);

	/* Contents */
	create_contents(ad);
	Elm_Object_Item *main_item = elm_naviframe_item_push(ad->naviframe, "TTS", NULL, NULL, ad->genlist, NULL);
	elm_naviframe_item_title_enabled_set(main_item, EINA_TRUE, EINA_TRUE);
	elm_naviframe_item_pop_cb_set(main_item, __naviframe_item_pop_cb, ad);
	elm_object_content_set(ad->conform, ad->naviframe);
	ad->current_contents = MAIN_LIST;

	/* Show window after base gui is set up */
	evas_object_show(ad->win);
}

static void
__tts_state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data)
{
	appdata_s *ad = (appdata_s *)user_data;
	dlog_print(DLOG_DEBUG, LOG_TAG, "== State is changed (%d) to (%d)", previous, current);
	if (TTS_STATE_CREATED == previous && TTS_STATE_READY == current) {
		elm_genlist_select_mode_set(ad->genlist, ELM_OBJECT_SELECT_MODE_DEFAULT);
	}
	g_current_state = current;
}

static void
__tts_utterance_completed_cb(tts_h tts, int utt_id, void* user_data)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "== Utterance (%d) is completed", utt_id);
	appdata_s *ad = (appdata_s *)user_data;

	GList *iter = NULL;
	if (NULL != g_tts_text_list) {
		iter = g_list_first(g_tts_text_list);

		while (NULL != iter) {
			tts_text_s *tmp = iter->data;
			if (NULL != tmp) {
				if (tmp->utt_id == utt_id) {
					if (NULL != tmp->text) {
						free(tmp->text);
						tmp->text = NULL;
					}
					free(tmp);
					tmp = NULL;
					g_tts_text_list = g_list_remove_link(g_tts_text_list, iter);
					break;
				}
				iter = g_list_next(g_tts_text_list);
			}
		}
	}

	if (TEXT_LIST == ad->current_contents) {
		elm_list_clear(ad->text_list);

		int i;
		iter = NULL;
		for (i = 0; i < g_list_length(g_tts_text_list); i++) {
				iter = g_list_nth(g_tts_text_list, i);
				if (NULL != iter) {
					tts_text_s *tmp = iter->data;
					if (NULL != tmp) {
						if (NULL != tmp->text) {
							elm_list_item_append(ad->text_list, tmp->text, NULL, NULL, NULL, NULL);
						}
					}
				}
		}
		elm_list_go(ad->text_list);
	}

	elm_genlist_item_update(ad->show_text);
}

static int
init_tts(appdata_s *ad)
{
	if (0 != tts_create(&g_tts)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to tts create");
		return -1;
	}

	if (0 != tts_set_state_changed_cb(g_tts, __tts_state_changed_cb, ad)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to set state changed cb");
		tts_destroy(g_tts);
		return -1;
	}

	if (0 != tts_set_utterance_completed_cb(g_tts, __tts_utterance_completed_cb, ad)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to set utt completed cb");
		tts_destroy(g_tts);
		return -1;
	}

	char *language = NULL;
	int voice_type;
	if (0 != tts_get_default_voice(g_tts, &language, &voice_type)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to get default voice");
		tts_destroy(g_tts);
		return -1;
	}
	if (NULL != language) {
		g_current_voice = (tts_voice_s *)calloc(1, sizeof(tts_voice_s));
		if (NULL == g_current_voice) {
			dlog_print(DLOG_ERROR, LOG_TAG, "Fail to memory allocation");
		} else {
			g_current_voice->language = strdup(language);
			g_current_voice->voice_type = voice_type;
		}
		free(language);
	}

	if (0 != tts_prepare(g_tts)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to tts prepare");
		tts_destroy(g_tts);
		return -1;
	}

	return 0;
}

static void
deinit_tts(appdata_s *ad)
{
	if (NULL != g_current_voice) {
		if (NULL != g_current_voice->language) {
			free(g_current_voice->language);
			g_current_voice->language = NULL;
		}
		free(g_current_voice);
		g_current_voice = NULL;
	}
	if (0 != tts_destroy(g_tts)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to tts destroy");
	}
}

static bool
app_create(void *data)
{
	/* Hook to take necessary actions before main event loop starts
		Initialize UI resources and application's data
		If this function returns true, the main loop of application starts
		If this function returns false, the application is terminated */
	appdata_s *ad = data;

	create_base_gui(ad);

	if (0 != init_tts(ad)) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Fail to init tts");
		return false;
	}

	return true;
}

static void
app_control(app_control_h app_control, void *data)
{
	/* Handle the launch request. */
}

static void
app_pause(void *data)
{
	/* Take necessary actions when application becomes invisible. */
}

static void
app_resume(void *data)
{
	/* Take necessary actions when application becomes visible. */
}

static void
app_terminate(void *data)
{
	appdata_s *ad = data;
	/* Release all resources. */
	deinit_tts(ad);
}

static void
ui_app_lang_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LANGUAGE_CHANGED*/
	char *locale = NULL;
	system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
	elm_language_set(locale);
	free(locale);
	return;
}

static void
ui_app_orient_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_DEVICE_ORIENTATION_CHANGED*/
	return;
}

static void
ui_app_region_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_REGION_FORMAT_CHANGED*/
}

static void
ui_app_low_battery(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LOW_BATTERY*/
}

static void
ui_app_low_memory(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LOW_MEMORY*/
}

int
main(int argc, char *argv[])
{
	appdata_s ad = {0,};
	int ret = 0;

	ui_app_lifecycle_callback_s event_callback = {0,};
	app_event_handler_h handlers[5] = {NULL, };

	event_callback.create = app_create;
	event_callback.terminate = app_terminate;
	event_callback.pause = app_pause;
	event_callback.resume = app_resume;
	event_callback.app_control = app_control;

	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, ui_app_orient_changed, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, ui_app_lang_changed, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, ui_app_region_changed, &ad);
	ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);

	ret = ui_app_main(argc, argv, &event_callback, &ad);
	if (ret != APP_ERROR_NONE) {
		dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
	}

	return ret;
}