Sticker Consumer / src /

main.c

/*
 * Copyright (c) 2019 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"

typedef struct appdata {
	Evas_Object *win;
	Evas_Object *conform;
	Evas_Object *nf;
	sticker_consumer_h sticker_h;
	char *sticker_path[STICKER_MAX];
	int idx;
} appdata_s;

typedef struct itemdata {
	int index;
	const char *path;
	appdata_s *ad;
} itemdata_s;

typedef enum {
	FOREACH_ALL = 0,
	FOREACH_BY_KEYWORD,
	FOREACH_BY_GROUP,
	FOREACH_BY_TYPE
} api_type;

/*
 * @brief Function will be operated when window deletion is requested
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
static void
win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
{
	ui_app_exit();
}

/*
 * @brief Function to get object on gengrid item's swallow part
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] part The name of swallow part
 * @param[out] Evas_Object An image to use as genlist item's swallow part
 */
static Evas_Object*
gengrid_content_get_cb(void *data, Evas_Object *obj, const char *part)
{
	itemdata_s *id = data;

	if (!strcmp(part, "elm.swallow.icon")) {
		Evas_Object *img = elm_image_add(obj);

		elm_image_file_set(img, id->path, NULL);
		elm_image_aspect_fixed_set(img, EINA_FALSE);
		elm_image_preload_disabled_set(img, EINA_FALSE);
		evas_object_show(img);

		return img;
	}

	return NULL;
}

/*
 * @brief Function to retrieve all sticker data
 * @param[in] data_handle The sticker data handle
 * @param[in] user_data The data to be passed to the callback function
 */
static void
sticker_info_cb(sticker_data_h data_handle, void *user_data)
{
	appdata_s *ad = user_data;
	int ret;
	sticker_data_uri_type_e type;
	/* Get sticker URI and URI type */
	ret = sticker_data_get_uri(data_handle, &type, &ad->sticker_path[ad->idx]);
	/* Check sticker error code */
	if (ret != STICKER_ERROR_NONE) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get sticker path");
		return;
	}

	ad->idx++;
}

/*
 * @brief Function to retrieve all keywords
 * @param[in] keyword The keyword of the sticker
 * @param[in] user_data The data to be passed to the callback function
 */
static void
keyword_list_cb(const char *keyword, void *user_data)
{
	dlog_print(DLOG_INFO, LOG_TAG, "keyword : %s", keyword);
}

/*
 * @brief Function to retrieve all group names
 * @param[in] group The group name of the sticker
 * @param[in] user_data The data to be passed to the callback function
 */
static void
group_list_cb(const char *group, void *user_data)
{
	dlog_print(DLOG_INFO, LOG_TAG, "group name : %s", group);
}

/*
 * @brief Function will be called when gengrid is deleted
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 */
void
gengrid_uri_del(void *data, Evas_Object *obj EINA_UNUSED)
{
	itemdata_s *id = data;
	eina_stringshare_del(id->path);
	free(id);
}

/*
 * @brief Function to create gengrid
 * @param[in] ad The data structure to manage gui object
 * @param[out] Evas_Object The layout object which is created
 */
