tizen 2.3.1 release
[apps/home/volume-app.git] / src / view.c
1 /*
2  * Copyright (c) 2009-2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <Ecore.h>
18 #include <Ecore_X.h>
19 #include <feedback.h>
20 #include <vconf.h>
21 #include <vconf-keys.h>
22
23 #include "main.h"
24 #include "_util_efl.h"
25 #include "_util_log.h"
26 #include "view.h"
27 #include "control.h"
28 #include "timer.h"
29 #include "x_event.h"
30 #include "key_event.h"
31 #include "sound.h"
32
33 static struct _s_info {
34         Evas_Object *win;
35         Evas_Object *ly_outer;
36         Evas_Object *icon_volume;
37         Evas_Object *icon_setting;
38         Evas_Object *slider;
39
40         Evas_Object *lockscreen_splash;
41
42         Evas_Object *ao_settings;
43
44         Eina_Bool is_registered_callback;
45         Eina_Bool is_slider_touching;
46         Eina_Bool is_warning_displayed;
47 } s_info = {
48         .win = NULL,
49         .ly_outer = NULL,
50         .icon_volume = NULL,
51         .icon_setting = NULL,
52         .slider = NULL,
53
54         .lockscreen_splash = NULL,
55
56         .ao_settings = NULL,
57
58         .is_registered_callback = EINA_FALSE,
59         .is_slider_touching = EINA_FALSE,
60         .is_warning_displayed = EINA_FALSE
61 };
62
63 static void _button_cb(void *data, Evas_Object *obj, void *event_info);
64 static void _button_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
65
66 Evas_Object* volume_view_win_get(void)
67 {
68         return s_info.win;
69 }
70
71 Evas_Object* volume_view_outer_layout_get(void)
72 {
73         return s_info.ly_outer;
74 }
75
76 Evas_Object* volume_view_icon_volume_get(void)
77 {
78         return s_info.icon_volume;
79 }
80
81 Evas_Object* volume_view_icon_setting_get(void)
82 {
83         return s_info.icon_setting;
84 }
85
86 Evas_Object* volume_view_slider_get(void)
87 {
88         return s_info.slider;
89 }
90
91 Eina_Bool volume_view_is_registered_callback_get(void)
92 {
93         return s_info.is_registered_callback;
94 }
95
96 Eina_Bool volume_view_is_slider_touching_get(void)
97 {
98         return s_info.is_slider_touching;
99 }
100
101 volume_error_e volume_view_set_default_slider(){
102         Evas_Object *slider = volume_view_slider_get();
103         elm_object_style_set(slider, "default");
104         return VOLUME_ERROR_OK;
105 }
106
107 volume_error_e volume_view_set_warning_slider(){
108         Evas_Object *slider = volume_view_slider_get();
109         elm_object_style_set(slider, "warning");
110         Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
111         msg->count = 1;
112         msg->val[0] = 0.66;
113         edje_object_message_send(elm_layout_edje_get(slider), EDJE_MESSAGE_FLOAT_SET, 0, msg);
114
115         return VOLUME_ERROR_OK;
116 }
117
118 int volume_mute_toggle_set()
119 {
120         sound_type_e sound_type = volume_control_sound_type_at_show_get();
121         _D("sound type at show : %d", sound_type);
122
123         int sound = volume_sound_vconf_status_get(TYPE_VCONF_SOUND_STATUS);
124         _D("sound status : %d", sound);
125
126         int vibration = volume_sound_vconf_status_get(TYPE_VCONF_VIBRATION_STATUS);
127         _E("vibration : %d", vibration);
128
129         if (sound == 1 || vibration == 1)
130         {
131                 volume_sound_vconf_status_set(TYPE_VCONF_SOUND_STATUS, 0);
132                 volume_sound_vconf_status_set(TYPE_VCONF_VIBRATION_STATUS, 0);
133
134                 if(VOLUME_ERROR_OK != volume_view_slider_value_set(0))
135                 {
136                         _E("Failed to set slider value");
137                 }
138
139                 return 0;
140         }
141         else
142         {
143                 volume_sound_vconf_status_set(TYPE_VCONF_SOUND_STATUS, 1);
144                 volume_sound_vconf_status_set(TYPE_VCONF_VIBRATION_STATUS, 0);
145
146                 int val = volume_sound_level_get(sound_type);
147                 retv_if(val == -1, 0);
148
149                 if(val == 0)
150                 {
151                         if(VOLUME_ERROR_OK != volume_view_slider_value_set(1)) {
152                                 _E("Failed to set slider value");
153                         }
154                         volume_sound_level_set(sound_type, 1);
155                 } else
156                 {
157                         if(VOLUME_ERROR_OK != volume_view_slider_value_set(val)) {
158                                 _E("Failed to set slider value");
159                         }
160                 }
161
162                 return 1;
163         }
164 }
165
166 static void _slider_start_cb(void *data, Evas_Object *obj, void *event_info)
167 {
168         s_info.is_slider_touching = EINA_TRUE;
169
170         volume_timer_del(TYPE_TIMER_POPUP);
171
172         volume_timer_add(0.2, TYPE_TIMER_SLIDER);
173 }
174
175 static void _slider_changed_cb(void *data, Evas_Object *obj, void *event_info)
176 {
177         volume_timer_del(TYPE_TIMER_POPUP);
178
179         double val = 0;
180
181         sound_type_e sound_type = volume_control_sound_type_at_show_get();
182         _D("sound type at show : %d", sound_type);
183
184         val = elm_slider_value_get(s_info.slider);
185         val += 0.5;
186         _D("slider value : %d", val);
187
188         if (s_info.is_slider_touching)
189         {
190                 return;
191         }
192
193         volume_sound_change_set((int)val);
194
195         if(!volume_key_event_is_pressing_get())
196         {
197                 volume_timer_add(3.0, TYPE_TIMER_POPUP);
198                 return;
199         }
200
201         if(!s_info.is_slider_touching)
202         {
203                 volume_timer_add(3.0, TYPE_TIMER_POPUP);
204                 return;
205         }
206 }
207
208 static void _slider_stop_cb(void *data, Evas_Object *obj, void *event_info)
209 {
210         s_info.is_slider_touching = EINA_FALSE;
211
212         volume_timer_del(TYPE_TIMER_SLIDER);
213
214         Evas_Object *slider = volume_view_slider_get();
215         ret_if(slider == NULL);
216
217         double val = 0;
218
219         val = elm_slider_value_get(slider);
220         val += 0.5;
221         _D("slider value : %d", (int)val);
222
223         volume_sound_change_set((int)val);
224
225         volume_timer_add(3.0, TYPE_TIMER_POPUP);
226 }
227
228 static void _hide_launcher(void *data, Evas_Object *obj, const char *emission, const char *source)
229 {
230         evas_object_hide(s_info.win);
231 }
232
233 //int _set_slider_value(void *data, int val)
234 volume_error_e volume_view_slider_value_set(int val)
235 {
236         retv_if(s_info.is_slider_touching, VOLUME_ERROR_FAIL);
237         retv_if(val<0, VOLUME_ERROR_FAIL);
238
239         elm_slider_value_set(s_info.slider, val);
240
241         return VOLUME_ERROR_OK;
242 }
243
244 static void _button_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
245 {
246         volume_view_setting_icon_set(IMG_VOLUME_ICON_SETTINGS_PRESSED);
247 }
248
249 static void _app_control_error_check(int ret)
250 {
251         if(ret != APP_CONTROL_ERROR_NONE)
252         {
253                 switch(ret)
254                 {
255                 case APP_CONTROL_ERROR_INVALID_PARAMETER :
256                         _E("error : APP_CONTROL_ERROR_INVALID_PARAMETER");
257                         break;
258                 case APP_CONTROL_ERROR_OUT_OF_MEMORY :
259                         _E("error : APP_CONTROL_ERROR_OUT_OF_MEMORY");
260                         break;
261                 case APP_CONTROL_ERROR_APP_NOT_FOUND :
262                         _E("error : APP_CONTROL_ERROR_APP_NOT_FOUND");
263                         break;
264                 case APP_CONTROL_ERROR_LAUNCH_REJECTED :
265                         _E("error : APP_CONTROL_ERROR_LAUNCH_REJECTED");
266                         break;
267                 default :
268                         _E("error : %d", ret);
269                         break;
270                 }
271         }
272 }
273
274 static void _button_cb(void *data, Evas_Object *obj, void *event_info)
275 {
276         _D("volume setting is clicked");
277         int ret = -1;
278         app_control_h svc;
279
280         if(evas_object_visible_get(s_info.win))
281         {
282                 volume_timer_del(TYPE_TIMER_POPUP);
283                 if(ecore_x_e_illume_quickpanel_state_get(ecore_x_e_illume_zone_get(elm_win_xwindow_get(s_info.win))) != ECORE_X_ILLUME_QUICKPANEL_STATE_OFF)
284                 {
285                         _D("Quickpanel is hide");
286                         ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(elm_win_xwindow_get(s_info.win)), ECORE_X_ILLUME_QUICKPANEL_STATE_OFF);
287                 }
288
289                 ret = app_control_create(&svc);
290                 _app_control_error_check(ret);
291
292                 ret = app_control_set_app_id(svc, "org.tizen.setting.volume");
293                 _app_control_error_check(ret);
294
295                 ret = app_control_send_launch_request(svc, NULL, NULL);
296                 _app_control_error_check(ret);
297
298                 if(VOLUME_ERROR_OK != volume_control_pause())
299                 {
300                         _E("Failed to pause volume");
301                 }
302
303                 app_control_destroy(svc);
304         }
305 }
306
307 void volume_view_volume_icon_set(sound_type_e sound_type, int sound, int vibration)
308 {
309         char *img = NULL;
310
311         if(sound == -1 || vibration == -1)
312         {
313                 img = IMG_VOLUME_ICON_MUTE;
314                 _D("img : %s", img);
315                 elm_image_file_set(s_info.icon_volume, EDJ_APP, img);
316                 return;
317         }
318
319         switch(sound_type)
320         {
321         case SOUND_TYPE_RINGTONE:
322                 if(sound)
323                 {
324                         img = IMG_VOLUME_ICON;
325                 }
326                 else if(vibration)
327                 {
328                         img = IMG_VOLUME_ICON_VIB;
329                 }
330                 else
331                 {
332                         img = IMG_VOLUME_ICON_MUTE;
333                 }
334                 break;
335         case SOUND_TYPE_MEDIA:
336                 img = IMG_VOLUME_ICON_MEDIA;
337                 break;
338         case SOUND_TYPE_CALL:
339                 img = IMG_VOLUME_ICON_CALL;
340                 break;
341         case SOUND_TYPE_NOTIFICATION:
342                 if(sound)
343                 {
344                         img = IMG_VOLUME_ICON_NOTI;
345                 }
346                 else if(vibration)
347                 {
348                         img = IMG_VOLUME_ICON_NOTI_VIB;
349                 }
350                 else
351                 {
352                         img = IMG_VOLUME_ICON_NOTI_MUTE;
353                 }
354                 break;
355         case SOUND_TYPE_ALARM:
356                 img = IMG_VOLUME_ICON_MEDIA;
357                 break;
358         default:
359                 img = IMG_VOLUME_ICON;
360                 break;
361         }
362
363         volume_view_set_default_slider();
364
365         _D("img : %s", img);
366         elm_image_file_set(s_info.icon_volume, EDJ_APP, img);
367 }
368
369 void volume_view_setting_icon_set(const char *file)
370 {
371         ret_if(!file);
372
373         Evas_Object *icon_setting = s_info.icon_setting;
374         ret_if(!icon_setting);
375
376         elm_image_file_set(icon_setting, EDJ_APP, file);
377 }
378
379 void volume_view_setting_icon_callback_add(void)
380 {
381         _D("Setting callback add");
382         ret_if(s_info.is_registered_callback);
383
384         Evas_Object *icon_setting = s_info.icon_setting;
385         ret_if(!icon_setting);
386
387         evas_object_event_callback_add(icon_setting, EVAS_CALLBACK_MOUSE_DOWN, _button_mouse_down_cb, NULL);
388         evas_object_smart_callback_add(icon_setting, "clicked", _button_cb, NULL);
389
390         s_info.is_registered_callback = EINA_TRUE;
391 }
392
393 void volume_view_setting_icon_callback_del(void)
394 {
395         _D("Setting callback del");
396         ret_if(!s_info.is_registered_callback);
397
398         Evas_Object *icon_setting = s_info.icon_setting;
399         ret_if(!icon_setting);
400
401         evas_object_smart_callback_del(icon_setting, "clicked", _button_cb );
402         evas_object_event_callback_del(icon_setting, EVAS_CALLBACK_MOUSE_DOWN, _button_mouse_down_cb);
403
404         s_info.is_registered_callback = EINA_FALSE;
405 }
406
407 static Evas_Object* _setting_icon_make()
408 {
409         Evas_Object *icon_setting = elm_icon_add(s_info.ly_outer);
410         retv_if(!icon_setting, NULL);
411
412         evas_object_size_hint_aspect_set(icon_setting, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
413         elm_image_resizable_set(icon_setting, EINA_TRUE, EINA_TRUE);
414
415         s_info.icon_setting = icon_setting;
416
417         volume_view_setting_icon_set(IMG_VOLUME_ICON_SETTINGS);
418         evas_object_show(icon_setting);
419
420         return icon_setting;
421 }
422
423 static Evas_Object* _volume_icon_make()
424 {
425         Evas_Object *icon_volume = elm_icon_add(s_info.ly_outer);
426         retv_if(!icon_volume, NULL);
427
428         evas_object_size_hint_aspect_set(icon_volume, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
429         elm_image_resizable_set(icon_volume, EINA_TRUE, EINA_TRUE);
430         evas_object_show(icon_volume);
431
432         return icon_volume;
433 }
434
435 Evas_Object *add_slider(Evas_Object *parent, int min, int max, int val)
436 {
437         Evas_Object *slider = elm_slider_add(parent);
438         retvm_if(!slider, NULL, "Failed to add slider");
439
440         elm_slider_horizontal_set(slider, EINA_TRUE);
441         elm_slider_indicator_show_set(slider, EINA_FALSE);
442         elm_slider_indicator_format_set(slider, "%.0f");
443         evas_object_size_hint_weight_set(slider, EVAS_HINT_EXPAND, 0.0);
444         evas_object_size_hint_align_set(slider, EVAS_HINT_FILL, 0.5);
445         elm_slider_min_max_set(slider, min, max);
446         elm_slider_value_set(slider, val);
447
448         return slider;
449 }
450
451 static Evas_Object* _slider_make()
452 {
453         sound_type_e sound_type = volume_control_sound_type_at_show_get();
454         _D("sound type at show : %d", sound_type);
455
456         int sound_step = volume_sound_sound_manager_step_get(sound_type);
457         _D("sound step : %d", sound_step);
458
459         int sound_val = volume_sound_level_get(sound_type);
460         if(sound_val == -1)
461         {
462                 _E("Failed to get volume level");
463                 sound_val = 0;
464         }
465         _D("sound value : %d", sound_val);
466
467         Evas_Object *slider = add_slider(s_info.ly_outer, 0, sound_step, sound_val);
468         evas_object_smart_callback_add(slider, "slider,drag,start", _slider_start_cb, NULL);
469         evas_object_smart_callback_add(slider, "changed", _slider_changed_cb, NULL);
470         evas_object_smart_callback_add(slider, "slider,drag,stop", _slider_stop_cb, NULL);
471
472         return slider;
473 }
474
475
476 static void _safety_warning_text_load()
477 {
478         elm_object_domain_translatable_part_text_set(s_info.ly_outer, "warning_rect", "org.tizen.volume", "IDS_COM_POP_TO_LOWER_YOUR_RISK_OF_HEARING_DAMAGE_DO_NOT_LISTEN_AT_HIGH_VOLUMES_FOR_LONG_PERIODS");
479         elm_object_part_text_translatable_set(s_info.ly_outer, "warning_rect", EINA_TRUE);
480         if (!elm_object_part_text_get(s_info.ly_outer, "warning_rect"))
481         {
482                 _E("Failed to set warning text");
483                 return;
484         }
485 }
486
487 volume_error_e volume_view_window_show(void)
488 {
489         evas_object_show(s_info.win);
490         elm_object_signal_emit(s_info.ly_outer, "show_effect", "clipper");
491         volume_view_setting_icon_callback_add();
492
493         return VOLUME_ERROR_OK;
494 }
495
496 volume_error_e volume_view_window_hide(void)
497 {
498         elm_object_signal_emit(s_info.ly_outer, "hide_effect", "clipper");
499         volume_view_setting_icon_callback_del();
500
501         return VOLUME_ERROR_OK;
502 }
503
504 Evas_Object *add_layout(Evas_Object *parent, const char *file, const char *group)
505 {
506         retvm_if(!parent, NULL, "Invalid argument: parent is NULL\n");
507         retvm_if(!file, NULL, "Invalid argument: file is NULL\n");
508         retvm_if(!group, NULL, "Invalid argument: group is NULL\n");
509
510         Evas_Object *eo = elm_layout_add(parent);
511         retvm_if(!eo, NULL, "Failed to add layout\n");
512
513         int r = -1;
514         r = elm_layout_file_set(eo, file, group);
515         if (!r)
516         {
517                 _E("Failed to set file[%s]\n", file);
518                 evas_object_del(eo);
519                 return NULL;
520         }
521
522         evas_object_size_hint_weight_set(eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
523         evas_object_show(eo);
524
525         return eo;
526 }
527
528 volume_error_e volume_view_layout_create(Evas_Object *win)
529 {
530         LOGD("Layout create");
531
532         retv_if(!win, VOLUME_ERROR_FAIL);
533
534         Evas_Object *ly_outer = add_layout(win, EDJ_APP, "volume_layout");
535         retv_if(!ly_outer, VOLUME_ERROR_FAIL);
536         elm_win_resize_object_add(win, ly_outer);
537         elm_object_signal_callback_add(ly_outer, "hide,popup", "event", _hide_launcher, NULL);
538         s_info.ly_outer = ly_outer;
539
540         /* make setting icon */
541         Evas_Object *icon_setting = _setting_icon_make();
542         retv_if(!icon_setting, VOLUME_ERROR_FAIL);
543         elm_object_part_content_set(ly_outer, "ic_setting", icon_setting);
544         s_info.icon_setting = icon_setting;
545
546         /* make volume icon */
547         Evas_Object *icon_volume = _volume_icon_make();
548         retv_if(!icon_volume, VOLUME_ERROR_FAIL);
549         elm_object_part_content_set(ly_outer, "ic_sound", icon_volume);
550         s_info.icon_volume = icon_volume;
551
552         /* make slider */
553         Evas_Object *slider = _slider_make();
554         retv_if(!slider, VOLUME_ERROR_FAIL);
555         s_info.slider = slider;
556         elm_object_part_content_set(ly_outer, "sw.slider", slider);
557
558         _safety_warning_text_load();
559
560         return VOLUME_ERROR_OK;
561 }
562
563 Evas_Object *add_volume_window(const char *name)
564 {
565         Evas_Object *eo = NULL;
566         int w = -1, h = -1;
567
568         eo = elm_win_add(NULL, name, ELM_WIN_NOTIFICATION);
569         retv_if(!eo, NULL);
570
571         elm_win_title_set(eo, name);
572         elm_win_borderless_set(eo, EINA_TRUE);
573         elm_win_alpha_set(eo, EINA_TRUE);
574         elm_win_role_set(eo, "no-dim");
575
576         ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
577         if(w == -1 || h == -1)
578         {
579                 _E("ecore_x_window_size_get() is failed\n");
580                 return NULL;
581         }
582
583         return eo;
584 }
585
586 Evas_Object *volume_view_window_create(void)
587 {
588         Evas_Object *win = add_volume_window(PACKAGE);
589         retv_if(!win, NULL);
590
591         s_info.win = win;
592
593         return win;
594 }
595
596 void _lock_sound_check(void)
597 {
598         int lcdoff_source = -1;
599         int lock_sound = -1;
600         int lock_type = -1;
601
602         if(vconf_get_int(VCONFKEY_PM_LCDOFF_SOURCE, &lcdoff_source) < 0) {
603                 _E("Failed to get vconfkey : VCONFKEY_PM_LCDOFF_SOURCE");
604                 return;
605         }
606         _D("lcd off source : %d", lcdoff_source);
607
608         if(lcdoff_source != VCONFKEY_PM_LCDOFF_BY_POWERKEY) {
609                 _E("Should not play lock sound");
610                 return;
611         }
612
613         if(vconf_get_bool(VCONFKEY_SETAPPL_SOUND_LOCK_BOOL, &lock_sound) < 0) {
614                 _E("Failed to get vconfkey : VCONFKEY_SETAPPL_SOUND_LOCK_BOOL");
615                 return;
616         }
617         _D("lock sound : %d", lock_sound);
618
619         if(lock_sound) { // play sound
620                 if(vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, &lock_type) < 0){
621                         _E("Failed to get vconfkey : VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT");
622                         lock_type = 0;
623                 }
624                 _D("lock type : %d", lock_type);
625
626                 if(lock_type == SETTING_SCREEN_LOCK_TYPE_SWIPE) {
627                         feedback_play_type(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_LOCK_SWIPE);
628
629                 } else {
630                         feedback_play_type(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_LOCK);
631                 }
632         }
633 }
634
635 Evas_Object* show_lockscreen_splash(const char* bg_path)
636 {
637         _D(" ");
638
639         retv_if(bg_path == NULL, NULL);
640
641         if(s_info.lockscreen_splash)
642         {
643                 _E("There is remain fake_bg : remove old one");
644                 evas_object_del(s_info.lockscreen_splash);
645                 s_info.lockscreen_splash = NULL;
646         }
647
648         /* Check Lock Sound */
649         _lock_sound_check();
650
651         /* hide volume window */
652         if(VOLUME_ERROR_OK != volume_view_window_hide())
653         {
654                 _E("Failed to hide window");
655         }
656
657         Evas_Object *win_splash = elm_win_add(NULL,"lockscreen_splash", ELM_WIN_NOTIFICATION);
658
659         if(!win_splash)
660         {
661                 _E("Failed to add splash window");
662                 return NULL;
663         }
664
665         _D("Splash window created");
666
667         Evas_Object *bg = elm_bg_add(win_splash);
668         if(!bg)
669         {
670                 _D("Failed to get background");
671                 evas_object_del(win_splash);
672                 return NULL;
673         }
674
675         elm_win_resize_object_add(win_splash, bg);
676         elm_bg_file_set(bg, bg_path, NULL);
677         evas_object_show(bg);
678
679         evas_object_show(win_splash);
680
681         _D("Splash window shown");
682
683         s_info.lockscreen_splash = win_splash;
684
685         return win_splash;
686 }
687
688 volume_error_e hide_lockscreen_splash(void)
689 {
690         _D(" ");
691
692         if (!s_info.lockscreen_splash) {
693                 _E("No splash window found");
694                 return VOLUME_ERROR_FAIL;
695         }
696
697         evas_object_del(s_info.lockscreen_splash);
698         s_info.lockscreen_splash = NULL;
699         _D("Splash window closed");
700
701         return VOLUME_ERROR_OK;
702 }