Merge branch 'master' into tizen_2.1
[apps/native/volume-app.git] / src / _logic.c
1 /*
2  * org.tizen.volume
3  * Copyright 2012  Samsung Electronics Co., Ltd
4  *
5  * Licensed under the Flora License, Version 1.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://floralicense.org/license/
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an AS IS BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19 #include <math.h>
20
21 #include <Ecore.h>
22 #include <Ecore_X.h>
23 #include <utilX.h>
24 #include <vconf.h>
25 #include <ui-gadget.h>
26 #include <X11/Xatom.h>
27 #include <X11/Xutil.h>
28 #include <system_info.h>
29
30 #include"_logic.h"
31 #include "volume.h"
32 #include "_util_log.h"
33 #include "_util_efl.h"
34 #include "_sound.h"
35
36 #define STRBUF_SIZE 128
37 #define PATHBUF_SIZE 256
38 #define EMUL_STR        "Emulator"
39
40 enum {
41         IDLELOCK_OFF = 0x0,
42         IDLELOCK_ON,
43         IDLELOCK_MAX,
44 };
45
46 /* _check_status() return value */
47 enum{
48         LOCK_AND_NOT_MEDIA = -0x1,
49         UNLOCK_STATUS,
50         LOCK_AND_MEIDA,
51 };
52
53 #ifndef VCONFKEY_SETAPPL_ACCESSIBILITY_TURN_OFF_ALL_SOUNDS
54 #define VCONFKEY_SETAPPL_ACCESSIBILITY_TURN_OFF_ALL_SOUNDS              VCONFKEY_SETAPPL_PREFIX"/accessibility/turn_off_all_sounds"
55 #endif
56
57 int _cache_flush(void *data)
58 {
59         struct appdata *ad = (struct appdata *)data;
60         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
61
62         Evas *evas = NULL;
63
64         int file_cache = -1;
65         int collection_cache = -1;
66         int image_cache = -1;
67         int font_cache = -1;
68
69         evas = evas_object_evas_get(ad->win);
70         retvm_if(evas == NULL, -1, "Evas is NULL\n");
71
72         file_cache = edje_file_cache_get();
73         collection_cache = edje_collection_cache_get();
74         image_cache = evas_image_cache_get(evas);
75         font_cache = evas_font_cache_get(evas);
76
77         edje_file_cache_set(file_cache);
78         edje_collection_cache_set(collection_cache);
79         evas_image_cache_set(evas, 0);
80         evas_font_cache_set(evas, 0);
81
82         evas_image_cache_flush(evas);
83         evas_render_idle_flush(evas);
84         evas_font_cache_flush(evas);
85
86         edje_file_cache_flush();
87         edje_collection_cache_flush();
88
89         edje_file_cache_set(file_cache);
90         edje_collection_cache_set(collection_cache);
91         evas_image_cache_set(evas, image_cache);
92         evas_font_cache_set(evas, font_cache);
93
94         return 0;
95 }
96
97 int _close_volume(void *data)
98 {
99         struct appdata *ad = (struct appdata *)data;
100         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
101         retvm_if(ad->flag_deleting == EINA_TRUE, -1, "Closing volume\n");
102
103         _D("start closing volume\n");
104         ad->flag_deleting = EINA_TRUE;
105
106         if(ad->flag_exclusive_grabed){
107                 _ungrab_key_new(ad);
108         }
109
110         if(ad->flag_top_positioni_grabed){
111                 _ungrab_key_new(ad);
112         }
113
114         if(ad->flag_shared_grabed){
115                 _ungrab_key_new(ad);
116         }
117
118         _grab_key_new(ad, ad->input_win, SHARED_GRAB);
119
120         DEL_TIMER(ad->sutimer)
121         DEL_TIMER(ad->lutimer)
122         DEL_TIMER(ad->sdtimer)
123         DEL_TIMER(ad->ldtimer)
124         DEL_TIMER(ad->ptimer)
125
126         _D("hide window\n");
127         evas_object_hide(ad->win);
128
129         appcore_flush_memory();
130
131         ad->flag_deleting = EINA_FALSE;
132         ad->flag_launching = EINA_FALSE;
133         _D("end closing volume\n");
134         return 0;
135 }
136
137 Eina_Bool popup_timer_cb(void *data)
138 {
139         _D("%s\n", __func__);
140         _close_volume(data);
141         return ECORE_CALLBACK_CANCEL;
142 }
143
144 Eina_Bool _lu_timer_cb(void *data)
145 {
146         int val = -1;
147         struct appdata *ad = (struct appdata *)data;
148         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
149         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "window is NULL");
150         retvm_if(evas_object_visible_get(ad->win) == EINA_FALSE, ECORE_CALLBACK_CANCEL, "window is hide\n");
151
152         DEL_TIMER(ad->stimer)
153
154         _get_sound_level(ad->type, &val);
155         if(val == 15){
156                 _D("already 15\n");
157                 return ECORE_CALLBACK_CANCEL;
158         }
159         _set_sound_level(ad->type, val +1 > ad->step ? ad->step : val + 1);
160         _D("down, type(%d), step(%d) val[%d]\n", ad->type, ad->step, val+1);
161         return ECORE_CALLBACK_RENEW;
162 }
163
164 Eina_Bool _su_timer_cb(void *data)
165 {
166         int val = -1;
167         struct appdata *ad = (struct appdata *)data;
168         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
169         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "window is NULL");
170         retvm_if(evas_object_visible_get(ad->win) == EINA_FALSE, ECORE_CALLBACK_CANCEL, "window is hide\n");
171
172         ecore_timer_interval_set(ad->sutimer, 0.1);
173         DEL_TIMER(ad->stimer)
174
175         _get_sound_level(ad->type, &val);
176         if(val == 15){
177                 _D("already 15\n");
178                 return ECORE_CALLBACK_CANCEL;
179         }
180         _set_sound_level(ad->type, val +1 > ad->step ? ad->step : val + 1);
181         _D("down, type(%d), step(%d) val[%d]\n", ad->type, ad->step, val+1);
182         return ECORE_CALLBACK_RENEW;
183 }
184
185 Eina_Bool _ld_timer_cb(void *data)
186 {
187         int val = 0;
188         struct appdata *ad = (struct appdata *)data;
189         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
190         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "window is NULL");
191         retvm_if(evas_object_visible_get(ad->win) == EINA_FALSE, ECORE_CALLBACK_CANCEL, "window is hide\n");
192
193         DEL_TIMER(ad->stimer)
194
195         _get_sound_level(ad->type, &val);
196         if(val == 0){
197                 _D("already 0\n");
198                 return ECORE_CALLBACK_CANCEL;
199         }
200         _set_sound_level(ad->type, val -1 <= 0 ? 0 : val - 1);
201         _D("down, type(%d), step(%d) val[%d]\n", ad->type, ad->step, val+1);
202         return ECORE_CALLBACK_RENEW;
203 }
204
205 Eina_Bool _sd_timer_cb(void *data)
206 {
207         int val = 0;
208         struct appdata *ad = (struct appdata *)data;
209         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
210         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "window is NULL");
211         retvm_if(evas_object_visible_get(ad->win) == EINA_FALSE, ECORE_CALLBACK_CANCEL, "window is hide\n");
212
213         ecore_timer_interval_set(ad->sdtimer, 0.1);
214         DEL_TIMER(ad->stimer)
215
216         _get_sound_level(ad->type, &val);
217         if(val == 0){
218                 _D("already 0\n");
219                 return ECORE_CALLBACK_CANCEL;
220         }
221         _set_sound_level(ad->type, val -1 <= 0 ? 0 : val - 1);
222         _D("down, type(%d), step(%d) val[%d]\n", ad->type, ad->step, val+1);
223         return ECORE_CALLBACK_RENEW;
224 }
225
226 static Eina_Bool _grab_top_position(void *data)
227 {
228         struct appdata *ad = (struct appdata *)data;
229         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
230         _grab_key_new(ad, -1, TOP_POSITION_GRAB);
231         return ECORE_CALLBACK_CANCEL;
232 }
233
234 Eina_Bool _volume_show(void *data)
235 {
236         _D("%s\n", __func__);
237         int status = -1;
238         int type = MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
239         int lock = IDLELOCK_ON;
240         struct appdata *ad = (struct appdata *)data;
241         retvm_if(ad == NULL, EINA_FALSE, "Invalid argument: appdata is NULL\n");
242         retvm_if(ad->flag_deleting ==  EINA_TRUE, EINA_FALSE, "volume is closing\n");
243
244         status = _check_status(&lock, &type);
245         if(status != LOCK_AND_NOT_MEDIA && ad->win)
246         {
247                 _init_mm_sound(ad);
248                 /* ungrab SHARED_GRAB */
249                 //_ungrab_key_new(ad);
250
251                 if(status == UNLOCK_STATUS)
252                 {
253                         _rotate_func(ad);
254                         elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_HIDE);
255                         evas_object_show(ad->win);
256                         if(syspopup_has_popup(ad->volume_bundle))
257                                 syspopup_reset(ad->volume_bundle);
258                         //_grab_key_new(ad, -1, TOP_POSITION_GRAB);
259                         ecore_idler_add(_grab_top_position, ad);
260                 }
261                 else if(status == LOCK_AND_MEIDA)
262                 {
263                         _grab_key_new(ad, ad->input_win, EXCLUSIVE_GRAB);
264                 }
265                 ad->flag_launching = EINA_TRUE;
266                 _mm_func(ad);
267                 return EINA_TRUE;
268         }
269         else if(!ad->win)
270         {
271                 /* recreate window */
272         }
273
274         _D("status == LOCK_AND_NOT_MEDIA\n");
275         return EINA_FALSE;
276 }
277
278 static Eina_Bool _key_press_cb(void *data, int type, void *event)
279 {
280         int val=0, snd=0, vib=0;
281         Ecore_Event_Key *ev = event;
282         _D("%s %s\n", __func__, ev->keyname);
283         int status = -1;
284         int mtype = MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
285         int lock = IDLELOCK_ON;
286         int is_turn_off_all_sounds = 0;
287         int ret = -1;
288         struct appdata *ad = (struct appdata *)data;
289
290         status = _check_status(&lock, &mtype);
291
292         retvm_if(ev == NULL, ECORE_CALLBACK_CANCEL, "Invalid arguemnt: event is NULL\n");
293         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
294         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: window is NULL\n");
295
296         if(!strcmp(ev->keyname, KEY_CANCEL))
297         {
298                 _D("CANCEL Key is pressed\n");
299                 _close_volume(ad);
300                 return ECORE_CALLBACK_CANCEL;
301         }
302
303         ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TURN_OFF_ALL_SOUNDS, &is_turn_off_all_sounds);
304         if(is_turn_off_all_sounds)
305         {
306                 if(status == LOCK_AND_NOT_MEDIA)
307                         return ECORE_CALLBACK_CANCEL;
308                 notification_status_message_post(_("IDS_PN_POP_UNABLE_TO_ADJUST_VOLUME_WHILE_ALL_SOUND_IS_OFF_YOU_CAN_TURN_ON_SOUND_BY_GOING_TO_ACCESSIBILITY_SETTINGS"));
309                 retvm_if(is_turn_off_all_sounds == EINA_TRUE, ECORE_CALLBACK_CANCEL,
310                         "VCONFKEY_SETAPPL_ACCESSIBILITY_TURN_OFF_ALL_SOUNDS is set, all sound is mute\n");
311         }
312
313         if(!ad->flag_launching)
314         {
315                 if(_volume_show(data) != EINA_TRUE)
316                 {
317                         return ECORE_CALLBACK_CANCEL;
318                 }
319         }
320
321         if(ad->flag_touching == EINA_TRUE) {
322                 return ECORE_CALLBACK_CANCEL;
323         }
324
325         ad->flag_pressing = EINA_TRUE;
326
327         DEL_TIMER(ad->ptimer)
328         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &snd);
329         vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vib);
330
331         /* If sound is set off, only RINGTONE, MEDIA types are able to change. */
332         if(!snd && ad->type != VOLUME_TYPE_MEDIA && ad->type != VOLUME_TYPE_RINGTONE){
333                 if(vib)_play_vib(ad->sh);
334                 return ECORE_CALLBACK_CANCEL;
335         }
336
337         if (!strcmp(ev->keyname, KEY_VOLUMEUP)) {
338                 _get_sound_level(ad->type, &val);
339                 if (val == ad->step) {
340                         _set_sound_level(ad->type, ad->step);
341                         if(snd)_play_sound(ad->type, ad->sh);
342                         return ECORE_CALLBACK_CANCEL;
343                 }
344                 _set_sound_level(ad->type, val + 1);
345                 if(snd)_play_sound(ad->type, ad->sh);
346                 DEL_TIMER(ad->sutimer)
347                 DEL_TIMER(ad->sdtimer)
348                 DEL_TIMER(ad->ldtimer)
349                 ADD_TIMER(ad->sutimer, 0.5, _su_timer_cb, ad)
350
351                 _D("set volume %d -> [%d]\n", val, val+1);
352                 if(ad->sutimer == NULL){
353                         _D("error\n");
354                 }
355         } else if (!strcmp(ev->keyname, KEY_VOLUMEDOWN)) {
356                 _get_sound_level(ad->type, &val);
357                 if (val == 0) {
358                         if(vib)_play_vib(ad->sh);
359                         return ECORE_CALLBACK_CANCEL;
360                 }
361                 _set_sound_level(ad->type, val - 1);
362                 if(snd)_play_sound(ad->type, ad->sh);
363                 DEL_TIMER(ad->sdtimer)
364                 DEL_TIMER(ad->sutimer)
365                 DEL_TIMER(ad->lutimer)
366                 ADD_TIMER(ad->sdtimer, 0.5, _sd_timer_cb, ad)
367
368                 _D("type (%d) set volume %d -> [%d]\n", ad->type, val, val-1);
369         if(ad->sdtimer == NULL)
370                 _D("error\n");
371
372         }
373         _D("key press fini\n");
374         return ECORE_CALLBACK_CANCEL;
375 }
376
377 static Eina_Bool _key_release_cb(void *data, int type, void *event)
378 {
379         Ecore_Event_Key *ev = event;
380         struct appdata *ad = (struct appdata *)data;
381         _D("%s %s\n", __func__, ev->keyname);
382
383         retvm_if(ev == NULL, ECORE_CALLBACK_CANCEL, "Invalid arguemnt: event is NULL\n");
384         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument:appdata is NULL\n");
385         retvm_if(ad->win == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: window is NULL\n");
386
387         if(!strcmp(ev->keyname, KEY_CANCEL))
388         {
389                 _D("CANCEL Key is released\n");
390                 _close_volume(ad);
391                 return ECORE_CALLBACK_CANCEL;
392         }
393
394         if (ad->flag_touching == EINA_TRUE) {
395                 return ECORE_CALLBACK_CANCEL;
396         }
397
398         if (!strcmp(ev->keyname, KEY_VOLUMEUP)) {
399                 _D("up key released and del timer\n");
400                 DEL_TIMER(ad->sutimer)
401                 DEL_TIMER(ad->lutimer)
402         } else if (!strcmp(ev->keyname, KEY_VOLUMEDOWN)) {
403                 _D("down key released and del timer\n");
404                 DEL_TIMER(ad->sdtimer)
405                 DEL_TIMER(ad->ldtimer)
406         }
407
408         ad->flag_pressing = EINA_FALSE;
409
410         DEL_TIMER(ad->ptimer)
411
412         ADD_TIMER(ad->ptimer, 3.0, popup_timer_cb, ad)
413
414         return ECORE_CALLBACK_CANCEL;
415 }
416
417 int _grab_key_new(struct appdata *ad, Ecore_X_Window _xwin, int grab_mode)
418 {
419         _D("%s\n", __func__);
420         Ecore_X_Display *disp = NULL;
421         Ecore_X_Window xwin = 0;
422         int ret = -1;
423
424         /* ALREADY GRAB check */
425         switch(grab_mode)
426         {
427                 case SHARED_GRAB : if(ad->flag_shared_grabed)return -1;
428                         break;
429                 case EXCLUSIVE_GRAB : if(ad->flag_exclusive_grabed)return -1;
430                         break;
431                 case TOP_POSITION_GRAB : if(ad->flag_top_positioni_grabed)return -1;
432                         break;
433         }
434
435         disp = ecore_x_display_get();
436         retvm_if(disp == NULL, -1, "Failed to get display\n");
437
438         if(_xwin == -1)
439         {
440                 /* TOP_POSITION_GRAB */
441                 xwin = elm_win_xwindow_get(ad->win);
442                 retvm_if(xwin == 0, -1, "elm_win_xwindow_get() failed\n");
443         }
444         else
445                 xwin = _xwin;
446
447         ret = utilx_grab_key(disp, xwin, KEY_VOLUMEDOWN, grab_mode);
448         retvm_if(ret < 0, -1, "Failed to grab key down\n");
449         retvm_if(ret == 1, -1, "Already grab\n");
450
451         ret = utilx_grab_key(disp, xwin, KEY_VOLUMEUP, grab_mode);
452         retvm_if(ret < 0, -1, "Failed to grab key up\n");
453         retvm_if(ret == 1, -1, "Already grab\n");
454
455         switch(grab_mode)
456         {
457                 case SHARED_GRAB :
458                         ad->flag_shared_grabed = EINA_TRUE;
459                         break;
460                 case EXCLUSIVE_GRAB :
461                         ad->flag_exclusive_grabed = EINA_TRUE;
462                         break;
463                 case TOP_POSITION_GRAB :
464                         ad->flag_top_positioni_grabed = EINA_TRUE;
465                         break;
466         }
467
468         return 0;
469 }
470
471 int _ungrab_key_new(struct appdata *ad)
472 {
473         Ecore_X_Window xwin = 0;
474         Ecore_X_Display *disp = NULL;
475
476         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
477         retvm_if(ad->input_win == 0, -1, "Invalid argument: ad->win is NULL\n");
478
479         xwin = elm_win_xwindow_get(ad->win);
480         retvm_if(xwin == 0, -1, "Failed to get xwindow\n");
481
482         disp = ecore_x_display_get();
483         retvm_if(disp == NULL, -1, "Failed to get display\n");
484
485         utilx_ungrab_key(disp, ad->input_win, KEY_VOLUMEUP);
486         utilx_ungrab_key(disp, ad->input_win, KEY_VOLUMEDOWN);
487         _D("key ungrabed\n");
488
489         if(ad->flag_exclusive_grabed)
490                 ad->flag_exclusive_grabed = EINA_FALSE;
491         else if(ad->flag_top_positioni_grabed)
492                 ad->flag_top_positioni_grabed = EINA_FALSE;
493         else if(ad->flag_shared_grabed)
494                 ad->flag_shared_grabed = EINA_FALSE;
495
496         return 0;
497 }
498
499 int _get_vconf_idlelock(void)
500 {
501         int ret = -1;
502         int lock = IDLELOCK_OFF;
503
504         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock);
505         retvm_if(ret < 0, -1, "Failed to get vconf %s\n",
506                  VCONFKEY_IDLE_LOCK_STATE);
507         _D("idlelock vconf:%d\n", lock);
508
509         return lock == VCONFKEY_IDLE_LOCK ? IDLELOCK_ON : IDLELOCK_OFF;
510 }
511
512 volume_type_t _get_volume_type(void)
513 {
514         int ret = MM_ERROR_NONE;
515         volume_type_t type = -1;
516
517         ret = mm_sound_volume_get_current_playing_type(&type);
518         switch (ret) {
519                 case MM_ERROR_NONE:
520                         break;
521                 case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
522                 case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
523                         type = VOLUME_TYPE_RINGTONE;
524                         break;
525                 default:
526                         _D("Failed to get sound type(errno:%x)\n", ret);
527                         return -1;
528         }
529         if(type == VOLUME_TYPE_NOTIFICATION || type == VOLUME_TYPE_SYSTEM)
530                 type = VOLUME_TYPE_RINGTONE;
531         return type;
532 }
533
534 int _check_status(int *lock, int *type)
535 {
536         *lock = _get_vconf_idlelock();
537         *type = _get_volume_type();
538         _D("lock(%d) type(%d)\n", *lock, *type);
539
540         if (*type == MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY
541                         || *type == MM_ERROR_SOUND_INTERNAL) {
542                 _D("Do not show by type\n");
543                 return -1;
544         }
545
546         if (*lock == IDLELOCK_ON && *type != VOLUME_TYPE_MEDIA) {
547                 _D("lock is set, not in media\n");
548                 return -1;
549         }
550
551         if (*lock == IDLELOCK_ON && *type == VOLUME_TYPE_MEDIA) {
552                 _D("lock is set, in media\n");
553                 return 1;
554         }
555         _D("unlock status, normal case\n");
556         return 0;
557 }
558
559 void _starter_user_volume_key_vconf_changed_cb(keynode_t *key, void *data){
560         _D("%s\n", __func__);
561         int ret = EINA_FALSE;
562         vconf_get_int(VCONFKEY_STARTER_USE_VOLUME_KEY, &ret);
563         if(ret != 0)
564         {
565                 _D("any other App grab volume hard key\n", __func__);
566                 _close_volume(data);
567                 vconf_set_int(VCONFKEY_STARTER_USE_VOLUME_KEY, 0);
568         }
569 }
570
571 void _idle_lock_state_vconf_chnaged_cb(keynode_t *key, void *data){
572         _close_volume(data);
573 }
574
575 int _app_create(struct appdata *ad)
576 {
577         _D("%s\n", __func__);
578         int ret = 0;
579         _init_svi(ad);
580
581         /* create input_window */
582         ad->input_win = _add_input_window();
583         retvm_if(ad->input_win == 0, -1, "Failed to create input window\n");
584
585         /* vconf changed callback */
586         vconf_notify_key_changed(VCONFKEY_STARTER_USE_VOLUME_KEY,
587                                  _starter_user_volume_key_vconf_changed_cb, ad);
588
589         /* Lock screen status vconf changed callback */
590         vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE,
591                                 _idle_lock_state_vconf_chnaged_cb, ad);
592
593         /* grab volume shared grab */
594         ret = _grab_key_new(ad, ad->input_win, SHARED_GRAB);
595
596         /* ecore event handler add once */
597         if(ad->event_volume_down == NULL)
598                 ad->event_volume_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_press_cb, ad);
599         if(ad->event_volume_up == NULL)
600                 ad->event_volume_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _key_release_cb, ad);
601
602         _init_mm_sound(ad);
603
604         return ret;
605 }
606
607 int __utilx_ss_get_window_property(Display *dpy, Window win, Atom atom,
608                                           Atom type, unsigned int *val,
609                                           unsigned int len)
610 {
611         unsigned char *prop_ret = NULL;
612         Atom type_ret = -1;
613         unsigned long bytes_after = 0;
614         unsigned long  num_ret = -1;
615         int format_ret = -1;
616         unsigned int i = 0;
617         int num = 0;
618
619         prop_ret = NULL;
620         if (XGetWindowProperty(dpy, win, atom, 0, 0x7fffffff, False,
621                                type, &type_ret, &format_ret, &num_ret,
622                                &bytes_after, &prop_ret) != Success)
623                 return -1;
624
625         if (type_ret != type || format_ret != 32)
626                 num = -1;
627         else if (num_ret == 0 || !prop_ret)
628                 num = 0;
629         else {
630                 if (num_ret < len)
631                         len = num_ret;
632                 for (i = 0; i < len; i++) {
633                         val[i] = ((unsigned long *)prop_ret)[i];
634                 }
635                 num = len;
636         }
637
638         if (prop_ret)
639                 XFree(prop_ret);
640
641         return num;
642 }
643
644 int _x_rotation_get(Display *dpy, void *data)
645 {
646         Window active_win = 0;
647         Window root_win = 0;
648         int rotation = -1;
649         int ret = -1;
650
651         Atom atom_active_win;
652         Atom atom_win_rotate_angle;
653
654         retvm_if(dpy == NULL, -1, "dpy is NULL\n");
655         root_win = XDefaultRootWindow(dpy);
656
657         atom_active_win = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
658         ret = __utilx_ss_get_window_property(dpy, root_win, atom_active_win,
659                                              XA_WINDOW,
660                                              (unsigned int *)&active_win, 1);
661
662         if(ret < 0)
663                 return ret;
664
665         atom_win_rotate_angle = XInternAtom(dpy, "_E_ILLUME_ROTATE_ROOT_ANGLE", False);
666         ret = __utilx_ss_get_window_property(dpy, root_win,
667                                           atom_win_rotate_angle, XA_CARDINAL,
668                                           (unsigned int *)&rotation, 1);
669
670         if(ret != -1)
671                 return rotation;
672
673         return -1;
674 }
675
676 int _volume_popup_resize(void *data, int angle)
677 {
678         int rotation = 0;
679         int offx=0, offy=0;
680         Evas_Coord minw = -1, minh = -1;
681         Evas_Coord w = 0, h = 0;
682         struct appdata *ad = (struct appdata *)data;
683         retvm_if(ad->win == NULL, -1, "Invalid argument: window is NULL\n");
684         retvm_if(ad->block_events == NULL, -1, "Invalid argument: notify is NULL\n");
685
686         if(angle == -1)
687                 rotation = ad->angle;
688         else
689                 rotation = angle;
690
691         ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
692
693         switch(rotation){
694                 case 90 :
695                 case 270 :
696                         evas_object_resize(ad->block_events, h, w);
697                         edje_object_size_min_get(ad->block_events, &minw, &minh);
698                         edje_object_size_min_restricted_calc(ad->block_events, &minw, &minh, minw, minh);
699                         offx = (h - minw) / 2;
700                         offy = (w - minh) / 5;
701                         break;
702                 case 0 :
703                 case 180 :
704                 default :
705                         evas_object_resize(ad->block_events, w, h);
706                         edje_object_size_min_get(ad->block_events, &minw, &minh);
707                         edje_object_size_min_restricted_calc(ad->block_events, &minw, &minh, minw, minh);
708                         offx = (w - minw) / 2;
709                         offy = (h - minh) / 5;
710                         break;
711         }
712         _D("w(%d) h(%d) offx(%d) offy(%d)\n", w, h, offx, offy);
713         evas_object_move(ad->ly, offx, offy);
714         return 1;
715 }
716
717 int _efl_rotate(Display *dpy, void *data)
718 {
719         int rotation = -1;
720         struct appdata *ad = (struct appdata *)data;
721
722         rotation = _x_rotation_get(dpy, ad);
723
724         if(rotation == -1)
725                 rotation = 0;
726
727         if(rotation >= 0){
728                 elm_win_rotation_set(ad->win, rotation);
729                 ad->angle = rotation;
730                 return _volume_popup_resize(data, rotation);
731         }
732
733         return 0;
734 }
735
736 int _rotate_func(void *data)
737 {
738         _D("%s\n", __func__);
739         struct appdata *ad = (struct appdata *)data;
740         Display *d = NULL;
741         int ret = 0;
742
743         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
744
745         d = XOpenDisplay(NULL);
746         ret = _efl_rotate(d, ad);
747         XCloseDisplay(d);
748
749         return ret;
750 }
751
752 int myterm(bundle *b, void *data)
753 {
754         return 0;
755 }
756
757 int mytimeout(bundle *b, void *data)
758 {
759         return 0;
760 }
761
762 syspopup_handler handler = {
763         .def_term_fn = myterm,
764         .def_timeout_fn = mytimeout
765 };
766
767 void _set_level(int type)
768 {
769         int val = 0;
770         _get_sound_level(type, &val);
771         _set_sound_level(type, val);
772         _D("type(%d) val(%d)\n", type, val);
773 }
774
775 static void _block_clicked_cb(void *data, Evas_Object *o, const char *emission, const char *source)
776 {
777         _close_volume(data);
778 }
779
780 Eina_Bool _slider_timer_cb(void *data)
781 {
782         double val = 0;
783         struct appdata *ad = (struct appdata *)data;
784         retvm_if(ad == NULL, 0, "Invalid argument: appdata is NULL\n");
785         if (ad->sl) {
786                 val = elm_slider_value_get(ad->sl);
787                 val += 0.5;
788                 if ((int)val != 0) {
789                         _set_sound_level(ad->type, (int)val);
790                 }
791                 if (val <= 0.5) {
792                         elm_slider_value_set(ad->sl, 0);
793                         _set_sound_level(ad->type, 0);
794                 }
795                 return ECORE_CALLBACK_RENEW;
796         }
797         return ECORE_CALLBACK_CANCEL;
798 }
799
800 static void _slider_start_cb(void *data, Evas_Object *obj, void *event_info)
801 {
802         _D("%s\n", __func__);
803         int snd= 0 ;
804         struct appdata *ad = (struct appdata *)data;
805         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
806
807         if (ad->flag_pressing == EINA_TRUE) {
808                 return;
809         }
810         ad->flag_touching = EINA_TRUE;
811
812         DEL_TIMER(ad->ptimer)
813
814         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &snd);
815         if(!snd){
816                 vconf_set_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, EINA_TRUE);
817                 _set_icon(data, -1);
818         }
819
820         if (ad->lutimer || ad->ldtimer) {
821                 _D("return when long press is working\n");
822                 return;
823         }
824
825         ADD_TIMER(ad->stimer, 0.2, _slider_timer_cb, data)
826 }
827
828 static void _slider_changed_cb(void *data, Evas_Object *obj, void *event_info)
829 {
830         struct appdata *ad = (struct appdata *)data;
831         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
832
833         if (ad->flag_pressing == EINA_TRUE) {
834                 return;
835         }
836         if (ad->lutimer || ad->ldtimer) {
837                 _D("return when long press is working\n");
838                 return;
839         }
840 }
841 static void _slider_stop_cb(void *data, Evas_Object *obj, void *event_info)
842 {
843         _D("func\n");
844         double val = 0;
845         struct appdata *ad = (struct appdata *)data;
846         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
847
848         if (ad->flag_pressing == EINA_TRUE) {
849                 return;
850         }
851         if (ad->lutimer || ad->ldtimer) {
852                 _D("return when long press is working\n");
853                 return;
854         }
855         DEL_TIMER(ad->stimer)
856         if (ad->sl) {
857                 val = elm_slider_value_get(ad->sl);
858                 val += 0.5;
859                 _set_sound_level(ad->type, (int)val);
860         }
861         _play_sound(ad->type, ad->sh);
862         ad->flag_touching = EINA_FALSE;
863         ADD_TIMER(ad->ptimer, 3.0, popup_timer_cb, ad)
864 }
865
866 Eina_Bool _lu_warmup_timer_cb(void *data)
867 {
868         struct appdata *ad = (struct appdata *)data;
869         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
870         ADD_TIMER(ad->lutimer, 0.0, _lu_timer_cb, ad)
871         return ECORE_CALLBACK_CANCEL;
872 }
873
874 Eina_Bool _ld_warmup_timer_cb(void *data)
875 {
876         struct appdata *ad = (struct appdata *)data;
877         retvm_if(ad == NULL, ECORE_CALLBACK_CANCEL, "Invalid argument: appdata is NULL\n");
878         ADD_TIMER(ad->ldtimer, 0.0, _ld_timer_cb, ad)
879         return ECORE_CALLBACK_CANCEL;
880 }
881
882 void _init_press_timers(void *data)
883 {
884         struct appdata *ad = (struct appdata *)data;
885         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
886         DEL_TIMER(ad->sdtimer)
887         DEL_TIMER(ad->ldtimer)
888         DEL_TIMER(ad->ldwarmtimer)
889         DEL_TIMER(ad->sutimer)
890         DEL_TIMER(ad->lutimer)
891         DEL_TIMER(ad->luwarmtimer)
892 }
893
894 int _handle_bundle(bundle *b, struct appdata *ad)
895 {
896         const char *bval = NULL;
897         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
898
899         bval = bundle_get_val(b, "LONG_PRESS");
900         if (bval) {
901                 _D("val(%s)\n", bval);
902
903                 if (!strncmp(bval, "VOLUME_UP", strlen("LONG_PRESS"))) {
904                         _D("volume up long press\n");
905                         DEL_TIMER(ad->ptimer)
906                         ADD_TIMER(ad->luwarmtimer, 0.5, _lu_warmup_timer_cb, ad);
907                 } else if (!strncmp(bval, "VOLUME_DOWN", strlen("LONG_PRESS"))) {
908                         _D("volume down long press\n");
909                         DEL_TIMER(ad->ptimer)
910                         ADD_TIMER(ad->ldwarmtimer, 0.5, _ld_warmup_timer_cb, ad);
911                 } else {
912                         ADD_TIMER(ad->ptimer, 3.0, popup_timer_cb, ad)
913                 }
914         } else {
915                 ADD_TIMER(ad->ptimer, 3.0, popup_timer_cb, ad)
916                 _init_press_timers(ad);
917         }
918         return 0;
919 }
920
921 static void _button_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
922 {
923         _D("%s\n", __func__);
924         struct appdata *ad = (struct appdata *)data;
925         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
926         char buf[PATHBUF_SIZE] = {0, };
927         snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR, IMG_VOLUME_ICON_SETTINGS_PRESSED);
928         elm_image_file_set(obj, buf, NULL);
929 }
930
931 static void _button_cb(void *data, Evas_Object *obj, void *event_info)
932 {
933         _D("%s\n", __func__);
934         struct appdata *ad = (struct appdata *)data;
935         retm_if(ad == NULL, "Invalid argument: appdata is NULL\n");
936         char buf[PATHBUF_SIZE] = {0, };
937         int ret = -1;
938
939         snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR, IMG_VOLUME_ICON_SETTINGS);
940         elm_image_file_set(obj, buf, NULL);
941         if(evas_object_visible_get(ad->win)){
942                 DEL_TIMER(ad->ptimer)
943                 if(ecore_x_e_illume_quickpanel_state_get(
944                         ecore_x_e_illume_zone_get(elm_win_xwindow_get(ad->win))) != ECORE_X_ILLUME_QUICKPANEL_STATE_OFF)
945                 {
946                         _D("Quickpanel is hide\n");
947                         ecore_x_e_illume_quickpanel_state_send(
948                                 ecore_x_e_illume_zone_get(elm_win_xwindow_get(ad->win)), ECORE_X_ILLUME_QUICKPANEL_STATE_OFF);
949                 }
950                 service_h svc;
951                 ret = service_create(&svc);
952                 if(ret != SERVICE_ERROR_NONE)
953                 {
954                         switch(ret)
955                         {
956                                 case SERVICE_ERROR_INVALID_PARAMETER :
957                                         _D("error : SERVICE_ERROR_INVALID_PARAMETER");
958                                         break;
959                                 case SERVICE_ERROR_OUT_OF_MEMORY :
960                                         _D("error : SERVICE_ERROR_OUT_OF_MEMORY");
961                                         break;
962                                 default :
963                                         _D("error : %d\n", ret);
964                                         break;
965                         }
966                 }
967                 ret = service_set_package(svc, "setting-profile-efl");
968
969                 if(ret != SERVICE_ERROR_NONE)
970                 {
971                         switch(ret)
972                         {
973                                 case SERVICE_ERROR_INVALID_PARAMETER :
974                                         _D("error : SERVICE_ERROR_INVALID_PARAMETER");
975                                         break;
976                                 case SERVICE_ERROR_OUT_OF_MEMORY :
977                                         _D("error : SERVICE_ERROR_OUT_OF_MEMORY");
978                                         break;
979                                 default :
980                                         _D("error : %d\n", ret);
981                                         break;
982                         }
983                 }
984                 ret = service_send_launch_request(svc, NULL, NULL);
985                 if(ret != SERVICE_ERROR_NONE)
986                 {
987                         switch(ret)
988                         {
989                                 case SERVICE_ERROR_INVALID_PARAMETER :
990                                         _D("error : SERVICE_ERROR_INVALID_PARAMETER");
991                                         break;
992                                 case SERVICE_ERROR_OUT_OF_MEMORY :
993                                         _D("error : SERVICE_ERROR_OUT_OF_MEMORY");
994                                         break;
995                                 case SERVICE_ERROR_APP_NOT_FOUND :
996                                         _D("error : SERVICE_ERROR_APP_NOT_FOUND");
997                                         break;
998                                 case SERVICE_ERROR_LAUNCH_REJECTED :
999                                         _D("error : SERVICE_ERROR_LAUNCH_REJECTED");
1000                                         break;
1001                                 default :
1002                                         _D("error : %d\n", ret);
1003                                         break;
1004                         }
1005                 }
1006                 _app_pause(ad);
1007
1008                 service_destroy(svc);
1009         }
1010 }
1011 static int _check_emul(void)
1012 {
1013         int is_emul = 0;
1014         char *info = NULL;
1015
1016         if (system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &info) == 0) {
1017                 if (info == NULL) return 0;
1018                 if (!strncmp(EMUL_STR, info, strlen(info))) {
1019                         is_emul = 1;
1020                 }
1021         }
1022
1023         if (info != NULL) free(info);
1024
1025         return is_emul;
1026 }
1027 int _app_reset(bundle *b, void *data)
1028 {
1029         _D("%s\n", __func__);
1030         int ret = -1, status = -1, val = 0;
1031         int type = MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
1032         int lock = IDLELOCK_ON;
1033         Evas_Object *win, *sl, *ic, *ic_settings;
1034         /* volume-app layout */
1035         Elm_Theme *th;
1036         Evas_Object *outer, *inner, *block;
1037         char buf[PATHBUF_SIZE] = {0, };
1038         struct appdata *ad = (struct appdata *)data;
1039         retvm_if(ad == NULL, -1, "Invalid argument: appdata is NULL\n");
1040
1041         ad->noti_seen = EINA_FALSE;
1042         ad->flag_launching = EINA_FALSE;
1043         ad->flag_pressing = EINA_FALSE;
1044         ad->flag_touching = EINA_FALSE;
1045
1046         status = _check_status(&lock, &type);
1047         ad->type = type;
1048         mm_sound_volume_get_value(type, (unsigned int*)(&val));
1049
1050         if(ad->win == NULL) {
1051                 win = _add_window(PACKAGE);
1052                 retvm_if(win == NULL, -1, "Failed add window\n");
1053                 _D("create window\n");
1054                 ad->win = win;
1055         }
1056         else {
1057                 _E("window already exist\n");
1058                 return -1;
1059         }
1060
1061         th = elm_theme_new();
1062         elm_theme_ref_set(th, NULL);
1063         elm_theme_extension_add(th, EDJ_APP);
1064
1065         ad->flag_emul = _check_emul();
1066
1067         if(!ad->flag_emul)
1068         {
1069                 block = _add_layout(win, EDJ_APP, GRP_VOLUME_BLOCKEVENTS);
1070                 retvm_if(block == NULL, -1, "Failed to add block layout\n");
1071
1072                 edje_object_signal_callback_add(elm_layout_edje_get(block), "clicked", "*", _block_clicked_cb, ad);
1073
1074                 outer = _add_layout(win, EDJ_APP, GRP_VOLUME_LAYOUT);
1075                 retvm_if(outer== NULL, -1, "Failed to add outer layout\n");
1076
1077                 inner = _add_layout(win, EDJ_APP, "popup_volumebar");
1078                 retvm_if(inner == NULL, -1, "Failed to add inner layout\n");
1079
1080                 ad->block_events = block;
1081                 ad->ly = outer;
1082
1083                 elm_object_part_content_set(outer, "elm.swallow.content", inner);
1084
1085                 sl = _add_slider(win, 0, ad->step, val);
1086                 elm_object_theme_set(sl, th);
1087                 evas_object_smart_callback_add(sl, "slider,drag,start", _slider_start_cb, ad);
1088                 evas_object_smart_callback_add(sl, "changed", _slider_changed_cb, ad);
1089                 evas_object_smart_callback_add(sl, "slider,drag,stop", _slider_stop_cb, ad);
1090
1091                 ic_settings = elm_icon_add(win);
1092                 evas_object_size_hint_aspect_set(ic_settings, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1093                 elm_image_resizable_set(ic_settings, EINA_FALSE, EINA_FALSE);
1094                 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR, IMG_VOLUME_ICON_SETTINGS);
1095                 _D("%s\n", buf);
1096                 elm_image_file_set(ic_settings, buf, NULL);
1097                 elm_object_part_content_set(inner, "elm.swallow.icon", ic_settings);
1098                 evas_object_event_callback_add(ic_settings, EVAS_CALLBACK_MOUSE_DOWN, _button_mouse_down_cb, ad);
1099                 evas_object_smart_callback_add(ic_settings, "clicked", _button_cb, ad);
1100                 evas_object_show(ic_settings);
1101                 ad->ic_settings = ic_settings;
1102
1103                 ad->sl = sl;
1104                 elm_object_part_content_set(inner, "elm.swallow.content", sl);
1105
1106                 ic = elm_icon_add(win);
1107                 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1108                 elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
1109                 elm_object_part_content_set(ad->sl, "icon", ic);
1110                 ad->ic = ic;
1111                 _set_icon(ad, val);
1112         }
1113         else
1114         {
1115                 block = _add_layout(win, EDJ_APP, GRP_VOLUME_BLOCKEVENTS);
1116                 retvm_if(block == NULL, -1, "Failed to add block layout\n");
1117
1118                 edje_object_signal_callback_add(elm_layout_edje_get(block), "clicked", "*", _block_clicked_cb, ad);
1119
1120                 outer = _add_layout(win, EDJ_APP, GRP_VOLUME_LAYOUT);
1121                 retvm_if(outer == NULL, -1, "Failed to add outer layout\n");
1122
1123                 inner = _add_layout(win, EDJ_APP, GRP_VOLUME_CONTENT);
1124                 retvm_if(inner == NULL, -1, "Failed to add inner layout\n");
1125
1126                 ad->block_events = block;
1127                 ad->ly = outer;
1128
1129                 elm_object_part_content_set(outer, "elm.swallow.content", inner);
1130
1131                 sl = _add_slider(win, 0, ad->step, val);
1132                 evas_object_smart_callback_add(sl, "slider,drag,start", _slider_start_cb, ad);
1133                 evas_object_smart_callback_add(sl, "changed", _slider_changed_cb, ad);
1134                 evas_object_smart_callback_add(sl, "slider,drag,stop", _slider_stop_cb, ad);
1135
1136                 ad->sl = sl;
1137                 elm_object_part_content_set(inner, "elm.swallow.content", sl);
1138                 evas_object_show(sl);
1139
1140                 ic = elm_icon_add(win);
1141                 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
1142                 elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
1143                 elm_object_part_content_set(ad->sl, "icon", ic);
1144                 ad->ic = ic;
1145                 _set_icon(ad, val);
1146         }
1147
1148
1149         ret = syspopup_create(b, &handler, ad->win, ad);
1150         retvm_if(ret < 0, -1, "Failed to create syspopup\n");
1151         ad->volume_bundle = bundle_dup(b);
1152
1153         return 0;
1154 }
1155
1156 int _app_pause(struct appdata *ad)
1157 {
1158         _D("%s\n", __func__);
1159         _close_volume(ad);
1160         _cache_flush(ad);
1161         return 0;
1162 }