Add channelinfo view 28/42628/3
authorjinwoo.shin <jw0227.shin@samsung.com>
Wed, 1 Jul 2015 01:19:45 +0000 (10:19 +0900)
committerjinwoo.shin <jw0227.shin@samsung.com>
Thu, 2 Jul 2015 01:19:28 +0000 (10:19 +0900)
Change-Id: Id78b567acc97d49c7acbcec4690b4b71b8f84533
Signed-off-by: jinwoo.shin <jw0227.shin@samsung.com>
17 files changed:
CMakeLists.txt
data/live-tv.edc
data/view/channelinfo.edc [new file with mode: 0644]
include/define.h
include/strings.h [new file with mode: 0644]
include/tv.h [new file with mode: 0644]
include/tv_service.h [new file with mode: 0644]
include/view_channelinfo.h [moved from include/main_view.h with 79% similarity]
packaging/org.tizen.live-tv.spec
res/images/ic_thumbnail_favorite_01.png [new file with mode: 0644]
res/images/ic_thumbnail_lock_01_foc.png [new file with mode: 0644]
res/images/ic_thumbnail_lock_01_nor.png [new file with mode: 0644]
src/main.c
src/main_view.c [deleted file]
src/tv.c [new file with mode: 0644]
src/tv_service.c [new file with mode: 0644]
src/view_channelinfo.c [new file with mode: 0644]

index bf712d2..ca1a401 100644 (file)
@@ -28,7 +28,7 @@ IF(NOT DEFINED RESDIR)
        SET(RESDIR "${PREFIX}/res")
 ENDIF(NOT DEFINED RESDIR)
 IF(NOT DEFINED IMAGEDIR)
-       SET(IMAGEDIR "${PREFIX}/res/images")
+       SET(IMAGEDIR "${PREFIX}/res/images/")
 ENDIF(NOT DEFINED IMAGEDIR)
 IF(NOT DEFINED EDJEDIR)
        SET(EDJEDIR "${PREFIX}/res/edje")
@@ -38,7 +38,9 @@ IF(NOT DEFINED MANIFESTDIR)
 ENDIF(NOT DEFINED MANIFESTDIR)
 
 SET(SRCS src/main.c
-               src/main_view.c)
+               src/tv.c
+               src/view_channelinfo.c
+               src/tv_service.c)
 
 SET(TARGET_EDJ "${PROJECT_NAME}.edj")
 SET(THEME_EDJ "${PROJECT_NAME}-theme.edj")
@@ -57,7 +59,9 @@ pkg_check_modules(PKGS REQUIRED
                ecore
                edje
                capi-appfw-application
-               app-utils)
+               app-utils
+               vconf
+               gobject-2.0)
 
 FOREACH(flag ${PKGS_CFLAGS})
        SET(EXTRA_CFLGAS "${EXTRA_CFLGAS} ${flag}")
@@ -70,5 +74,6 @@ CONFIGURE_FILE(${PACKAGE_NAME}.xml.in ${PACKAGE_NAME}.xml)
 
 INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR})
 INSTALL(FILES ${PACKAGE_NAME}.xml DESTINATION ${MANIFESTDIR})
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/res/images DESTINATION ${RESDIR})
 
 ADD_SUBDIRECTORY(data)
index a1cfbd7..26d27bf 100644 (file)
 #include "../include/define.h"
 
 collections {
-       group {
-               name: GRP_MAIN_VIEW;
-               parts {
-                       part {
-                               name, PART_CONTENT;
-                               type, RECT;
-                               scale, 1;
-                               description {
-                                       state, "default" 0.0;
-                               }
-                       }
-               }
-       }
+       #include "view/channelinfo.edc"
 }
diff --git a/data/view/channelinfo.edc b/data/view/channelinfo.edc
new file mode 100644 (file)
index 0000000..c0e95ad
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http,//www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../../include/define.h"
+
+group {
+       name, GRP_VIEW_CHANNELINFO;
+       parts {
+               part {
+                       name, "bg";
+                       type, RECT;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1.relative, 1.0 0.5;
+                               rel2.relative, 1.0 0.5;
+                               min, 536 174;
+                               align, 1.0 0.5;
+                               fixed, 1 1;
+                       }
+                       description {
+                               state, "focused" 0.0;
+                               inherit, "default" 0.0;
+                               color, COLOR_BG_FOCUSED;
+                       }
+               }
+               part {
+                       name, "padding.left_top";
+                       type, SPACER;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "bg";
+                                       relative, 0.0 0.0;
+                               }
+                               rel2 {
+                                       to, "bg";
+                                       relative, 0.0 0.0;
+                               }
+                               min, 28 26;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, PART_CHANNELINFO_CHANNEL;
+                       type, TEXT;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "padding.left_top";
+                                       relative, 1.0 1.0;
+                               }
+                               rel2 {
+                                       to, "padding.left_top";
+                                       relative, 1.0 1.0;
+                               }
+                               text {
+                                       font, FONT_LIGHT;
+                                       size, 28;
+                                       align, 0.0 0.5;
+                               }
+                               color, COLOR_TEXT_NORMAL;
+                               min, 344 32;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, "padding.title";
+                       type, SPACER;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, PART_CHANNELINFO_CHANNEL;
+                                       relative, 0.0 1.0;
+                               }
+                               rel2 {
+                                       to, PART_CHANNELINFO_CHANNEL;
+                                       relative, 0.0 1.0;
+                               }
+                               min, 0 6;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, PART_CHANNELINFO_TITLE;
+                       type, TEXT;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "padding.title";
+                                       relative, 0.0 1.0;
+                               }
+                               rel2 {
+                                       to, "padding.title";
+                                       relative, 0.0 1.0;
+                               }
+                               text {
+                                       font, FONT_LIGHT;
+                                       size, 28;
+                                       align, 0.0 0.5;
+                               }
+                               color, COLOR_TEXT_NORMAL;
+                               min, 484 32;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, "padding.time";
+                       type, SPACER;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, PART_CHANNELINFO_TITLE;
+                                       relative, 0.0 1.0;
+                               }
+                               rel2 {
+                                       to, PART_CHANNELINFO_TITLE;
+                                       relative, 0.0 1.0;
+                               }
+                               min, 0 24;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, PART_CHANNELINFO_TIME;
+                       type, TEXT;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "padding.time";
+                                       relative, 0.0 1.0;
+                               }
+                               rel2 {
+                                       to, "padding.time";
+                                       relative, 0.0 1.0;
+                               }
+                               text {
+                                       font, FONT_LIGHT;
+                                       size, 28;
+                                       align, 0.0 0.5;
+                               }
+                               color, 112 112 112 255;
+                               min, 484 28;
+                               align, 0.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, "padding.right_top";
+                       type, SPACER;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "bg";
+                                       relative, 1.0 0.0;
+                               }
+                               rel2 {
+                                       to, "bg";
+                                       relative, 1.0 0.0;
+                               }
+                               min, 22 28;
+                               align, 1.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+               part {
+                       name, PART_CHANNELINFO_STATUS;
+                       type, SWALLOW;
+                       scale, 1;
+                       description {
+                               state, "default" 0.0;
+                               rel1 {
+                                       to, "padding.right_top";
+                                       relative, 0.0 1.0;
+                               }
+                               rel2 {
+                                       to, "padding.right_top";
+                                       relative, 0.0 1.0;
+                               }
+                               min, 142 28;
+                               align, 1.0 0.0;
+                               fixed, 1 1;
+                       }
+               }
+       }
+}
index 42bb0dd..e11b3f4 100644 (file)
 #ifndef __LIVETV_DEFINE_H__
 #define __LIVETV_DEFINE_H__
 
-#define VIEW_MAIN "VIEW_MAIN"
-#define GRP_MAIN_VIEW "grp.main.view"
+#include "strings.h"
+
+#define KEY_SVCID "svcid"
+
+#define VIEW_CHANNELINFO "VIEW_CHANNELINFO"
 #define PART_CONTENT "part.content"
 
+#define FONT_REGULAR "TizenSans"
+#define FONT_LIGHT "TizenSans:style=Light"
+#define FONT_BOLD "TizenSans:style=Bold"
+
+#define COLOR_BG_NORMAL 255 255 255 255
+#define COLOR_BG_FOCUSED 0 119 246 255
+#define COLOR_TEXT_NORMAL 51 51 51 255
+#define COLOR_TEXT_FOCUSED 255 255 255 255
+
+#define IMG_LOCKED_NOR IMAGEDIR"ic_thumbnail_lock_01_nor.png"
+#define IMG_LOCKED_FOC IMAGEDIR"ic_thumbnail_lock_01_foc.png"
+#define IMG_FAVORITE_NOR IMAGEDIR"ic_thumbnail_favorite_01.png"
+#define IMG_FAVORITE_FOC IMG_FAVORITE_NOR
+
+#define GRP_VIEW_CHANNELINFO "grp.view.channelinfo"
+#define PART_CHANNELINFO_CHANNEL "part.channelinfo.channel"
+#define PART_CHANNELINFO_TITLE "part.channelinfo.title"
+#define PART_CHANNELINFO_TIME "part.channelinfo.time"
+#define PART_CHANNELINFO_STATUS "part.channelinfo.status"
+
 #endif /* __LIVETV_DEFINE_H__*/