static Evas_Object*
create_gengrid(appdata_s *ad, api_type type)
{
	int ret, result = 0;
	Elm_Gengrid_Item_Class *gic;
	Evas_Object *gengrid;
	int i;

	gengrid = elm_gengrid_add(ad->nf);
	evas_object_size_hint_weight_set(gengrid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	evas_object_size_hint_align_set(gengrid, EVAS_HINT_FILL, EVAS_HINT_EXPAND);
	elm_gengrid_item_size_set(gengrid, ELM_SCALE_SIZE(110), ELM_SCALE_SIZE(110));
	elm_gengrid_align_set(gengrid, 0.5, 0.1);

	gic = elm_gengrid_item_class_new();
	gic->item_style = "default";
	gic->func.text_get = NULL;
	gic->func.content_get = gengrid_content_get_cb;
	gic->func.state_get = NULL;
	gic->func.del = gengrid_uri_del;

	ad->idx = 0;
	switch (type) {
	case FOREACH_ALL:
		/* Retrieve all sticker data */
		ret = sticker_consumer_data_foreach_all(ad->sticker_h, 0, STICKER_MAX, &result, sticker_info_cb, ad);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_data_foreach_all()");

		break;
	case FOREACH_BY_KEYWORD:
		/* Retrieve all keywords */
		ret = sticker_consumer_keyword_list_foreach_all(ad->sticker_h, keyword_list_cb, NULL);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_keyword_list_foreach_all()");

		/* Retrieve all sticker data by keyword */
		ret = sticker_consumer_data_foreach_by_keyword(ad->sticker_h, 0, STICKER_MAX, &result, "face", sticker_info_cb, ad);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_data_foreach_by_keyword()");

		break;
	case FOREACH_BY_GROUP:
		/* Retrieve all group names */
		ret = sticker_consumer_group_list_foreach_all(ad->sticker_h, group_list_cb, NULL);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_group_list_foreach_all()");

		/* Retrieve all sticker data by group name */
		ret = sticker_consumer_data_foreach_by_group(ad->sticker_h, 0, STICKER_MAX, &result, "animal", sticker_info_cb, ad);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_data_foreach_by_group()");

		break;
	case FOREACH_BY_TYPE:
		/* Retrieve all sticker data by URI type */
		ret = sticker_consumer_data_foreach_by_type(ad->sticker_h, 0, STICKER_MAX, &result, STICKER_DATA_URI_LOCAL_PATH, sticker_info_cb, ad);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call sticker_consumer_data_foreach_by_type()");

		break;
	default:
		break;
	}

	for (i = 0; i < result; i++) {
		itemdata_s *id = calloc(sizeof(itemdata_s), 1);
		id->index = i;
		id->path = eina_stringshare_add(ad->sticker_path[i]);
		id->ad = ad;
		elm_gengrid_item_append(gengrid, gic, id, NULL, NULL);
	}

	evas_object_show(gengrid);

	return gengrid;
}

/*
 * @brief Function to create sticker image view layout
 * @param[in] ad The data structure to manage gui object
 * @param[out] Evas_Object The layout object which is created
 */
static Evas_Object *
create_sticker_view(appdata_s *ad, char *subject, api_type type)
{
	Elm_Object_Item *nf_it;
	Evas_Object *gengrid;

	gengrid = create_gengrid(ad, type);
	nf_it = elm_naviframe_item_push(ad->nf, subject, NULL, NULL, gengrid, NULL);

	return gengrid;
}

/*
 * @brief Function will be called when "Retrieves all sticker data" item is selected
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
void
foreach_all_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = (appdata_s *)data;
	Evas_Object *sticker_view;
	sticker_view = create_sticker_view(ad, "Retrieves all sticker data", FOREACH_ALL);
}

/*
 * @brief Function will be called when "Retrieves sticker data using keyword" item is selected
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
void
foreach_by_keyword_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = (appdata_s *)data;
	Evas_Object *sticker_view;
	sticker_view = create_sticker_view(ad, "Retrieves sticker data using keyword", FOREACH_BY_KEYWORD);
}

/*
 * @brief Function will be called when "Retrieves sticker data using group" item is selected
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
void
foreach_by_group_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = (appdata_s *)data;
	Evas_Object *sticker_view;
	sticker_view = create_sticker_view(ad, "Retrieves sticker data using group", FOREACH_BY_GROUP);
}

/*
 * @brief Function will be called when "Retrieves sticker data using URI type" item is selected
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
void
foreach_by_type_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = (appdata_s *)data;
	Evas_Object *sticker_view;
	sticker_view = create_sticker_view(ad, "Retrieves sticker data using URI type", FOREACH_BY_TYPE);
}

/*
 * @brief Function will be called when list item is selected
 * @param[in] data The data to be passed to the callback function
 * @param[in] obj The Evas object handle to be passed to the callback function
 * @param[in] event_info The system event information
 */
static void
list_selected_cb(void *data, Evas_Object *obj, void *event_info)
{
	Elm_Object_Item *it = event_info;
	elm_list_item_selected_set(it, EINA_FALSE);
}

/*
 * @brief Function to create main view layout
 * @param[in] ad The data structure to manage gui object
 * @param[out] Evas_Object The layout object which is created
 */
static Evas_Object *
create_main_list(appdata_s *ad)
{
	Evas_Object *list;

	/* List */
	list = elm_list_add(ad->nf);
	elm_list_mode_set(list, ELM_LIST_COMPRESS);
	evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);

	/* Main Menu Items Here */
	elm_list_item_append(list, "Retrieves all sticker data", NULL, NULL, foreach_all_cb, ad);
	elm_list_item_append(list, "Retrieves sticker data using keyword", NULL, NULL, foreach_by_keyword_cb, ad);
	elm_list_item_append(list, "Retrieves sticker data using group", NULL, NULL, foreach_by_group_cb, ad);
	elm_list_item_append(list, "Retrieves sticker data using URI type", NULL, NULL, foreach_by_type_cb, ad);

	elm_list_go(list);

	return list;
}

