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 bundle *volume_bundle;
43 Eina_Bool is_deleting;
44 Eina_Bool is_launching;
46 Eina_Bool is_warning_visible;
49 Eina_Bool safety_limit;
54 int time_for_safety_limit;
56 sound_type_e sound_type_at_show;
58 static struct _control_s_info control_info = {
59 .volume_bundle = NULL,
61 .is_deleting = EINA_FALSE,
62 .is_launching = EINA_FALSE,
64 .is_warning_visible = EINA_FALSE,
65 .reset_once = EINA_FALSE,
66 .show_once = EINA_FALSE,
67 .safety_limit = EINA_TRUE,
72 .time_for_safety_limit = 0,
74 .sound_type_at_show = SOUND_TYPE_RINGTONE,
77 static void _notify_pm_lcdoff_cb(keynode_t * node, void *data);
78 static void _idle_lock_state_vconf_changed_cb(keynode_t *key, void *data);
79 static void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data);
80 static void _control_set_window_rotation(Evas_Object *win);
81 static void _rotate_changed_cb(void *data, Evas_Object *obj, void *event_info);
82 static void _volume_service_region_set(Evas_Object *win, Evas_Object *warning_popup);
84 bundle* volume_control_reset_get_bundle(void)
86 return control_info.volume_bundle;
89 Eina_Bool volume_control_get_is_deleting(void)
91 return control_info.is_deleting;
94 Eina_Bool volume_control_get_is_launching(void)
96 return control_info.is_launching;
99 int volume_control_get_current_angle(void)
101 return control_info.current_angle;
104 sound_type_e volume_control_get_sound_type_at_show(void)
106 return control_info.sound_type_at_show;
109 int volume_control_get_viewport_height(void)
111 return control_info.viewport_height;
114 int volume_control_get_viewport_width(void)
116 return control_info.viewport_width;
119 Eina_Bool volume_control_get_safety_limit(void)
121 return control_info.safety_limit;
124 void volume_control_set_safety_limit(Eina_Bool limit)
126 control_info.safety_limit = limit;
129 void volume_control_set_time_for_safety_limit(void)
135 localtime_r(&raw_time, &time_info);
136 _D("Current time [%d] %d:%d-%d", time_info.tm_mday, time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
138 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;
141 Eina_Bool volume_control_get_time_for_safety_limit(void)
149 localtime_r(&raw_time, &time_info);
150 _D("Current time [%d] %d:%d-%d", time_info.tm_mday, time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
152 convert_sec = time_info.tm_mday * 3600 * 24 + time_info.tm_hour * 3600 + time_info.tm_min * 60 + time_info.tm_sec;
154 diff = convert_sec - control_info.time_for_safety_limit;
155 _D("%d hour is passed after checking warning popup", diff);
157 return diff >= 20 * 3600 ? EINA_TRUE : EINA_FALSE;
160 Eina_Bool volume_control_viewport_is_warning_visible(void)
162 return control_info.is_warning_visible;
165 volume_error_e volume_control_cache_flush(void)
167 Evas_Object *win = volume_view_win_get();
168 retv_if(win == NULL, VOLUME_ERROR_FAIL);
172 int collection_cache = -1;
173 int image_cache = -1;
176 evas = evas_object_evas_get(win);
177 retv_if(!evas, VOLUME_ERROR_FAIL);
179 file_cache = edje_file_cache_get();
180 collection_cache = edje_collection_cache_get();
181 image_cache = evas_image_cache_get(evas);
182 font_cache = evas_font_cache_get(evas);
184 edje_file_cache_set(file_cache);
185 edje_collection_cache_set(collection_cache);
186 evas_image_cache_set(evas, 0);
187 evas_font_cache_set(evas, 0);
189 evas_image_cache_flush(evas);
190 evas_render_idle_flush(evas);
191 evas_font_cache_flush(evas);
193 edje_file_cache_flush();
194 edje_collection_cache_flush();
196 edje_file_cache_set(file_cache);
197 edje_collection_cache_set(collection_cache);
198 evas_image_cache_set(evas, image_cache);
199 evas_font_cache_set(evas, font_cache);
201 return VOLUME_ERROR_OK;
204 /* rotation event callback func. */
205 volume_error_e volume_control_app_launch_with_bundle(const char *op_type, const char *operation, const char *pkgname)
207 app_control_h app_control;
210 ret = app_control_create(&app_control);
212 _E("Failed to create app control");
213 return VOLUME_ERROR_FAIL;
216 ret = app_control_set_app_id(app_control, pkgname);
219 _E("Failed to set appid");
220 app_control_destroy(app_control);
221 return VOLUME_ERROR_FAIL;
224 ret = app_control_add_extra_data(app_control, op_type, operation);
227 _E("Failed to add extra data");
228 app_control_destroy(app_control);
229 return VOLUME_ERROR_FAIL;
232 ret = app_control_send_launch_request(app_control, NULL, NULL);
233 _D("launch app with service : [%s][%d]", pkgname, ret);
235 app_control_destroy(app_control);
237 return VOLUME_ERROR_OK;
240 int volume_control_get_vconf_idlelock(void)
242 int lock = IDLELOCK_OFF;
243 int pm_state = VCONFKEY_PM_STATE_NORMAL;
245 /* Check Idle-Lock */
246 if(vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) < 0)
248 _E("Failed to get vconfkey : VCONFKEY_IDLE_LOCK_STATE");
249 return IDLELOCK_ERROR;
251 _D("idlelock vconf : %d", lock);
254 if(vconf_get_int(VCONFKEY_PM_STATE, &pm_state) < 0)
256 _E("Failed to get vconfkey : VCONFKEY_PM_STATE");
257 return IDLELOCK_ERROR;
259 _D("PM STATE vconf : %d", pm_state);
261 return (lock == VCONFKEY_IDLE_LOCK ||
262 pm_state == VCONFKEY_PM_STATE_LCDOFF ||
263 pm_state == VCONFKEY_PM_STATE_SLEEP
264 ) ? IDLELOCK_ON : IDLELOCK_OFF;
267 int volume_control_check_status(int *lock, sound_type_e *sound_type)
269 *lock = volume_control_get_vconf_idlelock();
270 *sound_type = volume_sound_sound_manager_type_get();
272 _D("lock : %d / sound_type : %d", *lock, *sound_type);
274 if (*lock == IDLELOCK_ON)
276 if (*sound_type == SOUND_TYPE_RINGTONE)
278 _D("IDLELOCK is ON / sound type is Ringtone");
279 return LOCK_AND_NOT_MEDIA;
282 if (*sound_type != SOUND_TYPE_RINGTONE)
284 _D("IDLELOCK is ON / sound type is not Ringtone(media or alaram)");
285 return LOCK_AND_MEDIA;
289 _D("IDLELOCK is OFF / normal case");
291 return UNLOCK_STATUS;
294 static Eina_Bool _volume_region_set_timer_cb(void *data)
296 Evas_Object *win = data;
298 _volume_service_region_set(win, volume_view_warning_popup_get());
303 Eina_Bool volume_control_show_view(int status, sound_type_e sound_type, int sound, bool bt_opened, int earphone_connected)
305 _D("Volume control show");
306 Evas_Object *win = NULL;
310 retv_if(control_info.is_deleting, EINA_FALSE);
312 control_info.is_new = EINA_TRUE;
314 win = volume_view_win_get();
315 retv_if(!win, EINA_FALSE);
317 control_info.sound_type_at_show = sound_type;
319 if (status == LOCK_AND_NOT_MEDIA) {
320 _D("Lock and Not Media");
321 if (evas_object_visible_get(win)) {
322 if (VOLUME_ERROR_OK != volume_control_hide_view()) {
323 _E("Failed to close volume");
326 if (VOLUME_ERROR_OK != volume_control_cache_flush()) {
327 _E("Failed to flush cache");
332 if (status == LOCK_AND_MEDIA) {
333 _D("LOCK_AND_MEDIA");
336 if (VOLUME_ERROR_OK != volume_view_change_slider_by_type(sound_type, bt_opened, earphone_connected)) {
337 _E("Failed to changed max volume");
340 if(VOLUME_ERROR_OK != volume_view_window_show(sound_type)) {
341 _E("Failed to show volume window");
343 ecore_timer_add(0.1f, _volume_region_set_timer_cb, win);
345 control_info.is_launching = EINA_TRUE;
347 if (bt_opened == 1 && sound_type == SOUND_TYPE_CALL) {
348 volume = bt_get_bt_volume();
350 volume = volume_sound_sound_manager_volume_get(sound_type);
351 _D("volume value: %d", volume);
352 vibration = volume_sound_vconf_status_get(TYPE_VCONF_VIBRATION_STATUS);
353 _D("vibration : %d", vibration);
355 if(((vibration == 1 && sound == 0) || sound == 0) && sound_type == SOUND_TYPE_RINGTONE) {
359 if(VOLUME_ERROR_OK != volume_view_slider_value_set(volume)) {
360 _E("Failed to set volume value to slider");
362 volume_view_volume_icon_set(sound_type, sound, vibration, bt_opened);
370 volume_error_e volume_control_close_bt_display(void)
372 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
374 _D("Start closing bt display");
376 control_info.is_deleting = EINA_TRUE;
379 if (VOLUME_ERROR_OK != volume_view_window_hide()) {
380 _E("Failed to hide window");
383 control_info.is_deleting = EINA_FALSE;
385 _D("End closing bt display");
386 volume_timer_del(TYPE_TIMER_BT);
391 volume_error_e volume_control_hide_view(void)
393 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
395 _D("Start closing volume view");
397 control_info.is_deleting = EINA_TRUE;
399 volume_timer_del(TYPE_TIMER_SU);
400 volume_timer_del(TYPE_TIMER_SD);
401 volume_timer_del(TYPE_TIMER_SLIDER);
402 volume_timer_del(TYPE_TIMER_POPUP);
403 volume_timer_del(TYPE_TIMER_WARNING_POPUP);
406 if (VOLUME_ERROR_OK != volume_view_window_hide()) {
407 _E("Failed to hide window");
410 control_info.is_deleting = EINA_FALSE;
411 control_info.is_launching = EINA_FALSE;
413 _D("End closing volume view");
418 void volume_control_register_vconfkey(void)
420 /* other app grab volume key => close volume */
421 if (vconf_notify_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb, NULL) != 0) {
422 _E("Failed to register callback function : VCONFKEY_STARTER_USE_VOLUME_KEY");
425 /* Lock screen status vconf changed callback */
426 if (vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb, NULL) != 0) {
427 _E("Failed to notify vconfkey : VCONFKEY_IDLE_LOCK_STATE");
430 if (vconf_notify_key_changed(VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb, NULL) != 0) {
431 _E("Failed to notify vconfkey : VCONFKEY_PM_LCDOFF_SOURCE");
435 void volume_control_unregister_vconfkey(void)
437 /* other app grab volume key => close volume */
438 if (vconf_ignore_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb) < 0) {
439 _E("Failed to ignore vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
442 /* Lock screen status vconf changed callback */
443 if (vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb) < 0) {
444 _E("Failed to ignore vconfkey : VCONFKEY_IDLE_LOCK_STATE");
447 if (vconf_ignore_key_changed
448 (VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb) != 0) {
449 _E("Fail vconf_ignore_key_changed : VCONFKEY_PM_LCDOFF_SOURCE");
453 volume_error_e volume_control_pause(void)
455 Evas_Object *win = volume_view_win_get();
456 retv_if(!win, VOLUME_ERROR_FAIL);
458 if (evas_object_visible_get(win)) {
459 if(VOLUME_ERROR_OK != volume_control_hide_view()) {
460 _E("Failed to close volume");
463 if (VOLUME_ERROR_OK != volume_control_cache_flush()) {
464 _E("Failed to flush cache");
468 return VOLUME_ERROR_OK;
471 volume_error_e volume_control_reset(bundle *b)
473 _D("Volume control reset");
474 Evas_Object *win = volume_view_win_get();
475 retv_if(!win, VOLUME_ERROR_FAIL);
477 int lock = IDLELOCK_ON;
482 int earphone_connected = 0;
483 bool bt_opened = false;
484 sound_type_e sound_type = 0;
485 const char *show_volume = NULL;
487 status = volume_control_check_status(&lock, &sound_type);
488 _D("status: %d, lock: %d, sound type : %d", status, lock, sound_type);
490 volume = volume_sound_sound_manager_volume_get(sound_type);
491 _D("volume : %d", volume);
493 sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);
494 _D("sound status : %d", sound);
496 error = bt_ag_is_sco_opened(&bt_opened);
497 if (error != BT_ERROR_NONE) {
498 _E("bt_ag_is_sco_opened return [%d]", error);
500 earphone_connected = earphone_get_earphone_is_connected();
501 _D("BT state %d, Earphone state: %d", bt_opened, earphone_connected);
503 show_volume = bundle_get_val(b, SHOWVOLUME);
504 retv_if(!show_volume, VOLUME_ERROR_FAIL);
506 if (!strncasecmp(show_volume, ISTRUE, strlen(ISTRUE))) {
507 _D("Bundle : %s", show_volume);
508 if (lock == IDLELOCK_OFF) {
510 volume_timer_add(3.0, TYPE_TIMER_POPUP);
511 volume_control_show_view(status, sound_type, sound, bt_opened, earphone_connected);
515 return VOLUME_ERROR_OK;
518 volume_error_e volume_control_initialize(void)
520 _D("Volume control initialize");
522 /* Create main window */
523 Evas_Object *win = volume_view_window_create();
524 retv_if(!win, VOLUME_ERROR_FAIL);
526 /* Create volume layout */
527 if(VOLUME_ERROR_OK != volume_view_layout_create(win)) {
528 _E("Failed to create volume layout");
529 return VOLUME_ERROR_FAIL;
532 elm_win_screen_size_get(win, NULL, NULL, &(control_info.viewport_width), &(control_info.viewport_height));
534 /* Set available rotations */
535 _control_set_window_rotation(win);
537 /* Register vconfkey changed callback
538 * : VCONFKEY_STARTER_USE_VOLUME_KEY
539 * : VCONFKEY_IDLE_LOCK_STATE
540 * : VCONFKEY_LOCKSCREEN_SVIEW_STATE
542 volume_control_register_vconfkey();
544 /* Register vconfkey changed callback
545 * : VCONFKEY_SETAPPL_SOUND_STATUS_BOOL
546 * : VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL
548 volume_sound_vconfkey_register();
550 /* Add key event handler */
551 volume_key_event_handler_add();
553 /* Register volume changed callback */
554 volume_sound_mm_sound_init();
556 /* BT initialize and register changed callback */
560 return VOLUME_ERROR_OK;
563 void volume_control_deinitialize(void)
565 /* Unregister earphone changed callback */
567 /* Unregister bt changed callback */
570 /* Unregister vconfkey changed callback */
571 volume_control_unregister_vconfkey();
573 /* Unregister sound vconfkey changed callback */
574 volume_sound_vconfkey_unregister();
578 static void _volume_service_region_set(Evas_Object *win, Evas_Object *warning_popup)
580 _D("X input event shape");
581 Evas_Object *ly = NULL;
583 tzsh_volume_service_h volume_service = NULL;
584 tzsh_region_h rect = NULL;
593 tzsh = volume_view_tzsh_get();
595 volume_service = volume_view_service_get();
596 ret_if(!volume_service);
598 int current_angle = volume_control_get_current_angle();
599 _D("Current angle : %d", current_angle);
601 if (!warning_popup) {
602 ly = volume_view_outer_layout_get();
604 _E("Failed to load edje");
608 edje_object_part_geometry_get(_EDJ(ly), "bg", &x, &y, &w, &h);
609 _D("The position of bg x: %d, y: %d, w: %d, h: %d", x, y, w, h);
611 if (current_angle == 90) {
622 else if (current_angle == 270) {
628 x = volume_control_get_viewport_width()-tmp_y-tmp_h;
640 rect = tzsh_region_create(tzsh);
642 tzsh_region_add(rect, x, y, w, h);
643 _D("shape x: %d, y: %d, w: %d, h: %d", x, y, w, h);
644 ret = tzsh_volume_service_content_region_set(volume_service, current_angle, rect);
645 _D("The result of volume region set is : %d", ret);
646 tzsh_region_destroy(rect);
649 static void _rotate_changed_cb(void *data, Evas_Object *obj, void *event_info)
651 static int current_angle = -1;
652 int changed_angle = elm_win_rotation_get(obj);
655 Evas_Object *ly_outer = volume_view_outer_layout_get();
658 _D("window rotated [%d] => [%d]", current_angle, changed_angle);
659 if(current_angle != changed_angle) {
660 current_angle = changed_angle;
661 control_info.current_angle = current_angle;
662 switch(current_angle){
665 _D("show,landscape");
666 elm_object_signal_emit(ly_outer, "show,landscape", "bg");
670 elm_object_signal_emit(ly_outer, "show,portrait", "bg");
674 _volume_service_region_set(obj, volume_view_warning_popup_get());
678 static void _control_set_window_rotation(Evas_Object *win)
682 if (elm_win_wm_rotation_supported_get(win)) {
683 const int rots[4] = { 0, 90, 180, 270 };
684 elm_win_wm_rotation_available_rotations_set(win, (const int *)&rots, 4);
685 _D("set available rotations");
688 /* rotation event callback */
689 evas_object_smart_callback_add(win, "wm,rotation,changed", _rotate_changed_cb, NULL);
691 /* initialize degree */
692 _rotate_changed_cb(NULL, win, NULL);
695 static void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data)
697 int ret = EINA_FALSE;
699 if(vconf_get_int(VCONFKEY_STARTER_USE_VOLUME_KEY, &ret) < 0)
701 _E("Failed to get vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
708 _D("any other App grab volume hard key");
709 if(VOLUME_ERROR_OK != volume_control_hide_view()) {
710 _E("Failed to close volume");
713 if(VOLUME_ERROR_OK != volume_control_cache_flush()) {
714 _E("Failed to flush cache");
717 if(vconf_set_int(VCONFKEY_STARTER_USE_VOLUME_KEY, 0) < 0) {
718 _E("Failed to get vconfkey : VCONFKEY_STATER_USE_VOLUME_KEY");
724 _D("setting App grab volume hard key");
728 static void _idle_lock_state_vconf_changed_cb(keynode_t *key, void *data)
730 int lock = VCONFKEY_IDLE_UNLOCK;
732 if(vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) < 0)
734 _E("Failed to get vconfkey : VCONFKEY_IDLE_LOCK_STATE");
737 _D("idle lock state : %d", lock);
739 if(lock == VCONFKEY_IDLE_LAUNCHING_LOCK)
741 if(VOLUME_ERROR_OK != volume_view_window_hide())
743 _E("Failed to hide window");
748 static void _notify_pm_lcdoff_cb(keynode_t * node, void *data)
750 if (volume_view_warning_popup_get()) {
751 volume_view_destroy_warning_popup();
754 if(VOLUME_ERROR_OK != volume_control_hide_view())
756 _E("Failed to close volume");
759 if(VOLUME_ERROR_OK != volume_control_cache_flush())
761 _E("Failed to flush cache");