diff --git a/include/strings.h b/include/strings.h
new file mode 100644 (file)
index 0000000..026a670
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __AIR_LIVETV_STRINGS_H__
+#define __AIR_LIVETV_STRINGS_H__
+
+#define STR_NOTITLE "No Information"
+#define STR_NOTIME "No Data"
+
+#endif /* __AIR_LIVETV_STRINGS_H__*/
diff --git a/include/tv.h b/include/tv.h
new file mode 100644 (file)
index 0000000..f98574a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TV_H__
+#define __TV_H__
+
+#include <stdbool.h>
+#include <Elementary.h>
+
+#define CHANNEL_NAME_MAX 128
+#define PROG_TITLE_MAX 128
+#define PROG_DESCR_MAX 128
+
+#define MAJOR_MAX 135
+#define MINOR_MAX 999
+#define EPG_PROGRAM_OFFSET 25000
+
+struct tv_channel_info {
+       int service_id;
+       long channel_major;
+       long channel_minor;
+       unsigned int channel_type;
+
+       char channel_name[CHANNEL_NAME_MAX];
+       time_t start_time;
+       time_t end_time;
+       time_t duration;
+
+       int locked;
+       int digital;
+       int favorite;
+       int remembered;
+       int tune_locked;
+};
+
+struct tv_program_info {
+       int service_id;
+       time_t start_time;
+       time_t end_time;
+       time_t duration;
+       time_t current_time;
+       char prog_title[PROG_TITLE_MAX];
+       char prog_description[PROG_DESCR_MAX];
+};
+
+struct tv_program_request {
+       void (*tv_program_cb)(Eina_List *program_list, void *user_data);
+       void *user_data;
+};
+
+int tv_create(void);
+int tv_destroy(void);
+int tv_pause(void);
+int tv_resume(void);
+
+int tv_overlay_set(void *window_id);
+
+Eina_List *tv_channel_get_list(void);
+Eina_List *tv_channel_search_by_number(long major, long minor);
+void tv_channel_del_list(Eina_List *channel_list);
+int tv_get_current_service_id(int *service_id);
+int tv_channel_tune(void);
+int tv_channel_direct_tune(long major, long minor);
+int tv_channel_tune_with_service_id(int service_id);
+int tv_channel_tune_locked_channel(int service_id, char *password);
+int tv_channel_next(void);
+int tv_channel_prev(void);
+int tv_channel_set_favorite(int service_id, Eina_Bool flag);
+int tv_channel_add_channel(int service_id);
+int tv_channel_del_channel(int service_id);
+int tv_channel_lock_channel(int service_id, char *password);
+int tv_channel_unlock_channel(int service_id, char *password);
+const struct tv_channel_info *tv_channel_get_info(void);
+void tv_channel_del_info(const struct tv_channel_info *channel_info);
+
+int tv_epg_get_program(int service_id, struct tv_program_request *request);
+int tv_epg_get_cache_program(int service_id, struct tv_program_request *request);
+int tv_epg_get_program_list(int service_id, struct tv_program_request *request);
+
+void tv_signal_cb_set(void (*cb)(void *data, int is_signal), void *data);
+
+#endif /* __TV_H__ */
diff --git a/include/tv_service.h b/include/tv_service.h
new file mode 100644 (file)
index 0000000..bae9260
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib-object.h>
+
+#define TVS_EPG_CURRENT_TIME                   -1
+#define PROGRAM_NAME_MAX_LEN                   25
+#define CHANNEL_FILTER_STRING_MAX_LEN  100
+
+/**
+ * An enumeration.
+ * Enumeration for tv service error type
+ */
+typedef enum
+{
+       TVS_ERROR_OK = 0,                                               /**< tv service error ok */
+       TVS_ERROR_NO_FREE_MEMORY = -1,                  /**< tv service error no free memory */
+       TVS_ERROR_HANDLE_UNINITIALIZED = -2,    /**< tv service error handle uninitialized */
+       TVS_ERROR_RPC_CALL_FAIL = -3,                   /**< tv service error rpc call fail */
+       TVS_ERROR_INVALID_PARAMETER = -4,               /**< tv service error invalid input parameter */
+       TVS_ERROR_INVALID_VALUE = -5,                   /**< tv service error invalid input value */
+       TVS_ERROR_NOT_AVAILABLE = -6,                   /**< tv service error not available */
+       TVS_ERROR_SEQLITE_BUSY = -7,                    /**< tv service error  SQLite busy */
+       TVS_ERROR_PROCESS_FAIL = -8,                    /**< tv service error  process error*/
+       TVS_ERROR_DATABASE_FAIL = -9,                   /**< tv service error  database query fail*/
+       TVS_ERROR_AUTHENTICATE_FAIL = -10,              /**< tv service error  Authenticate fail, ex, lock password match fail*/
+       TVS_ERROR_UNKNOWN = -255                                /**< tv service error unknown */
+} TvServiceError;
+
+typedef enum
+{
+       TV_SERVICE_CHANNEL_MODE_UNDEFINED = -1,         /* Unknown mode */
+       TV_SERVICE_CHANNEL_MODE_ALL,                            /* ALL channel mode */
+       TV_SERVICE_CHANNEL_MODE_DIGITAL,                        /* Digital channel mode */
+       TV_SERVICE_CHANNEL_MODE_ANALOG,                         /* Analog channel mode */
+       TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG,         /* Digital & Analog channel mode*/
+       TV_SERVICE_CHANNEL_MODE_FAVORITE,                       /* Analog channel mode */
+       TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG      /* Digital & Analog channel mode (include delete channel)*/
+} TvServiceChannelMode;
+
+/**
+ * An enumeration.
+ * Enumeration for channel list sort type.
+ */
+typedef enum
+{
+       CHANNEL_SORT_TYPE_MAJOR_MINOR_NUMBER = 0x0,
+       CHANNEL_SORT_TYPE_SERVICE_ID,
+       CHANNEL_SORT_TYPE_PROGRAM_NAME,
+       CHANNEL_SORT_TYPE_MAX
+} TvServiceChannelSortType;
+
+typedef enum
+{
+       TV_SERVICE_LIVE_EVENT_BEGIN,                    /* live event tune start*/
+       TV_SERVICE_LIVE_EVENT_TUNER_LOCK,               /* live event tune lock result*/
+       TV_SERVICE_LIVE_EVENT_CHANNEL_LOCK,             /* live event channel lock(video and audio mute)*/
+       TV_SERVICE_LIVE_EVENT_CHANNEL_UNLOCK,   /* live event channel unlock*/
+       TV_SERVICE_LIVE_EVENT_AUTO_DESTROY,             /* live event auto destroy*/
+       TV_SERVICE_LIVE_EVENT_RESOLUTION                /* live event resolution*/
+} TvServiceLiveEvent;
+typedef void (*TvServiceLiveCallback) (TvServiceLiveEvent event, gpointer user_data, const gpointer data);
+typedef struct
+{
+       gint freq;              /**the frequence*/
+       gint mod;               /**the modulation*/
+       gint apid;              /**the audio pid*/
+       gint vpid;              /**the videa pid*/
+       gint ppid;              /**the pmt pid*/
+       gint pro_num;   /**the program number*/
+} TvServiceLiveTuneInfo;
+
+typedef struct
+{
+       // TvServiceGenLive *proxy;                     /**the live proxy object*/
+       guint service_handle;                           /**the live service handle*/
+       gint antenna_type;                                      /**antenna type*/
+       gint service_id;                                        /**service id*/
+       gint unique;                                            /**identify*/
+       TvServiceLiveTuneInfo tune_info;        /**tune info*/
+       TvServiceLiveCallback call_back;        /**the call back function*/
+       gpointer user_data;                                     /**the user_data*/
+       gpointer window_id;                                     /**the window id*/
+} TvServiceLiveData;
+
+typedef gpointer TvServiceLive;
+
+typedef void* TvServiceEpg;
+
+typedef enum
+{
+       TVS_EPG_CREATE = 0,
+       TVS_EPG_DESTROY,
+       TVS_EPG_GET_CURRENT_PROGRAM,
+       TVS_EPG_GET_PROGRAM_LIST,
+       TVS_EPG_AUTO_DESTROY,
+       TVS_EPG_DATA_UPDATED
+} tvs_epg_event_e;
+
+typedef void (*TvServiceEpgCallback) (tvs_epg_event_e type, gpointer epg_data, gpointer user_data);
+
+typedef struct
+{
+       guint service_id;
+       guint event_id;
+       guint start_time;
+       guint etm_location;
+       guint length_in_seconds;
+       guint8 title_text[256];
+       guint current_time;
+       guint8 extended_text[256];
+} TvServiceEpgEventData;
+
+typedef enum
+{
+       TVS_MODULATION_TYPE_UNKNOWN = -1,
+       TVS_MODULATION_TYPE_QPSK,
+       TVS_MODULATION_TYPE_16QAM,
+       TVS_MODULATION_TYPE_32QAM,
+       TVS_MODULATION_TYPE_64QAM,
+       TVS_MODULATION_TYPE_128QAM,
+       TVS_MODULATION_TYPE_256QAM,
+       TVS_MODULATION_TYPE_AUTO_QAM,
+       TVS_MODULATION_TYPE_8VSB,
+       TVS_MODULATION_TYPE_16VSB,
+       TVS_MODULATION_TYPE_8PSK,
+       TVS_MODULATION_TYPE_NTSC,
+       TVS_MODULATION_TYPE_PAL,
+       TVS_MODULATION_TYPE_MAX
+} TvServiceModulationTpye;
+typedef enum
+{
+       TV_SERVICE_ANTENNA_TYPE_UNDEFINED = -1, /* Unknown type */
+       TV_SERVICE_ANTENNA_TYPE_AIR,                    /* Antenna air type */
+       TV_SERVICE_ANTENNA_TYPE_CABLE,                  /* Antenna cable type */
+       TV_SERVICE_ANTENNA_TYPE_ALL                             /*Antenna all type */
+} TvServiceAntenna;
+typedef enum
+{
+       TVS_VIDEO_TYPE_UNKNOWN = -1,
+       TVS_VIDEO_TYPE_MPEG2 ,
+       TVS_VIDEO_TYPE_H264,
+       TVS_VIDEO_TYPE_JPEG,
+       TVS_VIDEO_TYPE_AVS,
+       TVS_VIDEO_TYPE_MAX
+} TvServiceVideoType;
+
+typedef enum
+{
+       TVS_AUDIO_TYPE_UNKNOWN = -1,
+       TVS_AUDIO_TYPE_AC3,
+       TVS_AUDIO_TYPE_MPEG2,
+       TVS_AUDIO_TYPE_AAC,
+       TVS_AUDIO_TYPE_HE_AAC,
+       TVS_AUDIO_TYPE_MAX
+} TvServiceAudioType;
+typedef struct
+{
+       guint service_id;
+       guint frequency;
+       guint service_type;
+       guint channel_type;
+
+       gulong program_number;
+       gulong source_id;
+       gulong stream_id;
+       gulong pcr_id;
+       gulong major;
+       gulong minor;
+       gulong vpid;
+       gulong apid;
+       gulong pmt_pid;
+
+       gboolean hide_guide;
+       gboolean hidden;
+       gboolean locked;
+       gboolean remembered;
+       gboolean save_by_psi;
+       gboolean digital;
+       gboolean favorite;
+
+       gchar program_name[PROGRAM_NAME_MAX_LEN];
+
+       TvServiceModulationTpye modulation_type;
+       TvServiceAntenna antenna_type;
+       TvServiceVideoType video_type;
+       TvServiceAudioType audio_type;
+} TvServiceChannel;
+
+typedef enum {
+       CHANNEL_FILTER_MATCH_NONE = 0,
+       CHANNEL_FILTER_MATCH_EQUAL,
+       CHANNEL_FILTER_MATCH_MORE,
+       CHANNEL_FILTER_MATCH_LESS,
+       CHANNEL_FILTER_MATCH_UNEQUAL,
+       CHANNEL_FILTER_MATCH_CONTAIN,
+       CHANNEL_FILTER_MATCH_MAX
+} TvServiceChannelFilterMatchType;
+
+typedef enum {
+       TV_SERVICE_CHANNEL_DATA_NONE = 0,
+       TV_SERVICE_CHANNEL_DATA_SERVICE_ID,
+       TV_SERVICE_CHANNEL_DATA_FREQUENCY,
+       TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
+       TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
+       TV_SERVICE_CHANNEL_DATA_PROGRAM_NAME,
+       TV_SERVICE_CHANNEL_DATA_REMEMBERED,
+       TV_SERVICE_CHANNEL_DATA_MAX
+} TvServiceChannelDataAttr;
+
+typedef struct {
+       TvServiceChannelDataAttr attribute;
+       TvServiceChannelFilterMatchType match_type;
+       GValue *value;
+} TvServiceFilterNode;
+
+typedef struct {
+       gint identity;
+       // TvServiceGenEpg *proxy;
+       TvServiceEpgCallback cb;
+       gboolean cb_flag;
+       gpointer user_data;
+       GList *event_list;
+} EpgProxyData;
+
+typedef struct {
+       guint service_id;
+       guint start_time;
+       guint duration;
+       TvServiceEpgCallback event_callback;
+       gpointer event_callback_userdata;
+} EpgProxyEventData;
+
+gint tv_service_live_get_service_id (TvServiceLive live, gint * service_id);
+gint tv_service_get_channel (gint service_id, TvServiceChannel * channel);
+gint tv_service_get_channel_list (TvServiceChannelMode mode, TvServiceAntenna type, GList ** channels);
+gint tv_service_get_channel_list_ex (TvServiceChannelMode mode, TvServiceAntenna type, GList ** channels,
+               GList * filter, TvServiceChannelSortType sort_type);
+gint tv_service_epg_get_current_program (TvServiceEpg epg, guint service_id, TvServiceEpgCallback callback_func, gpointer user_data);
+gint tv_service_epg_get_cache_current_program (TvServiceEpg epg, guint service_id, TvServiceEpgEventData * app_data);
+gint tv_service_epg_get_program_list (TvServiceEpg epg, guint service_id, guint start_time, guint duration, TvServiceEpgCallback callback_func, gpointer user_data);
+gint tv_service_live_create (TvServiceLive * live);
+gint tv_service_live_destroy (TvServiceLive live);
+gint tv_service_live_tune_locked_channel (TvServiceLive live, gint service_id, gchar * password);
+gint tv_service_epg_create (TvServiceEpg * epg);
+gint tv_service_epg_destroy (TvServiceEpg epg);
+gint tv_service_live_get_last_channel (gint * service_id);
+gint tv_service_live_get_antenna_type (TvServiceLive live, TvServiceAntenna * type);
+gint tv_service_live_tune (TvServiceLive live, gint service_id);
+gint tv_service_lock_channel (gint service_id, gchar * password);
+gint tv_service_unlock_channel (gint service_id, gchar * password);
+gint tv_service_live_tune_down(TvServiceLive live, gint channel_mode,
+               TvServiceAntenna antenna_type);
+gint tv_service_live_tune_up(TvServiceLive live, gint channel_mode,
+               TvServiceAntenna antenna_type);
+gint tv_service_add_favorite_channel(gint service_id);
+gint tv_service_delete_favorite_channel(gint service_id);
+gint tv_service_add_channel(gint service_id);
+gint tv_service_delete_channel(gint service_id);
+gint tv_service_live_get_audio_mute(TvServiceLive live_svc, gboolean *mute);
+gint tv_service_live_set_audio_mute(TvServiceLive live_svc, gboolean mute);
+gint tv_service_live_get_volume(TvServiceLive live_svc, gdouble *vol);
+gint tv_service_live_set_volume(TvServiceLive live_svc, gdouble vol);
+gint tv_service_live_set_window_overlay(TvServiceLive live_svc, void *window_id);
+gint tv_service_channel_info_create();
+gint tv_service_channel_info_destroy();
+gint tv_service_live_register_callback(TvServiceLive live_svc,
+               void *_tv_service_event_cb, void *some_other_variable);
similarity index 79%
rename from include/main_view.h
rename to include/view_channelinfo.h
index 6beb35d..f5b01e2 100644 (file)
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef __LIVETV_MAIN_VIEW_H__
-#define __LIVETV_MAIN_VIEW_H__
+#ifndef __LIVETV_VIEW_CHANNELINFO_H__
+#define __LIVETV_VIEW_CHANNELINFO_H__
 