/*
 * @brief Function will be operated when naviframe pop its own item
 * @param[in] data The data to be passed to the callback function
 * @param[in] it The item to be popped from naviframe
 */
static Eina_Bool
naviframe_pop_cb(void *data, Elm_Object_Item *it)
{
	appdata_s *ad = data;

	/* Let window go to hide state. */
	elm_win_lower(ad->win);

	return EINA_FALSE;
}

/*
 * @brief Function to create base gui structure
 * @param[in] ad The data structure to manage gui object
 */
static void
create_base_gui(appdata_s *ad)
{
	Evas_Object *main_list;
	Elm_Object_Item *nf_it;

	/* Window */
	/* Create and initialize elm_win.
	   elm_win is mandatory to manipulate window. */
	ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
	elm_win_conformant_set(ad->win, EINA_TRUE);
	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);
	}

	evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);

	/* Conformant */
	/* Create and initialize elm_conformant.
	   elm_conformant is mandatory for base gui to have proper size
	   when indicator or virtual keypad is visible. */
	ad->conform = elm_conformant_add(ad->win);
	elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
	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->nf = elm_naviframe_add(ad->conform);
	eext_object_event_callback_add(ad->nf, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, ad);
	evas_object_size_hint_weight_set(ad->nf, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	elm_object_content_set(ad->conform, ad->nf);
	evas_object_show(ad->nf);

	/* Main list */
	main_list = create_main_list(ad);
	nf_it = elm_naviframe_item_push(ad->nf, "Sticker Consumer Sample", NULL, NULL, main_list, NULL);
	elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, ad);

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

/*
 * @brief Hook to take necessary actions before main event loop starts
 * Initialize UI resources and application's data
 * If this function return true, the main loop of application starts
 * If this function return false, the application is terminated
 * @param[in] user_data The data to be passed to the callback function
 */
static bool
app_create(void *data)
{
	appdata_s *ad = data;

	elm_app_base_scale_set(1.8);
	create_base_gui(ad);

	return true;
}

/*
 * @brief Function will be called when permission is selected
 * @param[in] cause The value representing a reason why this callback has been called
 * @param[in] result The result of a response triggered by calling ppm_request_permission()
 * @param[in] privilege The privilege that has been checked
 * @param[in] user_data The data to be passed to the callback function
 */
void ppm_popup_response_cb(ppm_call_cause_e cause, ppm_request_result_e result, const char *privilege, void *user_data)
{
	if (cause == PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get ppm_request_result");
		return;
	}

	appdata_s *ad = user_data;

	switch (result) {
	case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER:
			if (ad->sticker_h == NULL) {
				/* Create sticker consumer handle */
				int ret = sticker_consumer_create(&ad->sticker_h);
				/* Check sticker error code*/
				if (ret != STICKER_ERROR_NONE)
					dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create sticker consumer handle");
			}
			break;
		case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_FOREVER:
			dlog_print(DLOG_INFO, LOG_TAG, "PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_FOREVER");
			notification_status_message_post("The mediastorage privilege is required to use the Sticker Consumer");
			ui_app_exit();
			break;
		case PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_ONCE:
			dlog_print(DLOG_INFO, LOG_TAG, "PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_DENY_ONCE");
			notification_status_message_post("The mediastorage privilege is required to use the Sticker Consumer");
			ui_app_exit();
			break;
		default:
			break;
    }
}

/*
 * @brief Checks if the Sticker Consumer has privilege
 * @param[in] ad The data structure to manage gui object
 * @param[in] privilege The privilege that is to be checked
 */
