2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <app_debug.h>
24 #include <glib-object.h>
28 #include "tv_service.h"
30 #define DEFAULT_SERVICE 1
33 * The Storage structure to used by tv related functions and events.
36 /**< The handle to use tv service live api. */
37 TvServiceLive live_svc;
38 /**< The handle to use tv service epg api. */
41 /**< Stores service id if tune to locked channel was succeeded. */
42 int viewing_locked_channel;
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 */
50 static struct _tv_info g_tv_info;
53 * Gets the tv_channel_info with supplied TvServiceChannel.
55 * Abstracts tv service data structure.
57 * @param channel The channel data defined by tv service
58 * @return Channel information, or NULL if fails
60 static struct tv_channel_info *_tv_channel_get_info(TvServiceChannel *channel)
62 struct tv_channel_info *channel_info = NULL;
65 _ERR("failed to get channel");
69 channel_info = calloc(1, sizeof(*channel_info));
71 _ERR("failed to calloc channel info");
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,
86 if (channel->service_id == g_tv_info.viewing_locked_channel)
87 channel_info->tune_locked = EINA_TRUE;
93 * Clones the tv_channel_info.
95 * @param channel_info tv_channel_info pointer to be cloned
96 * @return Channel information, or NULL if fails
98 const struct tv_channel_info *tv_channel_clone_info(
99 const struct tv_channel_info *channel_info)
101 struct tv_channel_info *new_channel_info = NULL;
104 _ERR("failed to get channel info");
108 new_channel_info = calloc(1, sizeof(*channel_info));
109 if (!new_channel_info) {
110 _ERR("failed to calloc channel info");
114 memcpy(new_channel_info, channel_info, sizeof(*new_channel_info));
116 return new_channel_info;
120 * Frees the tv_channel_info.
122 * @param channel_info tv_channel_info pointer to be freed
124 void tv_channel_del_info(const struct tv_channel_info *channel_info)
127 _ERR("failed to get channel info");
131 free((void *)channel_info);
135 * Gets current channel's TvServiceChannel data from tv service.
137 * @param channel The pointer to store TvServiceChannel
138 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
140 static int _tv_get_channel(TvServiceChannel *channel)
145 if (!g_tv_info.live_svc) {
146 _ERR("failed to get live service");
150 r = tv_service_live_get_service_id(g_tv_info.live_svc, &svc_id);
152 _ERR("failed to get service id");
156 r = tv_service_get_channel(svc_id, channel);
158 _ERR("failed to get channel");
166 * Returns current channel's info.
168 * tv_channel_get_info retrieves current channel's information
171 * @return Returns current channel info, or NULL if fails
173 const struct tv_channel_info *tv_channel_get_info(void)
175 const struct tv_channel_info *channel_info;
176 TvServiceChannel channel;
179 r = _tv_get_channel(&channel);
181 _ERR("failed to get channel");
185 channel_info = _tv_channel_get_info(&channel);
191 * Returns tv_program_info with supplied TvServiceEpgEventData.
193 * Abstracts tv service data structure.
195 * @param prog TvServiceEpgEventData passed from tv service
196 * @return Returns tv_program_info, or NULL if fails
198 static struct tv_program_info *_tv_get_program_info(TvServiceEpgEventData *prog)
200 struct tv_program_info *prog_info;
202 prog_info = calloc(1, sizeof(*prog_info));
204 _ERR("failed to calloc program info");
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);
222 * Gets current channel's service id from tv service.
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
227 int tv_get_current_service_id(int *service_id)
231 if (!g_tv_info.live_svc) {
232 _ERR("failed to get live service");
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");
248 * @param epg_list Eina_List to be freed
250 static void _tv_epg_del_list(Eina_List *epg_list)
252 struct tv_program_info *data;
254 EINA_LIST_FREE(epg_list, data)
259 * Callback function to get EPG program list from tv service.
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.
266 * @param type Event type
267 * @param epg_list EPG program list
268 * @param user_data tv_program_request to handle request
270 static void _tv_epg_event_cb(tvs_epg_event_e type, GList *epg_list,
274 Eina_List *list = NULL;
275 TvServiceEpgEventData *epg_data;
276 struct tv_program_info *prog_info;
277 struct tv_program_request *request;
280 _ERR("failed to get user_data");
284 for (i = 0; i < g_list_length(epg_list); i++) {
285 epg_data = (TvServiceEpgEventData *)
286 g_list_nth_data(epg_list, i);
291 prog_info = _tv_get_program_info(epg_data);
293 list = eina_list_append(list, prog_info);
296 request = (struct tv_program_request *) user_data;
297 if (request->tv_program_cb)
298 request->tv_program_cb(list, request->user_data);
301 _tv_epg_del_list(list);
307 * Send a request to tv service to get a current program with supplied service_id.
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.
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
319 int tv_epg_get_program(int service_id, struct tv_program_request *request)
323 if (!g_tv_info.epg_svc) {
324 _ERR("failed to get epg service");
329 _ERR("failed to get tv_program_request");
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);
344 * Gets a cached current program with supplied service_id from tv service.
346 * Note that this function is vaild only when tv service having a cached data
348 * To have a cached data, the channel ever been tuned before calling
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
356 int tv_epg_get_cache_program(int service_id, struct tv_program_request *request)
358 Eina_List *list = NULL;
359 TvServiceEpgEventData epg_data;
360 struct tv_program_info *prog_info;
364 if (!g_tv_info.epg_svc) {
365 _ERR("failed to get epg service");
370 _ERR("failed to get tv_program_request");
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",
382 prog_info = _tv_get_program_info(&epg_data);
384 list = eina_list_append(list, prog_info);
386 if (request->tv_program_cb)
387 request->tv_program_cb(list, request->user_data);
390 _tv_epg_del_list(list);
398 * Sends a request to tv service to get programs with supplied service_id.
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.
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
409 int tv_epg_get_program_list(int service_id,
410 struct tv_program_request *request)
414 if (!g_tv_info.epg_svc) {
415 _ERR("failed to get epg service");
420 _ERR("failed to get tv_program_request");
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");
436 * Frees the TvServiceFilterNode.
438 * @param data TvServiceFilterNode pointer to be freed
440 static void _tv_channel_free_filter(gpointer data)
442 TvServiceFilterNode *filter_node;
447 filter_node = (TvServiceFilterNode *) data;
449 g_value_unset(filter_node->value);
450 g_free(filter_node->value);
455 * Gets a available channel list.
457 * Note that deleted channels and service channels are excluded by default.
459 * @return Available channel list, or NULL if fails
461 Eina_List *tv_channel_get_list()
463 GList *tvs_list = NULL;
464 Eina_List *channel_list = NULL;
465 TvServiceChannel *tvs_data = NULL;
466 const struct tv_channel_info *channel_info;
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");
477 for (i = 0; i < g_list_length(tvs_list); i++) {
478 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
480 channel_info = _tv_channel_get_info(tvs_data);
482 channel_list = eina_list_append(channel_list,
491 TvServiceFilterNode *_tv_channel_get_filter(
492 TvServiceChannelDataAttr attribute, int type, void *data)
494 TvServiceFilterNode *filter;
497 filter = g_malloc0(sizeof(*filter));
501 filter->attribute = attribute;
503 value = g_malloc0(sizeof(GValue));
511 g_value_init(value, G_TYPE_STRING);
512 g_value_set_string(value, data);
514 filter->match_type = CHANNEL_FILTER_MATCH_CONTAIN;
517 g_value_init(value, G_TYPE_INT);
518 g_value_set_int(value, (gint) data);
520 filter->match_type = CHANNEL_FILTER_MATCH_EQUAL;
523 filter->value = value;
529 * Search channels that are starts with supplied major and minor number.
531 * Note that deleted channels and service channels are excluded by default.
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
537 Eina_List *tv_channel_search_by_number(long major, long minor)
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;
547 if (major > 0 && major < MAJOR_MAX) {
548 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", major);
550 filter_node = _tv_channel_get_filter(
551 TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
554 filter = g_list_append(filter, (gpointer)filter_node);
557 if (minor > 0 && minor < MINOR_MAX) {
558 snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", minor);
560 filter_node = _tv_channel_get_filter(
561 TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
564 filter = g_list_append(filter, (gpointer)filter_node);
568 _ERR("failed to get filter");
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");
580 for (i = 0; i < g_list_length(tvs_list); i++) {
581 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
585 channel_info = _tv_channel_get_info(tvs_data);
587 channel_list = eina_list_append(channel_list,
594 g_list_free(tvs_list);
596 g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
603 * Frees the tv_channel_info.
605 * @param channel_list channel_list pointer to be freed
607 void tv_channel_del_list(Eina_List *channel_list)
609 struct tv_channel_info *data;
611 EINA_LIST_FREE(channel_list, data)
616 * Tunes to specific channel with service id.
618 * @param service_id The channel id
619 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
621 int tv_channel_tune_with_service_id(int service_id)
625 if (!g_tv_info.live_svc) {
626 _ERR("failed to get live service");
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");
636 g_tv_info.viewing_locked_channel = -1;
642 * Tunes to last viewed channel.
644 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
646 int tv_channel_tune(void)
651 if (!g_tv_info.live_svc) {
652 _ERR("failed to get live service");
656 r = tv_service_live_get_last_channel(&service_id);
658 _ERR("failed to get current service id");
659 service_id = DEFAULT_SERVICE;
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");
668 g_tv_info.viewing_locked_channel = -1;
674 * Tunes to specific channel with major and minor.
676 * @param service_id The channel id
677 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
679 int tv_channel_direct_tune(long major, long minor)
681 GList *tvs_list = NULL, *filter = NULL;
682 TvServiceFilterNode *filter_node;
683 TvServiceChannel *tvs_data;
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);
691 filter = g_list_append(filter, (gpointer)filter_node);
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);
699 filter = g_list_append(filter, (gpointer)filter_node);
703 _ERR("failed to get filter");
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)
713 tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, 0);
715 r = tv_channel_tune_with_service_id(tvs_data->service_id);
717 _ERR("failed to get tvs_data");
721 if (r == TVS_ERROR_OK)
722 g_tv_info.viewing_locked_channel = -1;
724 g_list_foreach(tvs_list, (GFunc) g_free, NULL);
725 g_list_free(tvs_list);
728 g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
735 * Tunes to locked channel.
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
741 int tv_channel_tune_locked_channel(int service_id, char *password)
745 if (!g_tv_info.live_svc) {
746 _ERR("failed to get live service");
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");
757 g_tv_info.viewing_locked_channel = service_id;
763 * Tunes to next channel.
765 * Note that deleted channels and service channels will skipped.
767 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
769 int tv_channel_next(void)
771 TvServiceAntenna antenna_type;
774 if (!g_tv_info.live_svc) {
775 _ERR("failed to get live service");
779 r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
781 _ERR("failed to get antenna type");
785 r = tv_service_live_tune_up(g_tv_info.live_svc,
786 TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
788 _ERR("failed to tune up");
792 g_tv_info.viewing_locked_channel = -1;
798 * Tunes to previous channel.
800 * Note that deleted channels and service channels will skipped.
802 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
804 int tv_channel_prev(void)
806 TvServiceAntenna antenna_type;
809 if (!g_tv_info.live_svc) {
810 _ERR("failed to get live service");
814 r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
816 _ERR("failed to get antenna type");
820 r = tv_service_live_tune_down(g_tv_info.live_svc,
821 TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
823 _ERR("failed to tune down");
827 g_tv_info.viewing_locked_channel = -1;
833 * Sets the channel's favorite status.
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
839 int tv_channel_set_favorite(int service_id, Eina_Bool flag)
844 r = tv_service_add_favorite_channel(service_id);
846 _ERR("failed to add favorite channel");
850 r = tv_service_delete_favorite_channel(service_id);
852 _ERR("failed to delete favorite channel");
863 * If channel is added, the channel will be included at
864 * tv_channel_next, tv_channel_prev and tv_channel_get_list.
866 * @param service_id The channel id
867 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
869 int tv_channel_add_channel(int service_id)
873 r = tv_service_add_channel(service_id);
875 _ERR("failed to add channel");
883 * Deletes the channel.
885 * If channel is deleted, the channel will be omitted at
886 * tv_channel_next, tv_channel_prev and tv_channel_get_list.
888 * @param service_id The channel id
889 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
891 int tv_channel_del_channel(int service_id)
895 r = tv_service_delete_channel(service_id);
897 _ERR("failed to delete channel");
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
911 int tv_channel_lock_channel(int service_id, char *password)
915 r = tv_service_lock_channel(service_id, password);
917 _ERR("failed to lock channel");
925 * Unlocks the channel.
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
931 int tv_channel_unlock_channel(int service_id, char *password)
935 r = tv_service_unlock_channel(service_id, password);
937 _ERR("failed to unlock channel");
945 * Callback function for receives tv service events.
947 * @param event Event type
948 * @param user_data Not in use
949 * @param data Event specific detailed data
951 void _tv_service_event_cb(TvServiceLiveEvent event,
952 gpointer user_data, const gpointer data)
954 gboolean *lock_status;
957 case TV_SERVICE_LIVE_EVENT_TUNER_LOCK:
959 _ERR("failed to get data");
963 lock_status = (gboolean *) data;
964 if (g_tv_info.signal_cb)
965 g_tv_info.signal_cb(g_tv_info.signal_cb_data,
968 case TV_SERVICE_LIVE_EVENT_AUTO_DESTROY:
969 g_tv_info.live_svc = NULL;
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:
980 * Sets tv signal callback function.
982 * @param cb The function pointer to get callback
983 * @param data An Additional data to passed to callback
985 void tv_signal_cb_set(void (*cb)(void *data, int is_signal), void *data)
987 g_tv_info.signal_cb = cb;
988 g_tv_info.signal_cb_data = data;
992 * Sets window id for tv overlay.
994 * @param window_id The window id to overlay
995 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
997 int tv_overlay_set(void *window_id)
1001 if (!g_tv_info.live_svc) {
1002 _ERR("failed to get live service");
1006 r = tv_service_live_set_window_overlay(g_tv_info.live_svc, window_id);
1008 _ERR("failed to set overlay");
1016 * Destory the tv service handles.
1018 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1020 int tv_destroy(void)
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;
1031 r = tv_service_channel_info_destroy();
1033 _ERR("failed to destroy channel info service");
1035 if (g_tv_info.epg_svc) {
1036 r = tv_service_epg_destroy(g_tv_info.epg_svc);
1038 _ERR("failed to destroy epg service");
1039 g_tv_info.epg_svc = NULL;
1046 * Create the tv service handles.
1048 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1054 r = tv_service_live_create(&g_tv_info.live_svc);
1055 if (r != TVS_ERROR_OK) {
1056 _ERR("failed to create live service");
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");
1067 r = tv_service_channel_info_create();
1068 if (r != TVS_ERROR_OK) {
1069 _ERR("failed to create channel info service");
1073 r = tv_service_epg_create(&g_tv_info.epg_svc);
1074 if (r != TVS_ERROR_OK) {
1075 _ERR("failed to create epg service");
1086 * Pause the tv service handles.
1088 * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
1096 * Resume the tv service handles.
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.
1105 * @return 0 if successful; 1 if live service was destroyed; otherwise negative value is returned
1111 if (g_tv_info.live_svc)
1114 r = tv_service_live_create(&g_tv_info.live_svc);
1115 if (r != TVS_ERROR_OK) {
1116 _ERR("failed to create live service");
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");