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