Add tv overlay control code
[profile/tv/apps/native/air_livetv.git] / src / tv.c
1 /*
2  * Copyright (c) 2014 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 <stdio.h>
18 #include <app.h>
19 #include <iconv.h>
20 #include <math.h>
21 #include <app_debug.h>
22 #include <app_contents.h>
23
24 #include <glib.h>
25 #include <glib-object.h>
26
27 #include "define.h"
28 #include "tv.h"
29 #include "tv_service.h"
30
31 #define DEFAULT_SERVICE 1
32
33 /**
34  * The Storage structure to used by tv related functions and events.
35  */
36 struct _tv_info {
37         /**< The handle to use tv service live api. */
38         TvServiceLive live_svc;
39         /**< The handle to use tv service epg api. */
40         TvServiceEpg epg_svc;
41
42         /**< Stores service id if tune to locked channel was succeeded. */
43         int viewing_locked_channel;
44
45         /**< The function pointer to pass tv signal event */
46         void (*signal_cb)(void *data, int is_signal);
47         /**< An Additional data to passed to tv signal event */
48         void *signal_cb_data;
49 };
50
51 static struct _tv_info g_tv_info;
52
53 /**
54  * Gets the tv_channel_info with supplied TvServiceChannel.
55  *
56  * Abstracts tv service data structure.
57  *
58  * @param channel The channel data defined by tv service
59  * @return Channel information, or NULL if fails
60  */
61 static struct tv_channel_info *_tv_channel_get_info(TvServiceChannel *channel)
62 {
63         struct tv_channel_info *channel_info = NULL;
64
65         if (!channel) {
66                 _ERR("failed to get channel");
67                 return NULL;
68         }
69
70         channel_info = calloc(1, sizeof(*channel_info));
71         if (!channel_info) {
72                 _ERR("failed to calloc channel info");
73                 return NULL;
74         }
75
76         channel_info->service_id = channel->service_id;
77         channel_info->channel_major = channel->major;
78         channel_info->channel_minor = channel->minor;
79         channel_info->channel_type = channel->channel_type;
80         channel_info->locked = channel->locked;
81         channel_info->digital = channel->digital;
82         channel_info->favorite = channel->favorite;
83         channel_info->remembered = channel->remembered;
84         strncpy(channel_info->channel_name, channel->program_name,
85                 CHANNEL_NAME_MAX);
86
87         if (channel->service_id == g_tv_info.viewing_locked_channel)
88                 channel_info->tune_locked = EINA_TRUE;
89
90         return channel_info;
91 }
92
93 /**
94  * Clones the tv_channel_info.
95  *
96  * @param channel_info tv_channel_info pointer to be cloned
97  * @return Channel information, or NULL if fails
98  */
99 const struct tv_channel_info *tv_channel_clone_info(
100                 const struct tv_channel_info *channel_info)
101 {
102         struct tv_channel_info *new_channel_info = NULL;
103
104         if (!channel_info) {
105                 _ERR("failed to get channel info");
106                 return NULL;
107         }
108
109         new_channel_info = calloc(1, sizeof(*channel_info));
110         if (!new_channel_info) {
111                 _ERR("failed to calloc channel info");
112                 return NULL;
113         }
114
115         memcpy(new_channel_info, channel_info, sizeof(*new_channel_info));
116
117         return new_channel_info;
118 }
119
120 /**
121  * Frees the tv_channel_info.
122  *
123  * @param channel_info tv_channel_info pointer to be freed
124  */
125 void tv_channel_del_info(const struct tv_channel_info *channel_info)
126 {
127         if (!channel_info) {
128                 _ERR("failed to get channel info");
129                 return;
130         }
131
132         free((void *)channel_info);
133 }
134
135 /**
136  * Gets current channel's TvServiceChannel data from tv service.
137  *
138  * @param channel The pointer to store TvServiceChannel
139  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
140  */
141 static int _tv_get_channel(TvServiceChannel *channel)
142 {
143         gint svc_id;
144         int r;
145
146         if (!g_tv_info.live_svc) {
147                 _ERR("failed to get live service");
148                 return -1;
149         }
150
151         r = tv_service_live_get_service_id(g_tv_info.live_svc, &svc_id);
152         if (r < 0) {
153                 _ERR("failed to get service id");
154                 return -1;
155         }
156
157         r = tv_service_get_channel(svc_id, channel);
158         if (r < 0) {
159                 _ERR("failed to get channel");
160                 return -1;
161         }
162
163         return 0;
164 }
165
166 /**
167  * Returns current channel's info.
168  *
169  * tv_channel_get_info retrieves current channel's information
170  * from tv service.
171  *
172  * @return Returns current channel info, or NULL if fails
173  */
174 const struct tv_channel_info *tv_channel_get_info(void)
175 {
176         const struct tv_channel_info *channel_info;
177         TvServiceChannel channel;
178         int r;
179
180         r = _tv_get_channel(&channel);
181         if (r < 0) {
182                 _ERR("failed to get channel");
183                 return NULL;
184         }
185
186         channel_info = _tv_channel_get_info(&channel);
187
188         return channel_info;
189 }
190
191 /**
192  * Returns tv_program_info with supplied TvServiceEpgEventData.
193  *
194  * Abstracts tv service data structure.
195  *
196  * @param prog TvServiceEpgEventData passed from tv service
197  * @return Returns tv_program_info, or NULL if fails
198  */
199 static struct tv_program_info *_tv_get_program_info(TvServiceEpgEventData *prog)
200 {
201         struct tv_program_info *prog_info;
202
203         prog_info = calloc(1, sizeof(*prog_info));
204         if (!prog_info) {
205                 _ERR("failed to calloc program info");
206                 return NULL;
207         }
208
209         prog_info->service_id = prog->service_id;
210         prog_info->start_time = prog->start_time;
211         prog_info->end_time = prog->start_time + prog->length_in_seconds;
212         prog_info->duration = prog->length_in_seconds;
213         prog_info->current_time = prog->current_time;
214         strncpy(prog_info->prog_title, (char *)prog->title_text,
215                         sizeof(prog_info->prog_title) - 1);
216         strncpy(prog_info->prog_description, (char *)prog->extended_text,
217                         sizeof(prog_info->prog_description) - 1);
218
219         return prog_info;
220 }
221
222 /**
223  * Gets current channel's service id from tv service.
224  *
225  * @param service_id The pointer to store service id
226  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
227  */
228 int tv_get_current_service_id(int *service_id)
229 {
230         int r;
231
232         if (!g_tv_info.live_svc) {
233                 _ERR("failed to get live service");
234                 return -1;
235         }
236
237         r = tv_service_live_get_service_id(g_tv_info.live_svc, service_id);
238         if (r != TVS_ERROR_OK) {
239                 _ERR("failed to get current service info");
240                 return -1;
241         }
242
243         return 0;
244 }
245
246 /**
247  * Frees epg list.
248  *
249  * @param epg_list Eina_List to be freed
250  */
251 static void _tv_epg_del_list(Eina_List *epg_list)
252 {
253         struct tv_program_info *data;
254
255         EINA_LIST_FREE(epg_list, data)
256                 free(data);
257 }
258
259 /**
260  * Callback function to get EPG program list from tv service.
261  *
262  * _tv_epg_event_cb is called from tv service when banner
263  * have requested to get program data.
264  * If this function is called, then derives program list from epg_list
265  * and calls banner's callback function which included in user_data.
266  *
267  * @param type Event type
268  * @param epg_list EPG program list
269  * @param user_data tv_program_request to handle request
270  */
271 static void _tv_epg_event_cb(tvs_epg_event_e type, GList *epg_list,
272                 void *user_data)
273 {
274         int i;
275         Eina_List *list = NULL;
276         TvServiceEpgEventData *epg_data;
277         struct tv_program_info *prog_info;
278         struct tv_program_request *request;
279
280         if (!user_data) {
281                 _ERR("failed to get user_data");
282                 return;
283         }
284
285         for (i = 0; i < g_list_length(epg_list); i++) {
286                 epg_data = (TvServiceEpgEventData *)
287                                 g_list_nth_data(epg_list, i);
288
289                 if (!epg_data)
290                         continue;
291
292                 prog_info = _tv_get_program_info(epg_data);
293                 if (prog_info)
294                         list = eina_list_append(list, prog_info);
295         }
296
297         request = (struct tv_program_request *) user_data;
298         if (request->tv_program_cb)
299                 request->tv_program_cb(list, request->user_data);
300
301         if (list)
302                 _tv_epg_del_list(list);
303
304         free(request);
305 }
306
307 /**
308  * Send a request to tv service to get a current program with supplied service_id.
309  *
310  * Beware that service_id should be current tuned channel.
311  * If not, calling this function may cause unexpected behavior.
312  * And note that get a EPG program is asynchronous operation.
313  * So tv_program_request should be supplied to get a result from tv service.
314  *
315  * @param service_id The channel id to get current program
316  * @param request The structure for return program data which contains function pointer
317  *        and additional data for banner
318  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
319  */
320 int tv_epg_get_program(int service_id, struct tv_program_request *request)
321 {
322         int r;
323
324         if (!g_tv_info.epg_svc) {
325                 _ERR("failed to get epg service");
326                 return -1;
327         }
328
329         if (!request) {
330                 _ERR("failed to get tv_program_request");
331                 return -1;
332         }
333
334         r = tv_service_epg_get_current_program(g_tv_info.epg_svc, service_id,
335                         (TvServiceEpgCallback) _tv_epg_event_cb, request);
336         if (r != TVS_ERROR_OK) {
337                 _ERR("failed to get epg get current program : %d", service_id);
338                 free(request);
339                 return -1;
340         }
341
342         return 0;
343 }
344
345 /**
346  * Gets a cached current program with supplied service_id from tv service.
347  *
348  * Note that this function is vaild only when tv service having a cached data
349  * on that channel.
350  * To have a cached data, the channel ever been tuned before calling
351  * this function.
352  *
353  * @param service_id The channel id to get current program
354  * @param request The structure for return program data which contains
355  *        function pointer and additional data for banner
356  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
357  */
358 int tv_epg_get_cache_program(int service_id, struct tv_program_request *request)
359 {
360         Eina_List *list = NULL;
361         TvServiceEpgEventData epg_data;
362         struct tv_program_info *prog_info;
363
364         int r;
365
366         if (!g_tv_info.epg_svc) {
367                 _ERR("failed to get epg service");
368                 return -1;
369         }
370
371         if (!request) {
372                 _ERR("failed to get tv_program_request");
373                 return -1;
374         }
375
376         r = tv_service_epg_get_cache_current_program(
377                         g_tv_info.epg_svc, service_id, &epg_data);
378         if (r != TVS_ERROR_OK) {
379                 _ERR("failed to get epg get cached current program : %d",
380                                 service_id);
381                 return -1;
382         }
383
384         prog_info = _tv_get_program_info(&epg_data);
385         if (prog_info)
386                 list = eina_list_append(list, prog_info);
387
388         if (request->tv_program_cb)
389                 request->tv_program_cb(list, request->user_data);
390
391         if (list)
392                 _tv_epg_del_list(list);
393
394         free(request);
395
396         return 0;
397 }
398
399 /**
400  * Sends a request to tv service to get programs with supplied service_id.
401  *
402  * Beware that service_id should be current tuned channel.
403  * If not, calling this function may cause unexpected behavior.
404  * And note that get a EPG program is asynchronous operation.
405  * So tv_program_request should be supplied to get a result from tv service.
406  *
407  * @param service_id The channel id to get current program
408  * @param request The structure for return program data which contains function pointer and additional data for banner
409  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
410  */
411 int tv_epg_get_program_list(int service_id,
412                 struct tv_program_request *request)
413 {
414         int r;
415
416         if (!g_tv_info.epg_svc) {
417                 _ERR("failed to get epg service");
418                 return -1;
419         }
420
421         if (!request) {
422                 _ERR("failed to get tv_program_request");
423                 return -1;
424         }
425
426         r = tv_service_epg_get_program_list(g_tv_info.epg_svc, service_id,
427                         TVS_EPG_CURRENT_TIME, EPG_PROGRAM_OFFSET,
428                         (TvServiceEpgCallback) _tv_epg_event_cb, request);
429         if (r != TVS_ERROR_OK) {
430                 _ERR("failed to get epg get current program");
431                 return -1;
432         }
433
434         return 0;
435 }
436
437 /**
438  * Frees the TvServiceFilterNode.
439  *
440  * @param data TvServiceFilterNode pointer to be freed
441  */
442 static void _tv_channel_free_filter(gpointer data)
443 {
444         TvServiceFilterNode *filter_node;
445
446         if (!data)
447                 return;
448
449         filter_node = (TvServiceFilterNode *) data;
450
451         g_value_unset(filter_node->value);
452         g_free(filter_node->value);
453         g_free(filter_node);
454 }
455
456 /**
457  * Gets a available channel list.
458  *
459  * Note that deleted channels and service channels are excluded by default.
460  *
461  * @return Available channel list, or NULL if fails
462  */
463 Eina_List *tv_channel_get_list()
464 {
465         GList *tvs_list = NULL;
466         Eina_List *channel_list = NULL;
467         TvServiceChannel *tvs_data = NULL;
468         const struct tv_channel_info *channel_info;
469         int r, i;
470
471         r = tv_service_get_channel_list(
472                         TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG,
473                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list);
474         if (r != TVS_ERROR_OK) {
475                 _ERR("failed to get channel list");
476                 return NULL;
477         }
478
479         for (i = 0; i < g_list_length(tvs_list); i++) {
480                 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
481                 if (tvs_data) {
482                         channel_info = _tv_channel_get_info(tvs_data);
483                         if (channel_info)
484                                 channel_list = eina_list_append(channel_list,
485                                                 channel_info);
486                         free(tvs_data);
487                 }
488         }
489
490         return channel_list;
491 }
492
493 TvServiceFilterNode *_tv_channel_get_filter(
494                 TvServiceChannelDataAttr attribute, int type, void *data)
495 {
496         TvServiceFilterNode *filter;
497         GValue *value;
498
499         filter = g_malloc0(sizeof(*filter));
500         if (!filter)
501                 return NULL;
502
503         filter->attribute = attribute;
504
505         value = g_malloc0(sizeof(GValue));
506         if (!value) {
507                 g_free(filter);
508                 return NULL;
509         }
510
511         switch (type) {
512         case G_TYPE_STRING:
513                 g_value_init(value, G_TYPE_STRING);
514                 g_value_set_string(value, data);
515
516                 filter->match_type = CHANNEL_FILTER_MATCH_CONTAIN;
517                 break;
518         case G_TYPE_INT:
519                 g_value_init(value, G_TYPE_INT);
520                 g_value_set_int(value, (gint) data);
521
522                 filter->match_type = CHANNEL_FILTER_MATCH_EQUAL;
523                 break;
524         }
525         filter->value = value;
526
527         return filter;
528 }
529
530 /**
531  * Search channels that are starts with supplied major and minor number.
532  *
533  * Note that deleted channels and service channels are excluded by default.
534  *
535  * @param major Major channel number to search
536  * @param minor Minor channel number to search
537  * @return Found channel list, or NULL if fails
538  */
539 Eina_List *tv_channel_search_by_number(long major, long minor)
540 {
541         char buf[CHANNEL_FILTER_STRING_MAX_LEN];
542         GList *tvs_list = NULL, *filter = NULL;
543         TvServiceFilterNode *filter_node;
544         TvServiceChannel *tvs_data;
545         Eina_List *channel_list = NULL;
546         const struct tv_channel_info *channel_info;
547         int i, r;
548
549         if (major > 0 && major < MAJOR_MAX) {
550                 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", major);
551
552                 filter_node = _tv_channel_get_filter(
553                                 TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
554                                 G_TYPE_STRING, buf);
555                 if (filter_node)
556                         filter = g_list_append(filter, (gpointer)filter_node);
557         }
558
559         if (minor > 0 && minor < MINOR_MAX) {
560                 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", minor);
561
562                 filter_node = _tv_channel_get_filter(
563                                 TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
564                                 G_TYPE_STRING, buf);
565                 if (filter_node)
566                         filter = g_list_append(filter, (gpointer)filter_node);
567         }
568
569         if (!filter) {
570                 _ERR("failed to get filter");
571                 return NULL;
572         }
573
574         r = tv_service_get_channel_list_ex(
575                         TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
576                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
577         if (r != TVS_ERROR_OK) {
578                 _ERR("failed to get channel list");
579                 goto free;
580         }
581
582         for (i = 0; i < g_list_length(tvs_list); i++) {
583                 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
584                 if (!tvs_data)
585                         continue;
586
587                 channel_info = _tv_channel_get_info(tvs_data);
588                 if (channel_info)
589                         channel_list = eina_list_append(channel_list,
590                                         channel_info);
591                 free(tvs_data);
592         }
593
594 free:
595         if (tvs_list)
596                 g_list_free(tvs_list);
597
598         g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
599         g_list_free(filter);
600
601         return channel_list;
602 }
603
604 /**
605  * Frees the tv_channel_info.
606  *
607  * @param channel_list channel_list pointer to be freed
608  */
609 void tv_channel_del_list(Eina_List *channel_list)
610 {
611         struct tv_channel_info *data;
612
613         EINA_LIST_FREE(channel_list, data)
614                 free(data);
615 }
616
617 void _tv_channel_add_history(int service_id)
618 {
619         char buf[128];
620
621         snprintf(buf, sizeof(buf), "%d", service_id);
622         app_contents_recent_add(CONTENTS_CHANNEL, buf);
623 }
624
625 /**
626  * Tunes to specific channel with service id.
627  *
628  * @param service_id The channel id
629  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
630  */
631 int tv_channel_tune_with_service_id(int service_id)
632 {
633         int r;
634
635         if (!g_tv_info.live_svc) {
636                 _ERR("failed to get live service");
637                 return -1;
638         }
639
640         r = tv_service_live_tune(g_tv_info.live_svc, service_id);
641         if (r != TVS_ERROR_OK) {
642                 _ERR("failed to set service");
643                 return -1;
644         }
645
646         _tv_channel_add_history(service_id);
647
648         g_tv_info.viewing_locked_channel = -1;
649
650         return 0;
651 }
652
653 /**
654  * Tunes to last viewed channel.
655  *
656  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
657  */
658 int tv_channel_tune(void)
659 {
660         int service_id;
661         int r;
662
663         if (!g_tv_info.live_svc) {
664                 _ERR("failed to get live service");
665                 return -1;
666         }
667
668         r = tv_service_live_get_last_channel(&service_id);
669         if (r < 0) {
670                 _ERR("failed to get current service id");
671                 service_id = DEFAULT_SERVICE;
672         }
673
674         r = tv_service_live_tune(g_tv_info.live_svc, service_id);
675         if (r != TVS_ERROR_OK) {
676                 _ERR("failed to set service");
677                 return -1;
678         }
679
680         _tv_channel_add_history(service_id);
681
682         g_tv_info.viewing_locked_channel = -1;
683
684         return 0;
685 }
686
687 /**
688  * Tunes to specific channel with major and minor.
689  *
690  * @param service_id The channel id
691  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
692  */
693 int tv_channel_direct_tune(long major, long minor)
694 {
695         GList *tvs_list = NULL, *filter = NULL;
696         TvServiceFilterNode *filter_node;
697         TvServiceChannel *tvs_data;
698         int r;
699
700         if (major > 0 && major < MAJOR_MAX) {
701                 filter_node = _tv_channel_get_filter(
702                                 TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
703                                 G_TYPE_INT, (void *) major);
704                 if (filter_node)
705                         filter = g_list_append(filter, (gpointer)filter_node);
706         }
707
708         if (minor > 0 && minor < MINOR_MAX) {
709                 filter_node = _tv_channel_get_filter(
710                                 TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
711                                 G_TYPE_INT, (void *) minor);
712                 if (filter_node)
713                         filter = g_list_append(filter, (gpointer)filter_node);
714         }
715
716         if (!filter) {
717                 _ERR("failed to get filter");
718                 return -1;
719         }
720
721         r = tv_service_get_channel_list_ex(
722                         TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
723                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
724         if (r != TVS_ERROR_OK)
725                 goto free;
726
727         tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, 0);
728         if (tvs_data)
729                 r = tv_channel_tune_with_service_id(tvs_data->service_id);
730         else {
731                 _ERR("failed to get tvs_data");
732                 r = -1;
733         }
734
735         if (r == TVS_ERROR_OK)
736                 g_tv_info.viewing_locked_channel = -1;
737
738         g_list_foreach(tvs_list, (GFunc) g_free, NULL);
739         g_list_free(tvs_list);
740
741 free:
742         g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
743         g_list_free(filter);
744
745         return r;
746 }
747
748 /**
749  * Tunes to locked channel.
750  *
751  * @param service_id The channel id
752  * @param password 4 digit password
753  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
754  */
755 int tv_channel_tune_locked_channel(int service_id, char *password)
756 {
757         int r;
758
759         if (!g_tv_info.live_svc) {
760                 _ERR("failed to get live service");
761                 return -1;
762         }
763
764         r = tv_service_live_tune_locked_channel(g_tv_info.live_svc,
765                         service_id, password);
766         if (r != TVS_ERROR_OK) {
767                 _ERR("failed to set service");
768                 return -1;
769         }
770
771         _tv_channel_add_history(service_id);
772
773         g_tv_info.viewing_locked_channel = service_id;
774
775         return 0;
776 }
777
778 /**
779  * Tunes to next channel.
780  *
781  * Note that deleted channels and service channels will skipped.
782  *
783  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
784  */
785 int tv_channel_next(void)
786 {
787         TvServiceAntenna antenna_type;
788         int service_id, r;
789
790         if (!g_tv_info.live_svc) {
791                 _ERR("failed to get live service");
792                 return -1;
793         }
794
795         r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
796         if (r < 0) {
797                 _ERR("failed to get antenna type");
798                 return -1;
799         }
800
801         r = tv_service_live_tune_up(g_tv_info.live_svc,
802                         TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
803         if (r < 0) {
804                 _ERR("failed to tune up");
805                 return -1;
806         }
807
808         g_tv_info.viewing_locked_channel = -1;
809
810         r = tv_service_live_get_service_id(g_tv_info.live_svc, &service_id);
811         if (r < 0) {
812                 _ERR("failed to get service id");
813                 return -1;
814         }
815
816         _tv_channel_add_history(service_id);
817
818         return 0;
819 }
820
821 /**
822  * Tunes to previous channel.
823  *
824  * Note that deleted channels and service channels will skipped.
825  *
826  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
827  */
828 int tv_channel_prev(void)
829 {
830         TvServiceAntenna antenna_type;
831         int service_id, r;
832
833         if (!g_tv_info.live_svc) {
834                 _ERR("failed to get live service");
835                 return -1;
836         }
837
838         r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
839         if (r < 0) {
840                 _ERR("failed to get antenna type");
841                 return -1;
842         }
843
844         r = tv_service_live_tune_down(g_tv_info.live_svc,
845                         TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
846         if (r < 0) {
847                 _ERR("failed to tune down");
848                 return -1;
849         }
850
851         g_tv_info.viewing_locked_channel = -1;
852
853         r = tv_service_live_get_service_id(g_tv_info.live_svc, &service_id);
854         if (r < 0) {
855                 _ERR("failed to get service id");
856                 return -1;
857         }
858
859         _tv_channel_add_history(service_id);
860
861         return 0;
862 }
863
864 /**
865  * Sets the channel's favorite status.
866  *
867  * @param service_id The channel id
868  * @param flag The value to be set
869  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
870  */
871 int tv_channel_set_favorite(int service_id, Eina_Bool flag)
872 {
873         int r;
874
875         if (flag) {
876                 r = tv_service_add_favorite_channel(service_id);
877                 if (r < 0) {
878                         _ERR("failed to add favorite channel");
879                         return -1;
880                 }
881         } else {
882                 r = tv_service_delete_favorite_channel(service_id);
883                 if (r < 0) {
884                         _ERR("failed to delete favorite channel");
885                         return -1;
886                 }
887         }
888
889         return 0;
890 }
891
892 /**
893  * Adds the channel.
894  *
895  * If channel is added, the channel will be included at
896  * tv_channel_next, tv_channel_prev and tv_channel_get_list.
897  *
898  * @param service_id The channel id
899  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
900  */
901 int tv_channel_add_channel(int service_id)
902 {
903         int r;
904
905         r = tv_service_add_channel(service_id);
906         if (r < 0) {
907                 _ERR("failed to add channel");
908                 return -1;
909         }
910
911         return 0;
912 }
913
914 /**
915  * Deletes the channel.
916  *
917  * If channel is deleted, the channel will be omitted at
918  * tv_channel_next, tv_channel_prev and tv_channel_get_list.
919  *
920  * @param service_id The channel id
921  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
922  */
923 int tv_channel_del_channel(int service_id)
924 {
925         int r;
926
927         r = tv_service_delete_channel(service_id);
928         if (r < 0) {
929                 _ERR("failed to delete channel");
930                 return -1;
931         }
932
933         return 0;
934 }
935
936 /**
937  * Locks the channel.
938  *
939  * @param service_id The channel id
940  * @param password 4 digits password
941  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
942  */
943 int tv_channel_lock_channel(int service_id, char *password)
944 {
945         int r;
946
947         r = tv_service_lock_channel(service_id, password);
948         if (r < 0) {
949                 _ERR("failed to lock channel");
950                 return -1;
951         }
952
953         return 0;
954 }
955
956 /**
957  * Unlocks the channel.
958  *
959  * @param service_id The channel id
960  * @param password 4 digits password
961  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
962  */
963 int tv_channel_unlock_channel(int service_id, char *password)
964 {
965         int r;
966
967         r = tv_service_unlock_channel(service_id, password);
968         if (r < 0) {
969                 _ERR("failed to unlock channel");
970                 return -1;
971         }
972
973         return 0;
974 }
975
976 /**
977  * Callback function for receives tv service events.
978  *
979  * @param event Event type
980  * @param user_data Not in use
981  * @param data Event specific detailed data
982  */
983 void _tv_service_event_cb(TvServiceLiveEvent event,
984                 gpointer user_data, const gpointer data)
985 {
986         gboolean *lock_status;
987
988         switch (event) {
989         case TV_SERVICE_LIVE_EVENT_TUNER_LOCK:
990                 if (!data) {
991                         _ERR("failed to get data");
992                         break;
993                 }
994
995                 lock_status = (gboolean *) data;
996                 if (g_tv_info.signal_cb)
997                         g_tv_info.signal_cb(g_tv_info.signal_cb_data,
998                                         *lock_status);
999                 break;
1000         case TV_SERVICE_LIVE_EVENT_AUTO_DESTROY:
1001                 g_tv_info.live_svc = NULL;
1002                 break;
1003         case TV_SERVICE_LIVE_EVENT_RESOLUTION:
1004         case TV_SERVICE_LIVE_EVENT_BEGIN:
1005         case TV_SERVICE_LIVE_EVENT_CHANNEL_LOCK:
1006         case TV_SERVICE_LIVE_EVENT_CHANNEL_UNLOCK:
1007                 break;
1008         }
1009 }
1010
1011 /**
1012  * Sets tv signal callback function.
1013  *
1014  * @param cb The function pointer to get callback
1015  * @param data An Additional data to passed to callback
1016  */
1017 void tv_signal_cb_set(void (*cb)(void *data, int is_signal), void *data)
1018 {
1019         g_tv_info.signal_cb = cb;
1020         g_tv_info.signal_cb_data = data;
1021 }
1022
1023 /**
1024  * Sets window id for tv overlay.
1025  *
1026  * @param window_id The window id to overlay
1027  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1028  */
1029 int tv_overlay_set(void *window_id)
1030 {
1031         int r;
1032
1033         if (!g_tv_info.live_svc) {
1034                 _ERR("failed to get live service");
1035                 return -1;
1036         }
1037
1038         r = tv_service_live_set_window_overlay(g_tv_info.live_svc, window_id);
1039         if (r < 0) {
1040                 _ERR("failed to set overlay");
1041                 return -1;
1042         }
1043
1044         return 0;
1045 }
1046
1047 /**
1048  * Destory the tv service handles.
1049  *
1050  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1051  */
1052 int tv_destroy(void)
1053 {
1054         int r;
1055
1056         if (g_tv_info.live_svc) {
1057                 r = tv_service_live_destroy(g_tv_info.live_svc);
1058                 if (r != TVS_ERROR_OK)
1059                         _ERR("failed to destroy live service");
1060                 g_tv_info.live_svc = NULL;
1061         }
1062
1063         r = tv_service_channel_info_destroy();
1064         if (r < 0)
1065                 _ERR("failed to destroy channel info service");
1066
1067         if (g_tv_info.epg_svc) {
1068                 r = tv_service_epg_destroy(g_tv_info.epg_svc);
1069                 if (r != 0)
1070                         _ERR("failed to destroy epg service");
1071                 g_tv_info.epg_svc = NULL;
1072         }
1073
1074         return 0;
1075 }
1076
1077 /**
1078  * Create the tv service handles.
1079  *
1080  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1081  */
1082 int tv_create(void)
1083 {
1084         int r;
1085
1086         r = tv_service_live_create(&g_tv_info.live_svc);
1087         if (r != TVS_ERROR_OK) {
1088                 _ERR("failed to create live service");
1089                 goto err;
1090         }
1091
1092         r = tv_service_live_register_callback(g_tv_info.live_svc,
1093                         _tv_service_event_cb, NULL);
1094         if (r != TVS_ERROR_OK) {
1095                 _ERR("failed to register live callback");
1096                 goto err;
1097         }
1098
1099         r = tv_service_channel_info_create();
1100         if (r != TVS_ERROR_OK) {
1101                 _ERR("failed to create channel info service");
1102                 goto err;
1103         }
1104
1105         r = tv_service_epg_create(&g_tv_info.epg_svc);
1106         if (r != TVS_ERROR_OK) {
1107                 _ERR("failed to create epg service");
1108                 goto err;
1109         }
1110
1111         return 0;
1112 err:
1113         tv_destroy();
1114         return -1;
1115 }
1116
1117 /**
1118  * Pause the tv service handles.
1119  *
1120  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1121  */
1122 int tv_pause(void)
1123 {
1124         int r;
1125
1126         if (g_tv_info.live_svc) {
1127                 r = tv_service_live_destroy(g_tv_info.live_svc);
1128                 if (r != TVS_ERROR_OK)
1129                         _ERR("failed to destroy live service");
1130                 g_tv_info.live_svc = NULL;
1131         }
1132
1133         return 0;
1134 }
1135
1136 /**
1137  * Resume the tv service handles.
1138  *
1139  * Live service could be destroyed by tv service while app is pausing.
1140  * If live service is destroyed, then _tv_service_event_cb sets
1141  * g_tv_info.live_svc to NULL.
1142  * So if g_tv_info.live_svc is NULL, then recreates live service and returns 1.
1143  * Therefore, if tv_resume returns 1, then app needs to be set overlay and tune.
1144  * Or returns 0, then app just needs to set overlay.
1145  *
1146  * @return 0 if successful; 1 if live service was destroyed; otherwise negative value is returned
1147  */
1148 int tv_resume(void)
1149 {
1150         int r;
1151
1152         if (g_tv_info.live_svc)
1153                 return 0;
1154
1155         r = tv_service_live_create(&g_tv_info.live_svc);
1156         if (r != TVS_ERROR_OK) {
1157                 _ERR("failed to create live service");
1158                 goto err;
1159         }
1160
1161         r = tv_service_live_register_callback(g_tv_info.live_svc,
1162                         _tv_service_event_cb, NULL);
1163         if (r != TVS_ERROR_OK) {
1164                 _ERR("failed to register live callback");
1165                 goto err;
1166         }
1167
1168         return 1;
1169
1170 err:
1171         tv_destroy();
1172         return -1;
1173 }