Add volume range translation
[profile/tv/apps/native/air_volume.git] / src / main.c
1 /*
2  * Copyright (c) 2013 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 <app.h>
18 #include <Elementary.h>
19 #include <inputmgr.h>
20 #include <app_debug.h>
21
22 #include "define.h"
23 #include "volume.h"
24
25 #define VOLUME_WIN_ROLE "tv-volume-popup"
26 #define VOLUME_WIN_WIDTH 120
27 #define VOLUME_WIN_HEIGHT 530
28 #define STYLE_VOLUME_PROGRESSBAR "volume_progressbar"
29
30 SET_TAG(PACKAGE)
31
32 struct _appdata {
33         const char *name;
34
35         Evas_Object *win;
36         Evas_Object *base;
37         Evas_Object *progress;
38
39         Ecore_Event_Handler *key_down;
40         Ecore_Timer *hide_timer;
41         Eina_Bool visibility;
42 };
43
44 static Eina_Bool _hide_timer(void *data);
45
46 Evas_Object *_add_win(const char *name)
47 {
48         Evas_Object *win;
49
50         win = elm_win_add(NULL, name, ELM_WIN_BASIC);
51         if (!win) {
52                 _ERR("failed to create win");
53                 return NULL;
54         }
55
56         elm_win_title_set(win, name);
57         elm_win_role_set(win, VOLUME_WIN_ROLE);
58         elm_win_alpha_set(win, EINA_TRUE);
59         elm_win_prop_focus_skip_set(win, EINA_TRUE);
60         evas_object_resize(win, VOLUME_WIN_WIDTH, VOLUME_WIN_HEIGHT);
61         evas_object_show(win);
62
63         return win;
64 }
65
66 Evas_Object *_add_progressbar(Evas_Object *base)
67 {
68         Evas_Object *bar;
69
70         if (!base) {
71                 _ERR("failed to get base object");
72                 return NULL;
73         }
74
75         bar = elm_progressbar_add(base);
76         if (!bar) {
77                 _ERR("failed to create progressbar");
78                 return NULL;
79         }
80
81         evas_object_size_hint_weight_set(bar, EVAS_HINT_EXPAND,
82                         EVAS_HINT_EXPAND);
83         elm_progressbar_horizontal_set(bar, EINA_FALSE);
84         elm_progressbar_inverted_set(bar, EINA_TRUE);
85         elm_object_style_set(bar, STYLE_VOLUME_PROGRESSBAR);
86         elm_object_part_content_set(base, PART_VOLUME_PROGRESSBAR, bar);
87
88         evas_object_show(bar);
89
90         return bar;
91 }
92
93 void _update_volume_bar(struct _appdata *ad, int vol)
94 {
95         double value;
96
97         if (!ad) {
98                 _ERR("failed to get ad");
99                 return;
100         }
101
102         value = (double)vol / VOLUME_MAX;
103         elm_progressbar_value_set(ad->progress, value);
104 }
105
106 void _show(struct _appdata *ad)
107 {
108         if (!ad) {
109                 _ERR("failed to get ad");
110                 return;
111         }
112
113         if (ad->hide_timer)
114                 ecore_timer_reset(ad->hide_timer);
115         else
116                 ad->hide_timer = ecore_timer_add(HIDE_DUR, _hide_timer, ad);
117
118         evas_object_show(ad->base);
119
120         ad->visibility = EINA_TRUE;
121 }
122
123 void _update_volume_info(struct _appdata *ad)
124 {
125         char buf[BUF_MAX];
126         int vol;
127
128         if (!ad) {
129                 _ERR("failed to get ad");
130                 return;
131         }
132
133         if (!ad->visibility)
134                 _show(ad);
135
136         vol = volume_get_volume();
137         if (vol < VOLUME_MIN || vol > VOLUME_MAX) {
138                 _ERR("failed to get volume info");
139                 return;
140         }
141
142         if (vol == 0 || volume_is_mute()) {
143                 _update_volume_bar(ad, MUTE_VALUE);
144                 snprintf(buf, sizeof(buf), "%d", MUTE_VALUE);
145                 elm_object_part_text_set(ad->base, PART_VOLUME_TEXT, buf);
146                 elm_object_signal_emit(ad->base,
147                                 SIGNAL_SHOW_MUTE, SOURCE_PROGRAM);
148         } else {
149                 _update_volume_bar(ad, vol);
150                 snprintf(buf, sizeof(buf), "%d", vol);
151                 elm_object_part_text_set(ad->base, PART_VOLUME_TEXT, buf);
152                 elm_object_signal_emit(ad->base,
153                                 SIGNAL_HIDE_MUTE, SOURCE_PROGRAM);
154         }
155 }
156
157 void _hide(struct _appdata *ad)
158 {
159         if (!ad) {
160                 _ERR("failed to get ad");
161                 return;
162         }
163
164         if (ad->hide_timer) {
165                 ecore_timer_del(ad->hide_timer);
166                 ad->hide_timer = NULL;
167         }
168
169         evas_object_hide(ad->base);
170
171         ad->visibility = EINA_FALSE;
172 }
173
174 Eina_Bool _hide_timer(void *data)
175 {
176         struct _appdata *ad;
177
178         if (!data)
179                 return ECORE_CALLBACK_CANCEL;
180
181         ad = data;
182
183         ad->hide_timer = NULL;
184
185         if (!volume_is_mute())
186                 _hide(ad);
187
188         return ECORE_CALLBACK_CANCEL;
189 }
190
191 static Eina_Bool _key_down(void *data, int type, void *ei)
192 {
193         struct _appdata *ad;
194         Evas_Event_Key_Down *ev;
195         int r, vol;
196
197         if (!data || !ei) {
198                 _ERR("failed to get data and ei");
199                 return ECORE_CALLBACK_PASS_ON;
200         }
201
202         ad = data;
203         ev = ei;
204
205         if (ad->hide_timer)
206                 ecore_timer_reset(ad->hide_timer);
207         else
208                 ad->hide_timer = ecore_timer_add(HIDE_DUR, _hide_timer, ad);
209
210         if (!strcmp(ev->keyname, KEY_VOLUMEUP)) {
211                 vol = volume_get_volume() + 1;
212
213                 r = volume_set_volume(vol);
214                 if (r < 0)
215                         _ERR("failed to set volume");
216
217                 volume_set_mute(false);
218
219                 _update_volume_info(ad);
220         } else if (!strcmp(ev->keyname, KEY_VOLUMEDOWN)) {
221                 vol = volume_get_volume() - 1;
222
223                 r = volume_set_volume(vol);
224                 if (r < 0)
225                         _ERR("failed to set volume");
226
227                 volume_set_mute(false);
228
229                 _update_volume_info(ad);
230         } else if (!strcmp(ev->keyname, KEY_MUTE)) {
231                 bool mute = !volume_is_mute();
232
233                 volume_set_mute(mute);
234
235                 _update_volume_info(ad);
236         }
237
238         return ECORE_CALLBACK_PASS_ON;
239 }
240
241 Eina_Bool _register_keygrab(void *data)
242 {
243         struct _appdata *ad;
244
245         if (!data) {
246                 _ERR("failed to get data");
247                 return false;
248         }
249
250         ad = data;
251
252         elm_win_keygrab_set(ad->win, KEY_VOLUMEUP,
253                         0, 0, 0, ELM_WIN_KEYGRAB_SHARED);
254         elm_win_keygrab_set(ad->win, KEY_VOLUMEDOWN,
255                         0, 0, 0, ELM_WIN_KEYGRAB_SHARED);
256         elm_win_keygrab_set(ad->win, KEY_MUTE,
257                         0, 0, 0, ELM_WIN_KEYGRAB_SHARED);
258
259         return ECORE_CALLBACK_CANCEL;
260 }
261
262 static bool _create(void *data)
263 {
264         struct _appdata *ad;
265         Evas_Object *win;
266         Evas_Object *base;
267         Evas_Object *progress;
268
269         if (!data) {
270                 _ERR("failed to get data");
271                 return false;
272         }
273
274         volume_init();
275
276         ad = data;
277
278         elm_theme_overlay_add(NULL, THEMEFILE);
279
280         win = _add_win(ad->name);
281         if (!win) {
282                 _ERR("failed to create win object");
283                 return false;
284         }
285
286         base = elm_layout_add(win);
287         if (!base) {
288                 _ERR("failed to create layout");
289                 evas_object_del(win);
290                 return false;
291         }
292
293         elm_layout_file_set(base, EDJEFILE, GRP_VOLUME);
294         evas_object_size_hint_weight_set(base,
295                         EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
296         elm_win_resize_object_add(win, base);
297
298         progress = _add_progressbar(base);
299
300         ad->win = win;
301         ad->base = base;
302         ad->progress = progress;
303
304         ecore_timer_add(1, _register_keygrab, ad);
305         ad->key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
306                         _key_down, ad);
307
308         return true;
309 }
310
311 static void _terminate(void *data)
312 {
313         struct _appdata *ad;
314
315         if (!data)
316                 return;
317
318         ad = data;
319
320         elm_win_keygrab_unset(ad->win, KEY_VOLUMEUP, 0, 0);
321         elm_win_keygrab_unset(ad->win, KEY_VOLUMEDOWN, 0, 0);
322         elm_win_keygrab_unset(ad->win, KEY_MUTE, 0, 0);
323
324         ecore_event_handler_del(ad->key_down);
325
326         if (ad->hide_timer)
327                 ecore_timer_del(ad->hide_timer);
328
329         if (ad->win)
330                 evas_object_del(ad->win);
331 }
332
333 static void _pause(void *data)
334 {
335 }
336
337 static void _resume(void *data)
338 {
339 }
340
341 static void _control(app_control_h control, void *data)
342 {
343 }
344
345 int main(int argc, char **argv)
346 {
347         struct _appdata ad;
348         ui_app_lifecycle_callback_s cbs = {
349                 .create = _create,
350                 .terminate = _terminate,
351                 .pause = _pause,
352                 .resume = _resume,
353                 .app_control = _control,
354         };
355
356         memset(&ad, 0x00, sizeof(ad));
357         ad.name = PACKAGE;
358
359         return ui_app_main(argc, argv, &cbs, &ad);
360 }