-view_class *view_main_get_vclass(void);
+view_class *view_channelinfo_get_vclass(void);
 
-#endif /* __LIVETV_MAIN_VIEW_H__*/
+#endif /* __LIVETV_VIEW_CHANNELINFO_H__*/
index 2b9626e..4b27b9c 100644 (file)
@@ -12,6 +12,8 @@ BuildRequires: pkgconfig(elementary)
 BuildRequires: pkgconfig(ecore)
 BuildRequires: pkgconfig(edje)
 BuildRequires: pkgconfig(app-utils)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(gobject-2.0)
 BuildRequires: gettext-devel
 BuildRequires: edje-bin
 
diff --git a/res/images/ic_thumbnail_favorite_01.png b/res/images/ic_thumbnail_favorite_01.png
new file mode 100644 (file)
index 0000000..6af72f0
Binary files /dev/null and b/res/images/ic_thumbnail_favorite_01.png differ
diff --git a/res/images/ic_thumbnail_lock_01_foc.png b/res/images/ic_thumbnail_lock_01_foc.png
new file mode 100644 (file)
index 0000000..f7c450d
Binary files /dev/null and b/res/images/ic_thumbnail_lock_01_foc.png differ
diff --git a/res/images/ic_thumbnail_lock_01_nor.png b/res/images/ic_thumbnail_lock_01_nor.png
new file mode 100644 (file)
index 0000000..dbfc763
Binary files /dev/null and b/res/images/ic_thumbnail_lock_01_nor.png differ
index 14c9672..4a9b31d 100644 (file)
 #include <app.h>
 #include <Elementary.h>
 #include <viewmgr.h>
+#include <inputmgr.h>
 #include <app_debug.h>
 
 #include "define.h"
