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