-/*\r
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-\r
-#include <Elementary.h>\r
-#include <glib.h>\r
-#include <string.h>\r
-#include <feedback.h>\r
-#include <notification.h>\r
-#include <vconf.h>\r
-#include <vconf-keys.h>\r
-#include <sound_manager.h>\r
-#include <device/display.h>\r
-#include <app_control.h>\r
-#include <tzsh.h>\r
-#include <tzsh_quickpanel_service.h>\r
-\r
-#include "common.h"\r
-#include "volume.h"\r
-#include "quickpanel-ui.h"\r
-#include "list_util.h"\r
-#include "quickpanel_def.h"\r
-#include "settings_view_featured.h"\r
-#include "preference.h"\r
-#include "setting_utils.h"\r
-\r
-#ifdef QP_SCREENREADER_ENABLE\r
-#include "accessibility.h"\r
-#endif\r
-\r
-#ifdef QP_EMERGENCY_MODE_ENABLE\r
-#include "emergency_mode.h"\r
-#endif\r
-#include "tzsh_volume_service.h"\r
-\r
-#define VOLUME_MIN 1\r
-#define VOLUME_MAX 100\r
-\r
-/** this height adjustment is required to compensate the slider layout size of 50 instead of 32 \r
- * to keep the slider in correct position 9unit of offset top/bottom is reuired. (50-32)/2 = 9unit\r
- */\r
-#define SLIDER_HEIGHT_ADJUSTMENT 9\r
-#define SLIDER_LAYOUT_WIDTH ELM_SCALE_SIZE(VOLUME_BRIGHTNESS_SLIDER_LAYOUT_W)\r
-#define SLIDER_LAYOUT_HEIGHT ELM_SCALE_SIZE(VOLUME_BRIGHTNESS_SLIDER_LAYOUT_H)\r
-\r
-\r
-#define VCONF_KEY_MUTE_TYPE_SYSTEM VCONF_KEY_MUTE_PREFIX"/system"\r
-#define VCONF_KEY_MUTE_TYPE_NOTIFICATION VCONF_KEY_MUTE_PREFIX"/notification"\r
-#define VCONF_KEY_MUTE_TYPE_ALARM VCONF_KEY_MUTE_PREFIX"/alarm"\r
-#define VCONF_KEY_MUTE_TYPE_RINGTONE VCONF_KEY_MUTE_PREFIX"/ringtone"\r
-#define VCONF_KEY_MUTE_TYPE_MEDIA VCONF_KEY_MUTE_PREFIX"/media"\r
-#define VCONF_KEY_MUTE_TYPE_CALL VCONF_KEY_MUTE_PREFIX"/call"\r
-#define VCONF_KEY_MUTE_TYPE_VOIP VCONF_KEY_MUTE_PREFIX"/voip"\r
-#define VCONF_KEY_MUTE_TYPE_VOICE VCONF_KEY_MUTE_PREFIX"/voice"\r
-\r
-/* For internal use */\r
-#define VCONF_KEY_VOLUME_TYPE_BIXBY VCONF_KEY_VOLUME_PREFIX"/bixby"\r
-\r
-typedef struct _volume_ctrl_obj {\r
- int min_level;\r
- int max_level;\r
- int is_event_registered;\r
- int last_requested_level;\r
- Evas_Object *viewer;\r
- void *data;\r
- int level_before;\r
- int pos_x;\r
- bool is_changing;\r
- Evas_Object *volume_slider;\r
-} volume_ctrl_obj;\r
-\r
-struct _control_s_info {\r
- Eina_Bool is_deleting;\r
- Eina_Bool is_launching;\r
- Eina_Bool is_new;\r
- Eina_Bool is_warning_visible;\r
- Eina_Bool reset_once;\r
- Eina_Bool show_once;\r
- Eina_Bool safety_limit;\r
-\r
- int current_angle;\r
- int viewport_width;\r
- int viewport_height;\r
- int time_for_safety_limit;\r
-\r
- sound_type_e sound_type_at_show;\r
-};\r
-static struct _control_s_info control_info = {\r
- .is_deleting = EINA_FALSE,\r
- .is_launching = EINA_FALSE,\r
- .is_new = EINA_FALSE,\r
- .is_warning_visible = EINA_FALSE,\r
- .reset_once = EINA_FALSE,\r
- .show_once = EINA_FALSE,\r
- .safety_limit = EINA_TRUE,\r
-\r
- .current_angle = 0,\r
- .viewport_width = 0,\r
- .viewport_height = 0,\r
- .time_for_safety_limit = 0,\r
-\r
- .sound_type_at_show = SOUND_TYPE_MEDIA,\r
-};\r
-\r
-struct _view_s_info {\r
- Evas_Object *win;\r
- tzsh_h tzsh;\r
- tzsh_volume_service_h volume_service;\r
- Evas_Object *evas;\r
- Evas_Object *ly_outer;\r
- Evas_Object *icon_volume;\r
- Evas_Object *icon_volume_mute;\r
- Evas_Object *icon_setting;\r
- Evas_Object *slider;\r
- Evas_Object *warning_popup;\r
- Evas_Object *ao_volume;\r
-\r
- Evas_Object *lockscreen_splash;\r
-\r
- Evas_Object *ao_settings;\r
-\r
- Eina_Bool is_registered_callback;\r
- Eina_Bool is_slider_touching;\r
- Eina_Bool is_warning_displayed;\r
- sound_type_e pre_sound_type;\r
-};\r
-static struct _view_s_info view_info = {\r
- .win = NULL,\r
- .tzsh = NULL,\r
- .volume_service = NULL,\r
- .evas = NULL,\r
- .ly_outer = NULL,\r
- .icon_volume = NULL,\r
- .icon_setting = NULL,\r
- .slider = NULL,\r
- .warning_popup = NULL,\r
- .ao_volume = NULL,\r
-\r
- .lockscreen_splash = NULL,\r
-\r
- .ao_settings = NULL,\r
-\r
- .is_registered_callback = EINA_FALSE,\r
- .is_slider_touching = EINA_FALSE,\r
- .is_warning_displayed = EINA_FALSE,\r
- .pre_sound_type = SOUND_TYPE_RINGTONE\r
-};\r
-\r
-struct _sound_s_info {\r
- int sound_step;\r
- int sound_status;\r
- int vibration_status;\r
- int sound_changed_callback_id;\r
- Eina_Bool is_vibration;\r
-};\r
-\r
-static struct _sound_s_info sound_info = {\r
- .sound_step = 0,\r
- .sound_status = 0,\r
- .vibration_status = 0,\r
- .sound_changed_callback_id = 1,\r
- .is_vibration = EINA_FALSE,\r
-};\r
-\r
-typedef enum {\r
- TYPE_VCONF_SOUND_STATUS = 0,\r
- TYPE_VCONF_VIBRATION_STATUS\r
-} volume_vconf_type_e;\r
-\r
-int volume_slider_drag_start = -1;\r
-\r
-static int _init(void *data);\r
-static int _fini(void *data);\r
-static void _lang_changed(void *data);\r
-static void _qp_opened(void *data);\r
-static void _qp_closed(void *data);\r
-static void _volume_view_update(void);\r
-static void _volume_register_event_cb(volume_ctrl_obj *ctrl_obj);\r
-static void _volume_deregister_event_cb(volume_ctrl_obj *ctrl_obj);\r
-\r
-static void _volume_set_image(int level);\r
-static void _refresh(void *data);\r
-\r
-QP_Module volume_ctrl = {\r
- .name = "volume_ctrl",\r
- .init = _init,\r
- .fini = _fini,\r
- .suspend = NULL,\r
- .resume = NULL,\r
- .hib_enter = NULL,\r
- .hib_leave = NULL,\r
- .lang_changed = _lang_changed,\r
- .refresh = _refresh,\r
- .get_height = NULL,\r
- .qp_opened = _qp_opened,\r
- .qp_closed = _qp_closed,\r
-};\r
-\r
-static volume_ctrl_obj *g_ctrl_obj;\r
-\r
-sound_type_e volume_control_get_sound_type_at_show(void)\r
-{\r
- return control_info.sound_type_at_show;\r
-}\r
-\r
-static Evas_Object *_controller_view_get(void)\r
-{\r
- Evas_Object *view = NULL;\r
-\r
- if (g_ctrl_obj != NULL) {\r
- if (g_ctrl_obj->viewer != NULL) {\r
- view = elm_object_part_content_get(g_ctrl_obj->viewer, "elm.swallow.controller");\r
- if (view == NULL)\r
- view = evas_object_data_get(g_ctrl_obj->viewer, "view.controller");\r
-\r
- }\r
- }\r
-\r
- return view;\r
-}\r
-\r
-void quickpanel_volume_slider_visible_set(unsigned char value)\r
-{\r
- if(g_ctrl_obj)\r
- {\r
- if(g_ctrl_obj->viewer)\r
- {\r
- DBG("volume_slider visibility value [%d]", value);\r
- Elm_Transit *transit = elm_transit_add();\r
- elm_transit_object_add(transit, g_ctrl_obj->viewer);\r
- elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);\r
- elm_transit_objects_final_state_keep_set(transit, EINA_TRUE);\r
- elm_transit_duration_set(transit, 0.4);\r
- if (!value) {\r
- elm_transit_effect_color_add(transit, 255, 255, 255, 255, 255, 255, 255, 0);\r
- } else {\r
- int r, g, b, a;\r
- evas_object_color_get(g_ctrl_obj->viewer, &r, &g, &b, &a);\r
- elm_transit_effect_color_add(transit, r, g, b, a, 255, 255, 255, 255);\r
- }\r
- elm_transit_go(transit);\r
- }\r
- }\r
-}\r
-\r
-static void _controller_view_set(Evas_Object *wrapper, Evas_Object *view)\r
-{\r
- retif(wrapper == NULL, , "invalid data");\r
- retif(view == NULL, , "invalid data");\r
-\r
- elm_object_part_content_set(wrapper, "elm.swallow.controller", view);\r
- evas_object_data_set(wrapper, "view.controller", view);\r
-}\r
-\r
-static char *_volume_access_state_cb(void *data, Evas_Object *obj)\r
-{\r
- char buf[512] = {0,};\r
- volume_ctrl_obj *ctrl_obj = data;\r
- retif(NULL == ctrl_obj, NULL, "invalid data");\r
-\r
- snprintf(buf, sizeof(buf) - 1, _NOT_LOCALIZED("Position %1$d of %2$d"),\r
- ctrl_obj->last_requested_level, ctrl_obj->max_level);\r
-\r
- return strdup(buf);\r
-}\r
-\r
-#ifdef QP_SCREENREADER_ENABLE\r
-static void _set_slider_accessiblity_state(Evas_Object *obj)\r
-{\r
- Evas_Object *ao = NULL;\r
- volume_ctrl_obj *ctrl_obj = g_ctrl_obj;\r
- retif(ctrl_obj == NULL, , "Invalid parameter!");\r
- retif(ctrl_obj->viewer == NULL, , "Invalid parameter!");\r
-\r
- ao = quickpanel_accessibility_screen_reader_object_get(obj,\r
- SCREEN_READER_OBJ_TYPE_ELM_OBJECT, NULL, NULL);\r
- if (ao != NULL) {\r
- elm_access_info_set(ao, ELM_ACCESS_INFO, _NOT_LOCALIZED("Volume"));\r
- elm_access_info_set(ao, ELM_ACCESS_TYPE, _NOT_LOCALIZED("Slider"));\r
- elm_access_info_cb_set(ao, ELM_ACCESS_STATE, _volume_access_state_cb, ctrl_obj);\r
- }\r
-}\r
-#endif\r
-\r
-static Evas_Object *_check_duplicated_loading(Evas_Object *obj, const char *part)\r
-{\r
- Evas_Object *old_content = NULL;\r
- retif(obj == NULL, NULL, "Invalid parameter!");\r
- retif(part == NULL, NULL, "Invalid parameter!");\r
-\r
- old_content = elm_object_part_content_get(obj, part);\r
- if (old_content != NULL)\r
- return old_content;\r
-\r
-\r
- return NULL;\r
-}\r
-\r
-static int _volume_set_level(int level)\r
-{\r
- int ret = SOUND_MANAGER_ERROR_NONE;\r
- ret = sound_manager_set_volume(SOUND_TYPE_MEDIA, level);\r
- if (ret != SOUND_MANAGER_ERROR_NONE)\r
- ERR("failed to set volume");\r
-\r
- return level;\r
-}\r
-\r
-static int _volume_get_level(void)\r
-{\r
- int level = 0;\r
- int ret = -1,val = 0;\r
- ret = sound_manager_get_volume(SOUND_TYPE_MEDIA, &val);\r
- if(ret<0)\r
- DBG("FAILED TO GET THE VOLUME");\r
- return val;\r
-}\r
-\r
-Evas_Object *volume_slider_get(Evas_Object *view, volume_ctrl_obj *ctrl_obj)\r
-{\r
- DBG("**** volume_slider_get *******");\r
- retif(view == NULL, NULL, "Data parameter is NULL");\r
-\r
- Evas_Object *obj = elm_object_part_content_get(view, "elm.swallow.slider.volume");\r
-\r
- if (obj)\r
- return obj;\r
- else\r
- return ctrl_obj->volume_slider;\r
-\r
-}\r
-\r
-void volume_sound_vconf_status_set(volume_vconf_type_e type, int val)\r
-{\r
- char *vconfkey = NULL;\r
- switch (type) {\r
- case TYPE_VCONF_SOUND_STATUS:\r
- vconfkey = VCONFKEY_SETAPPL_SOUND_STATUS_BOOL;\r
- break;\r
- case TYPE_VCONF_VIBRATION_STATUS:\r
- vconfkey = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;\r
- break;\r
- default:\r
- DBG("Failed to set vconfkey : Type error");\r
- return;\r
- }\r
-\r
- if (vconf_set_bool(vconfkey, val) < 0)\r
- DBG("Failed to set vconfkey : %s", vconfkey);\r
-}\r
-\r
-int volume_sound_vconf_status_get(volume_vconf_type_e type)\r
-{\r
- int ret = -1;\r
- char *vconfkey = NULL;\r
-\r
- switch (type) {\r
- case TYPE_VCONF_SOUND_STATUS:\r
- vconfkey = VCONFKEY_SETAPPL_SOUND_STATUS_BOOL;\r
- break;\r
- case TYPE_VCONF_VIBRATION_STATUS:\r
- vconfkey = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;\r
- break;\r
- default:\r
- DBG("Failed to get vconfkey : Type error");\r
- return -1;\r
- }\r
-\r
- if (vconf_get_bool(vconfkey, &ret) < 0) {\r
- DBG("Failed to get vconfkey : %s", vconfkey);\r
- return -1;\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-void volume_sound_play(void)\r
-{\r
- sound_type_e sound_type = volume_control_get_sound_type_at_show();\r
- DBG("sound type at show : %d", sound_type);\r
-\r
- ret_if(sound_type == SOUND_TYPE_ALARM);\r
- ret_if(sound_type == SOUND_TYPE_MEDIA);\r
- ret_if(sound_type == SOUND_TYPE_VOICE);\r
- ret_if(sound_type == SOUND_TYPE_NOTIFICATION);\r
-\r
- DBG("Play Feedback : sound");\r
- if (FEEDBACK_ERROR_NONE != feedback_play(FEEDBACK_PATTERN_VOLUME_KEY))\r
- DBG("Failed to play feedback");\r
-\r
- return;\r
-}\r
-\r
-typedef enum {\r
- VOLUME_ERROR_OK = 0,\r
- VOLUME_ERROR_FAIL = -1,\r
- VOLUME_ERROR_INVALID_PARAMETER = -2,\r
- VOLUME_ERROR_NO_DATA = -3\r
-} volume_error_e;\r
-\r
-volume_error_e volume_view_slider_value_set(int val)\r
-{\r
- DBG("Slider value set : %d", val);\r
- retv_if(view_info.is_slider_touching, VOLUME_ERROR_FAIL);\r
- retv_if(val < 0, VOLUME_ERROR_FAIL);\r
-\r
- elm_slider_value_set(view_info.slider, val);\r
-\r
- return VOLUME_ERROR_OK;\r
-}\r
-\r
-int volume_sound_level_set(sound_type_e type, int val)\r
-{\r
- int ret = -1;\r
- ret = sound_manager_set_volume(type, val);\r
-\r
- return ret;\r
-}\r
-\r
-void volume_sound_vib_play(void)\r
-{\r
- ret_if(sound_info.is_vibration);\r
-\r
- DBG("Play Feedback : vibration");\r
-\r
- if (FEEDBACK_ERROR_NONE != feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_VIBRATION_ON))\r
- DBG("Failed to play feedback");\r
-\r
- sound_info.is_vibration = EINA_TRUE;\r
-}\r
-\r
-void volume_sound_change_set(int val)\r
-{\r
- sound_type_e sound_type = volume_control_get_sound_type_at_show();\r
- DBG("sound type at show : %d", sound_type);\r
-\r
- int sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);\r
- DBG("sound status : %d", sound);\r
-\r
- if (val) {\r
- if (volume_sound_level_set(SOUND_TYPE_MEDIA, val) != 0)\r
- volume_sound_level_set(SOUND_TYPE_MEDIA, 9);\r
- volume_sound_play();\r
- } else {\r
- if (sound_type != SOUND_TYPE_MEDIA)\r
- volume_sound_vconf_status_set(TYPE_VCONF_SOUND_STATUS, 0);\r
-\r
- volume_view_slider_value_set(0);\r
- volume_sound_level_set(sound_type, 0);\r
-\r
- if (sound_type == SOUND_TYPE_RINGTONE) {\r
- volume_sound_vconf_status_set(TYPE_VCONF_VIBRATION_STATUS, 1);\r
- volume_sound_vib_play();\r
- }\r
- }\r
-}\r
-static void _volume_ctrl_slider_changed_cb(void *data, Evas_Object *obj, void *event_info)\r
-{\r
- double val=0.0;\r
- int value = 0;\r
- volume_ctrl_obj *ctrl_obj = data;\r
- sound_type_e sound_type = volume_control_get_sound_type_at_show();\r
- DBG("sound type at show : %d", sound_type);\r
- obj = volume_slider_get(_controller_view_get(), ctrl_obj);\r
- val = elm_slider_value_get(obj);\r
- DBG("*** val == %lf ***",val);\r
- value = (int)(val + 0.5);\r
- DBG("*** value == %d ***",value);\r
- _volume_set_image(value);\r
- volume_sound_change_set(value);\r
-}\r
-\r
-static void _volume_slider_drag_start_cb(void *data, Evas_Object *obj, void *event_info)\r
-{\r
- volume_slider_drag_start = _volume_get_level();\r
-}\r
-\r
-static void _volume_slider_drag_stop_cb(void *data, Evas_Object *obj, void *event_info)\r
-{\r
- view_info.is_slider_touching = EINA_FALSE;\r
- volume_ctrl_obj *ctrl_obj = data;\r
- Evas_Object *slider = volume_slider_get(_controller_view_get(), ctrl_obj);\r
- ret_if(slider == NULL);\r
-\r
- double val = 0;\r
-\r
- val = elm_slider_value_get(slider);\r
- val += 0.5;\r
- DBG("**** slider value : %d ***", (int)val);\r
- _volume_set_image(val);\r
- volume_sound_change_set((int)val);\r
-}\r
-\r
-/*!\r
- * workaround to avoid focus jump to other pages\r
- */\r
-static void _frame_focused(void *data, Evas_Object * obj, void *event_info)\r
-{\r
- DBG("");\r
-}\r
-\r
-static void _frame_unfocused(void *data, Evas_Object * obj, void *event_info)\r
-{\r
- DBG("");\r
-}\r
-\r
-\r
-static void _volume_view_pos_set()\r
-{\r
- struct appdata *ad = quickpanel_get_app_data();\r
-\r
- Evas_Coord base_y;\r
- Evas_Coord volume_y;\r
- \r
- int x= 0, w =0, h =0;\r
-\r
- Eina_Bool ret = EINA_FALSE;\r
-\r
- edje_object_part_geometry_get(_EDJ(ad->view_root), "qp.root.swallow", NULL, &base_y, NULL, NULL);\r
-\r
- Evas_Object *settings_swallow = quickpanel_setting_layout_get(ad->ly, QP_SETTING_BASE_PART);\r
- ret = edje_object_part_geometry_get(_EDJ(settings_swallow),"volume.container.swallow.wvga", &x, &volume_y, &w, &h);\r
- msgif(!ret, "ret is EINA_FALSE");\r
-\r
- evas_object_move(g_ctrl_obj->viewer, x, base_y + volume_y - SLIDER_HEIGHT_ADJUSTMENT);\r
-}\r
-\r
-static Evas_Object *_volume_view_create(Evas_Object *list)\r
-{\r
- Eina_Bool ret = EINA_TRUE;\r
- Evas_Object *view_wrapper = NULL;\r
- Evas_Object *view = NULL;\r
-\r
- retif(list == NULL, NULL, "list parameter is NULL");\r
-\r
- view_wrapper = elm_layout_add(list);\r
- if (view_wrapper != NULL) {\r
- ret = elm_layout_file_set(view_wrapper, util_get_res_file_path(DEFAULT_EDJ),\r
- "quickpanel/volume_controller/wrapper");\r
-\r
- if (ret == EINA_FALSE)\r
- ERR("failed to load volume wapper layout");\r
-\r
- evas_object_size_hint_weight_set(view_wrapper, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
- evas_object_size_hint_align_set(view_wrapper, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
-\r
- view = elm_layout_add(view_wrapper);\r
- if (view != NULL) {\r
- ret = elm_layout_file_set(view, util_get_res_file_path(DEFAULT_EDJ),\r
- "quickpanel/volume_controller/default");\r
-\r
- if (ret == EINA_FALSE)\r
- ERR("failed to load volume layout");\r
-\r
- evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
- evas_object_size_hint_align_set(view, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
-\r
- Evas_Object *focus = quickpanel_accessibility_ui_get_focus_object(view);\r
- elm_access_info_cb_set(focus, ELM_ACCESS_TYPE, quickpanel_accessibility_info_cb_s, _NOT_LOCALIZED("Volume"));\r
- elm_object_part_content_set(view, "focus", focus);\r
-\r
- evas_object_smart_callback_add(focus, "focused", _frame_focused, NULL);\r
- evas_object_smart_callback_add(focus, "unfocused", _frame_unfocused, NULL);\r
- evas_object_show(view);\r
- _volume_view_pos_set();\r
-\r
- g_ctrl_obj->volume_slider = view;\r
- _controller_view_set(view_wrapper, view);\r
- evas_object_show(view_wrapper);\r
- }\r
- }\r
-\r
- return view_wrapper;\r
-}\r
-\r
-static void _volume_set_image(int level)\r
-{\r
- int mapped_level;\r
- DBG("******_volume_set_image level = %d *********",level);\r
- if (!g_ctrl_obj) {\r
- ERR("Ctrl Obj is not defined");\r
- return;\r
- }\r
- if (level <= 1)\r
- mapped_level = 0;\r
-\r
- else if (level > 1 && level <= 9)\r
- mapped_level = 1;\r
-\r
- else\r
- mapped_level = 2;\r
- if (g_ctrl_obj->level_before != mapped_level) {\r
- char buf[128] = {0,};\r
- Evas_Object *view;\r
-\r
- view = _controller_view_get();\r
- snprintf(buf, sizeof(buf) - 1, "icon.state.%d", mapped_level);\r
- elm_object_signal_emit(view, buf, "prog");\r
- g_ctrl_obj->level_before = mapped_level;\r
- }\r
-}\r
-\r
-static void _volume_set_slider(void)\r
-{\r
- DBG("****** _volume_set_slider ******");\r
- int value = 0;\r
- Evas_Object *slider = NULL;\r
- Evas_Object *old_obj = NULL;\r
- volume_ctrl_obj *ctrl_obj = g_ctrl_obj;\r
- Evas_Object *view = _controller_view_get();\r
- retif(ctrl_obj == NULL, , "Invalid parameter!");\r
- retif(view == NULL, , "Invalid parameter!");\r
-\r
- old_obj = _check_duplicated_loading(view, "elm.swallow.slider.volume");\r
-\r
- if (old_obj == NULL) {\r
- slider = elm_slider_add(view);\r
-\r
- if (slider != NULL) {\r
- evas_object_size_hint_weight_set(slider, EVAS_HINT_EXPAND, 0.0);\r
- evas_object_size_hint_align_set(slider, EVAS_HINT_FILL, 0.5);\r
- elm_slider_min_max_set(slider, ctrl_obj->min_level, ctrl_obj->max_level);\r
- evas_object_smart_callback_add(slider, "changed", _volume_ctrl_slider_changed_cb, ctrl_obj);\r
- evas_object_smart_callback_add(slider, "slider,drag,start", _volume_slider_drag_start_cb, ctrl_obj);\r
- evas_object_smart_callback_add(slider, "slider,drag,stop", _volume_slider_drag_stop_cb, ctrl_obj);\r
- elm_object_part_content_set(view, "elm.swallow.slider.volume", slider);\r
- } else {\r
- ERR("failed to create slider");\r
- return;\r
- }\r
- } else {\r
- slider = old_obj;\r
- }\r
-\r
- elm_object_style_set(slider, "quickpanel_style");\r
-\r
- elm_slider_indicator_format_set(slider, NULL);\r
- elm_slider_indicator_format_function_set(slider, NULL, NULL);\r
- elm_slider_indicator_show_set(slider, EINA_FALSE);\r
-\r
-#ifdef QP_SCREENREADER_ENABLE\r
- _set_slider_accessiblity_state(slider);\r
-#endif\r
-\r
- value = _volume_get_level();\r
- elm_slider_value_set(slider, value);\r
- _volume_set_image(value);\r
-}\r
-\r
-static void _focus_pair_set()\r
-{\r
- volume_ctrl_obj *ctrl_obj = g_ctrl_obj;\r
- Evas_Object *focus = NULL;\r
- Evas_Object *slider = NULL;\r
- Evas_Object *view = _controller_view_get();\r
- retif(ctrl_obj == NULL, , "Invalid parameter!");\r
- retif(view == NULL, , "Invalid parameter!");\r
-\r
- focus = elm_object_part_content_get(view, "focus");\r
- slider = elm_object_part_content_get(view, "elm.swallow.slider.volume");\r
-\r
- if (focus != NULL && slider != NULL) {\r
- /* focus */\r
- elm_object_focus_next_object_set(focus, slider, ELM_FOCUS_RIGHT);\r
- elm_object_focus_next_object_set(focus, slider, ELM_FOCUS_DOWN);\r
-\r
- /* slider */\r
- elm_object_focus_next_object_set(slider, focus, ELM_FOCUS_LEFT);\r
- elm_object_focus_next_object_set(slider, focus, ELM_FOCUS_UP);\r
- }\r
-}\r
-\r
-static void _volume_view_update(void)\r
-{\r
- DBG("****** _volume_view_update ********");\r
- _volume_set_slider();\r
- _focus_pair_set();\r
-}\r
-\r
-static void _volume_add(volume_ctrl_obj *ctrl_obj, void *data)\r
-{\r
- struct appdata *ad = data;\r
- retif(!ad, , "list is NULL");\r
- retif(!ad->list, , "list is NULL");\r
- retif(ctrl_obj == NULL, , "ctrl_obj is null");\r
- retif(ctrl_obj->viewer != NULL, , "viewer is already created");\r
-\r
- ctrl_obj->viewer = _volume_view_create(ad->list);\r
- ctrl_obj->data = data;\r
-\r
- _volume_set_image(VOLUME_MIN);\r
- _refresh(ad);\r
-}\r
-\r
-static void _volume_remove(volume_ctrl_obj *ctrl_obj, void *data)\r
-{\r
- struct appdata *ad = data;\r
- retif(ad == NULL, , "list is NULL");\r
- retif(ad->list == NULL, , "list is NULL");\r
-\r
- if (g_ctrl_obj != NULL) {\r
- if (g_ctrl_obj->viewer != NULL) {\r
- quickpanel_list_util_item_unpack_by_object(ad->list\r
- , g_ctrl_obj->viewer, 0, 0);\r
- quickpanel_list_util_del_item_type(g_ctrl_obj->viewer);\r
- evas_object_del(g_ctrl_obj->viewer);\r
- g_ctrl_obj->viewer = NULL;\r
- }\r
- DBG("volume controller is removed");\r
- free(g_ctrl_obj);\r
- g_ctrl_obj = NULL;\r
- }\r
-}\r
-\r
-static void _volume_create(void *data)\r
-{\r
- if (g_ctrl_obj == NULL) {\r
- g_ctrl_obj = (volume_ctrl_obj *)calloc(1, sizeof(volume_ctrl_obj));\r
- if (g_ctrl_obj != NULL) {\r
- g_ctrl_obj->min_level = 1;\r
- g_ctrl_obj->max_level = 15;\r
- g_ctrl_obj->last_requested_level = _volume_get_level();\r
-\r
- _volume_add(g_ctrl_obj, data);\r
- _volume_view_update();\r
-\r
- g_ctrl_obj->volume_slider = NULL;\r
-\r
- DBG("volume controller is created");\r
- }\r
- }\r
-}\r
-\r
-static void _volume_destroy(void *data)\r
-{\r
- if (g_ctrl_obj != NULL) {\r
- _volume_remove(g_ctrl_obj, data);\r
-\r
- DBG("volume controller is removed");\r
- }\r
-\r
- g_ctrl_obj = NULL;\r
-}\r
-\r
-static int _init(void *data)\r
-{\r
- DBG("************ volume.c init() **********");\r
- retif(data == NULL, QP_FAIL, "Invalid parameter!");\r
-\r
-#ifdef QP_EMERGENCY_MODE_ENABLE\r
- if (quickpanel_emergency_mode_is_on())\r
- return QP_OK;\r
-\r
-#endif\r
- DBG("*********** volume_create() calling ******");\r
- _volume_create(data);\r
-\r
- return QP_OK;\r
-}\r
-\r
-static int _fini(void *data)\r
-{\r
- retif(data == NULL, QP_FAIL, "Invalid parameter!");\r
-\r
- _volume_destroy(data);\r
-\r
- return QP_OK;\r
-}\r
-\r
-static void _lang_changed(void *data)\r
-{\r
- retif(data == NULL, , "Invalid parameter!");\r
-\r
- if (g_ctrl_obj != NULL && g_ctrl_obj->viewer != NULL)\r
- _volume_view_update();\r
-\r
-}\r
-\r
-static void _qp_opened(void *data)\r
-{\r
- Evas_Object *slider = NULL;\r
- Evas_Object *view = _controller_view_get();\r
- retif(g_ctrl_obj == NULL, , "Invalid parameter!");\r
- retif(view == NULL, , "Invalid parameter!");\r
-\r
- if (view != NULL) {\r
- _volume_view_update();\r
- slider = elm_object_part_content_get(view, "elm.swallow.slider.volume");\r
- }\r
-}\r
-\r
-static void _qp_closed(void *data)\r
-{\r
- retif(g_ctrl_obj == NULL, , "Invalid parameter!");\r
-\r
- if (g_ctrl_obj->viewer != NULL)\r
- _volume_view_update();\r
-\r
-}\r
-\r
-static void _refresh(void *data)\r
-{\r
- int h = 0;\r
- struct appdata *ad = data;\r
- Evas_Object *view = _controller_view_get();\r
- retif(ad == NULL, , "Invalid parameter!");\r
- retif(g_ctrl_obj == NULL, , "Invalid parameter!");\r
- retif(g_ctrl_obj->viewer == NULL, , "Invalid parameter!");\r
- retif(view == NULL, , "Invalid parameter!");\r
-\r
- evas_object_geometry_get(g_ctrl_obj->viewer, NULL, NULL, NULL, &h);\r
-\r
- if (ad->angle == 90 || ad->angle == 270) {\r
- evas_object_resize(g_ctrl_obj->viewer, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);\r
- evas_object_resize(view, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);\r
- _volume_view_pos_set();\r
-\r
- } else {\r
- evas_object_resize(g_ctrl_obj->viewer, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);\r
- evas_object_resize(view, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);\r
- _volume_view_pos_set();\r
- }\r
-}\r
+/*
+ * 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 <Elementary.h>
+#include <glib.h>
+#include <string.h>
+#include <feedback.h>
+#include <notification.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+#include <sound_manager.h>
+#include <device/display.h>
+#include <app_control.h>
+#include <tzsh.h>
+#include <tzsh_quickpanel_service.h>
+
+#include "common.h"
+#include "volume.h"
+#include "quickpanel-ui.h"
+#include "list_util.h"
+#include "quickpanel_def.h"
+#include "settings_view_featured.h"
+#include "preference.h"
+#include "setting_utils.h"
+
+#ifdef QP_SCREENREADER_ENABLE
+#include "accessibility.h"
+#endif
+
+#ifdef QP_EMERGENCY_MODE_ENABLE
+#include "emergency_mode.h"
+#endif
+#include "tzsh_volume_service.h"
+
+#define VOLUME_MIN 1
+#define VOLUME_MAX 100
+
+/** this height adjustment is required to compensate the slider layout size of 50 instead of 32
+ * to keep the slider in correct position 9unit of offset top/bottom is reuired. (50-32)/2 = 9unit
+ */
+#define SLIDER_HEIGHT_ADJUSTMENT 9
+#define SLIDER_LAYOUT_WIDTH ELM_SCALE_SIZE(VOLUME_BRIGHTNESS_SLIDER_LAYOUT_W)
+#define SLIDER_LAYOUT_HEIGHT ELM_SCALE_SIZE(VOLUME_BRIGHTNESS_SLIDER_LAYOUT_H)
+
+
+#define VCONF_KEY_MUTE_TYPE_SYSTEM VCONF_KEY_MUTE_PREFIX"/system"
+#define VCONF_KEY_MUTE_TYPE_NOTIFICATION VCONF_KEY_MUTE_PREFIX"/notification"
+#define VCONF_KEY_MUTE_TYPE_ALARM VCONF_KEY_MUTE_PREFIX"/alarm"
+#define VCONF_KEY_MUTE_TYPE_RINGTONE VCONF_KEY_MUTE_PREFIX"/ringtone"
+#define VCONF_KEY_MUTE_TYPE_MEDIA VCONF_KEY_MUTE_PREFIX"/media"
+#define VCONF_KEY_MUTE_TYPE_CALL VCONF_KEY_MUTE_PREFIX"/call"
+#define VCONF_KEY_MUTE_TYPE_VOIP VCONF_KEY_MUTE_PREFIX"/voip"
+#define VCONF_KEY_MUTE_TYPE_VOICE VCONF_KEY_MUTE_PREFIX"/voice"
+
+/* For internal use */
+#define VCONF_KEY_VOLUME_TYPE_BIXBY VCONF_KEY_VOLUME_PREFIX"/bixby"
+
+typedef struct _volume_ctrl_obj {
+ int min_level;
+ int max_level;
+ int is_event_registered;
+ int last_requested_level;
+ Evas_Object *viewer;
+ void *data;
+ int level_before;
+ int pos_x;
+ bool is_changing;
+ Evas_Object *volume_slider;
+} volume_ctrl_obj;
+
+struct _control_s_info {
+ Eina_Bool is_deleting;
+ Eina_Bool is_launching;
+ Eina_Bool is_new;
+ Eina_Bool is_warning_visible;
+ Eina_Bool reset_once;
+ Eina_Bool show_once;
+ Eina_Bool safety_limit;
+
+ int current_angle;
+ int viewport_width;
+ int viewport_height;
+ int time_for_safety_limit;
+
+ sound_type_e sound_type_at_show;
+};
+static struct _control_s_info control_info = {
+ .is_deleting = EINA_FALSE,
+ .is_launching = EINA_FALSE,
+ .is_new = EINA_FALSE,
+ .is_warning_visible = EINA_FALSE,
+ .reset_once = EINA_FALSE,
+ .show_once = EINA_FALSE,
+ .safety_limit = EINA_TRUE,
+
+ .current_angle = 0,
+ .viewport_width = 0,
+ .viewport_height = 0,
+ .time_for_safety_limit = 0,
+
+ .sound_type_at_show = SOUND_TYPE_MEDIA,
+};
+
+struct _view_s_info {
+ Evas_Object *win;
+ tzsh_h tzsh;
+ tzsh_volume_service_h volume_service;
+ Evas_Object *evas;
+ Evas_Object *ly_outer;
+ Evas_Object *icon_volume;
+ Evas_Object *icon_volume_mute;
+ Evas_Object *icon_setting;
+ Evas_Object *slider;
+ Evas_Object *warning_popup;
+ Evas_Object *ao_volume;
+
+ Evas_Object *lockscreen_splash;
+
+ Evas_Object *ao_settings;
+
+ Eina_Bool is_registered_callback;
+ Eina_Bool is_slider_touching;
+ Eina_Bool is_warning_displayed;
+ sound_type_e pre_sound_type;
+};
+static struct _view_s_info view_info = {
+ .win = NULL,
+ .tzsh = NULL,
+ .volume_service = NULL,
+ .evas = NULL,
+ .ly_outer = NULL,
+ .icon_volume = NULL,
+ .icon_setting = NULL,
+ .slider = NULL,
+ .warning_popup = NULL,
+ .ao_volume = NULL,
+
+ .lockscreen_splash = NULL,
+
+ .ao_settings = NULL,
+
+ .is_registered_callback = EINA_FALSE,
+ .is_slider_touching = EINA_FALSE,
+ .is_warning_displayed = EINA_FALSE,
+ .pre_sound_type = SOUND_TYPE_RINGTONE
+};
+
+struct _sound_s_info {
+ int sound_step;
+ int sound_status;
+ int vibration_status;
+ int sound_changed_callback_id;
+ Eina_Bool is_vibration;
+};
+
+static struct _sound_s_info sound_info = {
+ .sound_step = 0,
+ .sound_status = 0,
+ .vibration_status = 0,
+ .sound_changed_callback_id = 1,
+ .is_vibration = EINA_FALSE,
+};
+
+typedef enum {
+ TYPE_VCONF_SOUND_STATUS = 0,
+ TYPE_VCONF_VIBRATION_STATUS
+} volume_vconf_type_e;
+
+int volume_slider_drag_start = -1;
+
+static int _init(void *data);
+static int _fini(void *data);
+static void _lang_changed(void *data);
+static void _qp_opened(void *data);
+static void _qp_closed(void *data);
+static void _volume_view_update(void);
+static void _volume_register_event_cb(volume_ctrl_obj *ctrl_obj);
+static void _volume_deregister_event_cb(volume_ctrl_obj *ctrl_obj);
+
+static void _volume_set_image(int level);
+static void _refresh(void *data);
+
+QP_Module volume_ctrl = {
+ .name = "volume_ctrl",
+ .init = _init,
+ .fini = _fini,
+ .suspend = NULL,
+ .resume = NULL,
+ .hib_enter = NULL,
+ .hib_leave = NULL,
+ .lang_changed = _lang_changed,
+ .refresh = _refresh,
+ .get_height = NULL,
+ .qp_opened = _qp_opened,
+ .qp_closed = _qp_closed,
+};
+
+static volume_ctrl_obj *g_ctrl_obj;
+
+sound_type_e volume_control_get_sound_type_at_show(void)
+{
+ return control_info.sound_type_at_show;
+}
+
+static Evas_Object *_controller_view_get(void)
+{
+ Evas_Object *view = NULL;
+
+ if (g_ctrl_obj != NULL) {
+ if (g_ctrl_obj->viewer != NULL) {
+ view = elm_object_part_content_get(g_ctrl_obj->viewer, "elm.swallow.controller");
+ if (view == NULL)
+ view = evas_object_data_get(g_ctrl_obj->viewer, "view.controller");
+
+ }
+ }
+
+ return view;
+}
+
+void quickpanel_volume_slider_visible_set(unsigned char value)
+{
+ if(g_ctrl_obj)
+ {
+ if(g_ctrl_obj->viewer)
+ {
+ DBG("volume_slider visibility value [%d]", value);
+ Elm_Transit *transit = elm_transit_add();
+ elm_transit_object_add(transit, g_ctrl_obj->viewer);
+ elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL);
+ elm_transit_objects_final_state_keep_set(transit, EINA_TRUE);
+ elm_transit_duration_set(transit, 0.4);
+ if (!value) {
+ elm_transit_effect_color_add(transit, 255, 255, 255, 255, 255, 255, 255, 0);
+ } else {
+ int r, g, b, a;
+ evas_object_color_get(g_ctrl_obj->viewer, &r, &g, &b, &a);
+ elm_transit_effect_color_add(transit, r, g, b, a, 255, 255, 255, 255);
+ }
+ elm_transit_go(transit);
+ }
+ }
+}
+
+static void _controller_view_set(Evas_Object *wrapper, Evas_Object *view)
+{
+ retif(wrapper == NULL, , "invalid data");
+ retif(view == NULL, , "invalid data");
+
+ elm_object_part_content_set(wrapper, "elm.swallow.controller", view);
+ evas_object_data_set(wrapper, "view.controller", view);
+}
+
+static char *_volume_access_state_cb(void *data, Evas_Object *obj)
+{
+ char buf[512] = {0,};
+ volume_ctrl_obj *ctrl_obj = data;
+ retif(NULL == ctrl_obj, NULL, "invalid data");
+
+ snprintf(buf, sizeof(buf) - 1, _NOT_LOCALIZED("Position %1$d of %2$d"),
+ ctrl_obj->last_requested_level, ctrl_obj->max_level);
+
+ return strdup(buf);
+}
+
+#ifdef QP_SCREENREADER_ENABLE
+static void _set_slider_accessiblity_state(Evas_Object *obj)
+{
+ Evas_Object *ao = NULL;
+ volume_ctrl_obj *ctrl_obj = g_ctrl_obj;
+ retif(ctrl_obj == NULL, , "Invalid parameter!");
+ retif(ctrl_obj->viewer == NULL, , "Invalid parameter!");
+
+ ao = quickpanel_accessibility_screen_reader_object_get(obj,
+ SCREEN_READER_OBJ_TYPE_ELM_OBJECT, NULL, NULL);
+ if (ao != NULL) {
+ elm_access_info_set(ao, ELM_ACCESS_INFO, _NOT_LOCALIZED("Volume"));
+ elm_access_info_set(ao, ELM_ACCESS_TYPE, _NOT_LOCALIZED("Slider"));
+ elm_access_info_cb_set(ao, ELM_ACCESS_STATE, _volume_access_state_cb, ctrl_obj);
+ }
+}
+#endif
+
+static Evas_Object *_check_duplicated_loading(Evas_Object *obj, const char *part)
+{
+ Evas_Object *old_content = NULL;
+ retif(obj == NULL, NULL, "Invalid parameter!");
+ retif(part == NULL, NULL, "Invalid parameter!");
+
+ old_content = elm_object_part_content_get(obj, part);
+ if (old_content != NULL)
+ return old_content;
+
+
+ return NULL;
+}
+
+static int _volume_set_level(int level)
+{
+ int ret = SOUND_MANAGER_ERROR_NONE;
+ ret = sound_manager_set_volume(SOUND_TYPE_MEDIA, level);
+ if (ret != SOUND_MANAGER_ERROR_NONE)
+ ERR("failed to set volume");
+
+ return level;
+}
+
+static int _volume_get_level(void)
+{
+ int level = 0;
+ int ret = -1,val = 0;
+ ret = sound_manager_get_volume(SOUND_TYPE_MEDIA, &val);
+ if(ret<0)
+ DBG("FAILED TO GET THE VOLUME");
+ return val;
+}
+
+Evas_Object *volume_slider_get(Evas_Object *view, volume_ctrl_obj *ctrl_obj)
+{
+ DBG("**** volume_slider_get *******");
+ retif(view == NULL, NULL, "Data parameter is NULL");
+
+ Evas_Object *obj = elm_object_part_content_get(view, "elm.swallow.slider.volume");
+
+ if (obj)
+ return obj;
+ else
+ return ctrl_obj->volume_slider;
+
+}
+
+void volume_sound_vconf_status_set(volume_vconf_type_e type, int val)
+{
+ char *vconfkey = NULL;
+ switch (type) {
+ case TYPE_VCONF_SOUND_STATUS:
+ vconfkey = VCONFKEY_SETAPPL_SOUND_STATUS_BOOL;
+ break;
+ case TYPE_VCONF_VIBRATION_STATUS:
+ vconfkey = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;
+ break;
+ default:
+ DBG("Failed to set vconfkey : Type error");
+ return;
+ }
+
+ if (vconf_set_bool(vconfkey, val) < 0)
+ DBG("Failed to set vconfkey : %s", vconfkey);
+}
+
+int volume_sound_vconf_status_get(volume_vconf_type_e type)
+{
+ int ret = -1;
+ char *vconfkey = NULL;
+
+ switch (type) {
+ case TYPE_VCONF_SOUND_STATUS:
+ vconfkey = VCONFKEY_SETAPPL_SOUND_STATUS_BOOL;
+ break;
+ case TYPE_VCONF_VIBRATION_STATUS:
+ vconfkey = VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL;
+ break;
+ default:
+ DBG("Failed to get vconfkey : Type error");
+ return -1;
+ }
+
+ if (vconf_get_bool(vconfkey, &ret) < 0) {
+ DBG("Failed to get vconfkey : %s", vconfkey);
+ return -1;
+ }
+
+ return ret;
+}
+
+void volume_sound_play(void)
+{
+ sound_type_e sound_type = volume_control_get_sound_type_at_show();
+ DBG("sound type at show : %d", sound_type);
+
+ ret_if(sound_type == SOUND_TYPE_ALARM);
+ ret_if(sound_type == SOUND_TYPE_MEDIA);
+ ret_if(sound_type == SOUND_TYPE_VOICE);
+ ret_if(sound_type == SOUND_TYPE_NOTIFICATION);
+
+ DBG("Play Feedback : sound");
+ if (FEEDBACK_ERROR_NONE != feedback_play(FEEDBACK_PATTERN_VOLUME_KEY))
+ DBG("Failed to play feedback");
+
+ return;
+}
+
+typedef enum {
+ VOLUME_ERROR_OK = 0,
+ VOLUME_ERROR_FAIL = -1,
+ VOLUME_ERROR_INVALID_PARAMETER = -2,
+ VOLUME_ERROR_NO_DATA = -3
+} volume_error_e;
+
+volume_error_e volume_view_slider_value_set(int val)
+{
+ DBG("Slider value set : %d", val);
+ retv_if(view_info.is_slider_touching, VOLUME_ERROR_FAIL);
+ retv_if(val < 0, VOLUME_ERROR_FAIL);
+
+ elm_slider_value_set(view_info.slider, val);
+
+ return VOLUME_ERROR_OK;
+}
+
+int volume_sound_level_set(sound_type_e type, int val)
+{
+ int ret = -1;
+ ret = sound_manager_set_volume(type, val);
+
+ return ret;
+}
+
+void volume_sound_vib_play(void)
+{
+ ret_if(sound_info.is_vibration);
+
+ DBG("Play Feedback : vibration");
+
+ if (FEEDBACK_ERROR_NONE != feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_VIBRATION_ON))
+ DBG("Failed to play feedback");
+
+ sound_info.is_vibration = EINA_TRUE;
+}
+
+void volume_sound_change_set(int val)
+{
+ sound_type_e sound_type = volume_control_get_sound_type_at_show();
+ DBG("sound type at show : %d", sound_type);
+
+ int sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);
+ DBG("sound status : %d", sound);
+
+ if (val) {
+ if (volume_sound_level_set(SOUND_TYPE_MEDIA, val) != 0)
+ volume_sound_level_set(SOUND_TYPE_MEDIA, 9);
+ volume_sound_play();
+ } else {
+ if (sound_type != SOUND_TYPE_MEDIA)
+ volume_sound_vconf_status_set(TYPE_VCONF_SOUND_STATUS, 0);
+
+ volume_view_slider_value_set(0);
+ volume_sound_level_set(sound_type, 0);
+
+ if (sound_type == SOUND_TYPE_RINGTONE) {
+ volume_sound_vconf_status_set(TYPE_VCONF_VIBRATION_STATUS, 1);
+ volume_sound_vib_play();
+ }
+ }
+}
+static void _volume_ctrl_slider_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ double val=0.0;
+ int value = 0;
+ volume_ctrl_obj *ctrl_obj = data;
+ sound_type_e sound_type = volume_control_get_sound_type_at_show();
+ DBG("sound type at show : %d", sound_type);
+ obj = volume_slider_get(_controller_view_get(), ctrl_obj);
+ val = elm_slider_value_get(obj);
+ DBG("*** val == %lf ***",val);
+ value = (int)(val + 0.5);
+ DBG("*** value == %d ***",value);
+ _volume_set_image(value);
+ volume_sound_change_set(value);
+}
+
+static void _volume_slider_drag_start_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ volume_slider_drag_start = _volume_get_level();
+}
+
+static void _volume_slider_drag_stop_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ view_info.is_slider_touching = EINA_FALSE;
+ volume_ctrl_obj *ctrl_obj = data;
+ Evas_Object *slider = volume_slider_get(_controller_view_get(), ctrl_obj);
+ ret_if(slider == NULL);
+
+ double val = 0;
+
+ val = elm_slider_value_get(slider);
+ val += 0.5;
+ DBG("**** slider value : %d ***", (int)val);
+ _volume_set_image(val);
+ volume_sound_change_set((int)val);
+}
+
+/*!
+ * workaround to avoid focus jump to other pages
+ */
+static void _frame_focused(void *data, Evas_Object * obj, void *event_info)
+{
+ DBG("");
+}
+
+static void _frame_unfocused(void *data, Evas_Object * obj, void *event_info)
+{
+ DBG("");
+}
+
+
+static void _volume_view_pos_set()
+{
+ struct appdata *ad = quickpanel_get_app_data();
+
+ Evas_Coord base_y;
+ Evas_Coord volume_y;
+
+ int x= 0, w =0, h =0;
+
+ Eina_Bool ret = EINA_FALSE;
+
+ edje_object_part_geometry_get(_EDJ(ad->view_root), "qp.root.swallow", NULL, &base_y, NULL, NULL);
+
+ Evas_Object *settings_swallow = quickpanel_setting_layout_get(ad->ly, QP_SETTING_BASE_PART);
+ ret = edje_object_part_geometry_get(_EDJ(settings_swallow),"volume.container.swallow.wvga", &x, &volume_y, &w, &h);
+ msgif(!ret, "ret is EINA_FALSE");
+
+ evas_object_move(g_ctrl_obj->viewer, x, base_y + volume_y - SLIDER_HEIGHT_ADJUSTMENT);
+}
+
+static Evas_Object *_volume_view_create(Evas_Object *list)
+{
+ Eina_Bool ret = EINA_TRUE;
+ Evas_Object *view_wrapper = NULL;
+ Evas_Object *view = NULL;
+
+ retif(list == NULL, NULL, "list parameter is NULL");
+
+ view_wrapper = elm_layout_add(list);
+ if (view_wrapper != NULL) {
+ ret = elm_layout_file_set(view_wrapper, util_get_res_file_path(DEFAULT_EDJ),
+ "quickpanel/volume_controller/wrapper");
+
+ if (ret == EINA_FALSE)
+ ERR("failed to load volume wapper layout");
+
+ evas_object_size_hint_weight_set(view_wrapper, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(view_wrapper, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ view = elm_layout_add(view_wrapper);
+ if (view != NULL) {
+ ret = elm_layout_file_set(view, util_get_res_file_path(DEFAULT_EDJ),
+ "quickpanel/volume_controller/default");
+
+ if (ret == EINA_FALSE)
+ ERR("failed to load volume layout");
+
+ evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ Evas_Object *focus = quickpanel_accessibility_ui_get_focus_object(view);
+ elm_access_info_cb_set(focus, ELM_ACCESS_TYPE, quickpanel_accessibility_info_cb_s, _NOT_LOCALIZED("Volume"));
+ elm_object_part_content_set(view, "focus", focus);
+
+ evas_object_smart_callback_add(focus, "focused", _frame_focused, NULL);
+ evas_object_smart_callback_add(focus, "unfocused", _frame_unfocused, NULL);
+ evas_object_show(view);
+ _volume_view_pos_set();
+
+ g_ctrl_obj->volume_slider = view;
+ _controller_view_set(view_wrapper, view);
+ evas_object_show(view_wrapper);
+ }
+ }
+
+ return view_wrapper;
+}
+
+static void _volume_set_image(int level)
+{
+ int mapped_level;
+ DBG("******_volume_set_image level = %d *********",level);
+ if (!g_ctrl_obj) {
+ ERR("Ctrl Obj is not defined");
+ return;
+ }
+ if (level <= 1)
+ mapped_level = 0;
+
+ else if (level > 1 && level <= 9)
+ mapped_level = 1;
+
+ else
+ mapped_level = 2;
+ if (g_ctrl_obj->level_before != mapped_level) {
+ char buf[128] = {0,};
+ Evas_Object *view;
+
+ view = _controller_view_get();
+ snprintf(buf, sizeof(buf) - 1, "icon.state.%d", mapped_level);
+ elm_object_signal_emit(view, buf, "prog");
+ g_ctrl_obj->level_before = mapped_level;
+ }
+}
+
+static void _slider_vg_resize_cb(void *data , Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Coord w, h;
+ Efl_VG *shape = data;
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+ double radius = w > h ? h/2.0 : w/2.0;
+ evas_vg_shape_reset(shape);
+ evas_vg_shape_append_rect(shape, 0, 0, w, h, radius, radius);
+}
+
+static Evas_Object* _slider_vg_object_create(Evas_Object *parent, int r, int g, int b, int a)
+{
+ Evas_Object *vg = evas_object_vg_add(evas_object_evas_get(parent));
+ if(vg == NULL)
+ {
+ ERR("Failed to create vg object, volume slider might not work properly");
+ return NULL;
+ }
+ Efl_VG *root = evas_vg_container_add(vg);
+ evas_object_vg_root_node_set(vg, root);
+ Efl_VG *shape = evas_vg_shape_add(root);
+ if(shape == NULL)
+ {
+ evas_object_del(vg);
+ ERR("Failed to create vg shape object, volume slider might not work properly");
+ return NULL;
+ }
+ evas_vg_node_color_set(shape, r, g, b, a);
+ evas_object_event_callback_add(vg, EVAS_CALLBACK_RESIZE, _slider_vg_resize_cb, shape);
+ return vg;
+}
+
+static void _add_slider_vg_object(Evas_Object *slider)
+{
+ Evas_Object *vg_base = _slider_vg_object_create(slider, 255, 255, 255, 255);
+ if(vg_base == NULL)
+ {
+ ERR("Failed to create base vg object for slider");
+ }
+ elm_object_part_content_set(slider, "base", vg_base);
+
+ Evas_Object *vg_level = _slider_vg_object_create(slider, 10, 14, 74, 255);
+ if(vg_level == NULL)
+ {
+ ERR("Failed to create level vg object for slider");
+ }
+ elm_object_part_content_set(slider, "level", vg_level);
+
+ Evas_Object *vg_level2 = _slider_vg_object_create(slider, 10, 14, 74, 255);
+ if(vg_level2 == NULL)
+ {
+ ERR("Failed to create level2 vg object for slider");
+ }
+ elm_object_part_content_set(slider, "level2", vg_level2);
+}
+
+static void _volume_set_slider(void)
+{
+ DBG("****** _volume_set_slider ******");
+ int value = 0;
+ Evas_Object *slider = NULL;
+ Evas_Object *old_obj = NULL;
+ volume_ctrl_obj *ctrl_obj = g_ctrl_obj;
+ Evas_Object *view = _controller_view_get();
+ retif(ctrl_obj == NULL, , "Invalid parameter!");
+ retif(view == NULL, , "Invalid parameter!");
+
+ old_obj = _check_duplicated_loading(view, "elm.swallow.slider.volume");
+
+ if (old_obj == NULL) {
+ slider = elm_slider_add(view);
+
+ if (slider != NULL) {
+ elm_object_style_set(slider, "quickpanel_style");
+ _add_slider_vg_object(slider);
+ elm_slider_min_max_set(slider, ctrl_obj->min_level, ctrl_obj->max_level);
+ evas_object_smart_callback_add(slider, "changed", _volume_ctrl_slider_changed_cb, ctrl_obj);
+ evas_object_smart_callback_add(slider, "slider,drag,start", _volume_slider_drag_start_cb, ctrl_obj);
+ evas_object_smart_callback_add(slider, "slider,drag,stop", _volume_slider_drag_stop_cb, ctrl_obj);
+ elm_object_part_content_set(view, "elm.swallow.slider.volume", slider);
+ } else {
+ ERR("failed to create slider");
+ return;
+ }
+ } else {
+ slider = old_obj;
+ }
+
+ elm_slider_indicator_format_set(slider, NULL);
+ elm_slider_indicator_format_function_set(slider, NULL, NULL);
+ elm_slider_indicator_show_set(slider, EINA_FALSE);
+
+#ifdef QP_SCREENREADER_ENABLE
+ _set_slider_accessiblity_state(slider);
+#endif
+
+ value = _volume_get_level();
+ elm_slider_value_set(slider, value);
+ _volume_set_image(value);
+}
+
+static void _focus_pair_set()
+{
+ volume_ctrl_obj *ctrl_obj = g_ctrl_obj;
+ Evas_Object *focus = NULL;
+ Evas_Object *slider = NULL;
+ Evas_Object *view = _controller_view_get();
+ retif(ctrl_obj == NULL, , "Invalid parameter!");
+ retif(view == NULL, , "Invalid parameter!");
+
+ focus = elm_object_part_content_get(view, "focus");
+ slider = elm_object_part_content_get(view, "elm.swallow.slider.volume");
+
+ if (focus != NULL && slider != NULL) {
+ /* focus */
+ elm_object_focus_next_object_set(focus, slider, ELM_FOCUS_RIGHT);
+ elm_object_focus_next_object_set(focus, slider, ELM_FOCUS_DOWN);
+
+ /* slider */
+ elm_object_focus_next_object_set(slider, focus, ELM_FOCUS_LEFT);
+ elm_object_focus_next_object_set(slider, focus, ELM_FOCUS_UP);
+ }
+}
+
+static void _volume_view_update(void)
+{
+ DBG("****** _volume_view_update ********");
+ _volume_set_slider();
+ _focus_pair_set();
+}
+
+static void _volume_add(volume_ctrl_obj *ctrl_obj, void *data)
+{
+ struct appdata *ad = data;
+ retif(!ad, , "list is NULL");
+ retif(!ad->list, , "list is NULL");
+ retif(ctrl_obj == NULL, , "ctrl_obj is null");
+ retif(ctrl_obj->viewer != NULL, , "viewer is already created");
+
+ ctrl_obj->viewer = _volume_view_create(ad->list);
+ ctrl_obj->data = data;
+
+ _volume_set_image(VOLUME_MIN);
+ _refresh(ad);
+}
+
+static void _volume_remove(volume_ctrl_obj *ctrl_obj, void *data)
+{
+ struct appdata *ad = data;
+ retif(ad == NULL, , "list is NULL");
+ retif(ad->list == NULL, , "list is NULL");
+
+ if (g_ctrl_obj != NULL) {
+ if (g_ctrl_obj->viewer != NULL) {
+ quickpanel_list_util_item_unpack_by_object(ad->list
+ , g_ctrl_obj->viewer, 0, 0);
+ quickpanel_list_util_del_item_type(g_ctrl_obj->viewer);
+ evas_object_del(g_ctrl_obj->viewer);
+ g_ctrl_obj->viewer = NULL;
+ }
+ DBG("volume controller is removed");
+ free(g_ctrl_obj);
+ g_ctrl_obj = NULL;
+ }
+}
+
+static void _volume_create(void *data)
+{
+ if (g_ctrl_obj == NULL) {
+ g_ctrl_obj = (volume_ctrl_obj *)calloc(1, sizeof(volume_ctrl_obj));
+ if (g_ctrl_obj != NULL) {
+ g_ctrl_obj->min_level = 1;
+ g_ctrl_obj->max_level = 15;
+ g_ctrl_obj->last_requested_level = _volume_get_level();
+
+ _volume_add(g_ctrl_obj, data);
+ _volume_view_update();
+
+ g_ctrl_obj->volume_slider = NULL;
+
+ DBG("volume controller is created");
+ }
+ }
+}
+
+static void _volume_destroy(void *data)
+{
+ if (g_ctrl_obj != NULL) {
+ _volume_remove(g_ctrl_obj, data);
+
+ DBG("volume controller is removed");
+ }
+
+ g_ctrl_obj = NULL;
+}
+
+static int _init(void *data)
+{
+ DBG("************ volume.c init() **********");
+ retif(data == NULL, QP_FAIL, "Invalid parameter!");
+
+#ifdef QP_EMERGENCY_MODE_ENABLE
+ if (quickpanel_emergency_mode_is_on())
+ return QP_OK;
+
+#endif
+ DBG("*********** volume_create() calling ******");
+ _volume_create(data);
+
+ return QP_OK;
+}
+
+static int _fini(void *data)
+{
+ retif(data == NULL, QP_FAIL, "Invalid parameter!");
+
+ _volume_destroy(data);
+
+ return QP_OK;
+}
+
+static void _lang_changed(void *data)
+{
+ retif(data == NULL, , "Invalid parameter!");
+
+ if (g_ctrl_obj != NULL && g_ctrl_obj->viewer != NULL)
+ _volume_view_update();
+
+}
+
+static void _qp_opened(void *data)
+{
+ Evas_Object *slider = NULL;
+ Evas_Object *view = _controller_view_get();
+ retif(g_ctrl_obj == NULL, , "Invalid parameter!");
+ retif(view == NULL, , "Invalid parameter!");
+
+ if (view != NULL) {
+ _volume_view_update();
+ slider = elm_object_part_content_get(view, "elm.swallow.slider.volume");
+ }
+}
+
+static void _qp_closed(void *data)
+{
+ retif(g_ctrl_obj == NULL, , "Invalid parameter!");
+
+ if (g_ctrl_obj->viewer != NULL)
+ _volume_view_update();
+
+}
+
+static void _refresh(void *data)
+{
+ int h = 0;
+ struct appdata *ad = data;
+ Evas_Object *view = _controller_view_get();
+ retif(ad == NULL, , "Invalid parameter!");
+ retif(g_ctrl_obj == NULL, , "Invalid parameter!");
+ retif(g_ctrl_obj->viewer == NULL, , "Invalid parameter!");
+ retif(view == NULL, , "Invalid parameter!");
+
+ evas_object_geometry_get(g_ctrl_obj->viewer, NULL, NULL, NULL, &h);
+
+ if (ad->angle == 90 || ad->angle == 270) {
+ evas_object_resize(g_ctrl_obj->viewer, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);
+ evas_object_resize(view, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);
+ _volume_view_pos_set();
+
+ } else {
+ evas_object_resize(g_ctrl_obj->viewer, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);
+ evas_object_resize(view, SLIDER_LAYOUT_WIDTH, SLIDER_LAYOUT_HEIGHT);
+ _volume_view_pos_set();
+ }
+}