2 * Copyright (c) 2009-2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <vconf-keys.h>
19 #include <app_manager.h>
20 #include <bluetooth.h>
21 #include <bluetooth_internal.h>
22 #include <bluetooth_extension.h>
23 #include <bundle_internal.h>
27 #include "_util_efl.h"
28 #include "_util_log.h"
33 #include "key_event.h"
36 #include "tzsh_volume_service.h"
38 #define VCONF_KEY_FMRADIO_RECORDING "memory/private/Sound/FMRadioRecording"
40 struct _control_s_info {
41 Eina_Bool is_deleting;
42 Eina_Bool is_launching;
44 Eina_Bool is_warning_visible;
47 Eina_Bool safety_limit;
52 int time_for_safety_limit;
54 sound_type_e sound_type_at_show;
56 static struct _control_s_info control_info = {
57 .is_deleting = EINA_FALSE,
58 .is_launching = EINA_FALSE,
60 .is_warning_visible = EINA_FALSE,
61 .reset_once = EINA_FALSE,
62 .show_once = EINA_FALSE,
63 .safety_limit = EINA_TRUE,
68 .time_for_safety_limit = 0,
70 .sound_type_at_show = SOUND_TYPE_RINGTONE,
73 static void _notify_pm_lcdoff_cb(keynode_t * node, void *data);
74 static void _idle_lock_state_vconf_changed_cb(keynode_t *key, void *data);
75 static void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data);
76 static void _control_set_window_rotation(Evas_Object *win);
77 static void _rotate_changed_cb(void *data, Evas_Object *obj, void *event_info);
78 static void _volume_service_region_set(Evas_Object *win, Evas_Object *warning_popup);
80 Eina_Bool volume_control_get_is_deleting(void)
82 return control_info.is_deleting;
85 Eina_Bool volume_control_get_is_launching(void)
87 return control_info.is_launching;
90 int volume_control_get_current_angle(void)
92 return control_info.current_angle;
95 sound_type_e volume_control_get_sound_type_at_show(void)
97 return control_info.sound_type_at_show;
100 int volume_control_get_viewport_height(void)
102 return control_info.viewport_height;
105 int volume_control_get_viewport_width(void)
107 return control_info.viewport_width;
110 Eina_Bool volume_control_get_safety_limit(void)
112 return control_info.safety_limit;
115 void volume_control_set_safety_limit(Eina_Bool limit)
117 control_info.safety_limit = limit;
120 void volume_control_set_time_for_safety_limit(void)
126 localtime_r(&raw_time, &time_info);
127 _D("Current time [%d] %d:%d-%d", time_info.tm_mday, time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
129 control_info.time_for_safety_limit = time_info.tm_mday * 3600 * 24 + time_info.tm_hour * 3600 + time_info.tm_min * 60 + time_info.tm_sec;
132 Eina_Bool volume_control_get_time_for_safety_limit(void)
140 localtime_r(&raw_time, &time_info);
141 _D("Current time [%d] %d:%d-%d", time_info.tm_mday, time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
143 convert_sec = time_info.tm_mday * 3600 * 24 + time_info.tm_hour * 3600 + time_info.tm_min * 60 + time_info.tm_sec;
145 diff = convert_sec - control_info.time_for_safety_limit;
146 _D("%d hour is passed after checking warning popup", diff);
148 return diff >= 20 * 3600 ? EINA_TRUE : EINA_FALSE;
151 Eina_Bool volume_control_viewport_is_warning_visible(void)
153 return control_info.is_warning_visible;
156 volume_error_e volume_control_cache_flush(void)
158 Evas_Object *win = volume_view_win_get();
159 retv_if(win == NULL, VOLUME_ERROR_FAIL);
163 int collection_cache = -1;
164 int image_cache = -1;
167 evas = evas_object_evas_get(win);
168 retv_if(!evas, VOLUME_ERROR_FAIL);
170 file_cache = edje_file_cache_get();
171 collection_cache = edje_collection_cache_get();
172 image_cache = evas_image_cache_get(evas);
173 font_cache = evas_font_cache_get(evas);
175 edje_file_cache_set(file_cache);
176 edje_collection_cache_set(collection_cache);
177 evas_image_cache_set(evas, 0);
178 evas_font_cache_set(evas, 0);
180 evas_image_cache_flush(evas);
181 evas_render_idle_flush(evas);
182 evas_font_cache_flush(evas);
184 edje_file_cache_flush();
185 edje_collection_cache_flush();
187 edje_file_cache_set(file_cache);
188 edje_collection_cache_set(collection_cache);
189 evas_image_cache_set(evas, image_cache);
190 evas_font_cache_set(evas, font_cache);
192 return VOLUME_ERROR_OK;
195 /* rotation event callback func. */
196 volume_error_e volume_control_app_launch_with_bundle(const char *op_type, const char *operation, const char *pkgname)
198 app_control_h app_control;
201 ret = app_control_create(&app_control);
203 _E("Failed to create app control");
204 return VOLUME_ERROR_FAIL;
207 ret = app_control_set_app_id(app_control, pkgname);
209 _E("Failed to set appid");
210 app_control_destroy(app_control);
211 return VOLUME_ERROR_FAIL;
214 ret = app_control_add_extra_data(app_control, op_type, operation);
216 _E("Failed to add extra data");
217 app_control_destroy(app_control);
218 return VOLUME_ERROR_FAIL;
221 ret = app_control_send_launch_request(app_control, NULL, NULL);
222 _D("launch app with service : [%s][%d]", pkgname, ret);
224 app_control_destroy(app_control);
226 return VOLUME_ERROR_OK;
229 int volume_control_get_vconf_idlelock(void)
231 int lock = IDLELOCK_OFF;
232 int pm_state = VCONFKEY_PM_STATE_NORMAL;
234 /* Check Idle-Lock */
235 if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) < 0) {
236 _E("Failed to get vconfkey : VCONFKEY_IDLE_LOCK_STATE");
237 return IDLELOCK_ERROR;
239 _D("idlelock vconf : %d", lock);
242 if (vconf_get_int(VCONFKEY_PM_STATE, &pm_state) < 0) {
243 _E("Failed to get vconfkey : VCONFKEY_PM_STATE");
244 return IDLELOCK_ERROR;
246 _D("PM STATE vconf : %d", pm_state);
248 return (lock == VCONFKEY_IDLE_LOCK ||
249 pm_state == VCONFKEY_PM_STATE_LCDOFF ||
250 pm_state == VCONFKEY_PM_STATE_SLEEP
251 ) ? IDLELOCK_ON : IDLELOCK_OFF;
254 int volume_control_check_status(int *lock, sound_type_e *sound_type)
256 *lock = volume_control_get_vconf_idlelock();
257 *sound_type = volume_sound_sound_manager_type_get();
259 _D("lock : %d / sound_type : %d", *lock, *sound_type);
261 if (*lock == IDLELOCK_ON) {
262 if (*sound_type == SOUND_TYPE_RINGTONE) {
263 _D("IDLELOCK is ON / sound type is Ringtone");
264 return LOCK_AND_NOT_MEDIA;
267 if (*sound_type != SOUND_TYPE_RINGTONE) {
268 _D("IDLELOCK is ON / sound type is not Ringtone(media or alaram)");
269 return LOCK_AND_MEDIA;
273 _D("IDLELOCK is OFF / normal case");
275 return UNLOCK_STATUS;
278 static Eina_Bool _volume_region_set_timer_cb(void *data)
280 Evas_Object *win = data;
282 _volume_service_region_set(win, volume_view_warning_popup_get());
287 Eina_Bool volume_control_show_view(int status, sound_type_e sound_type, int sound, bool bt_opened, int earphone_connected)
289 _D("Volume control show");
290 Evas_Object *win = NULL;
294 retv_if(control_info.is_deleting, EINA_FALSE);
296 control_info.is_new = EINA_TRUE;
298 win = volume_view_win_get();
299 retv_if(!win, EINA_FALSE);
301 control_info.sound_type_at_show = sound_type;
303 if (status == LOCK_AND_NOT_MEDIA) {
304 _D("Lock and Not Media");
305 if (evas_object_visible_get(win)) {
306 if (VOLUME_ERROR_OK != volume_control_hide_view())
307 _E("Failed to close volume");
309 if (VOLUME_ERROR_OK != volume_control_cache_flush())
310 _E("Failed to flush cache");
314 if (status == LOCK_AND_MEDIA) {
315 _D("LOCK_AND_MEDIA");
318 if (VOLUME_ERROR_OK != volume_view_change_slider_by_type(sound_type, bt_opened, earphone_connected))
319 _E("Failed to changed max volume");
321 if (VOLUME_ERROR_OK != volume_view_window_show(sound_type))
322 _E("Failed to show volume window");
324 ecore_timer_add(0.1f, _volume_region_set_timer_cb, win);
326 control_info.is_launching = EINA_TRUE;
328 if (bt_opened == 1 && sound_type == SOUND_TYPE_CALL)
329 volume = bt_get_bt_volume();
331 volume = volume_sound_sound_manager_volume_get(sound_type);
332 _D("volume value: %d", volume);
333 vibration = volume_sound_vconf_status_get(TYPE_VCONF_VIBRATION_STATUS);
334 _D("vibration : %d", vibration);
336 if ((vibration == 1 && sound == 0) && sound_type == SOUND_TYPE_RINGTONE)
339 if (VOLUME_ERROR_OK != volume_view_slider_value_set(volume))
340 _E("Failed to set volume value to slider");
342 volume_view_volume_icon_set(sound_type, sound, vibration, bt_opened);
343 volume_view_volume_icon_name_set_for_access(sound_type);
351 volume_error_e volume_control_close_bt_display(void)
353 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
355 _D("Start closing bt display");
357 control_info.is_deleting = EINA_TRUE;
360 if (VOLUME_ERROR_OK != volume_view_window_hide())
361 _E("Failed to hide window");
363 control_info.is_deleting = EINA_FALSE;
365 _D("End closing bt display");
366 volume_timer_del(TYPE_TIMER_BT);
371 volume_error_e volume_control_hide_view(void)
373 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
375 _D("Start closing volume view");
377 control_info.is_deleting = EINA_TRUE;
379 volume_timer_del(TYPE_TIMER_SU);
380 volume_timer_del(TYPE_TIMER_SD);
381 volume_timer_del(TYPE_TIMER_SLIDER);
382 volume_timer_del(TYPE_TIMER_POPUP);
383 volume_timer_del(TYPE_TIMER_WARNING_POPUP);
386 if (VOLUME_ERROR_OK != volume_view_window_hide())
387 _E("Failed to hide window");
389 control_info.is_deleting = EINA_FALSE;
390 control_info.is_launching = EINA_FALSE;
392 _D("End closing volume view");
397 void volume_control_register_vconfkey(void)
399 /* other app grab volume key => close volume */
400 if (vconf_notify_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb, NULL) != 0)
401 _E("Failed to register callback function : VCONFKEY_STARTER_USE_VOLUME_KEY");
403 /* Lock screen status vconf changed callback */
404 if (vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb, NULL) != 0)
405 _E("Failed to notify vconfkey : VCONFKEY_IDLE_LOCK_STATE");
407 if (vconf_notify_key_changed(VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb, NULL) != 0)
408 _E("Failed to notify vconfkey : VCONFKEY_PM_LCDOFF_SOURCE");
411 void volume_control_unregister_vconfkey(void)
413 /* other app grab volume key => close volume */
414 if (vconf_ignore_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb) < 0)
415 _E("Failed to ignore vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
417 /* Lock screen status vconf changed callback */
418 if (vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb) < 0)
419 _E("Failed to ignore vconfkey : VCONFKEY_IDLE_LOCK_STATE");
421 if (vconf_ignore_key_changed
422 (VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb) != 0) {
423 _E("Fail vconf_ignore_key_changed : VCONFKEY_PM_LCDOFF_SOURCE");
427 volume_error_e volume_control_pause(void)
429 Evas_Object *win = volume_view_win_get();
430 retv_if(!win, VOLUME_ERROR_FAIL);
432 if (evas_object_visible_get(win)) {
433 if (VOLUME_ERROR_OK != volume_control_hide_view())
434 _E("Failed to close volume");
436 if (VOLUME_ERROR_OK != volume_control_cache_flush())
437 _E("Failed to flush cache");
440 return VOLUME_ERROR_OK;
443 volume_error_e volume_control_reset(bundle *b)
445 _D("Volume control reset");
446 Evas_Object *win = volume_view_win_get();
447 retv_if(!win, VOLUME_ERROR_FAIL);
449 int lock = IDLELOCK_ON;
454 int earphone_connected = 0;
455 bool bt_opened = false;
456 sound_type_e sound_type = 0;
457 const char *show_volume = NULL;
459 status = volume_control_check_status(&lock, &sound_type);
460 _D("status: %d, lock: %d, sound type : %d", status, lock, sound_type);
462 volume = volume_sound_sound_manager_volume_get(sound_type);
463 _D("volume : %d", volume);
465 sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);
466 _D("sound status : %d", sound);
468 error = bt_ag_is_sco_opened(&bt_opened);
469 if (error != BT_ERROR_NONE)
470 _E("bt_ag_is_sco_opened return [%d]", error);
472 earphone_connected = earphone_get_earphone_is_connected();
473 _D("BT state %d, Earphone state: %d", bt_opened, earphone_connected);
475 show_volume = bundle_get_val(b, SHOWVOLUME);
476 retv_if(!show_volume, VOLUME_ERROR_FAIL);
478 if (!strncasecmp(show_volume, ISTRUE, strlen(ISTRUE))) {
479 _D("Bundle : %s", show_volume);
480 if (lock == IDLELOCK_OFF) {
482 volume_timer_add(3.0, TYPE_TIMER_POPUP);
483 volume_control_show_view(status, sound_type, sound, bt_opened, earphone_connected);
487 return VOLUME_ERROR_OK;
490 volume_error_e volume_control_initialize(void)
492 _D("Volume control initialize");
494 /* Create main window */
495 Evas_Object *win = volume_view_window_create();
496 retv_if(!win, VOLUME_ERROR_FAIL);
498 /* Create volume layout */
499 if (VOLUME_ERROR_OK != volume_view_layout_create(win)) {
500 _E("Failed to create volume layout");
501 return VOLUME_ERROR_FAIL;
504 elm_win_screen_size_get(win, NULL, NULL, &(control_info.viewport_width), &(control_info.viewport_height));
506 /* Set available rotations */
507 _control_set_window_rotation(win);
509 /* Register vconfkey changed callback
510 * : VCONFKEY_STARTER_USE_VOLUME_KEY
511 * : VCONFKEY_IDLE_LOCK_STATE
512 * : VCONFKEY_LOCKSCREEN_SVIEW_STATE
514 volume_control_register_vconfkey();
516 /* Register vconfkey changed callback
517 * : VCONFKEY_SETAPPL_SOUND_STATUS_BOOL
518 * : VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL
520 volume_sound_vconfkey_register();
522 /* Add key event handler */
523 volume_key_event_handler_add();
525 /* Register volume changed callback */
526 volume_sound_mm_sound_init();
528 /* BT initialize and register changed callback */
532 volume_view_accessible_create(win);
534 return VOLUME_ERROR_OK;
537 void volume_control_deinitialize(void)
539 /* Unregister earphone changed callback */
541 /* Unregister bt changed callback */
544 /* Unregister vconfkey changed callback */
545 volume_control_unregister_vconfkey();
547 /* Unregister sound vconfkey changed callback */
548 volume_sound_vconfkey_unregister();
552 static void _volume_service_region_set(Evas_Object *win, Evas_Object *warning_popup)
554 _D("X input event shape");
555 Evas_Object *ly = NULL;
557 tzsh_volume_service_h volume_service = NULL;
558 tzsh_region_h rect = NULL;
567 tzsh = volume_view_tzsh_get();
569 volume_service = volume_view_service_get();
570 ret_if(!volume_service);
572 int current_angle = volume_control_get_current_angle();
573 _D("Current angle : %d", current_angle);
575 if (!warning_popup) {
576 ly = volume_view_outer_layout_get();
578 _E("Failed to load edje");
582 edje_object_part_geometry_get(_EDJ(ly), "bg", &x, &y, &w, &h);
583 _D("The position of bg x: %d, y: %d, w: %d, h: %d", x, y, w, h);
585 if (current_angle == 90) {
595 } else if (current_angle == 270) {
601 x = volume_control_get_viewport_width()-tmp_y-tmp_h;
613 rect = tzsh_region_create(tzsh);
615 tzsh_region_add(rect, x, y, w, h);
616 _D("shape x: %d, y: %d, w: %d, h: %d", x, y, w, h);
617 //ret = tzsh_volume_service_content_region_set(volume_service, current_angle, rect);
618 _D("The result of volume region set is : %d", ret);
619 tzsh_region_destroy(rect);
622 static void _rotate_changed_cb(void *data, Evas_Object *obj, void *event_info)
624 static int current_angle = -1;
625 int changed_angle = elm_win_rotation_get(obj);
628 Evas_Object *ly_outer = volume_view_outer_layout_get();
631 _D("window rotated [%d] => [%d]", current_angle, changed_angle);
632 if (current_angle != changed_angle) {
633 current_angle = changed_angle;
634 control_info.current_angle = current_angle;
635 switch (current_angle) {
638 _D("show,landscape");
639 elm_object_signal_emit(ly_outer, "show,landscape", "bg");
643 elm_object_signal_emit(ly_outer, "show,portrait", "bg");
647 _volume_service_region_set(obj, volume_view_warning_popup_get());
651 static void _control_set_window_rotation(Evas_Object *win)
655 if (elm_win_wm_rotation_supported_get(win)) {
656 const int rots[4] = { 0, 90, 180, 270 };
657 elm_win_wm_rotation_available_rotations_set(win, (const int *)&rots, 4);
658 _D("set available rotations");
661 /* rotation event callback */
662 evas_object_smart_callback_add(win, "wm,rotation,changed", _rotate_changed_cb, NULL);
664 /* initialize degree */
665 _rotate_changed_cb(NULL, win, NULL);
668 static void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data)
670 int ret = EINA_FALSE;
672 if (vconf_get_int(VCONFKEY_STARTER_USE_VOLUME_KEY, &ret) < 0) {
673 _E("Failed to get vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
679 _D("any other App grab volume hard key");
680 if (VOLUME_ERROR_OK != volume_control_hide_view()) {
681 _E("Failed to close volume");
684 if (VOLUME_ERROR_OK != volume_control_cache_flush()) {
685 _E("Failed to flush cache");
688 if (vconf_set_int(VCONFKEY_STARTER_USE_VOLUME_KEY, 0) < 0) {
689 _E("Failed to get vconfkey : VCONFKEY_STATER_USE_VOLUME_KEY");
692 } else if (ret == 2) {
693 _D("setting App grab volume hard key");
697 static void _idle_lock_state_vconf_changed_cb(keynode_t *key, void *data)
699 int lock = VCONFKEY_IDLE_UNLOCK;
701 if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) < 0) {
702 _E("Failed to get vconfkey : VCONFKEY_IDLE_LOCK_STATE");
705 _D("idle lock state : %d", lock);
707 if (lock == VCONFKEY_IDLE_LAUNCHING_LOCK) {
708 if (VOLUME_ERROR_OK != volume_view_window_hide())
709 _E("Failed to hide window");
713 static void _notify_pm_lcdoff_cb(keynode_t * node, void *data)
715 if (volume_view_warning_popup_get())
716 volume_view_destroy_warning_popup();
718 if (VOLUME_ERROR_OK != volume_control_hide_view())
719 _E("Failed to close volume");
721 if (VOLUME_ERROR_OK != volume_control_cache_flush())
722 _E("Failed to flush cache");