Hide background image
[profile/tv/apps/native/air_livetv.git] / src / main.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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 <viewmgr.h>
20 #include <inputmgr.h>
21 #include <app_debug.h>
22 #include <app_define.h>
23 #include <tzsh_tvsrv.h>
24 #include <efl_util.h>
25 #include <ui-gadget.h>
26
27 #include "define.h"
28 #include "tv.h"
29 #include "util.h"
30 #include "view.h"
31
32 #define KEY_MAX 256
33 #define PAUSE_WAIT_TIME 0.5
34
35 SET_TAG(PACKAGE)
36
37 struct _appdata {
38         const char *name;
39         Evas_Object *win;
40         Ecore_Event_Handler *key_down;
41         Ecore_Event_Handler *key_up;
42         tzsh_h tzsh;
43         tzsh_tvsrv_h ta;
44         Ecore_Timer *pause_timer;
45         int service_id;
46
47         int is_signal;
48         int is_channel;
49         int is_tuned;
50 };
51
52 struct key_map {
53         const char *view;
54         const char *key[KEY_MAX];
55 };
56
57 static struct key_map g_kmap[] = {
58         {
59                 VIEW_CHANNELINFO,
60                 {
61                         KEY_ENTER,
62                         KEY_CHANNELUP,
63                         KEY_CHANNELDOWN,
64                         KEY_PREVIOUS,
65                 }
66         },
67         {
68                 VIEW_CHANNELNUMBER,
69                 {
70                         KEY_0, KEY_1, KEY_2, KEY_3,
71                         KEY_4, KEY_5, KEY_6, KEY_7,
72                         KEY_8, KEY_9, KEY_MINUS
73                 }
74         },
75         {
76                 VIEW_ACTION_MENU,
77                 {
78                 }
79         },
80 };
81
82 static Eina_Bool _event(void *data, Evas_Object *obj, Evas_Object *src,
83                 Evas_Callback_Type type, void *ei)
84 {
85         struct _appdata *ad;
86         size_t i, j;
87         char *keyname;
88         int update_type;
89
90         if (type == EVAS_CALLBACK_KEY_DOWN &&
91                         !strcmp(((Evas_Event_Key_Down *)ei)->keyname,
92                         KEY_SUPER_L)) {
93                 util_launch_home();
94                 return EINA_TRUE;
95         }
96
97         if (!data) {
98                 _ERR("failed to get data");
99                 return EINA_FALSE;
100         }
101
102         ad = data;
103
104         if (!ad->is_channel)
105                 return EINA_TRUE;
106
107         switch (type) {
108         case EVAS_CALLBACK_KEY_DOWN:
109                 keyname = ((Evas_Event_Key_Down *)ei)->keyname;
110                 update_type = UPDATE_TYPE_INPUT_KEY_DOWN;
111                 break;
112         case EVAS_CALLBACK_KEY_UP:
113                 keyname = ((Evas_Event_Key_Up *)ei)->keyname;
114                 update_type = UPDATE_TYPE_INPUT_KEY_UP;
115                 break;
116         default:
117                 return EINA_FALSE;
118         }
119
120         for (i = 0; i < sizeof(g_kmap) / sizeof(*g_kmap); i++) {
121                 j = 0;
122                 while (g_kmap[i].key[j]) {
123                         if (!strcmp(keyname, g_kmap[i].key[j])) {
124                                 viewmgr_update_view(g_kmap[i].view,
125                                                 update_type, ei);
126                                 return EINA_TRUE;
127                         }
128                         j++;
129                 }
130         }
131
132         return EINA_FALSE;
133 }
134
135 static Evas_Object *_add_win(const char *name)
136 {
137         Evas_Object *win;
138
139         win = elm_win_add(NULL, name, ELM_WIN_BASIC);
140         if (!win) {
141                 _ERR("elm_win_add failed");
142                 return NULL;
143         }
144         elm_win_title_set(win, PACKAGE);
145         elm_win_focus_highlight_enabled_set(win, EINA_FALSE);
146         elm_win_focus_highlight_style_set(win, "invisible");
147         efl_util_set_window_opaque_state(win, 1);
148
149         evas_object_show(win);
150
151         return win;
152 }
153
154 static tzsh_tvsrv_h _bind_win(Evas_Object *win, tzsh_h tzsh)
155 {
156         tzsh_window tz_win;
157         tzsh_tvsrv_h ta;
158
159         tz_win = elm_win_window_id_get(win);
160         if (!tz_win) {
161                 _ERR("failed to get window ID");
162                 return NULL;
163         }
164
165         ta = tzsh_tvsrv_create(tzsh, tz_win);
166         if (!ta) {
167                 _ERR("failed to create tvsrv");
168                 return NULL;
169         }
170         tzsh_tvsrv_bind(ta);
171
172         return ta;
173 }
174
175 static void _tv_signal_cb(void *data, int is_signal)
176 {
177         struct _appdata *ad;
178
179         if (!data) {
180                 _ERR("failed to get data");
181                 return;
182         }
183
184         ad = data;
185
186         ad->is_signal = is_signal;
187         ad->is_tuned = true;
188
189         if (is_signal) {
190                 viewmgr_hide_view(VIEW_ERROR);
191         } else {
192                 viewmgr_show_view(VIEW_ERROR);
193                 viewmgr_update_view(VIEW_ERROR, UPDATE_TYPE_NOSIGNAL, NULL);
194         }
195 }
196
197 Eina_Bool _tv_pause(void *data)
198 {
199         struct _appdata *ad;
200         int r;
201
202         if (!data) {
203                 _ERR("failed to get data");
204                 return ECORE_CALLBACK_CANCEL;
205         }
206
207         ad = data;
208
209         r = tv_pause();
210         if (r < 0)
211                 _ERR("Pause tv service failed");
212
213         ad->pause_timer = NULL;
214
215         return ECORE_CALLBACK_CANCEL;
216 }
217
218 static void _pause(void *data)
219 {
220         struct _appdata *ad;
221
222         if (!data) {
223                 _ERR("failed to get data");
224                 return;
225         }
226
227         ad = data;
228
229         ad->pause_timer = ecore_timer_add(PAUSE_WAIT_TIME, _tv_pause, ad);
230 }
231
232 static void _resume(void *data)
233 {
234         struct _appdata *ad;
235         int r;
236
237         if (!data) {
238                 _ERR("failed to get data");
239                 return;
240         }
241
242         ad = data;
243
244         if (ad->pause_timer) {
245                 ecore_timer_del(ad->pause_timer);
246                 ad->pause_timer = NULL;
247         }
248
249         r = tv_resume();
250         if (r < 0) {
251                 _ERR("Resume tv service failed");
252                 ui_app_exit();
253
254                 return;
255         } else if (r > 0) {
256                 ad->is_tuned = false;
257         }
258
259         /* Try to tune with service id if supplied from app control */
260         if (ad->service_id > 0) {
261                 r = tv_channel_tune_with_service_id(ad->service_id);
262                 ad->service_id = 0;
263
264                 if (!r) {
265                         ad->is_channel = true;
266                         return;
267                 }
268         }
269
270         if (ad->is_tuned)
271                 return;
272
273         r = tv_channel_tune();
274         if (r < 0) {
275                 ad->is_channel = false;
276                 viewmgr_show_view(VIEW_ERROR);
277                 viewmgr_update_view(VIEW_ERROR, UPDATE_TYPE_NOCHANNEL, NULL);
278         } else {
279                 ad->is_channel = true;
280         }
281 }
282
283 static bool _create(void *data)
284 {
285         struct _appdata *ad;
286         Evas_Object *win;
287         int r;
288
289         if (!data) {
290                 _ERR("failed to get data");
291                 return false;
292         }
293
294         ad = data;
295
296         elm_app_base_scale_set(APP_BASE_SCALE);
297         elm_theme_overlay_add(NULL, THEMEFILE);
298
299         ad->tzsh = tzsh_create(TZSH_TOOLKIT_TYPE_EFL);
300         if (!ad->tzsh) {
301                 _ERR("failed to create tzsh");
302                 return false;
303         }
304
305         win = _add_win(ad->name);
306         if (!win) {
307                 _ERR("failed to create win object");
308                 return false;
309         }
310
311         ad->ta = _bind_win(win, ad->tzsh);
312         if (!ad->ta) {
313                 _ERR("failed to bind win object");
314                 evas_object_del(win);
315                 return false;
316         }
317
318         r = ug_init_efl(win, UG_OPT_INDICATOR_ENABLE);
319         if (r < 0)
320                 _ERR("failed to init ug");
321
322         if (!viewmgr_create(win)) {
323                 _ERR("failed to initialize viewmgr");
324                 evas_object_del(win);
325                 return false;
326         }
327
328         viewmgr_add_view(view_error_get_vclass(), NULL);
329         viewmgr_add_view(view_channelinfo_get_vclass(), NULL);
330         viewmgr_add_view(view_channelnumber_get_vclass(), NULL);
331         viewmgr_add_view(view_action_menu_get_vclass(), NULL);
332         viewmgr_add_view(view_pin_get_vclass(), NULL);
333
334         r = tv_create();
335         if (r < 0) {
336                 _ERR("Create TV failed");
337                 evas_object_del(win);
338                 return false;
339         }
340
341         ad->win = win;
342
343         tv_signal_cb_set(_tv_signal_cb, ad);
344         elm_object_event_callback_add(win, _event, ad);
345
346         elm_config_focus_move_policy_set(ELM_FOCUS_MOVE_POLICY_IN);
347
348         return true;
349 }
350
351 static void _terminate(void *data)
352 {
353         struct _appdata *ad;
354
355         if (!data) {
356                 _ERR("failed to get data");
357                 return;
358         }
359
360         ad = data;
361
362         if (ad->pause_timer) {
363                 ecore_timer_del(ad->pause_timer);
364                 ad->pause_timer = NULL;
365         }
366
367         if (ad->win) {
368                 tv_destroy();
369
370                 elm_object_event_callback_del(ad->win, _event, ad);
371
372                 viewmgr_remove_view(VIEW_CHANNELINFO);
373                 viewmgr_remove_view(VIEW_CHANNELNUMBER);
374                 viewmgr_remove_view(VIEW_ERROR);
375                 viewmgr_remove_view(VIEW_ACTION_MENU);
376                 viewmgr_remove_view(VIEW_PIN);
377                 viewmgr_destroy();
378
379                 evas_object_del(ad->win);
380                 ad->win = NULL;
381
382                 if (ad->ta)
383                         tzsh_tvsrv_destroy(ad->ta);
384
385                 if (ad->tzsh)
386                         tzsh_destroy(ad->tzsh);
387         }
388 }
389
390 static void _control(app_control_h control, void *data)
391 {
392         struct _appdata *ad;
393         char *svcid;
394         int r;
395
396         if (!data) {
397                 _ERR("failed to get data");
398                 return;
399         }
400
401         ad = data;
402
403         r = app_control_get_extra_data(control, KEY_SVCID, &svcid);
404         if (r != APP_CONTROL_ERROR_NONE)
405                 return;
406
407         ad->service_id = atoll(svcid);
408         free(svcid);
409 }
410
411 int main(int argc, char *argv[])
412 {
413         struct _appdata ad;
414         ui_app_lifecycle_callback_s cbs = {
415                 .create = _create,
416                 .terminate = _terminate,
417                 .pause = _pause,
418                 .resume = _resume,
419                 .app_control = _control,
420         };
421
422         memset(&ad, 0x00, sizeof(ad));
423         ad.name = PACKAGE;
424
425         return ui_app_main(argc, argv, &cbs, &ad);
426 }