-#include "main_view.h"
+#include "view_channelinfo.h"
+#include "tv.h"
+
+#define KEY_MAX 256
 
 SET_TAG(PACKAGE)
 
 struct _appdata {
        const char *name;
        Evas_Object *win;
+
+       int is_signal;
+};
+
+struct key_map {
+    const char *view;
+    const char *key[KEY_MAX];
+};
+
+static struct key_map g_kmap[] = {
+       {
+               VIEW_CHANNELINFO,
+               {
+                       KEY_ENTER, KEY_ENTER_REMOTE, KEY_CHANNELUP,
+                       KEY_CHANNELUP_REMOTE, KEY_CHANNELDOWN, KEY_CHANNELDOWN_REMOTE
+               }
+       },
+};
+
+static void _key_up_cb(int id, void *data, Evas *e, Evas_Object *obj,
+               Evas_Event_Key_Up *ev)
+{
+       size_t i, j;
+
+       for (i = 0; i < sizeof(g_kmap) / sizeof(*g_kmap); i++) {
+               j = 0;
+               while (g_kmap[i].key[j]) {
+                       if (!strcmp(ev->keyname, g_kmap[i].key[j])) {
+                               viewmgr_show_view(g_kmap[i].view);
+                               viewmgr_update_view(g_kmap[i].view, ev);
+                               return;
+                       }
+                       j++;
+               }
+       }
+}
+
+static input_handler key_handler = {
+       .key_up = _key_up_cb,
 };
 
 static Evas_Object *_add_win(const char *name)
 {
-       Evas_Object *win;
+       Evas_Object *win, *trans;
 
        win = elm_win_add(NULL, name, ELM_WIN_BASIC);
        if (!win) {
-               _ERR("failed to create win");
+               _ERR("elm_win_add failed");
                return NULL;
        }
        elm_win_alpha_set(win, EINA_FALSE);
@@ -44,21 +87,93 @@ static Evas_Object *_add_win(const char *name)
 
        evas_object_show(win);
 
+       trans = evas_object_rectangle_add(evas_object_evas_get(win));
+       if (!trans) {
+               _ERR("Create transparent layer failed");
+               evas_object_del(win);
+               return NULL;
+       }
+
+       /* for transparent layer */
+       evas_object_color_set(trans, 0, 0, 0, 0);
+       evas_object_render_op_set(trans, EVAS_RENDER_COPY);
+       elm_win_resize_object_add(win, trans);
+       evas_object_size_hint_weight_set(trans,
+                       EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_show(trans);
+
        return win;
 }
 
+int _set_tv_overlay(Evas_Object *win)
+{
+       int r;
+       Ecore_Wl_Window *wl_win;
+
+       wl_win = elm_win_wl_window_get(win);
+
+       r = tv_overlay_set(wl_win);
+
+       return r;
+}
+
+static void _tv_signal_cb(void *data, int is_signal)
+{
+       struct _appdata *ad;
+
+       if (!data) {
+               _ERR("failed to get data");
+               return;
+       }
+
+       ad = data;
+
+       if (ad->is_signal == is_signal)
+               return;
+
+       ad->is_signal = is_signal;
+}
+
 static void _pause(void *data)
 {
 }
 
 static void _resume(void *data)
 {
+       struct _appdata *ad;
+       int r;
+
+       if (!data) {
+               _ERR("failed to get data");
+               return;
+       }
+
+       ad = data;
+
+       r = tv_resume();
+       if (r < 0) {
+               _ERR("Resume tv service failed");
+               return;
+       } else if (r > 0) {
+               r = tv_channel_tune();
+               if (r < 0) {
+                       _ERR("Tune channel failed");
+                       return;
+               }
+       }
+
+       r = _set_tv_overlay(ad->win);
+       if (r < 0) {
+               _ERR("Set overlay failed");
+               return;
+       }
 }
 
 static bool _create(void *data)
 {
        struct _appdata *ad;
        Evas_Object *win;
+       int r;
 
        if (!data) {
                _ERR("failed to get data");
@@ -75,16 +190,32 @@ static bool _create(void *data)
                return false;
        }
 
+       r = tv_create();
+       if (r < 0) {
+               _ERR("Create TV failed");
+               evas_object_del(win);
+               return false;
+       }
+
+       r = _set_tv_overlay(ad->win);
+       if (r < 0) {
+               _ERR("Set overlay failed");
+               evas_object_del(win);
+               return false;
+       }
+
        if (!viewmgr_create(win)) {
                _ERR("failed to initialize viewmgr");
                evas_object_del(win);
                return false;
        }
 
-       viewmgr_add_view(view_main_get_vclass(), NULL);
+       viewmgr_add_view(view_channelinfo_get_vclass(), NULL);
 
        ad->win = win;
 
+       tv_signal_cb_set(_tv_signal_cb, ad);
+       inputmgr_add_callback(ad->win, 0, &key_handler, NULL);
        return true;
 }
 
@@ -99,7 +230,11 @@ static void _terminate(void *data)
 
        ad = data;
 
-       viewmgr_remove_view(VIEW_MAIN);
+       tv_destroy();
+
+       inputmgr_remove_callback(ad->win, &key_handler);
+
+       viewmgr_remove_view(VIEW_CHANNELINFO);
        viewmgr_destroy();
 
        if (ad->win) {
@@ -110,19 +245,23 @@ static void _terminate(void *data)
 
 static void _control(app_control_h control, void *data)
 {
-       struct _appdata *ad;
+       char *svcid;
+       int r;
 
        if (!data) {
                _ERR("failed to get data");
                return;
        }
 
-       ad = data;
-
-       if (ad->win)
-               elm_win_activate(ad->win);
+       r = app_control_get_extra_data(control, KEY_SVCID, &svcid);
+       if (r == SERVICE_ERROR_NONE) {
+               tv_channel_tune_with_service_id(atoll(svcid));
+               free(svcid);
+       } else {
+               tv_channel_tune();
+       }
 
-       viewmgr_push_view(VIEW_MAIN);
+       viewmgr_show_view(VIEW_CHANNELINFO);
 }
 
 int main(int argc, char *argv[])
diff --git a/src/main_view.c b/src/main_view.c
deleted file mode 100644 (file)
index a159cdf..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <Elementary.h>
-#include <viewmgr.h>
-#include <inputmgr.h>
-#include <app_debug.h>
-
-#include "define.h"
-#include "main_view.h"
-
-struct _priv {
-       Evas_Object *base;
-};
-
-static Evas_Object *_create(Evas_Object *win, void *data)
-{
-       struct _priv *priv;
-       Evas_Object *base;
-
-       if (!win) {
-               _ERR("failed to get win object");
-               return NULL;
-       }
-
-       priv = calloc(1, sizeof(*priv));
-       if (!priv) {
-               _ERR("failed to allocate priv");
-               return NULL;
-       }
-
-       base = elm_layout_add(win);
-       if (!base) {
-               _ERR("failed to create base object");
-               free(priv);
-               return NULL;
-       }
-       elm_layout_file_set(base, EDJEFILE, GRP_MAIN_VIEW);
-
-       evas_object_size_hint_weight_set(base,
-                       EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-       elm_win_resize_object_add(win, base);
-
-       priv->base = base;
-       viewmgr_set_view_data(VIEW_MAIN, priv);
-
-       return base;
-}
-
-static void _show(void *view_data)
-{
-       struct _priv *priv;
-
-       if (!view_data) {
-               _ERR("failed to get view data");
-               return;
-       }
-
-       priv = (struct _priv *) view_data;
-
-       evas_object_show(priv->base);
-}
-
-static void _hide(void *view_data)
-{
-       struct _priv *priv;
-
-       if (!view_data) {
-               _ERR("failed to get view data");
-               return;
-       }
-
-       priv = (struct _priv *) view_data;
-
-       evas_object_hide(priv->base);
-}
-
-static void _destroy(void *view_data)
-{
-       struct _priv *priv;
-
-       if (!view_data) {
-               _ERR("failed to get view data");
-               return;
-       }
-
-       priv = (struct _priv *) view_data;
-
-       evas_object_del(priv->base);
-
-       free(priv);
-}
-
-static view_class vclass = {
-       .view_id = VIEW_MAIN,
-       .create = _create,
-       .show = _show,
-       .hide = _hide,
-       .destroy = _destroy,
-};
-
-view_class *view_main_get_vclass(void)
-{
-       return &vclass;
-}
diff --git a/src/tv.c b/src/tv.c
new file mode 100644 (file)
index 0000000..abacbe9
--- /dev/null
+++ b/src/tv.c
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <app.h>
+#include <iconv.h>
+#include <math.h>
+#include <app_debug.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "define.h"
+#include "tv.h"
+#include "tv_service.h"
+
+#define DEFAULT_SERVICE 1
+
+/**
+ * The Storage structure to used by tv related functions and events.
+ */
+struct _tv_info {
+       /**< The handle to use tv service live api. */
+       TvServiceLive live_svc;
+       /**< The handle to use tv service epg api. */
+       TvServiceEpg epg_svc;
+
+       /**< Stores service id if tune to locked channel was succeeded. */
+       int viewing_locked_channel;
+
+       /**< The function pointer to pass tv signal event */
+       void (*signal_cb)(void *data, int is_signal);
+       /**< An Additional data to passed to tv signal event */
+       void *signal_cb_data;
+};
+
+static struct _tv_info g_tv_info;
+
+/**
+ * Gets the tv_channel_info with supplied TvServiceChannel.
+ *
+ * Abstracts tv service data structure.
+ *
+ * @param channel The channel data defined by tv service
+ * @return Channel information, or NULL if fails
+ */
+static struct tv_channel_info *_tv_channel_get_info(TvServiceChannel *channel)
+{
+       struct tv_channel_info *channel_info = NULL;
+
+       if (!channel) {
+               _ERR("failed to get channel");
+               return NULL;
+       }
+
+       channel_info = calloc(1, sizeof(*channel_info));
+       if (!channel_info) {
+               _ERR("failed to calloc channel info");
+               return NULL;
+       }
+
+       channel_info->service_id = channel->service_id;
+       channel_info->channel_major = channel->major;
+       channel_info->channel_minor = channel->minor;
+       channel_info->channel_type = channel->channel_type;
+       channel_info->locked = channel->locked;
+       channel_info->digital = channel->digital;
+       channel_info->favorite = channel->favorite;
+       channel_info->remembered = channel->remembered;
+       strncpy(channel_info->channel_name, channel->program_name,
+               CHANNEL_NAME_MAX);
+
+       if (channel->service_id == g_tv_info.viewing_locked_channel)
+               channel_info->tune_locked = EINA_TRUE;
+
+       return channel_info;
+}
+
+/**
+ * Frees the tv_channel_info.
+ *
+ * @param channel_info tv_channel_info pointer to be freed
+ */
+void tv_channel_del_info(const struct tv_channel_info *channel_info)
+{
+       if (!channel_info) {
+               _ERR("failed to get channel info");
+               return;
+       }
+
+       free((void *)channel_info);
+}
+
+/**
+ * Gets current channel's TvServiceChannel data from tv service.
+ *
+ * @param channel The pointer to store TvServiceChannel
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+static int _tv_get_channel(TvServiceChannel *channel)
+{
+       gint svc_id;
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_get_service_id(g_tv_info.live_svc, &svc_id);
+       if (r < 0) {
+               _ERR("failed to get service id");
+               return -1;
+       }
+
+       r = tv_service_get_channel(svc_id, channel);
+       if (r < 0) {
+               _ERR("failed to get channel");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Returns current channel's info.
+ *
+ * tv_channel_get_info retrieves current channel's information
+ * from tv service.
+ *
+ * @return Returns current channel info, or NULL if fails
+ */
+const struct tv_channel_info *tv_channel_get_info(void)
+{
+       const struct tv_channel_info *channel_info;
+       TvServiceChannel channel;
+       int r;
+
+       r = _tv_get_channel(&channel);
+       if (r < 0) {
+               _ERR("failed to get channel");
+               return NULL;
+       }
+
+       channel_info = _tv_channel_get_info(&channel);
+
+       return channel_info;
+}
+
+/**
+ * Returns tv_program_info with supplied TvServiceEpgEventData.
+ *
+ * Abstracts tv service data structure.
+ *
+ * @param prog TvServiceEpgEventData passed from tv service
+ * @return Returns tv_program_info, or NULL if fails
+ */
+static struct tv_program_info *_tv_get_program_info(TvServiceEpgEventData *prog)
+{
+       struct tv_program_info *prog_info;
+
+       prog_info = calloc(1, sizeof(*prog_info));
+       if (!prog_info) {
+               _ERR("failed to calloc program info");
+               return NULL;
+       }
+
+       prog_info->service_id = prog->service_id;
+       prog_info->start_time = prog->start_time;
+       prog_info->end_time = prog->start_time + prog->length_in_seconds;
+       prog_info->duration = prog->length_in_seconds;
+       prog_info->current_time = prog->current_time;
+       strncpy(prog_info->prog_title, (char *)prog->title_text,
+                       sizeof(prog_info->prog_title) - 1);
+       strncpy(prog_info->prog_description, (char *)prog->extended_text,
+                       sizeof(prog_info->prog_description) - 1);
+
+       return prog_info;
+}
+
+/**
+ * Gets current channel's service id from tv service.
+ *
+ * @param service_id The pointer to store service id
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_get_current_service_id(int *service_id)
+{
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_get_service_id(g_tv_info.live_svc, service_id);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get current service info");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Frees epg list.
+ *
+ * @param epg_list Eina_List to be freed
+ */
+static void _tv_epg_del_list(Eina_List *epg_list)
+{
+       struct tv_program_info *data;
+
+       EINA_LIST_FREE(epg_list, data)
+               free(data);
+}
+
+/**
+ * Callback function to get EPG program list from tv service.
+ *
+ * _tv_epg_event_cb is called from tv service when banner
+ * have requested to get program data.
+ * If this function is called, then derives program list from epg_list
+ * and calls banner's callback function which included in user_data.
+ *
+ * @param type Event type
+ * @param epg_list EPG program list
+ * @param user_data tv_program_request to handle request
+ */
+static void _tv_epg_event_cb(tvs_epg_event_e type, GList *epg_list,
+               void *user_data)
+{
+       int i;
+       Eina_List *list = NULL;
+       TvServiceEpgEventData *epg_data;
+       struct tv_program_info *prog_info;
+       struct tv_program_request *request;
+
+       if (!user_data) {
+               _ERR("failed to get user_data");
+               return;
+       }
+
+       for (i = 0; i < g_list_length(epg_list); i++) {
+               epg_data = (TvServiceEpgEventData *)
+                               g_list_nth_data(epg_list, i);
+
+               if (!epg_data)
+                       continue;
+
+               prog_info = _tv_get_program_info(epg_data);
+               if (prog_info)
+                       list = eina_list_append(list, prog_info);
+       }
+
+       request = (struct tv_program_request *) user_data;
+       if (request->tv_program_cb)
+               request->tv_program_cb(list, request->user_data);
+
+       if (list)
+               _tv_epg_del_list(list);
+
+       free(request);
+}
+
+/**
+ * Send a request to tv service to get a current program with supplied service_id.
+ *
+ * Beware that service_id should be current tuned channel.
+ * If not, calling this function may cause unexpected behavior.
+ * And note that get a EPG program is asynchronous operation.
+ * So tv_program_request should be supplied to get a result from tv service.
+ *
+ * @param service_id The channel id to get current program
+ * @param request The structure for return program data which contains function pointer
+ *        and additional data for banner
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_epg_get_program(int service_id, struct tv_program_request *request)
+{
+       int r;
+
+       if (!g_tv_info.epg_svc) {
+               _ERR("failed to get epg service");
+               return -1;
+       }
+
+       if (!request) {
+               _ERR("failed to get tv_program_request");
+               return -1;
+       }
+
+       r = tv_service_epg_get_current_program(g_tv_info.epg_svc, service_id,
+                       (TvServiceEpgCallback) _tv_epg_event_cb, request);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get epg get current program : %d", service_id);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Gets a cached current program with supplied service_id from tv service.
+ *
+ * Note that this function is vaild only when tv service having a cached data
+ * on that channel.
+ * To have a cached data, the channel ever been tuned before calling
+ * this function.
+ *
+ * @param service_id The channel id to get current program
+ * @param request The structure for return program data which contains
+ *        function pointer and additional data for banner
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_epg_get_cache_program(int service_id, struct tv_program_request *request)
+{
+       Eina_List *list = NULL;
+       TvServiceEpgEventData epg_data;
+       struct tv_program_info *prog_info;
+
+       int r;
+
+       if (!g_tv_info.epg_svc) {
+               _ERR("failed to get epg service");
+               return -1;
+       }
+
+       if (!request) {
+               _ERR("failed to get tv_program_request");
+               return -1;
+       }
+
+       r = tv_service_epg_get_cache_current_program(
+                       g_tv_info.epg_svc, service_id, &epg_data);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get epg get cached current program : %d",
+                               service_id);
+               return -1;
+       }
+
+       prog_info = _tv_get_program_info(&epg_data);
+       if (prog_info)
+               list = eina_list_append(list, prog_info);
+
+       if (request->tv_program_cb)
+               request->tv_program_cb(list, request->user_data);
+
+       if (list)
+               _tv_epg_del_list(list);
+
+       free(request);
+
+       return 0;
+}
+
+/**
+ * Sends a request to tv service to get programs with supplied service_id.
+ *
+ * Beware that service_id should be current tuned channel.
+ * If not, calling this function may cause unexpected behavior.
+ * And note that get a EPG program is asynchronous operation.
+ * So tv_program_request should be supplied to get a result from tv service.
+ *
+ * @param service_id The channel id to get current program
+ * @param request The structure for return program data which contains function pointer and additional data for banner
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_epg_get_program_list(int service_id,
+               struct tv_program_request *request)
+{
+       int r;
+
+       if (!g_tv_info.epg_svc) {
+               _ERR("failed to get epg service");
+               return -1;
+       }
+
+       if (!request) {
+               _ERR("failed to get tv_program_request");
+               return -1;
+       }
+
+       r = tv_service_epg_get_program_list(g_tv_info.epg_svc, service_id,
+                       TVS_EPG_CURRENT_TIME, EPG_PROGRAM_OFFSET,
+                       (TvServiceEpgCallback) _tv_epg_event_cb, request);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get epg get current program");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Frees the TvServiceFilterNode.
+ *
+ * @param data TvServiceFilterNode pointer to be freed
+ */
+static void _tv_channel_free_filter(gpointer data)
+{
+       TvServiceFilterNode *filter_node;
+
+       if (!data)
+               return;
+
+       filter_node = (TvServiceFilterNode *) data;
+
+       g_value_unset(filter_node->value);
+       g_free(filter_node->value);
+       g_free(filter_node);
+}
+
+/**
+ * Gets a available channel list.
+ *
+ * Note that deleted channels and service channels are excluded by default.
+ *
+ * @return Available channel list, or NULL if fails
+ */
+Eina_List *tv_channel_get_list()
+{
+       GList *tvs_list = NULL;
+       Eina_List *channel_list = NULL;
+       TvServiceChannel *tvs_data = NULL;
+       const struct tv_channel_info *channel_info;
+       int r, i;
+
+       r = tv_service_get_channel_list(
+                       TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG,
+                       TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get channel list");
+               return NULL;
+       }
+
+       for (i = 0; i < g_list_length(tvs_list); i++) {
+               tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
+               if (tvs_data) {
+                       channel_info = _tv_channel_get_info(tvs_data);
+                       if (channel_info)
+                               channel_list = eina_list_append(channel_list,
+                                               channel_info);
+                       free(tvs_data);
+               }
+       }
+
+       return channel_list;
+}
+
+TvServiceFilterNode *_tv_channel_get_filter(
+               TvServiceChannelDataAttr attribute, int type, void *data)
+{
+       TvServiceFilterNode *filter;
+       GValue *value;
+
+       filter = g_malloc0(sizeof(*filter));
+       if (!filter)
+               return NULL;
+
+       filter->attribute = attribute;
+
+       value = g_malloc0(sizeof(GValue));
+       if (!value) {
+               g_free(filter);
+               return NULL;
+       }
+
+       switch (type) {
+       case G_TYPE_STRING:
+               g_value_init(value, G_TYPE_STRING);
+               g_value_set_string(value, data);
+
+               filter->match_type = CHANNEL_FILTER_MATCH_CONTAIN;
+               break;
+       case G_TYPE_INT:
+               g_value_init(value, G_TYPE_INT);
+               g_value_set_int(value, (gint) data);
+
+               filter->match_type = CHANNEL_FILTER_MATCH_EQUAL;
+               break;
+       }
+       filter->value = value;
+
+       return filter;
+}
+
+/**
+ * Search channels that are starts with supplied major and minor number.
+ *
+ * Note that deleted channels and service channels are excluded by default.
+ *
+ * @param major Major channel number to search
+ * @param minor Minor channel number to search
+ * @return Found channel list, or NULL if fails
+ */
+Eina_List *tv_channel_search_by_number(long major, long minor)
+{
+       char buf[CHANNEL_FILTER_STRING_MAX_LEN];
+       GList *tvs_list = NULL, *filter = NULL;
+       TvServiceFilterNode *filter_node;
+       TvServiceChannel *tvs_data;
+       Eina_List *channel_list = NULL;
+       const struct tv_channel_info *channel_info;
+       int i, r;
+
+       if (major > 0 && major < MAJOR_MAX) {
+               snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", major);
+
+               filter_node = _tv_channel_get_filter(
+                               TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
+                               G_TYPE_STRING, buf);
+               if (filter_node)
+                       filter = g_list_append(filter, (gpointer)filter_node);
+       }
+
+       if (minor > 0 && minor < MINOR_MAX) {
+               snprintf(buf, CHANNEL_FILTER_STRING_MAX_LEN, "%ld", minor);
+
+               filter_node = _tv_channel_get_filter(
+                               TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
+                               G_TYPE_STRING, buf);
+               if (filter_node)
+                       filter = g_list_append(filter, (gpointer)filter_node);
+       }
+
+       if (!filter) {
+               _ERR("failed to get filter");
+               return NULL;
+       }
+
+       r = tv_service_get_channel_list_ex(
+                       TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
+                       TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to get channel list");
+               goto free;
+       }
+
+       for (i = 0; i < g_list_length(tvs_list); i++) {
+               tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, i);
+               if (!tvs_data)
+                       continue;
+
+               channel_info = _tv_channel_get_info(tvs_data);
+               if (channel_info)
+                       channel_list = eina_list_append(channel_list,
+                                       channel_info);
+               free(tvs_data);
+       }
+
+free:
+       if (tvs_list)
+               g_list_free(tvs_list);
+
+       g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
+       g_list_free(filter);
+
+       return channel_list;
+}
+
+/**
+ * Frees the tv_channel_info.
+ *
+ * @param channel_list channel_list pointer to be freed
+ */
+void tv_channel_del_list(Eina_List *channel_list)
+{
+       struct tv_channel_info *data;
+
+       EINA_LIST_FREE(channel_list, data)
+               free(data);
+}
+
+/**
+ * Tunes to specific channel with service id.
+ *
+ * @param service_id The channel id
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_tune_with_service_id(int service_id)
+{
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_tune(g_tv_info.live_svc, service_id);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to set service");
+               return -1;
+       }
+
+       g_tv_info.viewing_locked_channel = -1;
+
+       return 0;
+}
+
+/**
+ * Tunes to last viewed channel.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_tune(void)
+{
+       int service_id;
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_get_last_channel(&service_id);
+       if (r < 0) {
+               _ERR("failed to get current service id");
+               service_id = DEFAULT_SERVICE;
+       }
+
+       r = tv_service_live_tune(g_tv_info.live_svc, service_id);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to set service");
+               return -1;
+       }
+
+       g_tv_info.viewing_locked_channel = -1;
+
+       return 0;
+}
+
+/**
+ * Tunes to specific channel with major and minor.
+ *
+ * @param service_id The channel id
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_direct_tune(long major, long minor)
+{
+       GList *tvs_list = NULL, *filter = NULL;
+       TvServiceFilterNode *filter_node;
+       TvServiceChannel *tvs_data;
+       int r;
+
+       if (major > 0 && major < MAJOR_MAX) {
+               filter_node = _tv_channel_get_filter(
+                               TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER,
+                               G_TYPE_INT, (void *) major);
+               if (filter_node)
+                       filter = g_list_append(filter, (gpointer)filter_node);
+       }
+
+       if (minor > 0 && minor < MINOR_MAX) {
+               filter_node = _tv_channel_get_filter(
+                               TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER,
+                               G_TYPE_INT, (void *) minor);
+               if (filter_node)
+                       filter = g_list_append(filter, (gpointer)filter_node);
+       }
+
+       if (!filter) {
+               _ERR("failed to get filter");
+               return -1;
+       }
+
+       r = tv_service_get_channel_list_ex(
+                       TV_SERVICE_CHANNEL_MODE_ALL_DIGITAL_ANALOG,
+                       TV_SERVICE_ANTENNA_TYPE_ALL, &tvs_list, filter, 0);
+       if (r != TVS_ERROR_OK)
+               goto free;
+
+       tvs_data = (TvServiceChannel *) g_list_nth_data(tvs_list, 0);
+       if (tvs_data)
+               r = tv_channel_tune_with_service_id(tvs_data->service_id);
+       else {
+               _ERR("failed to get tvs_data");
+               r = -1;
+       }
+
+       if (r == TVS_ERROR_OK)
+               g_tv_info.viewing_locked_channel = -1;
+
+       g_list_foreach(tvs_list, (GFunc) g_free, NULL);
+       g_list_free(tvs_list);
+
+free:
+       g_list_foreach(filter, (GFunc) _tv_channel_free_filter, NULL);
+       g_list_free(filter);
+
+       return r;
+}
+
+/**
+ * Tunes to locked channel.
+ *
+ * @param service_id The channel id
+ * @param password 4 digit password
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_tune_locked_channel(int service_id, char *password)
+{
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_tune_locked_channel(g_tv_info.live_svc,
+                       service_id, password);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to set service");
+               return -1;
+       }
+
+       g_tv_info.viewing_locked_channel = service_id;
+
+       return 0;
+}
+
+/**
+ * Tunes to next channel.
+ *
+ * Note that deleted channels and service channels will skipped.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_next(void)
+{
+       TvServiceAntenna antenna_type;
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
+       if (r < 0) {
+               _ERR("failed to get antenna type");
+               return -1;
+       }
+
+       r = tv_service_live_tune_up(g_tv_info.live_svc,
+                       TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
+       if (r < 0) {
+               _ERR("failed to tune up");
+               return -1;
+       }
+
+       g_tv_info.viewing_locked_channel = -1;
+
+       return 0;
+}
+
+/**
+ * Tunes to previous channel.
+ *
+ * Note that deleted channels and service channels will skipped.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_prev(void)
+{
+       TvServiceAntenna antenna_type;
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_get_antenna_type(g_tv_info.live_svc, &antenna_type);
+       if (r < 0) {
+               _ERR("failed to get antenna type");
+               return -1;
+       }
+
+       r = tv_service_live_tune_down(g_tv_info.live_svc,
+                       TV_SERVICE_CHANNEL_MODE_DIGITAL_ANALOG, antenna_type);
+       if (r < 0) {
+               _ERR("failed to tune down");
+               return -1;
+       }
+
+       g_tv_info.viewing_locked_channel = -1;
+
+       return 0;
+}
+
+/**
+ * Sets the channel's favorite status.
+ *
+ * @param service_id The channel id
+ * @param flag The value to be set
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_set_favorite(int service_id, Eina_Bool flag)
+{
+       int r;
+
+       if (flag) {
+               r = tv_service_add_favorite_channel(service_id);
+               if (r < 0) {
+                       _ERR("failed to add favorite channel");
+                       return -1;
+               }
+       } else {
+               r = tv_service_delete_favorite_channel(service_id);
+               if (r < 0) {
+                       _ERR("failed to delete favorite channel");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * Adds the channel.
+ *
+ * If channel is added, the channel will be included at
+ * tv_channel_next, tv_channel_prev and tv_channel_get_list.
+ *
+ * @param service_id The channel id
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_add_channel(int service_id)
+{
+       int r;
+
+       r = tv_service_add_channel(service_id);
+       if (r < 0) {
+               _ERR("failed to add channel");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Deletes the channel.
+ *
+ * If channel is deleted, the channel will be omitted at
+ * tv_channel_next, tv_channel_prev and tv_channel_get_list.
+ *
+ * @param service_id The channel id
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_del_channel(int service_id)
+{
+       int r;
+
+       r = tv_service_delete_channel(service_id);
+       if (r < 0) {
+               _ERR("failed to delete channel");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Locks the channel.
+ *
+ * @param service_id The channel id
+ * @param password 4 digits password
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_lock_channel(int service_id, char *password)
+{
+       int r;
+
+       r = tv_service_lock_channel(service_id, password);
+       if (r < 0) {
+               _ERR("failed to lock channel");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Unlocks the channel.
+ *
+ * @param service_id The channel id
+ * @param password 4 digits password
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_channel_unlock_channel(int service_id, char *password)
+{
+       int r;
+
+       r = tv_service_unlock_channel(service_id, password);
+       if (r < 0) {
+               _ERR("failed to unlock channel");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Callback function for receives tv service events.
+ *
+ * @param event Event type
+ * @param user_data Not in use
+ * @param data Event specific detailed data
+ */
+void _tv_service_event_cb(TvServiceLiveEvent event,
+               gpointer user_data, const gpointer data)
+{
+       gboolean *lock_status;
+
+       switch (event) {
+       case TV_SERVICE_LIVE_EVENT_TUNER_LOCK:
+               if (!data) {
+                       _ERR("failed to get data");
+                       break;
+               }
+
+               lock_status = (gboolean *) data;
+               if (g_tv_info.signal_cb)
+                       g_tv_info.signal_cb(g_tv_info.signal_cb_data,
+                                       *lock_status);
+               break;
+       case TV_SERVICE_LIVE_EVENT_AUTO_DESTROY:
+               g_tv_info.live_svc = NULL;
+               break;
+       case TV_SERVICE_LIVE_EVENT_RESOLUTION:
+       case TV_SERVICE_LIVE_EVENT_BEGIN:
+       case TV_SERVICE_LIVE_EVENT_CHANNEL_LOCK:
+       case TV_SERVICE_LIVE_EVENT_CHANNEL_UNLOCK:
+               break;
+       }
+}
+
+/**
+ * Sets tv signal callback function.
+ *
+ * @param cb The function pointer to get callback
+ * @param data An Additional data to passed to callback
+ */
+void tv_signal_cb_set(void (*cb)(void *data, int is_signal), void *data)
+{
+       g_tv_info.signal_cb = cb;
+       g_tv_info.signal_cb_data = data;
+}
+
+/**
+ * Sets window id for tv overlay.
+ *
+ * @param window_id The window id to overlay
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_overlay_set(void *window_id)
+{
+       int r;
+
+       if (!g_tv_info.live_svc) {
+               _ERR("failed to get live service");
+               return -1;
+       }
+
+       r = tv_service_live_set_window_overlay(g_tv_info.live_svc, window_id);
+       if (r < 0) {
+               _ERR("failed to set overlay");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Destory the tv service handles.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_destroy(void)
+{
+       int r;
+
+       if (g_tv_info.live_svc) {
+               r = tv_service_live_destroy(g_tv_info.live_svc);
+               if (r != TVS_ERROR_OK)
+                       _ERR("failed to destroy live service");
+               g_tv_info.live_svc = NULL;
+       }
+
+       r = tv_service_channel_info_destroy();
+       if (r < 0)
+               _ERR("failed to destroy channel info service");
+
+       if (g_tv_info.epg_svc) {
+               r = tv_service_epg_destroy(g_tv_info.epg_svc);
+               if (r != 0)
+                       _ERR("failed to destroy epg service");
+               g_tv_info.epg_svc = NULL;
+       }
+
+       return 0;
+}
+
+/**
+ * Create the tv service handles.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_create(void)
+{
+       int r;
+
+       r = tv_service_live_create(&g_tv_info.live_svc);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to create live service");
+               goto err;
+       }
+
+       r = tv_service_live_register_callback(g_tv_info.live_svc,
+                       _tv_service_event_cb, NULL);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to register live callback");
+               goto err;
+       }
+
+       r = tv_service_channel_info_create();
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to create channel info service");
+               goto err;
+       }
+
+       r = tv_service_epg_create(&g_tv_info.epg_svc);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to create epg service");
+               goto err;
+       }
+
+       return 0;
+err:
+       tv_destroy();
+       return -1;
+}
+
+/**
+ * Pause the tv service handles.
+ *
+ * @return If the operation was sucessful 0 is returned; otherwise negative value is returned
+ */
+int tv_pause(void)
+{
+       return 0;
+}
+
+/**
+ * Resume the tv service handles.
+ *
+ * Live service could be destroyed by tv service while app is pausing.
+ * If live service is destroyed, then _tv_service_event_cb sets
+ * g_tv_info.live_svc to NULL.
+ * So if g_tv_info.live_svc is NULL, then recreates live service and returns 1.
+ * Therefore, if tv_resume returns 1, then app needs to be set overlay and tune.
+ * Or returns 0, then app just needs to set overlay.
+ *
+ * @return 0 if successful; 1 if live service was destroyed; otherwise negative value is returned
+ */
+int tv_resume(void)
+{
+       int r;
+
+       if (g_tv_info.live_svc)
+               return 0;
+
+       r = tv_service_live_create(&g_tv_info.live_svc);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to create live service");
+               goto err;
+       }
+
+       r = tv_service_live_register_callback(g_tv_info.live_svc,
+                       _tv_service_event_cb, NULL);
+       if (r != TVS_ERROR_OK) {
+               _ERR("failed to register live callback");
+               goto err;
+       }
+
+       return 1;
+
+err:
+       tv_destroy();
+       return -1;
+}
diff --git a/src/tv_service.c b/src/tv_service.c
new file mode 100644 (file)
index 0000000..ea18fe7
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/time.h>
+#include <glib.h>
+#include <vconf.h>
+#include <app_debug.h>
+
+#include "tv.h"
+#include "tv_service.h"
+
+#define DEFAULT_TIMER_INTERVAL 1.0
+#define TVS_VOLUME_MIN 0.0
+#define TVS_VOLUME_MAX 10.0
+#define TVS_PASSWORD "0000"
+
+#define VCONF_CHANNEL "db/menu/broadcasting/last_channel"
+
+struct dummy_tv_service_struct
+{
+       guint service_id;
+       TvServiceEpgCallback callback_func;
+       gpointer user_data;
+};
+
+struct _tv_service_info
+{
+       gdouble volume;
+       gboolean is_mute;
+};
+
+struct _tv_service_info tv_service_info;
+GList *channel_list = NULL, *program_list = NULL;
+
+static void init_constant_channel_data(TvServiceChannel *channel)
+{
+       memset(channel, 0, sizeof(TvServiceChannel));
+
+       channel->frequency = 567000000;
+       channel->service_type = 2;
+       channel->channel_type = 0;
+
+       channel->program_number = 1;
+       channel->source_id = 1;
+       // channel->stream_id =
+       channel->pcr_id = 17;
+       channel->minor = 1;
+       channel->vpid = 17;
+       // channel->apid =
+       channel->pmt_pid =16;
+
+       channel->hide_guide = FALSE;
+       channel->hidden = FALSE;
+       channel->locked = FALSE;
+       channel->remembered = TRUE;
+       channel->save_by_psi = TRUE;
+       channel->digital = TRUE;
+
+       channel->modulation_type = TVS_MODULATION_TYPE_8VSB;
+       channel->antenna_type = TV_SERVICE_ANTENNA_TYPE_CABLE;
+       channel->video_type = TVS_VIDEO_TYPE_MPEG2;
+       channel->audio_type = TVS_AUDIO_TYPE_AAC;
+}
+
+/* Creates 3 programs for each channel (service_id)
+ * with one hour duration each.
+*/
+static void init_program_data(int service_id, struct timeval tv)
+{
+       GList *epg_program_glist = NULL;
+       int i;
+       for (i = 0; i < 15; i++)
+       {
+               TvServiceEpgEventData *epg_data = NULL;
+               epg_data = (TvServiceEpgEventData *)g_malloc0 (sizeof(TvServiceEpgEventData));
+               memset(epg_data, 0, sizeof(TvServiceEpgEventData));
+
+               epg_data->service_id = service_id;
+               // epg_data->event_id =
+               if (i == 0 && service_id % 2 == 0)
+               {
+                       // Start first programs of some channels 30 minutes earlier than current time
+                       // and substitute the difference with length
+                       epg_data->start_time = tv.tv_sec - 30 * 60;
+                       epg_data->length_in_seconds = 90 * 60;
+               } else {
+                       epg_data->start_time = tv.tv_sec + i * 60 * 60;
+                       epg_data->length_in_seconds = 60 * 60;
+               }
+               epg_data->etm_location= 1;
+               snprintf(epg_data->title_text, 255, "Awesome Program %d", i + 1);
+               snprintf(epg_data->extended_text, 255, "Description of Awesome Program %d", i + 1);
+               epg_data->current_time = tv.tv_sec;
+               epg_program_glist = g_list_append (epg_program_glist, epg_data);
+       }
+       program_list = g_list_append(program_list, (gpointer)epg_program_glist);
+}
+
+static void init_data()
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       int i;
+       for (i = 1; i < 6; i++)
+       {
+               TvServiceChannel *channel = NULL;
+               channel = (TvServiceChannel *)g_malloc0(sizeof(TvServiceChannel));
+               init_constant_channel_data(channel);
+               channel->service_id = i;
+               channel->major = (5 + i);
+               channel->favorite = i % 2 == 0 ? TRUE : FALSE;
+               snprintf(channel->program_name, PROGRAM_NAME_MAX_LEN - 1, "Super Channel %d", i);
+               channel_list = g_list_append(channel_list, (gpointer)channel);
+               init_program_data(i, tv);
+       }
+
+       tv_service_info.volume = TVS_VOLUME_MAX / 2;
+       tv_service_info.is_mute = FALSE;
+}
+
+/* 9 */
+gint tv_service_live_get_service_id(TvServiceLive live, gint *service_id)
+{
+       TvServiceLiveData *live_proxy;
+
+       if (!live || !service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       live_proxy = (TvServiceLiveData *)live;
+       *service_id = live_proxy->service_id;
+
+       _DBG("service_id = %d", *service_id);
+
+       return TVS_ERROR_OK;
+}
+
+/* 10 */
+gint tv_service_get_channel(gint service_id, TvServiceChannel *channel)
+{
+       _DBG("service_id = %d", service_id);
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       TvServiceChannel *local_channel = NULL;
+       local_channel = (TvServiceChannel *)g_list_nth_data(channel_list, service_id - 1);
+       memcpy(channel, local_channel, sizeof(TvServiceChannel));
+
+       return TVS_ERROR_OK;
+}
+
+/* We intentionally make a new copy of the channel_list,
+ * because live-tv frees the list internally
+ */
+TvServiceChannel *first_match_channel = NULL;
+static gint _get_channel_list(TvServiceChannelMode channel_mode, TvServiceAntenna antenna_type, GList **channels,
+               GList *filter, TvServiceChannelSortType sort_type)
+{
+       GList *tmp_list = NULL;
+       TvServiceChannel *from, *to;
+       int i, size = g_list_length(channel_list);
+       if (filter == NULL)
+       {
+               // return the whole list
+               for (i = 0; i < size; i++)
+               {
+                       from = g_list_nth_data(channel_list, i);
+                       to = (TvServiceChannel *)malloc(sizeof(TvServiceChannel));
+                       memcpy(to, from, sizeof(TvServiceChannel));
+                       tmp_list = g_list_append(tmp_list, to);
+               }
+               *channels = tmp_list;
+               return TVS_ERROR_OK;
+       }
+
+       TvServiceFilterNode *filter_node;
+       // FIXME: g_list_length(filter) is always 1, why?
+       filter_node = g_list_nth_data(filter, 0);
+       switch (filter_node->attribute)
+       {
+       case TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER:
+       case TV_SERVICE_CHANNEL_DATA_MINOR_NUMBER:
+               if (filter_node->match_type == CHANNEL_FILTER_MATCH_CONTAIN)
+               {
+                       _DBG("CHANNEL_FILTER_MATCH_CONTAIN");
+                       gchar *str_value;
+                       str_value = (gchar *)g_value_get_string((const GValue *)filter_node->value);
+                       gulong gul_major_minor;
+                       int length;
+                       for (i = 0; i < size; i++)
+                       {
+                               from = g_list_nth_data(channel_list, i);
+                               gul_major_minor = filter_node->attribute == TV_SERVICE_CHANNEL_DATA_MAJOR_NUMBER
+                                               ? from->major : from->minor;
+                               length = snprintf(NULL, 0, "%lu", gul_major_minor);
+                               char char_major_minor[length + 1];
+                               snprintf(char_major_minor, length + 1, "%lu", gul_major_minor);
+                               if (strstr(char_major_minor, str_value))
+                               {
+                                       if (first_match_channel == NULL)
+                                       {
+                                               // reserve a copy for CHANNEL_FILTER_MATCH_EQUAL
+                                               first_match_channel = (TvServiceChannel *)malloc(sizeof(TvServiceChannel));
+                                               memcpy(first_match_channel, from, sizeof(TvServiceChannel));
+                                       }
+                                       to = (TvServiceChannel *)malloc(sizeof(TvServiceChannel));
+                                       memcpy(to, from, sizeof(TvServiceChannel));
+                                       tmp_list = g_list_append(tmp_list, to);
+                               }
+                       }
+               }
+               else
+               {
+                       // FIXME: filter_node->value is always NULL at this point, why?
+                       // gint *int_value;
+                       // int_value = g_value_get_int(filter_node->value);
+                       if (filter_node->match_type == CHANNEL_FILTER_MATCH_EQUAL)
+                       {
+                               _DBG("CHANNEL_FILTER_MATCH_EQUAL");
+                               if (first_match_channel)
+                               {
+                                       tmp_list = g_list_append(tmp_list, first_match_channel);
+                                       first_match_channel = NULL;
+                               }
+                       }
+                       else if (filter_node->match_type == CHANNEL_FILTER_MATCH_MORE)
+                       {
+                               _DBG("[NOT IMPLEMENTED YET] channel_filter_match_more");
+                       }
+                       else if (filter_node->match_type == CHANNEL_FILTER_MATCH_LESS)
+                       {
+                               _DBG("[NOT IMPLEMENTED YET] channel_filter_match_less");
+                       }
+                       else if (filter_node->match_type == CHANNEL_FILTER_MATCH_UNEQUAL)
+                       {
+                               _DBG("[NOT IMPLEMENTED YET] channel_filter_match_unequal");
+                       }
+                       else
+                       {
+                               _ERR("match_type[%d] is out of range", filter_node->match_type);
+                               return TVS_ERROR_PROCESS_FAIL;
+                       }
+               }
+               break;
+       case TV_SERVICE_CHANNEL_DATA_SERVICE_ID:
+       case TV_SERVICE_CHANNEL_DATA_FREQUENCY:
+       case TV_SERVICE_CHANNEL_DATA_REMEMBERED:
+       case TV_SERVICE_CHANNEL_DATA_PROGRAM_NAME:
+               _DBG("case %d is not implemented yet", filter_node->attribute);
+               break;
+       default:
+               _ERR("attribute[%d] is out of range", filter_node->attribute);
+               return TVS_ERROR_PROCESS_FAIL;
+       }
+
+       if (g_list_length(tmp_list) < 1) {
+               first_match_channel = NULL;
+               *channels = NULL;
+               return TVS_ERROR_PROCESS_FAIL;
+       }
+       *channels = tmp_list;
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_get_channel_list(TvServiceChannelMode mode, TvServiceAntenna antenna_type, GList **channels)
+{
+       _DBG("");
+       return _get_channel_list(mode, antenna_type, channels, NULL, 0);
+}
+
+gint tv_service_get_channel_list_ex(TvServiceChannelMode mode, TvServiceAntenna antenna_type, GList **channels,
+               GList *filter, TvServiceChannelSortType sort_type)
+{
+       _DBG("");
+       return _get_channel_list(mode, antenna_type, channels, filter, sort_type);
+}
+
+static Eina_Bool _tv_service_epg_get_current_program_cb(void *data)
+{
+       struct dummy_tv_service_struct *tvs_epg;
+       tvs_epg = data;
+       TvServiceEpgCallback callback_func = tvs_epg->callback_func;
+       callback_func(TVS_EPG_GET_CURRENT_PROGRAM,
+                                       g_list_nth_data(program_list, tvs_epg->service_id - 1),
+                                       tvs_epg->user_data);
+       free(tvs_epg);
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+/* 11 */
+gint tv_service_epg_get_current_program(TvServiceEpg epg, guint service_id,
+                                                               TvServiceEpgCallback callback_func, gpointer user_data)
+{
+       _DBG("service_id = %d", service_id);
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+
+       struct dummy_tv_service_struct *tvs_epg;
+       tvs_epg = calloc(1, sizeof(*tvs_epg));
+       tvs_epg->service_id = service_id;
+       tvs_epg->callback_func = callback_func;
+       tvs_epg->user_data = user_data;
+       ecore_timer_add(DEFAULT_TIMER_INTERVAL, _tv_service_epg_get_current_program_cb, tvs_epg);
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_epg_get_cache_current_program(TvServiceEpg epg, guint service_id,
+                                                               TvServiceEpgEventData *app_data)
+{
+       _DBG("service_id = %d", service_id);
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       GList *prog_list = NULL;
+       prog_list = g_list_nth_data(program_list, service_id - 1);
+       TvServiceEpgEventData *epg_data = NULL;
+       gint result = TVS_ERROR_NOT_AVAILABLE;
+       int i;
+       for (i = 0; i < g_list_length(prog_list); i++)
+       {
+               epg_data = (TvServiceEpgEventData *)g_list_nth_data(prog_list, i);
+               if (epg_data == NULL)
+               {
+                       continue;
+               }
+               if (epg_data->start_time <= tv.tv_sec &&
+                       epg_data->start_time + epg_data->length_in_seconds > tv.tv_sec)
+               {
+                       app_data->service_id = epg_data->service_id;
+                       app_data->event_id = epg_data->event_id;
+                       app_data->start_time = epg_data->start_time;
+                       app_data->etm_location = epg_data->etm_location;
+                       app_data->length_in_seconds = epg_data->length_in_seconds;
+                       g_stpcpy ((gchar *)app_data->title_text, (gchar *)epg_data->title_text);
+                       g_stpcpy ((gchar *)app_data->extended_text, (gchar *)epg_data->extended_text);
+                       app_data->current_time = tv.tv_sec;
+                       result = TVS_ERROR_OK;
+                       break;
+               }
+       }
+
+       return result;
+}
+
+gint tv_service_epg_get_program_list(TvServiceEpg epg, guint service_id,
+                                                               guint start_time, guint duration,
+                                                               TvServiceEpgCallback callback_func, gpointer user_data)
+{
+       _DBG("service_id = %d", service_id);
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+
+       struct dummy_tv_service_struct *tvs_epg;
+       tvs_epg = calloc(1, sizeof(*tvs_epg));
+       tvs_epg->service_id = service_id;
+       tvs_epg->callback_func = callback_func;
+       tvs_epg->user_data = user_data;
+       ecore_timer_add(DEFAULT_TIMER_INTERVAL, _tv_service_epg_get_current_program_cb, tvs_epg);
+
+       return TVS_ERROR_OK;
+}
+
+/* 7 */
+gint tv_service_live_tune(TvServiceLive live, gint service_id)
+{
+       TvServiceLiveData *live_proxy;
+
+       if (!live)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       _DBG("service_id = %d", service_id);
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       live_proxy = (TvServiceLiveData *)live;
+       live_proxy->service_id = service_id;
+
+       vconf_set_int(VCONF_CHANNEL, service_id);
+
+       return TVS_ERROR_OK;
+}
+
+static gboolean _check_lock_unlock_password(gchar *password)
+{
+       if (g_strcmp0(TVS_PASSWORD, password))
+       {
+               return FALSE;
+       }
+       return TRUE;
+}
+
+gint tv_service_live_tune_locked_channel(TvServiceLive live, gint service_id, gchar * password)
+{
+       if (!live)
+               return TVS_ERROR_HANDLE_UNINITIALIZED;
+
+       if (!password) {
+               _ERR("Password is NULL");
+               return TVS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       TvServiceChannel *channel = NULL;
+       channel = (TvServiceChannel *)g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       if (_check_lock_unlock_password(password))
+               return TVS_ERROR_OK;
+       else
+               return TVS_ERROR_AUTHENTICATE_FAIL;
+}
+
+gint tv_service_live_tune_up(TvServiceLive live, gint channel_mode, TvServiceAntenna antenna_type)
+{
+       TvServiceLiveData *live_proxy;
+       gint service_id;
+
+       if (!live)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       live_proxy = (TvServiceLiveData *)live;
+       service_id = (live_proxy->service_id) % g_list_length(channel_list) + 1;
+
+       return tv_service_live_tune(live, service_id);
+}
+
+gint tv_service_live_get_antenna_type(TvServiceLive live, TvServiceAntenna *type)
+{
+       _DBG("");
+       TvServiceLiveData *live_proxy;
+       live_proxy = (TvServiceLiveData *)live;
+       *type = live_proxy->antenna_type;
+
+       return TVS_ERROR_OK;
+}
+
+/* 6 */
+gint tv_service_live_get_last_channel(gint *service_id)
+{
+       gint r = -1;
+
+       r = vconf_get_int(VCONF_CHANNEL, service_id);
+       if (r < 0)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       if ((*service_id) < 1)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_live_tune_down(TvServiceLive live, gint channel_mode,
+               TvServiceAntenna antenna_type)
+{
+       TvServiceLiveData *live_proxy;
+       gint service_id;
+
+       if (!live)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       live_proxy = (TvServiceLiveData *)live;
+       service_id = live_proxy->service_id - 1;
+       if (service_id == 0)
+               service_id = g_list_length(channel_list);
+
+       return tv_service_live_tune(live, service_id);
+}
+
+gint tv_service_add_favorite_channel(gint service_id)
+{
+       TvServiceChannel *channel = NULL;
+
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel = (TvServiceChannel *) g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel->favorite = TRUE;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_delete_favorite_channel(gint service_id)
+{
+       TvServiceChannel *channel = NULL;
+
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel = (TvServiceChannel *) g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel->favorite = FALSE;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_add_channel(gint service_id)
+{
+       TvServiceChannel *channel = NULL;
+
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel = (TvServiceChannel *) g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel->remembered = TRUE;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_delete_channel(gint service_id)
+{
+       TvServiceChannel *channel = NULL;
+
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel = (TvServiceChannel *) g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+               return TVS_ERROR_NOT_AVAILABLE;
+
+       channel->remembered = FALSE;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_lock_channel(gint service_id, gchar *password)
+{
+       if (!password)
+       {
+               _ERR("Password is NULL");
+               return TVS_ERROR_INVALID_PARAMETER;
+       }
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+       TvServiceChannel *channel = NULL;
+       channel = (TvServiceChannel *)g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+       if (channel->locked)
+       {
+               // if channel is already locked, simply return success code
+               return TVS_ERROR_OK;
+       }
+
+       if (_check_lock_unlock_password(password))
+       {
+               channel->locked = TRUE;
+               return TVS_ERROR_OK;
+       }
+
+       return TVS_ERROR_AUTHENTICATE_FAIL;
+}
+
+gint tv_service_unlock_channel(gint service_id, gchar *password)
+{
+       if (!password)
+       {
+               _ERR("Password is NULL");
+               return TVS_ERROR_INVALID_PARAMETER;
+       }
+       if (service_id < 1 || g_list_length(channel_list) < service_id)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+       TvServiceChannel *channel = NULL;
+       channel = (TvServiceChannel *)g_list_nth_data(channel_list, service_id - 1);
+       if (!channel)
+       {
+               return TVS_ERROR_NOT_AVAILABLE;
+       }
+       if (!channel->locked)
+       {
+               // if channel is already unlocked, simply return success code
+               return TVS_ERROR_OK;
+       }
+
+       if (_check_lock_unlock_password(password))
+       {
+               channel->locked = FALSE;
+               return TVS_ERROR_OK;
+       }
+
+       return TVS_ERROR_AUTHENTICATE_FAIL;
+}
+
+gint tv_service_live_get_audio_mute(TvServiceLive live_svc, gboolean *mute)
+{
+       if (!live_svc)
+               return TVS_ERROR_HANDLE_UNINITIALIZED;
+
+       if (!mute)
+               return TVS_ERROR_INVALID_PARAMETER;
+
+       *mute = tv_service_info.is_mute;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_live_set_audio_mute(TvServiceLive live_svc, gboolean mute)
+{
+       if (!live_svc)
+               return TVS_ERROR_HANDLE_UNINITIALIZED;
+
+       if (mute != TRUE && mute != FALSE)
+               return TVS_ERROR_INVALID_VALUE;
+
+       tv_service_info.is_mute = mute;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_live_get_volume(TvServiceLive live_svc, gdouble *vol)
+{
+       if (!live_svc)
+               return TVS_ERROR_HANDLE_UNINITIALIZED;
+
+       if (!vol)
+               return TVS_ERROR_INVALID_PARAMETER;
+
+       *vol = tv_service_info.volume;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_live_set_volume(TvServiceLive live_svc, gdouble vol)
+{
+       if (!live_svc)
+               return TVS_ERROR_HANDLE_UNINITIALIZED;
+
+       if (vol < TVS_VOLUME_MIN || vol > TVS_VOLUME_MAX)
+               return TVS_ERROR_INVALID_VALUE;
+
+       tv_service_info.is_mute = FALSE;
+       tv_service_info.volume = vol;
+
+       return TVS_ERROR_OK;
+}
+
+/* 5 */
+/* 8 */
+gint tv_service_live_set_window_overlay(TvServiceLive live_svc, void *window_id)
+{
+       _DBG("");
+       return 0;
+}
+
+/* 1 */
+gint tv_service_live_create(TvServiceLive *live)
+{
+       _DBG("");
+       init_data();
+       TvServiceLiveData *local = NULL;
+       local = (TvServiceLiveData*)g_malloc0 (sizeof (TvServiceLiveData));
+       // local->service_handle =
+       local->antenna_type = TV_SERVICE_ANTENNA_TYPE_CABLE;
+       local->service_id = -1;
+       // local->unique =
+
+       local->tune_info.freq = 567000000;
+       local->tune_info.mod = 7;
+       // local->tune_info.apid =
+       local->tune_info.vpid = 17;
+       local->tune_info.ppid = 17;
+       local->tune_info.pro_num = 1;
+
+       // local->call_back =
+       // local->user_data =
+       // local->window_id =
+
+       *live = (TvServiceLive)local;
+
+       return TVS_ERROR_OK;
+}
+
+void _free_program_data(gpointer data)
+{
+       GList *epg_program_glist;
+       epg_program_glist = (GList *) data;
+       if (epg_program_glist)
+               g_list_free_full(epg_program_glist, (GDestroyNotify)g_free);
+}
+
+gint tv_service_live_destroy(TvServiceLive live)
+{
+       _DBG("");
+       g_list_free_full(program_list, (GDestroyNotify) _free_program_data);
+       g_list_free_full(channel_list, (GDestroyNotify)g_free);
+
+       TvServiceLiveData *live_proxy;
+       live_proxy = (TvServiceLiveData *)live;
+       g_free (live_proxy);
+       live_proxy = NULL;
+
+       return TVS_ERROR_OK;
+}
+
+/* 2 */
+gint tv_service_live_register_callback(TvServiceLive live_svc,
+               void *_tv_service_event_cb, void *some_other_variable)
+{
+       _DBG("");
+       return 0;
+}
+
+/* 3 */
+gint tv_service_channel_info_create()
+{
+       _DBG("");
+       return 0;
+}
+
+gint tv_service_channel_info_destroy()
+{
+       _DBG("");
+       return 0;
+}
+
+/* 4 */
+gint tv_service_epg_create(TvServiceEpg * epg)
+{
+       _DBG("");
+       EpgProxyData *proxy_data = NULL;
+       proxy_data = (EpgProxyData *)g_malloc0 (sizeof (EpgProxyData));
+       // proxy_data->identity = identity;
+       proxy_data->event_list = NULL;
+       proxy_data->cb_flag = FALSE;
+       *epg = proxy_data;
+
+       return TVS_ERROR_OK;
+}
+
+gint tv_service_epg_destroy(TvServiceEpg epg)
+{
+       _DBG("");
+       EpgProxyData *proxy_data = (EpgProxyData *)epg;
+       // g_object_unref (proxy_data->proxy);
+       g_list_free_full (proxy_data->event_list, (GDestroyNotify)g_free);
+       g_free (proxy_data);
+
+       return TVS_ERROR_OK;
+}
diff --git a/src/view_channelinfo.c b/src/view_channelinfo.c
new file mode 100644 (file)
index 0000000..365a0f8
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Elementary.h>
+#include <viewmgr.h>
+#include <inputmgr.h>
+#include <app_debug.h>
+
+#include "define.h"
+#include "tv.h"
+#include "view_channelinfo.h"
+
+#define HIDE_DUR 10.0
+#define BUF_MAX 128
+#define STATUS_BOX_PADDING 10
+
+struct _priv {
+       Evas_Object *base;
+       Ecore_Timer *hide_timer;
+       const struct tv_channel_info *channel_info;
+};
+
+static int _get_program_time(char *buf, int buf_len, time_t start_time,
+               time_t end_time)
+{
+       struct tm tm;
+       int r;
+
+       if (start_time >= end_time) {
+               _ERR("invalid time");
+               return -1;
+       }
+
+       localtime_r(&start_time, &tm);
+       r = strftime(buf, buf_len, "%I:%M %P -", &tm);
+       if (r <= 0)
+               return -1;
+
+       localtime_r(&end_time, &tm);
+       r = strftime(buf + r, buf_len - r, " %I:%M %P", &tm);
+       if (r <= 0)
+               return -1;
+
+       return 0;
+}
+
+static Eina_Bool _hide_timer(void *data)
+{
+       struct _priv *priv;
+
+       if (!data)
+               return ECORE_CALLBACK_CANCEL;
+
+       priv = data;
+
+       priv->hide_timer = NULL;
+
+       viewmgr_hide_view(VIEW_CHANNELINFO);
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+static void _start_hide_timer(struct _priv *priv)
+{
+       if (!priv) {
+               _ERR("failed to get priv");
+               return;
+       }
+
+       if (priv->hide_timer)
+               ecore_timer_reset(priv->hide_timer);
+       else
+               priv->hide_timer = ecore_timer_add(HIDE_DUR, _hide_timer, priv);
+}
+
+static void _add_icon(Evas_Object *box, const char *file)
+{
+       Evas_Object *ic;
+
+       ic = elm_icon_add(box);
+       if (!ic) {
+               _ERR("failed to create icon");
+               return;
+       }
+
+       elm_image_file_set(ic, file, NULL);
+       elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
+       elm_image_no_scale_set(ic, EINA_TRUE);
+       evas_object_show(ic);
+
+       elm_box_pack_end(box, ic);
+}
+
+static void _pack_icon_box(struct _priv *priv,
+               const struct tv_channel_info *channel_info)
+{
+       Evas_Object *box;
+
+       if (!priv) {
+               _ERR("failed to get priv");
+               return;
+       }
+
+       box = elm_box_add(priv->base);
+       if (!box) {
+               _ERR("failed to create box");
+               return;
+       }
+       evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND,
+                       EVAS_HINT_EXPAND);
+       elm_box_horizontal_set(box, EINA_TRUE);
+       elm_box_padding_set(box, STATUS_BOX_PADDING, 0);
+       elm_box_align_set(box, 1.0, 0.5);
+       elm_object_part_content_set(priv->base, PART_CHANNELINFO_STATUS, box);
+
+       if (channel_info->locked)
+               _add_icon(box, IMG_LOCKED_NOR);
+       if (channel_info->favorite)
+               _add_icon(box, IMG_FAVORITE_NOR);
+}
+
+static void _load_channel_text(struct _priv *priv,
+               const struct tv_channel_info *channel_info)
+{
+       char buf[BUF_MAX];
+
+       if (!priv || !channel_info) {
+               _ERR("failed to get priv and channel info");
+               return;
+       }
+
+       if (channel_info->channel_minor > 0 &&
+                       channel_info->channel_minor < MINOR_MAX)
+               snprintf(buf, sizeof(buf), "%lu-%lu %s",
+                               channel_info->channel_major,
+                               channel_info->channel_minor,
+                               channel_info->channel_name);
+       else
+               snprintf(buf, sizeof(buf), "%lu %s",
+                               channel_info->channel_major,
+                               channel_info->channel_name);
+
+       elm_object_part_text_set(priv->base,
+                       PART_CHANNELINFO_CHANNEL, buf);
+
+       elm_object_part_text_set(priv->base,
+                       PART_CHANNELINFO_TITLE,
+                       STR_NOTITLE);
+       elm_object_part_text_set(priv->base,
+                       PART_CHANNELINFO_TIME,
+                       STR_NOTIME);
+}
+
+static void _load_program_info(struct _priv *priv,
+               const struct tv_program_info *prog)
+{
+       char buf[BUF_MAX];
+       int r;
+
+       if (!priv || !prog) {
+               _ERR("failed to get priv and program data");
+               return;
+       }
+
+       if (prog->start_time && prog->end_time) {
+               r = _get_program_time(buf, sizeof(buf),
+                               prog->start_time,
+                               prog->end_time);
+               if (!r)
+                       elm_object_part_text_set(priv->base,
+                                       PART_CHANNELINFO_TIME, buf);
+       }
+
+       if (strlen(prog->prog_title) > 0)
+               elm_object_part_text_set(priv->base,
+                               PART_CHANNELINFO_TITLE, prog->prog_title);
+}
+
+static void _tv_program_cb(Eina_List *prog_list, void *data)
+{
+       struct _priv *priv;
+       struct tv_program_info *prog = NULL;
+
+       if (!data) {
+               _ERR("failed to get data");
+               return;
+       }
+
+       priv = data;
+
+       prog = (struct tv_program_info *) eina_list_nth(prog_list, 0);
+       if (prog) {
+               if (priv->channel_info &&
+                               prog->service_id != priv->channel_info->service_id)
+                       return;
+               else
+                       _load_program_info(priv, prog);
+       } else {
+               _ERR("failed to get tv_program_info");
+       }
+
+       _start_hide_timer(priv);
+}
+
+static void _update_channel_info(struct _priv *priv)
+{
+       struct tv_program_request *prog_req;
+       int r;
+
+       if (!priv) {
+               _ERR("failed to get priv");
+               return;
+       }
+
+       if (priv->channel_info) {
+               tv_channel_del_info(priv->channel_info);
+               priv->channel_info = NULL;
+       }
+
+       priv->channel_info = tv_channel_get_info();
+       if (!priv->channel_info) {
+               _ERR("failed to get channel info");
+
+               return;
+       }
+
+       if (priv->hide_timer) {
+               ecore_timer_del(priv->hide_timer);
+               priv->hide_timer = NULL;
+       }
+
+       _load_channel_text(priv, priv->channel_info);
+       _pack_icon_box(priv, priv->channel_info);
+
+       prog_req = calloc(1, sizeof(*prog_req));
+       prog_req->tv_program_cb = _tv_program_cb;
+       prog_req->user_data = priv;
+       r = tv_epg_get_program(priv->channel_info->service_id,
+                       prog_req);
+       if (r < 0)
+               _start_hide_timer(priv);
+}
+
+static Evas_Object *_create(Evas_Object *win, void *data)
+{
+       struct _priv *priv;
+       Evas_Object *base;
+
+       if (!win) {
+               _ERR("failed to get win object");
+               return NULL;
+       }
+
+       priv = calloc(1, sizeof(*priv));
+       if (!priv) {
+               _ERR("failed to allocate priv");
+               return NULL;
+       }
+
+       base = elm_layout_add(win);
+       if (!base) {
+               _ERR("failed to create base object");
+               free(priv);
+               return NULL;
+       }
+       elm_layout_file_set(base, EDJEFILE, GRP_VIEW_CHANNELINFO);
+
+       evas_object_size_hint_weight_set(base,
+                       EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       elm_win_resize_object_add(win, base);
+
+       priv->base = base;
+       viewmgr_set_view_data(VIEW_CHANNELINFO, priv);
+
+       return base;
+}
+
+static void _show(void *view_data)
+{
+       struct _priv *priv;
+
+       if (!view_data) {
+               _ERR("failed to get view data");
+               return;
+       }
+
+       priv = view_data;
+
+       _update_channel_info(priv);
+
+       evas_object_show(priv->base);
+}
+
+static void _hide(void *view_data)
+{
+       struct _priv *priv;
+
+       if (!view_data) {
+               _ERR("failed to get view data");
+               return;
+       }
+
+       priv = view_data;
+
+       evas_object_hide(priv->base);
+}
+
+static void _destroy(void *view_data)
+{
+       struct _priv *priv;
+
+       if (!view_data) {
+               _ERR("failed to get view data");
+               return;
+       }
+
+       priv = view_data;
+
+       evas_object_del(priv->base);
+
+       free(priv);
+}
+
+static view_class vclass = {
+       .view_id = VIEW_CHANNELINFO,
+       .create = _create,
+       .show = _show,
+       .hide = _hide,
+       .destroy = _destroy,
+};
+
+view_class *view_channelinfo_get_vclass(void)
+{
+       return &vclass;
+}