Add channel prev key 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 #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                 free(request);
348                 return -1;
349         }
350
351         return 0;
352 }
353
354 /**
355  * Gets a cached current program with supplied service_id from tv service.
356  *
357  * Note that this function is vaild only when tv service having a cached data
358  * on that channel.
359  * To have a cached data, the channel ever been tuned before calling
360  * this function.
361  *
362  * @param service_id The channel id to get current program
363  * @param request The structure for return program data which contains
364  *        function pointer and additional data for banner
365  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
366  */
367 int tv_epg_get_cache_program(int service_id, struct tv_program_request *request)
368 {
369         Eina_List *list = NULL;
370         TvServiceEpgEventData epg_data;
371         struct tv_program_info *prog_info;
372
373         int r;
374
375         if (!g_tv_info.epg_svc) {
376                 _ERR("failed to get epg service");
377                 return -1;
378         }
379
380         if (!request) {
381                 _ERR("failed to get tv_program_request");
382                 return -1;
383         }
384
385         r = tv_service_epg_get_cache_current_program(
386                         g_tv_info.epg_svc, service_id, &epg_data);
387         if (r != TVS_ERROR_OK) {
388                 _ERR("failed to get epg get cached current program : %d",
389                                 service_id);
390                 return -1;
391         }
392
393         prog_info = _tv_get_program_info(&epg_data);
394         if (prog_info)
395                 list = eina_list_append(list, prog_info);
396
397         if (request->tv_program_cb)
398                 request->tv_program_cb(list, request->user_data);
399
400         if (list)
401                 _tv_epg_del_list(list);
402
403         free(request);
404
405         return 0;
406 }
407
408 /**
409  * Sends a request to tv service to get programs with supplied service_id.
410  *
411  * Beware that service_id should be current tuned channel.
412  * If not, calling this function may cause unexpected behavior.
413  * And note that get a EPG program is asynchronous operation.
414  * So tv_program_request should be supplied to get a result from tv service.
415  *
416  * @param service_id The channel id to get current program
417  * @param request The structure for return program data which contains function pointer and additional data for banner
418  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
419  */
420 int tv_epg_get_program_list(int service_id,
421                 struct tv_program_request *request)
422 {
423         int r;
424
425         if (!g_tv_info.epg_svc) {
426                 _ERR("failed to get epg service");
427                 return -1;
428         }
429
430         if (!request) {
431                 _ERR("failed to get tv_program_request");
432                 return -1;
433         }
434
435         r = tv_service_epg_get_program_list(g_tv_info.epg_svc, service_id,
436                         TVS_EPG_CURRENT_TIME, EPG_PROGRAM_OFFSET,
437                         (TvServiceEpgCallback) _tv_epg_event_cb, request);
438         if (r != TVS_ERROR_OK) {
439                 _ERR("failed to get epg get current program");
440                 return -1;
441         }
442
443         return 0;
444 }
445
446 /**
447  * Frees the TvServiceFilterNode.
448  *
449  * @param data TvServiceFilterNode pointer to be freed
450  */
451 static void _tv_channel_free_filter(gpointer data)
452 {
453         TvServiceFilterNode *filter_node;
454
455         if (!data)
456                 return;
457
458         filter_node = (TvServiceFilterNode *) data;
459
460         g_value_unset(filter_node->value);
461         g_free(filter_node->value);
462         g_free(filter_node);
463 }
464
465 /**
466  * Gets a available channel list.
467  *
468  * Note that deleted channels and service channels are excluded by default.
469  *
470  * @return Available channel list, or NULL if fails
471  */
472 Eina_List *tv_channel_get_list()
473 {
474         GList *tvs_list = NULL;
475         Eina_List *channel_list = NULL;
476         TvServiceChannel *tvs_data = NULL;
477         const struct tv_channel_info *channel_info;
478         int r, i;
479
480         r = tv_service_get_channel_list(
481                         TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG,
482                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list);
483         if (r != TVS_ERROR_OK) {
484                 _ERR("failed to get channel list");
485                 return NULL;
486         }
487
488         for (i = 0; i < g_list_length(tvs_list); i++) {
489                 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
490                 if (tvs_data) {
491                         channel_info = _tv_channel_get_info(tvs_data);
492                         if (channel_info)
493                                 channel_list = eina_list_append(channel_list,
494                                                 channel_info);
495                         free(tvs_data);
496                 }
497         }
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                         free(tvs_data);
531                 }
532         }
533
534         return channel_list;
535 }
536
537 TvServiceFilterNode *_tv_channel_get_filter(
538                 TvServiceChannelDataAttr attribute, int type, void *data)
539 {
540         TvServiceFilterNode *filter;
541         GValue *value;
542
543         filter = g_malloc0(sizeof(*filter));
544         if (!filter)
545                 return NULL;
546
547         filter->attribute = attribute;
548
549         value = g_malloc0(sizeof(GValue));
550         if (!value) {
551                 g_free(filter);
552                 return NULL;
553         }
554
555         switch (type) {
556         case G_TYPE_STRING:
557                 g_value_init(value, G_TYPE_STRING);
558                 g_value_set_string(value, data);
559
560                 filter->match_type = CHANNEL_FILTER_MATCH_CONTAIN;
561                 break;
562         case G_TYPE_INT:
563                 g_value_init(value, G_TYPE_INT);
564                 g_value_set_int(value, (gint) data);
565
566                 filter->match_type = CHANNEL_FILTER_MATCH_EQUAL;
567                 break;
568         }
569         filter->value = value;
570
571         return filter;
572 }
573
574 /**
575  * Search channels that are starts with supplied major and minor number.
576  *
577  * Note that deleted channels and service channels are excluded by default.
578  *
579  * @param major Major channel number to search
580  * @param minor Minor channel number to search
581  * @return Found channel list, or NULL if fails
582  */
583 Eina_List *tv_channel_search_by_number(long major, long minor)
584 {
585         char buf[CHANNEL_FILTER_STRING_MAX_LEN];
586         GList *tvs_list = NULL, *filter = NULL;
587         TvServiceFilterNode *filter_node;
588         TvServiceChannel *tvs_data;
589         Eina_List *channel_list = NULL;
590         const struct tv_channel_info *channel_info;
591         int i, r;
592
593         if (major > 0 && major < MAJOR_MAX) {
594                 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", major);
595
596                 filter_node = _tv_channel_get_filter(
597                                 TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
598                                 G_TYPE_STRING, buf);
599                 if (filter_node)
600                         filter = g_list_append(filter, (gpointer)filter_node);
601         }
602
603         if (minor > 0 && minor < MINOR_MAX) {
604                 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", minor);
605
606                 filter_node = _tv_channel_get_filter(
607                                 TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
608                                 G_TYPE_STRING, buf);
609                 if (filter_node)
610                         filter = g_list_append(filter, (gpointer)filter_node);
611         }
612
613         if (!filter) {
614                 _ERR("failed to get filter");
615                 return NULL;
616         }
617
618         r = tv_service_get_channel_list_ex(
619                         TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
620                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
621         if (r != TVS_ERROR_OK) {
622                 _ERR("failed to get channel list");
623                 goto free;
624         }
625
626         for (i = 0; i < g_list_length(tvs_list); i++) {
627                 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
628                 if (!tvs_data)
629                         continue;
630
631                 channel_info = _tv_channel_get_info(tvs_data);
632                 if (channel_info)
633                         channel_list = eina_list_append(channel_list,
634                                         channel_info);
635                 free(tvs_data);
636         }
637
638 free:
639         if (tvs_list)
640                 g_list_free(tvs_list);
641
642         g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
643         g_list_free(filter);
644
645         return channel_list;
646 }
647
648 /**
649  * Frees the tv_channel_info.
650  *
651  * @param channel_list channel_list pointer to be freed
652  */
653 void tv_channel_del_list(Eina_List *channel_list)
654 {
655         struct tv_channel_info *data;
656
657         EINA_LIST_FREE(channel_list, data)
658                 free(data);
659 }
660
661 static void _tv_channel_add_history(int service_id)
662 {
663         char buf[128];
664
665         g_tv_info.history.service_id[g_tv_info.history.idx++ % 2]
666                         = service_id;
667
668         snprintf(buf, sizeof(buf), "%d", service_id);
669         app_contents_recent_add(CONTENTS_CHANNEL, buf);
670 }
671
672 static int _tv_channel_get_history(void)
673 {
674         int service_id;
675
676         service_id = g_tv_info.history.service_id[g_tv_info.history.idx % 2];
677
678         return service_id;
679 }
680
681 /**
682  * Tunes to specific channel with service id.
683  *
684  * @param service_id The channel id
685  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
686  */
687 int tv_channel_tune_with_service_id(int service_id)
688 {
689         int r;
690
691         if (!g_tv_info.live_svc) {
692                 _ERR("failed to get live service");
693                 return -1;
694         }
695
696         r = tv_service_live_tune(g_tv_info.live_svc, service_id);
697         if (r != TVS_ERROR_OK) {
698                 _ERR("failed to set service");
699                 return -1;
700         }
701
702         _tv_channel_add_history(service_id);
703
704         g_tv_info.viewing_locked_channel = -1;
705
706         return 0;
707 }
708
709 /**
710  * Tunes to last viewed channel.
711  *
712  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
713  */
714 int tv_channel_tune(void)
715 {
716         int service_id;
717         int r;
718
719         if (!g_tv_info.live_svc) {
720                 _ERR("failed to get live service");
721                 return -1;
722         }
723
724         r = tv_service_live_get_last_channel(&service_id);
725         if (r < 0 || service_id < 1) {
726                 _ERR("failed to get current service id");
727                 service_id = DEFAULT_SERVICE;
728         }
729
730         r = tv_service_live_tune(g_tv_info.live_svc, service_id);
731         if (r != TVS_ERROR_OK) {
732                 _ERR("failed to set service");
733                 return -1;
734         }
735
736         _tv_channel_add_history(service_id);
737
738         g_tv_info.viewing_locked_channel = -1;
739
740         return 0;
741 }
742
743 /**
744  * Tunes to previously viewed channel.
745  *
746  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
747  */
748 int tv_channel_tune_prev_channel(void)
749 {
750         int service_id;
751         int r;
752
753         if (!g_tv_info.live_svc) {
754                 _ERR("failed to get live service");
755                 return -1;
756         }
757
758         service_id = _tv_channel_get_history();
759         if (service_id < 1) {
760                 _ERR("no previous channel");
761                 return -1;
762         }
763
764         r = tv_service_live_tune(g_tv_info.live_svc, service_id);
765         if (r != TVS_ERROR_OK) {
766                 _ERR("failed to set service");
767                 return -1;
768         }
769
770         _tv_channel_add_history(service_id);
771
772         g_tv_info.viewing_locked_channel = -1;
773
774         return 0;
775 }
776
777 /**
778  * Tunes to specific channel with major and minor.
779  *
780  * @param service_id The channel id
781  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
782  */
783 int tv_channel_direct_tune(long major, long minor)
784 {
785         GList *tvs_list = NULL, *filter = NULL;
786         TvServiceFilterNode *filter_node;
787         TvServiceChannel *tvs_data;
788         int r;
789
790         if (!g_tv_info.live_svc) {
791                 _ERR("failed to get live service");
792                 return -1;
793         }
794
795         if (major > 0 && major < MAJOR_MAX) {
796                 filter_node = _tv_channel_get_filter(
797                                 TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
798                                 G_TYPE_INT, (void *) major);
799                 if (filter_node)
800                         filter = g_list_append(filter, (gpointer)filter_node);
801         }
802
803         if (minor > 0 && minor < MINOR_MAX) {
804                 filter_node = _tv_channel_get_filter(
805                                 TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
806                                 G_TYPE_INT, (void *) minor);
807                 if (filter_node)
808                         filter = g_list_append(filter, (gpointer)filter_node);
809         }
810
811         if (!filter) {
812                 _ERR("failed to get filter");
813                 return -1;
814         }
815
816         r = tv_service_get_channel_list_ex(
817                         TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
818                         TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
819         if (r != TVS_ERROR_OK)
820                 goto free;
821
822         tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, 0);
823         if (tvs_data)
824                 r = tv_channel_tune_with_service_id(tvs_data->service_id);
825         else {
826                 _ERR("failed to get tvs_data");
827                 r = -1;
828         }
829
830         if (r == TVS_ERROR_OK)
831                 g_tv_info.viewing_locked_channel = -1;
832
833         g_list_foreach(tvs_list, (GFunc) g_free, NULL);
834         g_list_free(tvs_list);
835
836 free:
837         g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
838         g_list_free(filter);
839
840         return r;
841 }
842
843 /**
844  * Tunes to locked channel.
845  *
846  * @param service_id The channel id
847  * @param password 4 digit password
848  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
849  */
850 int tv_channel_tune_locked_channel(int service_id, char *password)
851 {
852         int r;
853
854         if (!g_tv_info.live_svc) {
855                 _ERR("failed to get live service");
856                 return -1;
857         }
858
859         r = tv_service_live_tune_locked_channel(g_tv_info.live_svc,
860                         service_id, password);
861         if (r != TVS_ERROR_OK) {
862                 _ERR("failed to set service");
863                 return -1;
864         }
865
866         _tv_channel_add_history(service_id);
867
868         g_tv_info.viewing_locked_channel = service_id;
869
870         return 0;
871 }
872
873 /**
874  * Sets the channel's favorite status.
875  *
876  * @param service_id The channel id
877  * @param flag The value to be set
878  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
879  */
880 int tv_channel_set_favorite(int service_id, Eina_Bool flag)
881 {
882         int r;
883
884         if (flag) {
885                 r = tv_service_add_favorite_channel(service_id);
886                 if (r < 0) {
887                         _ERR("failed to add favorite channel");
888                         return -1;
889                 }
890         } else {
891                 r = tv_service_delete_favorite_channel(service_id);
892                 if (r < 0) {
893                         _ERR("failed to delete favorite channel");
894                         return -1;
895                 }
896         }
897
898         return 0;
899 }
900
901 /**
902  * Adds the channel.
903  *
904  * If channel is added, the channel will be included at
905  * tv_channel_next, tv_channel_prev and tv_channel_get_list.
906  *
907  * @param service_id The channel id
908  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
909  */
910 int tv_channel_add_channel(int service_id)
911 {
912         int r;
913
914         r = tv_service_add_channel(service_id);
915         if (r < 0) {
916                 _ERR("failed to add channel");
917                 return -1;
918         }
919
920         return 0;
921 }
922
923 /**
924  * Deletes the channel.
925  *
926  * If channel is deleted, the channel will be omitted at
927  * tv_channel_next, tv_channel_prev and tv_channel_get_list.
928  *
929  * @param service_id The channel id
930  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
931  */
932 int tv_channel_del_channel(int service_id)
933 {
934         int r;
935
936         r = tv_service_delete_channel(service_id);
937         if (r < 0) {
938                 _ERR("failed to delete channel");
939                 return -1;
940         }
941
942         return 0;
943 }
944
945 /**
946  * Locks the channel.
947  *
948  * @param service_id The channel id
949  * @param password 4 digits password
950  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
951  */
952 int tv_channel_lock_channel(int service_id, char *password)
953 {
954         int r;
955
956         r = tv_service_lock_channel(service_id, password);
957         if (r < 0) {
958                 _ERR("failed to lock channel");
959                 return -1;
960         }
961
962         return 0;
963 }
964
965 /**
966  * Unlocks the channel.
967  *
968  * @param service_id The channel id
969  * @param password 4 digits password
970  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
971  */
972 int tv_channel_unlock_channel(int service_id, char *password)
973 {
974         int r;
975
976         r = tv_service_unlock_channel(service_id, password);
977         if (r < 0) {
978                 _ERR("failed to unlock channel");
979                 return -1;
980         }
981
982         return 0;
983 }
984
985 /**
986  * Callback function for receives tv service events.
987  *
988  * @param event Event type
989  * @param user_data Not in use
990  * @param data Event specific detailed data
991  */
992 void _tv_service_event_cb(TvServiceLiveEvent event,
993                 gpointer user_data, const gpointer data)
994 {
995         gboolean *lock_status;
996
997         switch (event) {
998         case TV_SERVICE_LIVE_EVENT_TUNER_LOCK:
999                 if (!data) {
1000                         _ERR("failed to get data");
1001                         break;
1002                 }
1003
1004                 lock_status = (gboolean *) data;
1005                 if (g_tv_info.signal_cb)
1006                         g_tv_info.signal_cb(g_tv_info.signal_cb_data,
1007                                         *lock_status);
1008                 break;
1009         case TV_SERVICE_LIVE_EVENT_AUTO_DESTROY:
1010                 g_tv_info.live_svc = NULL;
1011                 break;
1012         case TV_SERVICE_LIVE_EVENT_RESOLUTION:
1013         case TV_SERVICE_LIVE_EVENT_BEGIN:
1014         case TV_SERVICE_LIVE_EVENT_CHANNEL_LOCK:
1015         case TV_SERVICE_LIVE_EVENT_CHANNEL_UNLOCK:
1016                 break;
1017         }
1018 }
1019
1020 /**
1021  * Sets tv signal callback function.
1022  *
1023  * @param cb The function pointer to get callback
1024  * @param data An Additional data to passed to callback
1025  */
1026 void tv_signal_cb_set(void (*cb)(void *data, int is_signal), void *data)
1027 {
1028         g_tv_info.signal_cb = cb;
1029         g_tv_info.signal_cb_data = data;
1030 }
1031
1032 /**
1033  * Destory the tv service handles.
1034  *
1035  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1036  */
1037 int tv_destroy(void)
1038 {
1039         int r;
1040
1041         if (g_tv_info.live_svc)
1042                 g_tv_info.live_svc = NULL;
1043
1044         r = tv_service_channel_info_destroy();
1045         if (r < 0)
1046                 _ERR("failed to destroy channel info service");
1047
1048         if (g_tv_info.epg_svc) {
1049                 r = tv_service_epg_destroy(g_tv_info.epg_svc);
1050                 if (r != 0)
1051                         _ERR("failed to destroy epg service");
1052                 g_tv_info.epg_svc = NULL;
1053         }
1054
1055         return 0;
1056 }
1057
1058 /**
1059  * Create the tv service handles.
1060  *
1061  * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1062  */
1063 int tv_create(void)
1064 {
1065         int r;
1066
1067         r = tv_service_live_create(&g_tv_info.live_svc);
1068         if (r != TVS_ERROR_OK) {
1069                 _ERR("failed to create live service");
1070                 goto err;
1071         }
1072
1073         r = tv_service_live_register_callback(g_tv_info.live_svc,
1074                         _tv_service_event_cb, NULL);
1075         if (r != TVS_ERROR_OK) {
1076                 _ERR("failed to register live callback");
1077                 goto err;
1078         }
1079
1080         r = tv_service_channel_info_create();
1081         if (r != TVS_ERROR_OK) {
1082                 _ERR("failed to create channel info service");
1083                 goto err;
1084         }
1085
1086         r = tv_service_epg_create(&g_tv_info.epg_svc);
1087         if (r != TVS_ERROR_OK) {
1088                 _ERR("failed to create epg service");
1089                 goto err;
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 }