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(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);
363 volume_view_volume_icon_name_set_for_access(sound_type);
371 volume_error_e volume_control_close_bt_display(void)
373 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
375 _D("Start closing bt display");
377 control_info.is_deleting = EINA_TRUE;
380 if (VOLUME_ERROR_OK != volume_view_window_hide()) {
381 _E("Failed to hide window");
384 control_info.is_deleting = EINA_FALSE;
386 _D("End closing bt display");
387 volume_timer_del(TYPE_TIMER_BT);
392 volume_error_e volume_control_hide_view(void)
394 retv_if(volume_control_get_is_deleting(), VOLUME_ERROR_FAIL);
396 _D("Start closing volume view");
398 control_info.is_deleting = EINA_TRUE;
400 volume_timer_del(TYPE_TIMER_SU);
401 volume_timer_del(TYPE_TIMER_SD);
402 volume_timer_del(TYPE_TIMER_SLIDER);
403 volume_timer_del(TYPE_TIMER_POPUP);
404 volume_timer_del(TYPE_TIMER_WARNING_POPUP);
407 if (VOLUME_ERROR_OK != volume_view_window_hide()) {
408 _E("Failed to hide window");
411 control_info.is_deleting = EINA_FALSE;
412 control_info.is_launching = EINA_FALSE;
414 _D("End closing volume view");
419 void volume_control_register_vconfkey(void)
421 /* other app grab volume key => close volume */
422 if (vconf_notify_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb, NULL) != 0) {
423 _E("Failed to register callback function : VCONFKEY_STARTER_USE_VOLUME_KEY");
426 /* Lock screen status vconf changed callback */
427 if (vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb, NULL) != 0) {
428 _E("Failed to notify vconfkey : VCONFKEY_IDLE_LOCK_STATE");
431 if (vconf_notify_key_changed(VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb, NULL) != 0) {
432 _E("Failed to notify vconfkey : VCONFKEY_PM_LCDOFF_SOURCE");
436 void volume_control_unregister_vconfkey(void)
438 /* other app grab volume key => close volume */
439 if (vconf_ignore_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY, _starter_user_volume_key_vconf_changed_cb) < 0) {
440 _E("Failed to ignore vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
443 /* Lock screen status vconf changed callback */
444 if (vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE, _idle_lock_state_vconf_changed_cb) < 0) {
445 _E("Failed to ignore vconfkey : VCONFKEY_IDLE_LOCK_STATE");
448 if (vconf_ignore_key_changed
449 (VCONFKEY_PM_LCDOFF_SOURCE, _notify_pm_lcdoff_cb) != 0) {
450 _E("Fail vconf_ignore_key_changed : VCONFKEY_PM_LCDOFF_SOURCE");
454 volume_error_e volume_control_pause(void)
456 Evas_Object *win = volume_view_win_get();
457 retv_if(!win, VOLUME_ERROR_FAIL);
459 if (evas_object_visible_get(win)) {
460 if(VOLUME_ERROR_OK != volume_control_hide_view()) {
461 _E("Failed to close volume");
464 if (VOLUME_ERROR_OK != volume_control_cache_flush()) {
465 _E("Failed to flush cache");
469 return VOLUME_ERROR_OK;
472 volume_error_e volume_control_reset(bundle *b)
474 _D("Volume control reset");
475 Evas_Object *win = volume_view_win_get();
476 retv_if(!win, VOLUME_ERROR_FAIL);
478 int lock = IDLELOCK_ON;
483 int earphone_connected = 0;
484 bool bt_opened = false;
485 sound_type_e sound_type = 0;
486 const char *show_volume = NULL;
488 status = volume_control_check_status(&lock, &sound_type);
489 _D("status: %d, lock: %d, sound type : %d", status, lock, sound_type);
491 volume = volume_sound_sound_manager_volume_get(sound_type);
492 _D("volume : %d", volume);
494 sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);
495 _D("sound status : %d", sound);
497 error = bt_ag_is_sco_opened(&bt_opened);
498 if (error != BT_ERROR_NONE) {
499 _E("bt_ag_is_sco_opened return [%d]", error);
501 earphone_connected = earphone_get_earphone_is_connected();
502 _D("BT state %d, Earphone state: %d", bt_opened, earphone_connected);
504 show_volume = bundle_get_val(b, SHOWVOLUME);
505 retv_if(!show_volume, VOLUME_ERROR_FAIL);
507 if (!strncasecmp(show_volume, ISTRUE, strlen(ISTRUE))) {
508 _D("Bundle : %s", show_volume);
509 if (lock == IDLELOCK_OFF) {
511 volume_timer_add(3.0, TYPE_TIMER_POPUP);
512 volume_control_show_view(status, sound_type, sound, bt_opened, earphone_connected);
516 return VOLUME_ERROR_OK;
519 volume_error_e volume_control_initialize(void)
521 _D("Volume control initialize");
523 /* Create main window */
524 Evas_Object *win = volume_view_window_create();
525 retv_if(!win, VOLUME_ERROR_FAIL);
527 /* Create volume layout */
528 if(VOLUME_ERROR_OK != volume_view_layout_create(win)) {
529 _E("Failed to create volume layout");
530 return VOLUME_ERROR_FAIL;
533 elm_win_screen_size_get(win, NULL, NULL, &(control_info.viewport_width), &(control_info.viewport_height));
535 /* Set available rotations */
536 _control_set_window_rotation(win);
538 /* Register vconfkey changed callback
539 * : VCONFKEY_STARTER_USE_VOLUME_KEY
540 * : VCONFKEY_IDLE_LOCK_STATE
541 * : VCONFKEY_LOCKSCREEN_SVIEW_STATE
543 volume_control_register_vconfkey();
545 /* Register vconfkey changed callback
546 * : VCONFKEY_SETAPPL_SOUND_STATUS_BOOL
547 * : VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL
549 volume_sound_vconfkey_register();
551 /* Add key event handler */
552 volume_key_event_handler_add();
554 /* Register volume changed callback */
555 volume_sound_mm_sound_init();
557 /* BT initialize and register changed callback */
561 volume_view_accessible_create(win);
563 return VOLUME_ERROR_OK;
566 void volume_control_deinitialize(void)
568 /* Unregister earphone changed callback */
570 /* Unregister bt changed callback */
573 /* Unregister vconfkey changed callback */
574 volume_control_unregister_vconfkey();
576 /* Unregister sound vconfkey changed callback */
577 volume_sound_vconfkey_unregister();
581 static void _volume_service_region_set(Evas_Object *win, Evas_Object *warning_popup)
583 _D("X input event shape");
584 Evas_Object *ly = NULL;
586 tzsh_volume_service_h volume_service = NULL;
587 tzsh_region_h rect = NULL;
596 tzsh = volume_view_tzsh_get();
598 volume_service = volume_view_service_get();
599 ret_if(!volume_service);
601 int current_angle = volume_control_get_current_angle();
602 _D("Current angle : %d", current_angle);
604 if (!warning_popup) {
605 ly = volume_view_outer_layout_get();
607 _E("Failed to load edje");
611 edje_object_part_geometry_get(_EDJ(ly), "bg", &x, &y, &w, &h);
612 _D("The position of bg x: %d, y: %d, w: %d, h: %d", x, y, w, h);
614 if (current_angle == 90) {
625 else if (current_angle == 270) {
631 x = volume_control_get_viewport_width()-tmp_y-tmp_h;
643 rect = tzsh_region_create(tzsh);
645 tzsh_region_add(rect, x, y, w, h);
646 _D("shape x: %d, y: %d, w: %d, h: %d", x, y, w, h);
647 //ret = tzsh_volume_service_content_region_set(volume_service, current_angle, rect);
648 _D("The result of volume region set is : %d", ret);
649 tzsh_region_destroy(rect);
652 static void _rotate_changed_cb(void *data, Evas_Object *obj, void *event_info)
654 static int current_angle = -1;
655 int changed_angle = elm_win_rotation_get(obj);
658 Evas_Object *ly_outer = volume_view_outer_layout_get();
661 _D("window rotated [%d] => [%d]", current_angle, changed_angle);
662 if(current_angle != changed_angle) {
663 current_angle = changed_angle;
664 control_info.current_angle = current_angle;
665 switch(current_angle){
668 _D("show,landscape");
669 elm_object_signal_emit(ly_outer, "show,landscape", "bg");
673 elm_object_signal_emit(ly_outer, "show,portrait", "bg");
677 _volume_service_region_set(obj, volume_view_warning_popup_get());
681 static void _control_set_window_rotation(Evas_Object *win)
685 if (elm_win_wm_rotation_supported_get(win)) {
686 const int rots[4] = { 0, 90, 180, 270 };
687 elm_win_wm_rotation_available_rotations_set(win, (const int *)&rots, 4);
688 _D("set available rotations");
691 /* rotation event callback */
692 evas_object_smart_callback_add(win, "wm,rotation,changed", _rotate_changed_cb, NULL);
694 /* initialize degree */
695 _rotate_changed_cb(NULL, win, NULL);
698 static void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data)
700 int ret = EINA_FALSE;
702 if(vconf_get_int(VCONFKEY_STARTER_USE_VOLUME_KEY, &ret) < 0)
704 _E("Failed to get vconfkey : VCONFKEY_STARTER_USE_VOLUME_KEY");
711 _D("any other App grab volume hard key");
712 if(VOLUME_ERROR_OK != volume_control_hide_view()) {
713 _E("Failed to close volume");
716 if(VOLUME_ERROR_OK != volume_control_cache_flush()) {
717 _E("Failed to flush cache");
720 if(vconf_set_int(VCONFKEY_STARTER_USE_VOLUME_KEY, 0) < 0) {
721 _E("Failed to get vconfkey : VCONFKEY_STATER_USE_VOLUME_KEY");
727 _D("setting App grab volume hard key");
731 static void _idle_lock_state_vconf_changed_cb(keynode_t *key, void *data)
733 int lock = VCONFKEY_IDLE_UNLOCK;
735 if(vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) < 0)
737 _E("Failed to get vconfkey : VCONFKEY_IDLE_LOCK_STATE");
740 _D("idle lock state : %d", lock);
742 if(lock == VCONFKEY_IDLE_LAUNCHING_LOCK)
744 if(VOLUME_ERROR_OK != volume_view_window_hide())
746 _E("Failed to hide window");
751 static void _notify_pm_lcdoff_cb(keynode_t * node, void *data)
753 if (volume_view_warning_popup_get()) {
754 volume_view_destroy_warning_popup();
757 if(VOLUME_ERROR_OK != volume_control_hide_view())
759 _E("Failed to close volume");
762 if(VOLUME_ERROR_OK != volume_control_cache_flush())
764 _E("Failed to flush cache");