void check_privilege(appdata_s *ad, const char* privilege)
{
	ppm_check_result_e result;

	/* Checks if an application, which calls this function, has permission to use the given privilege */
	int ret = ppm_check_permission(privilege, &result);

	/* If there is an error, print log */
	if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call ppm_check_permission()");
		return;
	}

	/* Allow, deny or ask */
	switch (result) {
		case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
			dlog_print(DLOG_INFO, LOG_TAG, "An application has permission to use the %s privilege", privilege);
			if (ad->sticker_h == NULL) {
				/* Create sticker consumer handle */
				int ret = sticker_consumer_create(&ad->sticker_h);
				/* Check sticker error code*/
				if (ret != STICKER_ERROR_NONE)
					dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create sticker consumer handle");
			}
			break;
		case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY:
			notification_status_message_post("Sticker Consumer doesn't have permission to use the mediastorage privilege");
			ui_app_exit();
			break;
		case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
			dlog_print(DLOG_INFO, LOG_TAG, "Ask to user whether to grant permission to use the %s privilege", privilege);
			/* Requests a user's response to obtain permission for using the given privilege */
			int ret_popup = ppm_request_permission(privilege, ppm_popup_response_cb, ad);
			if (ret_popup != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
				dlog_print(DLOG_ERROR, LOG_TAG, "Failed to call ppm_request_permission()");
				return;
			}
			break;
		default:
			dlog_print(DLOG_ERROR, LOG_TAG, "Unknown result (%d) for the %s privilege", result, privilege);
			break;
	}
}

/*
 * @brief This callback function is called when another application
 * sends the launch request to the application
 * @param[in] app_control The handle to the app_control
 * @param[in] user_data The data to be passed to the callback function
 */
static void
app_control(app_control_h app_control, void *data)
{
	/* Handle the launch request. */
}

/*
 * @brief This callback function is called each time
 * the application is completely obscured by another application
 * and becomes invisible to the user
 * @param[in] user_data The data to be passed to the callback function
 */
static void
app_pause(void *data)
{
	/* Take necessary actions when application becomes invisible. */
}

/*
 * @brief This callback function is called each time
 * the application becomes visible to the user
 * @param[in] user_data The data to be passed to the callback function
 */
static void
app_resume(void *data)
{
	/* Take necessary actions when application becomes visible. */
	const char* sticker_privilege = "http://tizen.org/privilege/mediastorage";
	check_privilege(data, sticker_privilege);
}

/*
 * @brief This callback function is called once after the main loop of the application exits
 * @param[in] user_data The data to be passed to the callback function
 */
static void
app_terminate(void *data)
{
	appdata_s *ad = data;
	/* Release all resources. */
	if (ad->sticker_h != NULL) {
		/* Destroy sticker consumer handle */
		int ret = sticker_consumer_destroy(ad->sticker_h);
		/* Check sticker error code */
		if (ret != STICKER_ERROR_NONE)
			dlog_print(DLOG_ERROR, LOG_TAG, "Failed to destroy sticker consumer handle");
	}
}

/*
 * @brief This function will be called when the language is changed
 * @param[in] event_info The system event information
 * @param[in] user_data The user data to be passed to the callback function
 */
static void
ui_app_lang_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LANGUAGE_CHANGED*/

	int ret;
	char *language;

	/* Get locale */
	ret = app_event_get_language(event_info, &language);
	if (ret != APP_ERROR_NONE) {
		dlog_print(DLOG_ERROR, LOG_TAG, "app_event_get_language() failed. Err = %d.", ret);
		return;
	}

	if (language != NULL) {
		elm_language_set(language);
		free(language);
	}
}

/*
 * @brief This function will be called when the orientation is changed
 * @param[in] event_info The system event information
 * @param[in] user_data The user data to be passed to the callback function
 */
static void
ui_app_orient_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_DEVICE_ORIENTATION_CHANGED*/
	return;
}

/*
 * @brief This function will be called when the region is changed
 * @param[in] event_info The system event information
 * @param[in] user_data The user data to be passed to the callback function
 */
static void
ui_app_region_changed(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_REGION_FORMAT_CHANGED*/
}

/*
 * @brief This function will be called when the battery is low
 * @param[in] event_info The system event information
 * @param[in] user_data The user data to be passed to the callback function
 */
static void
ui_app_low_battery(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LOW_BATTERY*/
}

/*
 * @brief This function will be called when the memory is low
 * @param[in] event_info The system event information
 * @param[in] user_data The user data to be passed to the callback function
 */
static void
ui_app_low_memory(app_event_info_h event_info, void *user_data)
{
	/*APP_EVENT_LOW_MEMORY*/
}

/*
 * @brief Main function of the application
 * @param[in] argc The argument count
 * @param[in] argv The argument vector
 */
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;

	/* Register for low battery event handler */
	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad);

	/* Register for low memory event handler */
	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad);

	/* Register for device operation changed event handler */
	ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, ui_app_orient_changed, &ad);

	/* Register for language changed event handler */
	ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, ui_app_lang_changed, &ad);

	/* Register for region format changed event handler */
	ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, ui_app_region_changed, &ad);

	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;
}