sync wit master
authorJinkun Jang <jinkun.jang@samsung.com>
Sat, 16 Mar 2013 12:49:29 +0000 (21:49 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Sat, 16 Mar 2013 12:49:29 +0000 (21:49 +0900)
44 files changed:
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
include/client.h [new file with mode: 0644]
include/conf.h [new file with mode: 0644]
include/critical_log.h [new file with mode: 0644]
include/debug.h [new file with mode: 0644]
include/desc_parser.h [new file with mode: 0644]
include/dlist.h [new file with mode: 0644]
include/fb.h [new file with mode: 0644]
include/livebox-viewer_PG.h [new file with mode: 0644]
include/livebox.h [new file with mode: 0644]
include/livebox_internal.h [new file with mode: 0644]
include/master_rpc.h [new file with mode: 0644]
include/util.h [new file with mode: 0644]
liblivebox-viewer.manifest [new file with mode: 0644]
live.viewer/CMakeLists.txt [new file with mode: 0644]
live.viewer/image/folder [new file with mode: 0644]
live.viewer/include/debug.h [new file with mode: 0644]
live.viewer/include/dlist.h [new file with mode: 0644]
live.viewer/include/lb.h [new file with mode: 0644]
live.viewer/include/live_scroller.h [new file with mode: 0644]
live.viewer/include/main.h [new file with mode: 0644]
live.viewer/include/scroller.h [new file with mode: 0644]
live.viewer/include/util.h [new file with mode: 0644]
live.viewer/live.viewer.xml [new file with mode: 0644]
live.viewer/packaging/live.viewer.spec [new file with mode: 0644]
live.viewer/res/CMakeLists.txt [new file with mode: 0644]
live.viewer/res/live-viewer.edc [new file with mode: 0644]
live.viewer/src/dlist.c [new file with mode: 0644]
live.viewer/src/lb.c [new file with mode: 0644]
live.viewer/src/live_scroller.c [new file with mode: 0644]
live.viewer/src/main.c [new file with mode: 0644]
live.viewer/src/scroller.c [new file with mode: 0644]
live.viewer/src/util.c [new file with mode: 0644]
livebox-viewer.pc.in [new file with mode: 0644]
packaging/liblivebox-viewer.spec [new file with mode: 0644]
src/client.c [new file with mode: 0644]
src/critical_log.c [new file with mode: 0644]
src/desc_parser.c [new file with mode: 0644]
src/dlist.c [new file with mode: 0644]
src/fb.c [new file with mode: 0644]
src/livebox.c [new file with mode: 0644]
src/master_rpc.c [new file with mode: 0644]
src/util.c [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..006c861
--- /dev/null
@@ -0,0 +1,68 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(livebox-viewer C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(PROJECT_NAME "${PROJECT_NAME}")
+SET(LIBDIR "\${exec_prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}")
+SET(VERSION_MAJOR 0)
+SET(VERSION "${VERSION_MAJOR}.0.1")
+
+set(CMAKE_SKIP_BUILD_RPATH true)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED
+       dlog
+       aul
+       glib-2.0
+       gio-2.0
+       com-core
+       x11
+       xext
+       sqlite3
+       db-util
+       livebox-service
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline -g")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+ADD_DEFINITIONS("-DLOG_TAG=\"LIVEBOX_VIEWER\"")
+ADD_DEFINITIONS("-DNDEBUG")
+#ADD_DEFINITIONS("-DFLOG")
+ADD_DEFINITIONS("-DMASTER_PKGNAME=\"org.tizen.data-provider-master\"")
+ADD_DEFINITIONS("-DINFO_SOCKET=\"/opt/usr/share/live_magazine/.live.socket\"")
+ADD_DEFINITIONS("-DCLIENT_SOCKET=\"/opt/usr/share/live_magazine/.client.socket\"")
+ADD_DEFINITIONS("-DSLAVE_SOCKET=\"/opt/usr/share/live_magazine/.slave.socket\"")
+ADD_DEFINITIONS("-DSERVICE_SOCKET=\"/opt/usr/share/live_magazine/.service.socket\"")
+ADD_LIBRARY(${PROJECT_NAME} SHARED
+       src/dlist.c
+       src/livebox.c
+       src/util.c
+       src/fb.c
+       src/desc_parser.c
+       src/master_rpc.c
+       src/client.c
+       src/critical_log.c
+)
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-lpthread")
+
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc")
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/livebox.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/livebox-viewer_PG.h DESTINATION /usr/share/doc/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION /usr/share/license RENAME "lib${PROJECT_NAME}")
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..27daa90
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,83 @@
+Flora License 
+
+Version 1.0, May, 2012 
+
+http://www.tizenopensource.org/license 
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 
+
+1. Definitions. 
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 
+
+"Tizen Certified Platform" shall mean a software platform that complies with the standards set forth in the Compatibility Definition Document and passes the Compatibility Test Suite as defined from time to time by the Tizen Technical Steering Group and certified by the Tizen Association or its designated agent. 
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work solely as incorporated into a Tizen Certified Platform, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work solely as incorporated into a Tizen Certified Platform to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof pursuant to the copyright license above, in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and 
+You must cause any modified files to carry prominent notices stating that You changed the files; and 
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 
+
+END OF TERMS AND CONDITIONS 
+
+APPENDIX: How to apply the Flora License to your work 
+
+To apply the Flora License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. 
+
+   Copyright [yyyy] [name of copyright owner] 
+
+
+   Licensed under the Flora License, Version 1.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.tizenopensource.org/license 
+
+
+   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. 
diff --git a/include/client.h b/include/client.h
new file mode 100644 (file)
index 0000000..873ae9d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int client_init(void);
+extern int client_fd(void);
+extern const char *client_addr(void);
+extern int client_fini(void);
+
+/* End of a file */
diff --git a/include/conf.h b/include/conf.h
new file mode 100644 (file)
index 0000000..25b158d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+/*!
+ * \note
+ * milli seconds
+ */
+#define RECONNECT_PERIOD       1000
+#define MAX_LOG_FILE   3
+#define MAX_LOG_LINE   1000
+#define SLAVE_LOG_PATH "/opt/usr/share/live_magazine/log"
diff --git a/include/critical_log.h b/include/critical_log.h
new file mode 100644 (file)
index 0000000..070ac47
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int critical_log(const char *func, int line, const char *fmt, ...);
+extern int critical_log_init(const char *tag);
+extern int critical_log_fini(void);
+
+#define CRITICAL_LOG(args...) critical_log(__func__, __LINE__, args)
+
+/* End of a file */
diff --git a/include/debug.h b/include/debug.h
new file mode 100644 (file)
index 0000000..2d2748e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...)       LOGD("[\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...)       LOGE("[\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+
+#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+#endif
+
+/* End of a file */
diff --git a/include/desc_parser.h b/include/desc_parser.h
new file mode 100644 (file)
index 0000000..0bb5502
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int parse_desc(struct livebox *handle, const char *descfile, int is_pd);
+
+/* End of a file */
diff --git a/include/dlist.h b/include/dlist.h
new file mode 100644 (file)
index 0000000..b4a5719
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+#define dlist_remove_data(list, data) do { \
+       struct dlist *l; \
+       l = dlist_find_data(list, data); \
+       list = dlist_remove(list, l); \
+} while (0)
+
+#define dlist_foreach(list, l, data) \
+       for ((l) = (list); (l) && ((data) = dlist_data(l)); (l) = dlist_next(l))
+
+#define dlist_foreach_safe(list, l, n, data) \
+       for ((l) = (list), (n) = dlist_next(l); \
+               (l) && ((data) = dlist_data(l)); \
+               (l) = (n), (n) = dlist_next(l))
+
+struct dlist;
+
+extern struct dlist *dlist_append(struct dlist *list, void *data);
+extern struct dlist *dlist_prepend(struct dlist *list, void *data);
+extern struct dlist *dlist_remove(struct dlist *list, struct dlist *l);
+extern struct dlist *dlist_find_data(struct dlist *list, void *data);
+extern void *dlist_data(struct dlist *l);
+extern struct dlist *dlist_next(struct dlist *l);
+extern struct dlist *dlist_prev(struct dlist *l);
+extern int dlist_count(struct dlist *l);
+extern struct dlist *dlist_nth(struct dlist *l, int nth);
+
+/* End of a file */
diff --git a/include/fb.h b/include/fb.h
new file mode 100644 (file)
index 0000000..7491aa3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+struct fb_info;
+
+enum buffer_type { /*!< Must have to be sync with libprovider, liblivebox-viewer */
+       BUFFER_TYPE_FILE,
+       BUFFER_TYPE_SHM,
+       BUFFER_TYPE_PIXMAP,
+       BUFFER_TYPE_ERROR,
+};
+
+extern int fb_init(void *disp);
+extern int fb_fini(void);
+extern const char *fb_id(struct fb_info *info);
+extern int fb_get_size(struct fb_info *info, int *w, int *h);
+extern int fb_sync(struct fb_info *info);
+extern int fb_size(struct fb_info *info);
+extern int fb_refcnt(void *data);
+extern int fb_is_created(struct fb_info *info);
+
+extern struct fb_info *fb_create(const char *filename, int w, int h);
+extern int fb_destroy(struct fb_info *info);
+
+extern void *fb_acquire_buffer(struct fb_info *info);
+extern int fb_release_buffer(void *data);
+
+/* End of a file */
diff --git a/include/livebox-viewer_PG.h b/include/livebox-viewer_PG.h
new file mode 100644 (file)
index 0000000..62077ae
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
diff --git a/include/livebox.h b/include/livebox.h
new file mode 100644 (file)
index 0000000..1b3d711
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 __LIVEBOX_H
+#define __LIVEBOX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct livebox;
+
+/*!
+ * \note size list
+ * 172x172
+ * 348x172
+ * 348x348
+ * 700x348
+ * 700x172
+ * 700x700
+ */
+#define DEFAULT_PERIOD -1.0f
+
+enum content_event_type {
+       CONTENT_EVENT_MOUSE_DOWN        = 0x00000001, /*!< LB mouse down event for livebox */
+       CONTENT_EVENT_MOUSE_UP          = 0x00000002, /*!< LB mouse up event for livebox */
+       CONTENT_EVENT_MOUSE_MOVE        = 0x00000004, /*!< LB mouse move event for livebox */
+       CONTENT_EVENT_MOUSE_ENTER       = 0x00000008, /*!< LB mouse enter event for livebox */
+       CONTENT_EVENT_MOUSE_LEAVE       = 0x00000010, /*!< LB mouse leave event for livebox */
+
+       CONTENT_EVENT_ACCESS_READ       = 0x00000100, /*!< LB accessibility read for livebox */
+       CONTENT_EVENT_ACCESS_READ_NEXT  = 0x00000200, /*!< LB accessibility read next for livebox */
+       CONTENT_EVENT_ACCESS_READ_PREV  = 0x00000400, /*!< LB accessibility read prev for livebox */
+       CONTENT_EVENT_ACCESS_ACTIVATE   = 0x00000800, /*!< LB accessibility activate */
+       CONTENT_EVENT_ACCESS_UP         = 0x00001000, /*!< LB accessibility up */
+       CONTENT_EVENT_ACCESS_DOWN       = 0x00002000, /*!< LB accessibility down */
+
+       CONTENT_EVENT_KEY_DOWN          = 0x00100000, /*!< LB key press */
+       CONTENT_EVENT_KEY_UP            = 0x00200000, /*!< LB key release */
+
+       CONTENT_EVENT_KEY_MASK          = 0x80000000,
+       CONTENT_EVENT_ACCESS_MASK       = 0x40000000,
+       CONTENT_EVENT_MOUSE_MASK        = 0x20000000,
+       CONTENT_EVENT_PD_MASK           = 0x10000000,
+       CONTENT_EVENT_LB_MASK           = 0x00000000,
+
+       LB_MOUSE_DOWN                   = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_DOWN,
+       LB_MOUSE_UP                     = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_UP,
+       LB_MOUSE_MOVE                   = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_MOVE,
+       LB_MOUSE_ENTER                  = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_ENTER,
+       LB_MOUSE_LEAVE                  = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_LEAVE,
+
+       PD_MOUSE_DOWN                   = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_DOWN,
+       PD_MOUSE_UP                     = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_UP,
+       PD_MOUSE_MOVE                   = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_MOVE,
+       PD_MOUSE_ENTER                  = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_ENTER,
+       PD_MOUSE_LEAVE                  = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_LEAVE,
+
+       LB_ACCESS_READ                  = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ,
+       LB_ACCESS_READ_NEXT             = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ_NEXT,
+       LB_ACCESS_READ_PREV             = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ_PREV,
+       LB_ACCESS_ACTIVATE              = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_ACTIVATE,
+       LB_ACCESS_UP                    = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_UP,
+       LB_ACCESS_DOWN                  = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_DOWN,
+
+       PD_ACCESS_READ                  = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ,
+       PD_ACCESS_READ_NEXT             = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ_NEXT,
+       PD_ACCESS_READ_PREV             = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_READ_PREV,
+       PD_ACCESS_ACTIVATE              = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_ACTIVATE,
+       PD_ACCESS_UP                    = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_UP,
+       PD_ACCESS_DOWN                  = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_DOWN,
+
+       LB_KEY_DOWN                     = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_DOWN,
+       LB_KEY_UP                       = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_UP,
+
+       PD_KEY_DOWN                     = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_DOWN,
+       PD_KEY_UP                       = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_UP,
+
+       CONTENT_EVENT_MAX       = 0xFFFFFFFF,
+};
+
+/* Exported to user app */
+enum livebox_lb_type {
+       LB_TYPE_IMAGE = 0x01, /*!< Contents of a livebox is based on the image file */
+       LB_TYPE_BUFFER = 0x02, /*!< Contents of a livebox is based on canvas buffer(shared) */
+       LB_TYPE_TEXT = 0x04, /*!< Contents of a livebox is based on formatted text file */
+       LB_TYPE_PIXMAP = 0x08, /*!< Contens of a livebox is shared by the pixmap(depends on X) */
+
+       LB_TYPE_INVALID = 0xFF,
+};
+
+enum livebox_pd_type {
+       PD_TYPE_BUFFER = 0x01, /*!< Contents of a PD is based on canvas buffer(shared) */
+       PD_TYPE_TEXT = 0x02, /*!< Contents of a PD is based on formatted text file */
+       PD_TYPE_PIXMAP = 0x04, /*!< Contents of a livebox is shared by the pixmap(depends on X) */
+
+       PD_TYPE_INVALID = 0xFF,
+};
+
+enum livebox_event_type { /*!< livebox_event_handler_set Event list */
+       LB_EVENT_LB_UPDATED, /*!< Contents of the given livebox is updated */
+       LB_EVENT_PD_UPDATED, /*!< Contents of the given pd is updated */
+
+       LB_EVENT_CREATED, /*!< A new livebox is created */
+       LB_EVENT_DELETED, /*!< A livebox is deleted */
+
+       LB_EVENT_GROUP_CHANGED, /*!< Group (Cluster/Sub-cluster) information is changed */
+       LB_EVENT_PINUP_CHANGED, /*!< PINUP status is changed */
+       LB_EVENT_PERIOD_CHANGED, /*!< Update period is changed */
+
+       LB_EVENT_LB_SIZE_CHANGED, /*!< Livebox size is changed */
+       LB_EVENT_PD_SIZE_CHANGED, /*!< PD size is changed */
+
+       LB_EVENT_PD_CREATED, /*!< If a PD is created even if you didn't call the livebox_create_pd API */
+       LB_EVENT_PD_DESTROYED, /*!< If a PD is destroyed even if you didn't call the livebox_destroy_pd API */
+
+       LB_EVENT_IGNORED, /*!< Request is ignored */
+};
+
+enum livebox_fault_type {
+       LB_FAULT_DEACTIVATED, /*!< Livebox is deactivated by its fault operation */
+       LB_FAULT_PROVIDER_DISCONNECTED, /*!< Provider is disconnected */
+};
+
+enum livebox_visible_state { /*!< Must be sync'd with the provider */
+       LB_SHOW = 0x00, /*!< Livebox is showed. Default state */
+       LB_HIDE = 0x01, /*!< Livebox is hide, Update timer is not be freezed. but you cannot receive any updates events. you should refresh(reload) the content of a livebox when you make this show again */
+
+       LB_HIDE_WITH_PAUSE = 0x02, /*!< Livebix is hide, it will paused the update timer, but if a livebox update its contents, update event will come to you */
+
+       LB_VISIBLE_ERROR = 0xFFFFFFFF, /* To enlarge the size of this enumeration type */
+};
+
+/*!
+ * \note
+ * TEXT type livebox contents handling opertators.
+ */
+struct livebox_script_operators {
+       int (*update_begin)(struct livebox *handle); /*!< Content parser is started */
+       int (*update_end)(struct livebox *handle); /*!< Content parser is stopped */
+
+       /*!
+        * \brief
+        * Listed functions will be called when parser meets each typed component
+        */
+       int (*update_text)(struct livebox *handle, const char *id, const char *part, const char *data); /*!< Update text content */
+       int (*update_image)(struct livebox *handle, const char *id, const char *part, const char *data); /*!< Update image content */
+       int (*update_script)(struct livebox *handle, const char *id, const char *part, const char *file, const char *group); /*!< Update script content */
+       int (*update_signal)(struct livebox *handle, const char *id, const char *emission, const char *signal); /*!< Update signal */
+       int (*update_drag)(struct livebox *handle, const char *id, const char *part, double dx, double dy); /*!< Update drag info */
+       int (*update_info_size)(struct livebox *handle, const char *id, int w, int h); /*!< Update content size */
+       int (*update_info_category)(struct livebox *handle, const char *id, const char *category); /*!< Update content category info */
+};
+
+/*!
+ * \brief Prototype of the return callback of every async functions.
+ * \param[in] handle
+ * \param[in] ret
+ * \param[in] data
+ * \return void
+ */
+typedef void (*ret_cb_t)(struct livebox *handle, int ret, void *data);
+
+/*!
+ * \brief Initialize the livebox system
+ * \param[in] disp
+ * \return int
+ */
+extern int livebox_init(void *disp);
+
+/*!
+ * \brief Finalize the livebox system
+ * \return int
+ */
+extern int livebox_fini(void);
+
+/*!
+ * \brief Client is paused.
+ * \return int
+ */
+extern int livebox_client_paused(void);
+
+/*!
+ * \brief Client is rfesumed.
+ * \return int
+ */
+extern int livebox_client_resumed(void);
+
+/*!
+ * \brief Add a new livebox
+ * \param[in] pkgname
+ * \param[in] content
+ * \param[in] cluster
+ * \param[in] category
+ * \param[in] period
+ * \param[in] cb
+ * \param[in] data
+ * \return handle
+ */
+extern struct livebox *livebox_add(const char *pkgname, const char *content, const char *cluster, const char *category, double period, ret_cb_t cb, void *data);
+extern struct livebox *livebox_add_with_size(const char *pkgname, const char *content, const char *cluster, const char *category, double period, int type, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Delete a livebox
+ * \param[in] handle
+ * \param[in] ret_cb_t return callback
+ * \param[in] data user data for return callback
+ * \return int
+ */
+extern int livebox_del(struct livebox *handler, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Set a livebox events callback
+ * \param[in] cb Event handler
+ * \param[in] data User data for the event handler
+ * \return int
+ * \sa livebox_unset_event_handler
+ */
+
+extern int livebox_set_event_handler(int (*cb)(struct livebox *handler, enum livebox_event_type event, void *data), void *data);
+
+/*!
+ * \brief Unset the livebox event handler
+ * \param[in] cb
+ * \return void * pointer of 'data' which is registered from the livebox_event_handler_set
+ * \sa livebox_set_event_handler
+ */
+extern void *livebox_unset_event_handler(int (*cb)(struct livebox *handler, enum livebox_event_type event, void *data));
+
+/*!
+ * \note
+ *   argument list
+ *     event, pkgname, filename, funcname
+ *
+ * \brief Live box fault event handler registeration function
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ * \sa livebox_unset_fault_handler
+ */
+extern int livebox_set_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *), void *data);
+
+/*!
+ * \brief Unset the live box fault event handler
+ * \param[in] cb
+ * \return pointer of 'data'
+ * \sa livebox_set_fault_handler
+ */
+extern void *livebox_unset_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *));
+
+/*!
+ * \brief Activate the faulted livebox.
+ * \param[in] pkgname
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_activate(const char *pkgname, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Resize the livebox
+ * \param[in] handler Handler of a livebox
+ * \param[in] type Type of a livebox size, LB_SIZE_TYPE_1x1, ...
+ * \param[in] cb Result callback of the resize operation.
+ * \param[in] data User data for return callback
+ * \return int
+ */
+extern int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Send the click event for a livebox.
+ * \param[in] handler Handler of a livebox
+ * \param[in] x Rational X of the content width.
+ * \param[in] y Rational Y of the content height.
+ * \return int
+ */
+extern int livebox_click(struct livebox *handler, double x, double y);
+
+/*!
+ * \brief Change the cluster/sub-cluster name of given livebox handler
+ * \param[in] handler Handler of a livebox
+ * \param[in] cluster New cluster of a livebox
+ * \param[in] category New category of a livebox
+ * \param[in] cb Result callback for changing the cluster/category of a livebox
+ * \param[in] data User data for the result callback
+ * \return int
+ */
+extern int livebox_set_group(struct livebox *handler, const char *cluster, const char *category, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Get the cluster and category(sub-cluster) name of given livebox (It is not I18N format, only english)
+ * \param[in] handler Handler of a livebox
+ * \param[out] cluster Storage(memory) for containing the cluster name
+ * \param[out] category Storage(memory) for containing the category name
+ * \return int
+ */
+extern int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category);
+
+/*!
+ * \brief Get the period of this livebox handler
+ * \param[in] handler Handler of a livebox
+ * \return double Current update period of a livebox
+ */
+extern double livebox_period(struct livebox *handler);
+
+/*!
+ * \brief Change the update period
+ * \param[in] handler Handler of a livebox
+ * \param[in] period New update period of a livebox
+ * \param[in] cb Result callback of changing the update period of this livebox
+ * \param[in] data User data for the result callback
+ * \return int
+ */
+extern int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Is this an text type livebox?
+ * \param[in] handler
+ * \return content_type
+ */
+extern enum livebox_lb_type livebox_lb_type(struct livebox *handler);
+
+/*!
+ * \brief Is this livebox is created by a user?
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_is_user(struct livebox *handler);
+
+/*!
+ * \brief Get the content information string of given livebox
+ * \param[in] handler
+ * \return content
+ */
+extern const char *livebox_content(struct livebox *handler);
+
+/*!
+ * \brief Get the sub cluster title string of given livebox
+ * \param[in] handler
+ * \return sub cluster title
+ */
+extern const char *livebox_category_title(struct livebox *handler);
+
+/*!
+ * \brief Get the filename of given livebox, if it is an IMAGE type livebox
+ * \param[in] handler
+ * \return filename
+ */
+extern const char *livebox_filename(struct livebox *handler);
+
+/*!
+ * \brief Get the package name of given livebox handler
+ * \param[in] handler
+ * \return pkgname
+ */
+extern const char *livebox_pkgname(struct livebox *handler);
+
+/*!
+ * \brief Get the priority of a current content.
+ * \param[in] handler
+ * \return priority
+ */
+extern double livebox_priority(struct livebox *handler);
+
+/*!
+ * \brief Acquire the buffer of given livebox (Only for the buffer type)
+ * \param[in] handler
+ * \return address of a FB
+ */
+extern void *livebox_acquire_fb(struct livebox *handler);
+
+/*!
+ * \brief Release the buffer of a livebox (Only for the buffer type)
+ * \param[in] buffer
+ * \return int
+ */
+extern int livebox_release_fb(void *buffer);
+
+/*!
+ * \brief Get the reference count of Livebox buffer (Only for the buffer type)
+ * \param[in] buffer
+ * \return int
+ */
+extern int livebox_fb_refcnt(void *buffer);
+
+/*!
+ * \brief Acquire the buffer of a PD frame (Only for the buffer type)
+ * \param[in] handler
+ * \return int
+ */
+extern void *livebox_acquire_pdfb(struct livebox *handler);
+
+/*!
+ * \brief Release the acquired buffer of the PD Frame (Only for the buffer type)
+ * \param[in] buffer
+ * \return int
+ */
+extern int livebox_release_pdfb(void *buffer);
+
+/*!
+ * \brief Reference count of given PD buffer (Only for the buffer type)
+ * \param[in] buffer
+ * \return int
+ */
+extern int livebox_pdfb_refcnt(void *buffer);
+
+/*!
+ * \brief Get the size of the Livebox
+ * \param[in] handler
+ * \param[out] w
+ * \param[out] h
+ * \return int
+ */
+extern int livebox_size(struct livebox *handler);
+
+/*!
+ * \brief Get the size of the Progressive Disclosure
+ * \param[in] handler
+ * \param[out] w
+ * \param[out] h
+ * \return int
+ */
+extern int livebox_get_pdsize(struct livebox *handler, int *w, int *h);
+
+/*!
+ * \brief List of supported sizes of given handler
+ * \param[in] handler
+ * \param[out] cnt
+ * \param[out] w
+ * \param[out] h
+ * \return int
+ */
+extern int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *size_list);
+
+/*!
+ * \brief BUFFER SIZE of the livebox if it is a buffer type
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_lbfb_bufsz(struct livebox *handler);
+
+/*!
+ * \brief BUFFER SIZE of the progiressive disclosure if it is a buffer type
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_pdfb_bufsz(struct livebox *handler);
+
+/*!
+ * \brief Send the content event (for buffer type) to provider(livebox)
+ * \param[in] handler
+ * \param[in] type
+ * \param[in] x
+ * \param[in] y
+ */
+extern int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y);
+
+/*!
+ * \brief Do pin up or not.
+ * \param[in] handler
+ * \param[in] flag
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Check the PIN-UP status of given handler
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_is_pinned_up(struct livebox *handler);
+
+/*!
+ * \brief Check the PINUP feature availability of the given handler
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_has_pinup(struct livebox *handler);
+
+/*!
+ * \brief Check the PD existence of given handler
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_has_pd(struct livebox *handler);
+
+/*!
+ * \brief Create the PD of given handler
+ * \param[in] handler
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Create the PD of given handler with the relative position from livebox
+ * \param[in] handler
+ * \param[in] x 0.0 ~ 1.0
+ * \param[in] y 0.0 ~ 1.0
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_create_pd_with_position(struct livebox *handler, double x, double y, ret_cb_t cb, void *data);
+
+/*!
+ * \brief PD position is updated.
+ * \param[in] handler
+ * \param[in] x 0.0 ~ 1.0
+ * \param[in] y 0.0 ~ 1.0
+ * \return int 0 if succeed to send request for updating position of the PD.
+ */
+extern int livebox_move_pd(struct livebox *handler, double x, double y);
+
+/*!
+ * \brief Destroy the PD of given handler if it is created.
+ * \param[in] handler
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Check the create status of given livebox handler
+ * \param[in] handler
+ * \return int
+ */
+extern int livebox_pd_is_created(struct livebox *handler);
+
+/*!
+ * \brief Check the content type of the progressive disclosure of given handler
+ * \param[in] handler
+ * \return int
+ */
+extern enum livebox_pd_type livebox_pd_type(struct livebox *handler);
+
+/*!
+ * \brief Check the existence of a livebox about given package name
+ * \param[in] pkgname
+ * \return int
+ */
+extern int livebox_is_exists(const char *pkgname);
+
+/*!
+ * \brief Set function table for parsing the text content of a livebox
+ * \param[in] handler
+ * \param[in] ops
+ * \return int
+ */
+extern int livebox_set_text_handler(struct livebox *handler, struct livebox_script_operators *ops);
+
+/*!
+ * \brief Set function table for parsing the text content of a Progressive Disclosure
+ * \param[in] handler
+ * \param[in] ops
+ * \return int
+ */
+extern int livebox_set_pd_text_handler(struct livebox *handler, struct livebox_script_operators *ops);
+
+/*!
+ * \brief Emit a text signal to given livebox only if it is a text type.
+ * \param[in] handler
+ * \param[in] emission
+ * \param[in] source
+ * \param[in] sx
+ * \param[in] sy
+ * \param[in] ex
+ * \param[in] ey
+ * \param[in] cb
+ * \param[in] data
+ */
+extern int livebox_emit_text_signal(struct livebox *handler, const char *emission, const char *source, double sx, double sy, double ex, double ey, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Set a private data pointer to carry it using given handler
+ * \param[in] handler
+ * \param[in] data
+ * \return int
+ */
+extern int livebox_set_data(struct livebox *handler, void *data);
+
+/*!
+ * \brief Get private data pointer which is carried by given handler
+ * \param[in] handler
+ * \return int
+ */
+extern void *livebox_get_data(struct livebox *handler);
+
+/*!
+ * \brief Subscribe the event for liveboxes only in given cluster and sub-cluster
+ * \param[in] cluster   "*" can be used for subscribe all cluster's liveboxes event.
+ *                      If you use the "*", value in the category will be ignored.
+ * \param[in] category  "*" can be used for subscribe liveboxes events of all category(sub-cluster) in given "cluster"
+ * \return int Success 0, fails error code
+ */
+extern int livebox_subscribe_group(const char *cluster, const char *category);
+
+/*!
+ * \brief Unsubscribe the event for the liveboxes, but you will receive already added liveboxes event.
+ * \param[in] cluster   "*" can be used for subscribe all cluster's liveboxes event.
+ *                      If you use the "*", value in the category will be ignored.
+ * \param[in] category  "*" can be used for subscribe all sub-cluster's liveboxes event in given "cluster"
+ * \return int Success 0, fails error code
+ */
+extern int livebox_unsubscribe_group(const char *cluster, const char *category);
+
+/*!
+ * \brief Refresh the group(cluster/sub-cluser(aka. category))
+ * \param[in] cluster Cluster ID
+ * \param[in] category Sub-cluster ID
+ * \return int Success 0 or negative value
+ */
+extern int livebox_refresh_group(const char *cluster, const char *category);
+
+/*!
+ * \brief Refresh a livebox
+ * \param[in] handler
+ * \return int Success 0 or negative value
+ */
+extern int livebox_refresh(struct livebox *handler);
+
+/*!
+ * \brief Pixmap Id of a livebox content
+ * \param[in] handler
+ * \return int
+ * \sa livebox_pd_pixmap
+ */
+extern int livebox_lb_pixmap(const struct livebox *handler);
+
+/*!
+ * \brief Pixmap Id of a PD content
+ * \param[in] handler
+ * \return int
+ * \sa livebox_lb_pixmap
+ */
+extern int livebox_pd_pixmap(const struct livebox *handler);
+
+/*!
+ * \brief
+ * \param[in] handler
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ * \sa livebox_release_pd_pixmap
+ * \sa livebox_acquire_lb_pixmap
+ */
+extern int livebox_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *data);
+
+/*!
+ * \brief Release the acquired pixmap ID
+ * \param[in] handler
+ * \param[in] pixmap
+ * \return int
+ * \sa livebox_acquire_pd_pixmap
+ * \sa livebox_release_lb_pixmap
+ */
+extern int livebox_release_pd_pixmap(struct livebox *handler, int pixmap);
+
+/*!
+ * \brief
+ * \param[in] handler
+ * \param[in] cb
+ * \param[in] data
+ * \return int
+ * \sa livebox_release_lb_pixmap
+ * \sa livebox_acquire_pd_pixmap
+ */
+extern int livebox_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *data);
+
+/*!
+ * \brief
+ * \param[in] handler
+ * \param[in] pixmap
+ * \return int
+ * \sa livebox_acquire_lb_pixmap
+ * \sa livebox_release_pd_pixmap
+ */
+extern int livebox_release_lb_pixmap(struct livebox *handler, int pixmap);
+
+/*!
+ * \brief Update the visible state of a livebox
+ * \param[in] handler Handler of a livebox
+ * \param[in] state Configure the current visible state of a livebox
+ * \return int
+ */
+extern int livebox_set_visibility(struct livebox *handler, enum livebox_visible_state state);
+
+/*!
+ * \brief Current visible state of a livebox
+ * \param[in] handler Handler of a livebox
+ * \return enum visible state
+ */
+extern enum livebox_visible_state livebox_visibility(struct livebox *handler);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* End of a file */
diff --git a/include/livebox_internal.h b/include/livebox_internal.h
new file mode 100644 (file)
index 0000000..4a6b100
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int lb_set_group(struct livebox *handler, const char *cluster, const char *category);
+extern void lb_set_size(struct livebox *handler, int w, int h);
+extern void lb_set_pdsize(struct livebox *handler, int w, int h);
+extern void lb_set_default_pdsize(struct livebox *handler, int w, int h);
+extern void lb_invoke_event_handler(struct livebox *handler, enum livebox_event_type event);
+extern void lb_invoke_fault_handler(enum livebox_fault_type type, const char *pkgname, const char *filename, const char *function);
+extern int lb_set_content(struct livebox *handler, const char *content);
+extern int lb_set_title(struct livebox *handler, const char *title);
+extern void lb_set_auto_launch(struct livebox *handler, const char *auto_launch);
+extern struct livebox *lb_find_livebox(const char *pkgname, const char *filename);
+extern struct livebox *lb_new_livebox(const char *pkgname, const char *filename, double timestamp);
+extern struct livebox *lb_find_livebox_by_timestamp(double timestamp);
+extern void lb_set_id(struct livebox *handler, const char *id);
+extern void lb_set_size_list(struct livebox *handler, int size_list);
+extern void lb_set_priority(struct livebox *handler, double priority);
+extern int lb_set_lb_fb(struct livebox *handler, const char *filename);
+extern int lb_set_pd_fb(struct livebox *handler, const char *filename);
+extern struct fb_info *lb_get_pd_fb(struct livebox *handler);
+extern struct fb_info *lb_get_lb_fb(struct livebox *handler);
+extern void lb_set_user(struct livebox *handler, int user);
+extern void lb_set_pinup(struct livebox *handler, int pinup);
+extern void lb_set_text_lb(struct livebox *handler);
+extern void lb_set_text_pd(struct livebox *handler);
+extern int lb_text_lb(struct livebox *handler);
+extern int lb_text_pd(struct livebox *handler);
+extern void lb_set_period(struct livebox *handler, double period);
+extern struct livebox *lb_ref(struct livebox *handler);
+extern struct livebox *lb_unref(struct livebox *handler);
+extern int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data);
+extern int lb_delete_all(void);
+
+enum lb_type { /*!< Must have to be sync with data-provider-master */
+       _LB_TYPE_NONE = 0x0,
+       _LB_TYPE_SCRIPT,
+       _LB_TYPE_FILE,
+       _LB_TYPE_TEXT,
+       _LB_TYPE_BUFFER,
+};
+
+enum pd_type { /*!< Must have to be sync with data-provider-master */
+       _PD_TYPE_NONE = 0x0,
+       _PD_TYPE_SCRIPT,
+       _PD_TYPE_TEXT,
+       _PD_TYPE_BUFFER,
+};
+
+struct livebox {
+       int refcnt;
+       enum {
+               CREATE = 0xBEEFbeef,
+               DELETE = 0xDEADdead, /* Delete only for this client */
+               DESTROYED = 0x00DEAD00,
+       } state;
+
+       char *cluster;
+       char *category;
+
+       char *pkgname;
+       char *id;
+       char *content;
+       char *title;
+       char *filename;
+
+       double timestamp;
+
+       enum livebox_visible_state visible;
+
+       int is_user;
+       int is_pd_created;
+       int is_pinned_up;
+
+       struct {
+               enum lb_type type;
+               union {
+                       struct fb_info *fb;
+                       struct livebox_script_operators ops;
+               } data;
+
+               int size_list;
+
+               int width;
+               int height;
+               double priority;
+
+               char *auto_launch;
+               double period;
+               int pinup_supported;
+               int mouse_event;
+
+               /* For the filtering event */
+               double x;
+               double y;
+       } lb;
+
+       struct {
+               enum pd_type type;
+               union {
+                       struct fb_info *fb;
+                       struct livebox_script_operators ops;
+               } data;
+
+               int width;
+               int height;
+
+               int default_width;
+               int default_height;
+
+               /* For the filtering event */
+               double x;
+               double y;
+       } pd;
+
+       int nr_of_sizes;
+
+       void *data;
+
+       ret_cb_t created_cb;
+       void *created_cbdata;
+
+       ret_cb_t deleted_cb;
+       void *deleted_cbdata;
+
+       ret_cb_t pinup_cb;
+       void *pinup_cbdata;
+
+       ret_cb_t group_changed_cb;
+       void *group_cbdata;
+
+       ret_cb_t period_changed_cb;
+       void *period_cbdata;
+
+       ret_cb_t size_changed_cb;
+       void *size_cbdata;
+
+       ret_cb_t pd_created_cb;
+       void *pd_created_cbdata;
+
+       ret_cb_t pd_destroyed_cb;
+       void *pd_destroyed_cbdata;
+};
+
+/* End of a file */
diff --git a/include/master_rpc.h b/include/master_rpc.h
new file mode 100644 (file)
index 0000000..e507c27
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int master_rpc_async_request(struct livebox *handler, struct packet *packet, int urgent, void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data), void *data);
+extern int master_rpc_sync_request(struct packet *packet);
+extern void master_rpc_check_and_fire_consumer(void);
+extern int master_rpc_request_only(struct livebox *handler, struct packet *packet);
+extern int master_rpc_clear_fault_package(const char *pkgname);
+extern int master_rpc_clear_all_request(void);
+
+/* End of a file */
diff --git a/include/util.h b/include/util.h
new file mode 100644 (file)
index 0000000..2c9275b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int util_check_extension(const char *filename, const char *check_ptr);
+extern double util_timestamp(void);
+extern const char *util_basename(const char *name);
+extern int util_validate_livebox_package(const char *pkgname);
+extern const char *util_uri_to_path(const char *uri);
+
+#define SCHEMA_FILE    "file://"
+#define SCHEMA_PIXMAP  "pixmap://"
+#define SCHEMA_SHM     "shm://"
+
+#define container_of(ptr, type, member) \
+        ({ const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/* End of a file */
diff --git a/liblivebox-viewer.manifest b/liblivebox-viewer.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/live.viewer/CMakeLists.txt b/live.viewer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9be5a14
--- /dev/null
@@ -0,0 +1,48 @@
+PROJECT(live-viewer C)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED
+       capi-appfw-application
+       capi-appfw-app-manager
+       ail
+       bundle
+       dlog
+       elementary
+       ecore-x
+       appcore-efl
+       livebox-viewer
+       livebox-service
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -Werror -Winline -g")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+SET(PKGROOT "/opt/usr/apps/live.viewer")
+ADD_DEFINITIONS("-DNDEBUG")
+ADD_DEFINITIONS("-DPKGROOT=\"${PKGROOT}\"")
+#ADD_DEFINITIONS("-DFLOG")
+ADD_DEFINITIONS("-DLOG_TAG=\"${PROJECT_NAME}\"")
+ADD_DEFINITIONS(${pkgs_CFLAGS})
+ADD_DEFINITIONS(${pkgs_LDFLAGS})
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+ADD_EXECUTABLE(${PROJECT_NAME}
+       src/main.c
+       src/dlist.c
+       src/live_scroller.c
+       src/util.c
+       src/scroller.c
+       src/lb.c
+)
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${PKGROOT}/bin)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/live.viewer.xml DESTINATION /opt/share/packages)
+
+ADD_SUBDIRECTORY(res)
diff --git a/live.viewer/image/folder b/live.viewer/image/folder
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/live.viewer/include/debug.h b/live.viewer/include/debug.h
new file mode 100644 (file)
index 0000000..2d2748e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...)       LOGD("[\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...)       LOGE("[\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+
+#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%d] " format, util_basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+#endif
+
+/* End of a file */
diff --git a/live.viewer/include/dlist.h b/live.viewer/include/dlist.h
new file mode 100644 (file)
index 0000000..b4a5719
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+#define dlist_remove_data(list, data) do { \
+       struct dlist *l; \
+       l = dlist_find_data(list, data); \
+       list = dlist_remove(list, l); \
+} while (0)
+
+#define dlist_foreach(list, l, data) \
+       for ((l) = (list); (l) && ((data) = dlist_data(l)); (l) = dlist_next(l))
+
+#define dlist_foreach_safe(list, l, n, data) \
+       for ((l) = (list), (n) = dlist_next(l); \
+               (l) && ((data) = dlist_data(l)); \
+               (l) = (n), (n) = dlist_next(l))
+
+struct dlist;
+
+extern struct dlist *dlist_append(struct dlist *list, void *data);
+extern struct dlist *dlist_prepend(struct dlist *list, void *data);
+extern struct dlist *dlist_remove(struct dlist *list, struct dlist *l);
+extern struct dlist *dlist_find_data(struct dlist *list, void *data);
+extern void *dlist_data(struct dlist *l);
+extern struct dlist *dlist_next(struct dlist *l);
+extern struct dlist *dlist_prev(struct dlist *l);
+extern int dlist_count(struct dlist *l);
+extern struct dlist *dlist_nth(struct dlist *l, int nth);
+
+/* End of a file */
diff --git a/live.viewer/include/lb.h b/live.viewer/include/lb.h
new file mode 100644 (file)
index 0000000..d6ea8bc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern int lb_init(void);
+extern int lb_fini(void);
+extern int lb_add(Evas_Object *sc, const char *pkgname);
+
+/* End of a file */
diff --git a/live.viewer/include/live_scroller.h b/live.viewer/include/live_scroller.h
new file mode 100644 (file)
index 0000000..de7e77e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+struct live_sc_event_info {
+       int curidx;
+       int toidx;
+};
+
+struct live_sc_drag_info {
+       int dx;
+       int dy;
+};
+
+struct live_sc_move_info {
+       Evas_Object *item;
+       Evas_Coord x;
+       Evas_Coord y;
+       Evas_Coord w;
+       Evas_Coord h;
+
+       double relx;
+       double rely;
+};
+
+extern Evas_Object *live_scroller_add(Evas_Object *parent);
+extern int live_scroller_append(Evas_Object *scroller, Evas_Object *item);
+extern Evas_Object *live_scroller_remove(Evas_Object *scroller, int idx);
+extern Evas_Object *live_scroller_get_item(Evas_Object *scroller, int idx);
+extern int live_scroller_get_current(Evas_Object *scroller);
+extern int live_scroller_loop_set(Evas_Object *scroller, int is_loop);
+
+extern int live_scroller_freeze(Evas_Object *scroller);
+extern int live_scroller_thaw(Evas_Object *scroller);
+
+extern int live_scroller_anim_to(Evas_Object *scroller, double fps, int offset);
+extern int live_scroller_go_to(Evas_Object *scroller, int idx);
+
+extern int live_scroller_update(Evas_Object *scroller);
+
+extern int live_scroller_remove_by_obj(Evas_Object *scroller, Evas_Object *obj);
+extern int live_scroller_get_item_index(Evas_Object *scroller, Evas_Object *item);
+extern int live_scroller_get_item_count(Evas_Object *scroller);
+
+/* End of a file */
diff --git a/live.viewer/include/main.h b/live.viewer/include/main.h
new file mode 100644 (file)
index 0000000..33f292f
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern Evas_Object *main_get_window(void);
diff --git a/live.viewer/include/scroller.h b/live.viewer/include/scroller.h
new file mode 100644 (file)
index 0000000..41d6757
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern Evas_Object *scroller_create(Evas_Object *parent);
+extern Evas_Object *scroller_peek_by_idx(Evas_Object *sc, int idx);
+extern int scroller_peek_by_obj(Evas_Object *sc, Evas_Object *obj);
+extern int scroller_append(Evas_Object *sc, Evas_Object *child);
+extern int scroller_get_current_idx(Evas_Object *sc);
+extern int scroller_peek_by_obj(Evas_Object *sc, Evas_Object *obj);
+extern Evas_Object *scroller_get_page(Evas_Object *sc, int idx);
+extern int scroller_is_scrolling(Evas_Object *sc);
+
+extern int scroller_add_stop_cb(Evas_Object *scroller, int (*cb)(Evas_Object *sc, void *data), void *data);
+extern void scroller_del_stop_cb(Evas_Object *scroller, int (*cb)(Evas_Object *sc, void *data), void *data);
+
+extern int scroller_get_page_index(Evas_Object *sc, Evas_Object *page);
+
+extern void scroller_unlock(Evas_Object *sc);
+extern void scroller_lock(Evas_Object *sc);
+
+extern int scroller_get_page_count(Evas_Object *sc);
+extern int scroller_scroll_to(Evas_Object *sc, int idx);
+extern int scroller_jump_to(Evas_Object *sc, int idx);
+
+extern int scroller_destroy(Evas_Object *sc);
+extern int scroller_update(Evas_Object *sc, void *data);
+extern int scroller_fast_scroll(Evas_Object *sc, int idx);
+extern void scroller_loop_set(Evas_Object *sc, Eina_Bool val);
+extern void scroller_quick_navi(Evas_Object *sc, Eina_Bool val);
+
+/* End of a file */
diff --git a/live.viewer/include/util.h b/live.viewer/include/util.h
new file mode 100644 (file)
index 0000000..bf99fb4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+extern const char *util_basename(const char *name);
+
+/* End of a file */
diff --git a/live.viewer/live.viewer.xml b/live.viewer/live.viewer.xml
new file mode 100644 (file)
index 0000000..7a55872
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<manifest xmlns="http://tizen.org/ns/packages" package="live.viewer" version="0.0.1" install-location="auto">
+       <label>Live viewer (native)</label>
+       <author email="nicesj.park@samsung.com" href="www.samsung.com">Sung-jae Park</author>
+       <description>Live box simple viewer (native)</description>
+
+       <ui-application appid="live.viewer" exec="/opt/usr/apps/live.viewer/bin/live-viewer" nodisplay="false" multiple="false" type="capp" taskmanage="true">
+               <icon>live-viewer.png</icon>
+               <label>Live box simple viewer (native)</label>
+               <label xml:lang="en-us">Live box simple viewer (native)</label>
+       </ui-application>
+</manifest>
diff --git a/live.viewer/packaging/live.viewer.spec b/live.viewer/packaging/live.viewer.spec
new file mode 100644 (file)
index 0000000..f817c32
--- /dev/null
@@ -0,0 +1,41 @@
+Name: live.viewer
+Summary: viewer
+Version: 0.0.1
+Release: 1
+Group: main/app
+License: Flora License
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: cmake, gettext-tools
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(ail)
+BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(appcore-efl)
+BuildRequires: pkgconfig(livebox-viewer)
+BuildRequires: pkgconfig(ecore-x)
+BuildRequires: pkgconfig(livebox-service)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-appfw-app-manager)
+BuildRequires: edje-bin
+
+%description
+Livebox viewer development library
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+
+%files
+%defattr(-,root,root,-)
+/opt/usr/apps/live.viewer/*
+/opt/share/*
diff --git a/live.viewer/res/CMakeLists.txt b/live.viewer/res/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5f6447c
--- /dev/null
@@ -0,0 +1,7 @@
+ADD_CUSTOM_TARGET(live-viewer.edj ALL
+               COMMAND edje_cc -id ${CMAKE_SOURCE_DIR}/res/image
+               ${CMAKE_CURRENT_SOURCE_DIR}/live-viewer.edc live-viewer.edj
+               DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/live-viewer.edc
+)
+ADD_DEPENDENCIES(${PROJECT_NAME} live-viewer.edj)
+INSTALL(FILES live-viewer.edj DESTINATION ${PKGROOT}/res/edje)
diff --git a/live.viewer/res/live-viewer.edc b/live.viewer/res/live-viewer.edc
new file mode 100644 (file)
index 0000000..f4d4242
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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.
+ */
+
+images {
+       /* image: "a" COMP; */
+}
+
+collections {
+       group {
+               name: "layout";
+               parts {
+                       part {
+                               name: "indicator";
+                               type: RECT;
+                               mouse_events: 0;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 0.0 0.0; }
+                                       rel2 { relative: 1.0 100/1280; }
+                                       color: 0 0 0 0;
+                               }
+                       }
+
+                       part {
+                               name: "delete,btn";
+                               type: SWALLOW;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 4/720 1.0; to_y, "viewer"; }
+                                       rel2 { relative: 716/720 900/1280; }
+                               }
+                       }
+
+                       part {
+                               name: "controller"; /* size list */
+                               type: SWALLOW;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 0.0 1.0; to_y, "delete,btn"; }
+                                       rel2 { relative: 0.3 1.0; }
+                               }
+                       }
+
+                       part {
+                               name: "logger";
+                               type: SWALLOW;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 1.0 1.0; to_x: "controller"; to_y: "delete,btn"; }
+                                       rel2 { relative: 1.0 1.0; }
+                               }
+                       }
+
+                       part {
+                               name: "viewer";
+                               type: RECT;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 4/720 1.0; to, "indicator"; }
+                                       rel2 { relative: 716/720 800/1280; }
+                                       color: 255 255 255 255;
+                               }
+                       }
+
+                       part {
+                               name: "event,blocker";
+                               type: RECT;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 0.0 0.0; }
+                                       rel2 { relative: 1.0 1.0; }
+                                       color: 0 0 0 0;
+                                       visible: 0;
+                               }
+                               description {
+                                       state: "show" 0.0;
+                                       inherit: "default" 0.0;
+                                       color: 50 50 50 50;
+                                       visible: 1;
+                               }
+                       }
+
+                       part {
+                               name: "livebox";
+                               type: SWALLOW;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 0.4 0.4; to, "viewer"; }
+                                       rel2 { relative: 0.6 0.6; to, "viewer"; }
+                               }
+                       }
+
+                       part {
+                               name: "pd";
+                               type: SWALLOW;
+                               mouse_events: 1;
+                               description {
+                                       state: "default" 0.0;
+                                       rel1 { relative: 0.0 0.95; to_y, "livebox"; }
+                                       rel2 { relative: 1.0 1.0; to_y, "livebox"; }
+                                       visible: 0;
+                                       align: 0.0 0.0;
+                               }
+
+                               description {
+                                       state: "show" 0.0;
+                                       rel1 { relative: 0.0 1.0; to_y, "livebox"; }
+                                       rel2 { relative: 1.0 1.0; }
+                                       visible: 1;
+                                       align: 0.0 0.0;
+                               }
+                       }
+               }
+
+               programs {
+                       program {
+                               name: "open,pd";
+                               source: "pd";
+                               signal: "open";
+                               action: STATE_SET "show" 0.0;
+                               target: "pd";
+                               target: "event,blocker";
+                               transition: LINEAR 0.2;
+                       }
+                       program {
+                               name: "hide,pd";
+                               source: "pd";
+                               signal: "close";
+                               action: STATE_SET "default" 0.0;
+                               target: "pd";
+                               target: "event,blocker";
+                               transition: LINEAR 0.1;
+                               after: "hide,pd,done";
+                       }
+
+                       program {
+                               name: "hide,pd,done";
+                               action: SIGNAL_EMIT "hide,done" "pd";
+                       }
+
+                       program {
+                               name: "event,blocker";
+                               source: "event,blocker";
+                               signal: "mouse,clicked,1";
+                               action: SIGNAL_EMIT "close" "pd";
+                       }
+
+                       program {
+                               name: "pd,close,pd";
+                               source: "viewer";
+                               signal: "mouse,clicked,1";
+                               action: SIGNAL_EMIT "close" "pd";
+                       }
+               }
+       }
+}
diff --git a/live.viewer/src/dlist.c b/live.viewer/src/dlist.c
new file mode 100644 (file)
index 0000000..56ff060
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+
+#include "dlist.h"
+
+/*!
+ * \brief
+ * This dlist is called Modified Doubly Linked List.
+ *
+ * Noramlly, The dobule linked list contains address of previous and next element.
+ * This dlist also contains them, but the tail element only contains prev address.
+ *
+ * The head element's prev pointer indicates the last element.
+ * But the last element's next pointer indicates NIL.
+ *
+ * So we can find the last element while crawling this DList
+ * But we have to remember the address of the head element.
+ */
+
+struct dlist {
+       struct dlist *next;
+       struct dlist *prev;
+       void *data;
+};
+
+struct dlist *dlist_append(struct dlist *list, void *data)
+{
+       struct dlist *item;
+
+       item = malloc(sizeof(*item));
+       if (!item)
+               return NULL;
+
+       item->next = NULL;
+       item->data = data;
+
+       if (!list) {
+               item->prev = item;
+
+               list = item;
+       } else {
+               item->prev = list->prev;
+               item->prev->next = item;
+               list->prev = item;
+       }
+
+       assert(!list->prev->next && "item NEXT");
+
+       return list;
+}
+
+struct dlist *dlist_prepend(struct dlist *list, void *data)
+{
+       struct dlist *item;
+
+       item = malloc(sizeof(*item));
+       if (!item)
+               return NULL;
+
+       item->data = data;
+
+       if (!list) {
+               item->prev = item;
+               item->next = NULL;
+       } else {
+               if (list->prev->next)
+                       list->prev->next = item;
+
+               item->prev = list->prev;
+               item->next = list;
+
+               list->prev = item;
+
+       }
+
+       return item;
+}
+
+struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
+{
+       if (!list || !l)
+               return NULL;
+
+       if (l == list)
+               list = l->next;
+       else
+               l->prev->next = l->next;
+
+       if (l->next)
+               l->next->prev = l->prev;
+       /*!
+        * \note
+        * If the removed entry 'l' has no next element, it is the last element.
+        * In this case, check the existence of the list first,
+        * and if the list is not empty, update the 'prev' of the list (which is a head element of the list) 
+        *
+        * If we didn't care about this, the head element(list) can indicates the invalid element.
+        */
+       else if (list)
+               list->prev = l->prev;
+
+       free(l);
+       return list;
+}
+
+struct dlist *dlist_find_data(struct dlist *list, void *data)
+{
+       struct dlist *l;
+       void *_data;
+
+       dlist_foreach(list, l, _data) {
+               if (data == _data)
+                       return l;
+       }
+
+       return NULL;
+}
+
+void *dlist_data(struct dlist *l)
+{
+       return l ? l->data : NULL;
+}
+
+struct dlist *dlist_next(struct dlist *l)
+{
+       return l ? l->next : NULL;
+}
+
+struct dlist *dlist_prev(struct dlist *l)
+{
+       return l ? l->prev : NULL;
+}
+
+int dlist_count(struct dlist *l)
+{
+       register int i;
+       struct dlist *n;
+       void *data;
+
+       i = 0;
+       dlist_foreach(l, n, data) {
+               i++;
+       }
+
+       return i;
+}
+
+struct dlist *dlist_nth(struct dlist *l, int nth)
+{
+       register int i;
+       struct dlist *n;
+
+       i = 0;
+       for (n = l; n; n = n->next) {
+               if (i == nth)
+                       return n;
+               i++;
+       }
+
+       return NULL;
+}
+
+/* End of a file */
diff --git a/live.viewer/src/lb.c b/live.viewer/src/lb.c
new file mode 100644 (file)
index 0000000..cbe928b
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <Ecore_X.h>
+
+#include <dlog.h>
+
+#include <livebox.h>
+#include <livebox-service.h>
+
+#include "main.h"
+#include "util.h"
+#include "debug.h"
+#include "lb.h"
+#include "scroller.h"
+
+#define FLICK_COND     100
+
+static Evas_Object *create_canvas(Evas_Object *parent)
+{
+       Evas_Object *canvas;
+
+       canvas = evas_object_image_add(evas_object_evas_get(parent));
+       if (!canvas)
+               return NULL;
+
+       evas_object_image_content_hint_set(canvas, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
+       evas_object_image_colorspace_set(canvas, EVAS_COLORSPACE_ARGB8888);
+       evas_object_image_alpha_set(canvas, EINA_TRUE);
+       evas_object_move(canvas, 0, 0);
+       return canvas;
+}
+
+static int update_pd_canvas(struct livebox *handle, Evas_Object *image)
+{
+       Evas_Native_Surface surface;
+       int w;
+       int h;
+
+       DbgPrint("Updated\n");
+
+       switch (livebox_pd_type(handle)) {
+       case PD_TYPE_PIXMAP:
+               h = w = 0;
+               livebox_get_pdsize(handle, &w, &h);
+               if (w <= 0 || h <= 0)
+                       break;
+
+               //evas_object_image_size_set(image, w, h);
+
+               DbgPrint("Update: %dx%d\n", w, h);
+               surface.version = EVAS_NATIVE_SURFACE_VERSION;
+               surface.type = EVAS_NATIVE_SURFACE_X11;
+               surface.data.x11.pixmap = livebox_pd_pixmap(handle);
+               surface.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
+               evas_object_image_native_surface_set(image, &surface);
+
+               evas_object_image_data_update_add(image, 0, 0, w, h);
+               evas_object_size_hint_max_set(image, w, h);
+               evas_object_resize(image, w, h);
+               evas_object_show(image);
+               break;
+       case PD_TYPE_BUFFER:
+               livebox_get_pdsize(handle, &w, &h);
+               if (w > 0 && h > 0) {
+                       void *data;
+
+                       data = livebox_acquire_pdfb(handle);
+                       if (data) {
+                               evas_object_image_data_set(image, NULL);
+                               evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
+                               evas_object_image_alpha_set(image, EINA_TRUE);
+                               evas_object_image_size_set(image, w, h);
+                               evas_object_image_smooth_scale_set(image, EINA_TRUE);
+                               evas_object_image_data_copy_set(image, data);
+                               evas_object_image_data_update_add(image, 0, 0, w, h);
+                               livebox_release_pdfb(data);
+                       }
+                       evas_object_resize(image, w, h);
+                       //evas_object_size_hint_min_set(image, w, h);
+                       evas_object_size_hint_max_set(image, w, h);
+               }
+               break;
+       case PD_TYPE_TEXT:
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int update_canvas(struct livebox *handle, Evas_Object *image)
+{
+       Evas_Native_Surface surface;
+       const char *filename;
+       int w;
+       int h;
+       int type;
+
+       DbgPrint("Updated\n");
+
+       switch (livebox_lb_type(handle)) {
+       case LB_TYPE_PIXMAP:
+               w = h = 0;
+               type = livebox_size(handle);
+               livebox_service_get_size(type, &w, &h);
+               if (w <= 0 || h <= 0)
+                       break;
+
+               DbgPrint("Update: %dx%d\n", w, h);
+
+               //evas_object_image_size_set(image, w, h);
+
+               surface.version = EVAS_NATIVE_SURFACE_VERSION;
+               surface.type = EVAS_NATIVE_SURFACE_X11;
+               surface.data.x11.pixmap = livebox_lb_pixmap(handle);
+               surface.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
+               evas_object_image_native_surface_set(image, &surface);
+
+               evas_object_image_data_update_add(image, 0, 0, w, h);
+
+               evas_object_resize(image, w, h);
+               evas_object_size_hint_min_set(image, w, h);
+               evas_object_size_hint_max_set(image, w, h);
+               evas_object_show(image);
+               break;
+       case LB_TYPE_BUFFER:
+               w = h = 0;
+               type = livebox_size(handle);
+               livebox_service_get_size(type, &w, &h);
+               if (w > 0 && h > 0) {
+                       void *data;
+                       data = livebox_acquire_fb(handle);
+                       if (data) {
+                               evas_object_image_data_set(image, NULL);
+                               evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
+                               evas_object_image_alpha_set(image, EINA_TRUE);
+                               evas_object_image_size_set(image, w, h);
+                               evas_object_image_smooth_scale_set(image, EINA_TRUE);
+                               evas_object_image_data_copy_set(image, data);
+                               evas_object_image_data_update_add(image, 0, 0, w, h);
+                               livebox_release_fb(data);
+                       }
+                       evas_object_resize(image, w, h);
+                       evas_object_size_hint_min_set(image, w, h);
+                       evas_object_size_hint_max_set(image, w, h);
+               }
+               break;
+       case LB_TYPE_IMAGE:
+               filename = livebox_filename(handle);
+               if (filename) {
+                       const char *old;
+                       evas_object_image_file_get(image, &old, NULL);
+                       if (old && !strcmp(filename, old)) {
+                               evas_object_image_reload(image);
+                       } else {
+                               evas_object_image_file_set(image, filename, NULL);
+                       }
+
+                       w = h = 0;
+                       type = livebox_size(handle);
+                       livebox_service_get_size(type, &w, &h);
+                       if (w > 0 && h > 0) {
+                               evas_object_resize(image, w, h);
+                               evas_object_size_hint_min_set(image, w, h);
+                               evas_object_size_hint_max_set(image, w, h);
+                       }
+               }
+               break;
+       case LB_TYPE_TEXT:
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static inline void prepend_log(struct livebox *handle, const char *buffer)
+{
+       Evas_Object *layout;
+       Evas_Object *logger;
+
+       layout = livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout\n");
+               return;
+       }
+
+       logger = elm_object_part_content_get(layout, "logger");
+       if (logger)
+               elm_list_item_prepend(logger, buffer, NULL, NULL, NULL, NULL);
+}
+
+static int lb_event_cb(struct livebox *handle, enum livebox_event_type event, void *data)
+{
+       Evas_Object *layout;
+       Evas_Object *sc;
+       Evas_Object *pd;
+       Evas_Object *image;
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout)
+               return -EFAULT;
+
+       switch (event) {
+       case LB_EVENT_LB_UPDATED:
+               DbgPrint("Contents: [%s]\n", livebox_content(handle));
+               image = elm_object_part_content_get(layout, "livebox");
+               if (image)
+                       update_canvas(handle, image);
+               break;
+       case LB_EVENT_PD_UPDATED:
+               image = elm_object_part_content_get(layout, "pd");
+               if (image)
+                       update_pd_canvas(handle, image);
+               break;
+       case LB_EVENT_DELETED:
+               sc = evas_object_data_del(layout, "sc");
+               if (sc)
+                       scroller_peek_by_obj(sc, layout);
+
+               evas_object_del(layout);
+               break;
+       case LB_EVENT_PD_DESTROYED:
+               pd = elm_object_part_content_unset(layout, "pd");
+               if (pd)
+                       evas_object_del(pd);
+
+               sc = evas_object_data_del(layout, "sc");
+               if (sc)
+                       scroller_unlock(sc);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int lb_fault_cb(enum livebox_fault_type event,
+                                       const char *pkgname, const char *filename,
+                                       const char *funcname, void *data)
+{
+       DbgPrint("pkgname: %s\nfilename: %s\n:funcname: %s\n", pkgname, filename, funcname);
+       return 0;
+}
+
+static void del_cb(struct livebox *handle, int ret, void *data)
+{
+       Evas_Object *layout = data;
+       Evas_Object *sc;
+
+       sc = evas_object_data_del(layout, "sc");
+       if (sc) {
+               DbgPrint("Scroller: %p\n", sc);
+               scroller_peek_by_obj(sc, layout);
+       }
+
+       DbgPrint("Delete a layout object\n");
+       evas_object_del(layout);
+}
+
+static void delete_btn_cb(void *handle, Evas_Object *obj, void *event_info)
+{
+       int ret;
+       Evas_Object *layout;
+       layout = livebox_get_data(handle);
+       DbgPrint("Livebox Get Data %p - %p\n", handle, layout);
+       ret = livebox_del(handle, del_cb, layout);
+       if (ret < 0) {
+               char buffer[256];
+               snprintf(buffer, sizeof(buffer), "Delete returns: %d\n", ret);
+               prepend_log(handle, buffer);
+       }
+}
+
+static void error_popup(Evas_Object *parent, struct livebox *handle, int ret)
+{
+       ErrPrint("Failed to add a box: %d\n", ret);
+       return;
+}
+
+static void resize_cb(struct livebox *handle, int ret, void *data)
+{
+       Evas_Object *layout;
+       Evas_Object *log_list;
+       char buffer[256];
+
+       layout = livebox_get_data(handle);
+       if (!layout)
+               return;
+
+       log_list = elm_object_part_content_get(layout, "logger");
+       if (!log_list)
+               return;
+
+       snprintf(buffer, sizeof(buffer) - 1, "Resize: %d", ret);
+       elm_list_item_prepend(log_list, buffer, NULL, NULL, NULL, NULL);
+}
+
+static void resize_click_cb(void *handle, Evas_Object *obj, void *event_info)
+{
+       Elm_Object_Item *item;
+       const char *label;
+       int w;
+       int h;
+       int size_type;
+
+       item = elm_list_selected_item_get(obj);
+       if (!item)
+               return;
+
+       label = elm_object_item_part_text_get(item, NULL);
+       if (!label)
+               return;
+
+       sscanf(label, "%dx%d", &w, &h);
+       size_type = livebox_service_size_type(w, h);
+
+       livebox_resize(handle, size_type, resize_cb, NULL);
+}
+
+static void create_resize_controller(struct livebox *handle, Evas_Object *layout)
+{
+       Evas_Object *size_list;
+       char buffer[256];
+       int sizes[NR_OF_SIZE_LIST];
+       int cnt;
+       int i;
+       int w;
+       int h;
+
+       size_list = elm_list_add(layout);
+       cnt = sizeof(sizes) / sizeof(sizes[0]);
+       livebox_get_supported_sizes(handle, &cnt, sizes);
+       for (i = 0; i < cnt; i++) {
+               livebox_service_get_size(sizes[i], &w, &h);
+               snprintf(buffer, sizeof(buffer) - 1, "%dx%d", w, h);
+
+               elm_list_item_append(size_list, buffer, NULL, NULL, resize_click_cb, handle);
+       }
+       evas_object_show(size_list);
+       elm_list_go(size_list);
+       evas_object_size_hint_weight_set(size_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_size_hint_align_set(size_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       elm_object_part_content_set(layout, "controller", size_list);
+}
+
+static void create_logger(struct livebox *handle, Evas_Object *layout)
+{
+       Evas_Object *log_list;
+
+       log_list = elm_list_add(layout);
+       if (!log_list)
+               return;
+
+       elm_list_item_prepend(log_list, "Created", NULL, NULL, NULL, NULL);
+       evas_object_show(log_list);
+       elm_list_go(log_list);
+
+       evas_object_size_hint_weight_set(log_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_size_hint_align_set(log_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       elm_object_part_content_set(layout, "logger", log_list);
+}
+
+struct event_data {
+       Evas_Coord x;
+       Evas_Coord y;
+
+       enum flick {
+               FLICK_UNKNOWN = 0x00,
+               FLICK_DOWN = 0x01,
+               FLICK_UP = 0x02,
+       } flick;
+};
+
+static void pd_closed_cb(struct livebox *handle, int ret, void *data)
+{
+       evas_object_del(data);
+}
+
+static void pd_hide_done_cb(void *data, Evas_Object *obj, const char *emission, const char *source) 
+{
+       Evas_Object *pd;
+       Evas_Object *sc;
+
+       sc = evas_object_data_get(obj, "sc");
+       scroller_unlock(sc);
+
+       elm_object_signal_callback_del(obj, emission, source, pd_hide_done_cb);
+       pd = elm_object_part_content_unset(obj, "pd");
+       livebox_destroy_pd(data, pd_closed_cb, pd);
+}
+
+static void pd_mouse_up_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Evas_Event_Mouse_Up *up = event_info;
+       Evas_Coord x, y, w, h;
+       double rx, ry;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+
+       rx = (double)(up->canvas.x - x) / (double)w;
+       ry = (double)(up->canvas.y - y) / (double)h;
+       DbgPrint("%dx%d - %dx%d, %lfx%lf\n", x, y, w, h, rx, ry);
+       livebox_content_event(handle, PD_MOUSE_UP, rx, ry);
+}
+
+static void pd_mouse_down_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Evas_Event_Mouse_Down *down = event_info;
+       Evas_Coord x, y, w, h;
+       double rx, ry;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+       rx = (double)(down->canvas.x - x) / (double)w;
+       ry = (double)(down->canvas.y - y) / (double)h;
+       DbgPrint("%dx%d - %dx%d, %lfx%lf\n", x, y, w, h, rx, ry);
+       livebox_content_event(handle, PD_MOUSE_DOWN, rx, ry);
+}
+
+static void pd_mouse_move_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Evas_Event_Mouse_Move *move = event_info;
+       Evas_Coord x, y, w, h;
+       double rx, ry;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+       rx = (double)(move->cur.canvas.x - x) / (double)w;
+       ry = (double)(move->cur.canvas.y - y) / (double)h;
+       DbgPrint("%dx%d - %dx%d, %lfx%lf\n", x, y, w, h, rx, ry);
+       livebox_content_event(handle, PD_MOUSE_MOVE, rx, ry);
+}
+
+static void pd_created_cb(struct livebox *handle, int ret, void *data)
+{
+       Evas_Object *layout;
+       Evas_Object *pd_image;
+       Evas_Object *sc;
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout)
+               return;
+
+       sc = evas_object_data_get(layout, "sc");
+
+       pd_image = create_canvas(layout);
+       if (!pd_image)
+               return;
+
+       evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_UP, pd_mouse_up_cb, handle);
+       evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_DOWN, pd_mouse_down_cb, handle);
+       evas_object_event_callback_add(pd_image, EVAS_CALLBACK_MOUSE_MOVE, pd_mouse_move_cb, handle);
+
+       update_pd_canvas(handle, pd_image);
+
+       elm_object_signal_callback_add(layout, "hide,done", "pd", pd_hide_done_cb, handle);
+       elm_object_part_content_set(layout, "pd", pd_image);
+       elm_object_signal_emit(layout, "open", "pd");
+       scroller_lock(sc);
+}
+
+static void lb_mouse_up_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Evas_Event_Mouse_Up *up = event_info;
+       Evas_Coord x, y, w, h;
+       struct event_data *evt;
+
+       evt = evas_object_data_del(obj, "evt");
+       if (!evt)
+               return;
+
+       evas_object_geometry_get(obj, &x, &y, &w, &h);
+
+       if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
+               double rx, ry;
+               rx = (double)(up->canvas.x - x) / (double)w;
+               ry = (double)(up->canvas.y - y) / (double)h;
+               livebox_content_event(handle, LB_MOUSE_UP, rx, ry);
+       }
+
+       if (x < up->canvas.x && up->canvas.x < x + w) {
+               if (y < up->canvas.y && up->canvas.y < y + h) {
+                       livebox_click(handle, (double)x / (double)w, (double)y / (double)h);
+               }
+       }
+
+       if (evt->flick == FLICK_DOWN && (up->canvas.y - evt->y) > (FLICK_COND>>1)) {
+               int ret;
+               /* Open PD */
+               ret = livebox_create_pd_with_position(handle, 0.5, 0.0, pd_created_cb, NULL);
+       }
+
+       free(evt);
+}
+
+static void lb_mouse_down_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       struct event_data *evt;
+       Evas_Event_Mouse_Down *down = event_info;
+       Evas_Object *layout;
+       Evas_Object *sc;
+
+       layout = livebox_get_data(handle);
+       if (!layout)
+               return;
+
+       sc = evas_object_data_get(layout, "sc");
+       if (!sc)
+               return;
+
+       if (scroller_is_scrolling(sc))
+               return;
+
+       if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
+               Evas_Coord x, y, w, h;
+               double rx, ry;
+
+               evas_object_geometry_get(obj, &x, &y, &w, &h);
+               rx = (double)(down->canvas.x - x) / (double)w;
+               ry = (double)(down->canvas.y - y) / (double)h;
+               livebox_content_event(handle, LB_MOUSE_DOWN, rx, ry);
+       }
+
+       evt = evas_object_data_get(obj, "evt");
+       if (evt) {
+               ErrPrint("Huh?");
+       } else {
+               evt = malloc(sizeof(*evt));
+               if (!evt) {
+                       ErrPrint("Heap: %s\n", strerror(errno));
+                       return;
+               }
+       }
+
+       evas_object_data_set(obj, "evt", evt);
+
+       evt->x = down->canvas.x;
+       evt->y = down->canvas.y;
+       evt->flick = FLICK_UNKNOWN;
+}
+
+static void lb_mouse_move_cb(void *handle, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Evas_Event_Mouse_Move *move = event_info;
+       struct event_data *evt;
+
+       evt = evas_object_data_get(obj, "evt");
+       if (!evt)
+               return;
+
+       if (livebox_lb_type(handle) == LB_TYPE_PIXMAP || livebox_lb_type(handle) == LB_TYPE_BUFFER) {
+               Evas_Coord x, y, w, h;
+               double rx, ry;
+
+               evas_object_geometry_get(obj, &x, &y, &w, &h);
+               rx = (double)(move->cur.canvas.x - x) / (double)w;
+               ry = (double)(move->cur.canvas.y - y) / (double)h;
+               livebox_content_event(handle, LB_MOUSE_MOVE, rx, ry);
+       }
+
+       if ((move->cur.canvas.x - move->prev.canvas.x) > FLICK_COND) {
+               evt->flick = FLICK_UNKNOWN;
+               return;
+       } else if ((move->cur.canvas.x - move->prev.canvas.x) < -FLICK_COND) {
+               evt->flick = FLICK_UNKNOWN;
+               return;
+       }
+
+       if ((move->cur.canvas.y - move->prev.canvas.y) > 0) {
+               if (evt->flick != FLICK_DOWN)
+                       evt->flick = FLICK_DOWN;
+       } else if ((move->cur.canvas.y - move->prev.canvas.y) < 0) {
+               if (evt->flick != FLICK_UP)
+                       evt->flick = FLICK_UP;
+       }
+}
+
+static int lb_update_begin(struct livebox *handle)
+{
+       DbgPrint("%p\n", handle);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "begin");
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+
+       return 0;
+}
+
+static int lb_update_end(struct livebox *handle)
+{
+       DbgPrint("%p\n", handle);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "end");
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+
+       return 0;
+}
+
+static int lb_update_text(struct livebox *handle, const char *id, const char *part, const char *data)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], part[%s], data[%s]\n", id, part, data);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s=%s", part, data);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+
+       return 0;
+}
+
+static int lb_update_image(struct livebox *handle, const char *id, const char *part, const char *data)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], part[%s], data[%s]\n", id, part, data);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s=%s", part, data);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+
+       return 0;
+}
+
+static int lb_update_script(struct livebox *handle, const char *id, const char *part, const char *file, const char *group)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], part[%s], file[%s], group[%s]\n", id, part, file, group);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s=%s, %s", part, file, group);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+
+       return 0;
+}
+
+static int lb_update_signal(struct livebox *handle, const char *id, const char *emission, const char *signal)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], emission[%s], signal[%s]\n", id, emission, signal);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s,%s", emission, signal);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+       return 0;
+}
+
+static int lb_update_drag(struct livebox *handle, const char *id, const char *part, double dx, double dy)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], part[%s], pos[%lfx%lf]\n", id, part, dx, dy);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s=%lfx%lf", part, dx, dy);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+       return 0;
+}
+
+static int lb_update_info_size(struct livebox *handle, const char *id, int w, int h)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], size[%dx%d]\n", id, w, h);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+       return 0;
+}
+
+static int lb_update_info_category(struct livebox *handle, const char *id, const char *category)
+{
+       DbgPrint("%p\n", handle);
+       DbgPrint("id: [%s], category: [%s]\n", id, category);
+
+       Evas_Object *layout;
+       Evas_Object *list;
+       char buffer[80];
+
+       layout = (Evas_Object *)livebox_get_data(handle);
+       if (!layout) {
+               ErrPrint("Failed to get layout object\n");
+               return 0;
+       }
+
+       list = elm_object_part_content_get(layout, "livebox");
+       if (!list) {
+               ErrPrint("Failed to get list\n");
+               return 0;
+       }
+
+       snprintf(buffer, sizeof(buffer), "%s=%s", id, category);
+       elm_list_item_prepend(list, buffer, NULL, NULL, NULL, NULL);
+       return 0;
+}
+
+static void livebox_added_cb(struct livebox *handle, int ret, void *data)
+{
+       Evas_Object *layout;
+       Evas_Object *btn;
+       int w;
+       int h;
+       int type;
+       int idx;
+
+       DbgPrint("%s - %d\n", livebox_pkgname(handle), ret);
+
+       if (ret != 0) {
+               error_popup(main_get_window(), handle, ret);
+               return;
+       }
+
+       layout = elm_layout_add(main_get_window());
+       if (!layout) {
+               ErrPrint("Failed to add a layout\n");
+               return;
+       }
+
+       if (elm_layout_file_set(layout, PKGROOT "/res/edje/live-viewer.edj", "layout") == EINA_FALSE) {
+               DbgPrint("Failed to add a layout\n");
+               evas_object_del(layout);
+               return;
+       }
+
+       if (livebox_lb_type(handle) == LB_TYPE_TEXT) {
+               Evas_Object *list;
+               static struct livebox_script_operators ops = {
+                       .update_begin = lb_update_begin,
+                       .update_end = lb_update_end,
+                       .update_text = lb_update_text,
+                       .update_image = lb_update_image,
+                       .update_script = lb_update_script,
+                       .update_signal = lb_update_signal,
+                       .update_drag = lb_update_drag,
+                       .update_info_size = lb_update_info_size,
+                       .update_info_category = lb_update_info_category,
+               };
+
+               list = elm_list_add(layout);
+               if (!list) {
+                       evas_object_del(layout);
+                       return;
+               }
+
+               (void)livebox_set_text_handler(handle, &ops);
+               elm_object_part_content_set(layout, "livebox", list);
+               elm_list_go(list);
+       } else {
+               Evas_Object *lb_image;
+               lb_image = create_canvas(layout);
+               if (!lb_image) {
+                       ErrPrint("Failed to create a canvas\n");
+                       evas_object_del(layout);
+                       return;
+               }
+
+               evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_UP, lb_mouse_up_cb, handle);
+               evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_DOWN, lb_mouse_down_cb, handle);
+               evas_object_event_callback_add(lb_image, EVAS_CALLBACK_MOUSE_MOVE, lb_mouse_move_cb, handle);
+
+               w = 0;
+               h = 0;
+               type = livebox_size(handle);
+               if (type != LB_SIZE_TYPE_UNKNOWN) {
+                       livebox_service_get_size(type, &w, &h);
+                       DbgPrint("%dx%d\n", w, h);
+               }
+               evas_object_resize(lb_image, w, h);
+               evas_object_show(lb_image);
+
+               update_canvas(handle, lb_image);
+
+               btn = elm_button_add(main_get_window());
+               if (btn) {
+                       elm_object_text_set(btn, "Delete");
+                       evas_object_smart_callback_add(btn, "clicked", delete_btn_cb, handle);
+                       elm_object_part_content_set(layout, "delete,btn", btn);
+               }
+
+               elm_object_part_content_set(layout, "livebox", lb_image);
+       }
+       evas_object_resize(layout, 720, 1280);
+       evas_object_show(layout);
+
+       create_resize_controller(handle, layout);
+       create_logger(handle, layout);
+
+       livebox_set_data(handle, layout);
+       DbgPrint("Livebox Set Data: %p - %p\n", handle, layout);
+       evas_object_data_set(layout, "sc", data);
+
+       scroller_append(data, layout);
+
+       idx = scroller_get_page_index(data, layout);
+       DbgPrint("Scroll to %d\n", idx);
+       scroller_scroll_to(data, idx);
+}
+
+int lb_add(Evas_Object *sc, const char *pkgname)
+{
+       int w, h;
+       struct livebox *handle;
+
+       evas_object_geometry_get(sc, NULL, NULL, &w, &h);
+
+       DbgPrint("sc: %dx%d, package: %s\n", w, h, pkgname);
+       livebox_activate(pkgname, NULL, NULL);
+
+       handle = livebox_add(pkgname, "default", "user,created", "default",
+                                               DEFAULT_PERIOD, livebox_added_cb, sc);
+       if (!handle) {
+               ErrPrint("Failed to add a new livebox\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int lb_init(void)
+{
+       livebox_init(ecore_x_display_get());
+       livebox_set_event_handler(lb_event_cb, NULL);
+       livebox_set_fault_handler(lb_fault_cb, NULL);
+       return 0;
+}
+
+int lb_fini(void)
+{
+       livebox_fini();
+       return 0;
+}
+
+/* End of a file */
diff --git a/live.viewer/src/live_scroller.c b/live.viewer/src/live_scroller.c
new file mode 100644 (file)
index 0000000..4a23dd2
--- /dev/null
@@ -0,0 +1,1457 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <dlog.h>
+
+#include "live_scroller.h"
+#include "util.h"
+#include "debug.h"
+
+#define SAMPLE_MAX 10
+#define EVT_PERIOD 0.016 /* 60 fps */
+#define EVT_SAMPLE_PERIOD 9
+#define DRAG_SENS 100
+#define ANIM_MIN 40
+#define ANIM_UNIT 15
+
+struct item_list_entry {
+       struct item_list_entry *prev;
+       struct item_list_entry *next;
+
+       Evas_Object *data;
+       Evas_Coord x;
+       Evas_Coord y;
+       Evas_Coord w;
+       Evas_Coord h;
+};
+
+struct evt_info {
+       Evas_Coord x;
+       unsigned int timestamp;
+};
+
+struct evt_queue {
+       struct evt_info ei[SAMPLE_MAX];
+       int front;
+       int rear;
+       int cnt;
+       unsigned int old_timestamp;
+};
+
+struct widget_data {
+       Eina_Bool is_loop;
+       Eina_Bool is_freezed;
+
+       struct item_list_entry *item_list;
+
+       int item_cnt;
+       struct item_list_entry *curlist;
+       struct item_list_entry *tolist;
+
+       Eina_Bool drag_started;
+       Eina_Bool is_pressed;
+       Evas_Coord press_x;
+       Evas_Coord press_y;
+
+       Ecore_Timer *sc_anim_timer;
+       int sc_anim_dx;
+
+       Evas_Object *clip;
+       Evas_Object *evt_layer;
+       Evas_Object *scroller;
+
+       Evas_Coord clip_bx;
+       Evas_Coord clip_bw;
+
+       struct evt_queue evtq;
+       Ecore_Timer *evt_emulator;
+       Evas_Coord old_x;
+       unsigned int prev_timestamp;
+};
+
+#ifdef PROFILE
+#define PROFILE_START() \
+static int _exec_cnt = 0; \
+struct timeval _stv, _etv; \
+long _elapsed; \
+gettimeofday(&_stv, NULL);
+
+#define PROFILE_END() \
+do { \
+       _exec_cnt++; \
+       gettimeofday(&_etv, NULL); \
+       _elapsed = (_etv.tv_sec - _stv.tv_sec) * 1000000l + (_etv.tv_usec - _stv.tv_usec); \
+       DbgPrint("[%d] Elapsed time: %lu\n", _exec_cnt, _elapsed); \
+} while (0)
+#else
+#define PROFILE_START()
+#define PROFILE_END()
+#endif
+
+#define LIST_NEXT(list)        ((list)->next)
+#define LIST_PREV(list)        ((list)->prev)
+#define LIST_DATA(list)        ((list) ? (list)->data : NULL)
+
+static inline void LIST_ITEM_GEO_SET(struct item_list_entry *list, int x, int y, int w, int h)
+{
+       list->x = x;
+       list->y = y;
+       list->w = w;
+       list->h = h;
+}
+
+static inline void LIST_ITEM_GEO_GET(struct item_list_entry *list, int *x, int *y, int *w, int *h)
+{
+       if (x)
+               *x = list->x;
+       if (y)
+               *y = list->y;
+       if (w)
+               *w = list->w;
+       if (h)
+               *h = list->h;
+}
+
+static inline struct item_list_entry *list_item_append(struct item_list_entry *list, void *obj)
+{
+       struct item_list_entry *item;
+
+       item = malloc(sizeof(*item));
+       if (!item)
+               return NULL;
+
+       item->data = obj;
+
+       if (list) {
+               list->prev->next = item;
+               item->prev = list->prev;
+
+               item->next = list;
+               list->prev = item;
+       } else{
+               item->prev = item;
+               item->next = item;
+               list = item;
+       }
+
+       return list;
+}
+
+static inline void *list_item_nth(struct item_list_entry *list, int idx)
+{
+       if (!list)
+               return NULL;
+
+       while (--idx >= 0)
+               list = list->next;
+
+       return list->data;
+}
+
+static inline struct item_list_entry *list_item_nth_list(struct item_list_entry *list, int idx)
+{
+       if (!list)
+               return NULL;
+
+       while (--idx >= 0)
+               list = list->next;
+
+       return list;
+}
+
+static inline struct item_list_entry *list_item_find(struct item_list_entry *list, void *data)
+{
+       struct item_list_entry *item;
+
+       if (!list)
+               return NULL;
+
+       item = list;
+       do {
+               if (LIST_DATA(item) == data)
+                       return item;
+
+               item = LIST_NEXT(item);
+       } while (item != list);
+
+       return NULL;
+}
+
+static inline struct item_list_entry *list_item_remove(struct item_list_entry *list, void *data)
+{
+       struct item_list_entry *item;
+
+       if (!list) {
+               ErrPrint("List is not valid\n");
+               return NULL;
+       }
+
+       DbgPrint("Start\n");
+       item = list;
+       do {
+               if (LIST_DATA(item) == data) {
+                       DbgPrint("ITEM is removed\n");
+                       if (item == list) {
+                               if (list == LIST_NEXT(list))
+                                       list = NULL;
+                               else
+                                       list = LIST_NEXT(list);
+                       }
+
+                       item->prev->next = item->next;
+                       item->next->prev = item->prev;
+                       free(item);
+                       break;
+               }
+
+               item = LIST_NEXT(item);
+       } while (item != list);
+       DbgPrint("End\n");
+
+       return list;
+}
+
+static inline void *list_item_last(struct item_list_entry *list)
+{
+       if (!list)
+               return NULL;
+
+       return list->prev->data;
+}
+
+static inline struct item_list_entry *list_item_last_list(struct item_list_entry *list)
+{
+       if (!list)
+               return NULL;
+
+       return list->prev;
+}
+
+static inline int list_item_count(struct item_list_entry *list)
+{
+       struct item_list_entry *n;
+       int cnt;
+
+       if (!list)
+               return 0;
+
+       cnt = 0;
+       n = list;
+       do {
+               cnt++;
+               n = LIST_NEXT(n);
+       } while (n != list);
+
+       return cnt;
+}
+
+static inline int list_item_idx(struct widget_data *sc_data, struct item_list_entry *ilist)
+{
+       int idx;
+       idx = 0;
+
+       while (ilist != sc_data->item_list) {
+               idx++;
+               ilist = LIST_PREV(ilist);
+       }
+
+       return idx;
+}
+
+static inline void init_evtq(struct evt_queue *evtq)
+{
+       evtq->front = 0;
+       evtq->rear = 0;
+       evtq->cnt = 0;
+       evtq->old_timestamp = 0;
+}
+
+static inline void dq_evt(struct evt_queue *evtq)
+{
+       if (evtq->cnt <= 0)
+               return;
+       evtq->front++;
+       if (evtq->front >= SAMPLE_MAX)
+               evtq->front -= SAMPLE_MAX;
+       evtq->cnt--;
+}
+
+static inline void enq_evt(struct evt_queue *evtq, Evas_Coord x, unsigned int timestamp)
+{
+       unsigned int t_diff;
+       int replace;
+
+       replace = 0;
+       t_diff = timestamp - evtq->old_timestamp;
+
+       if (evtq->cnt <= 0)
+               evtq->old_timestamp = timestamp;
+       else if (t_diff > EVT_SAMPLE_PERIOD)
+               evtq->old_timestamp += EVT_SAMPLE_PERIOD * (t_diff / EVT_SAMPLE_PERIOD);
+       else
+               replace = 1;
+
+       if (!replace) {
+               if (evtq->cnt >= SAMPLE_MAX)
+                       dq_evt(evtq);
+               evtq->rear++;
+               if (evtq->rear >= SAMPLE_MAX)
+                       evtq->rear -= SAMPLE_MAX;
+               evtq->cnt++;
+       }
+
+       evtq->ei[evtq->rear].x = x;
+       evtq->ei[evtq->rear].timestamp = evtq->old_timestamp;
+}
+
+static inline Evas_Coord get_evt_avg(struct evt_queue *evtq)
+{
+       int i;
+       int rear;
+       Evas_Coord x;
+       int weight;
+       int t;
+
+       t = (int)(ecore_time_get() * 1000);
+       rear = evtq->rear;
+
+       x = 0;
+       for (i = 0; i < evtq->cnt; i += weight) {
+               weight = (t - evtq->ei[rear].timestamp) / EVT_SAMPLE_PERIOD;
+               if (weight > (evtq->cnt - i))
+                       weight = evtq->cnt - i;
+               else
+                       weight = 1;
+
+               x += evtq->ei[rear].x * weight;
+               t = evtq->ei[rear].timestamp;
+               rear--;
+               if (rear < 0)
+                       rear += SAMPLE_MAX;
+       }
+
+       x /= evtq->cnt;
+       return x;
+}
+
+/* Move the item to given direction to fit its coordinates to border */
+static inline int calc_anim_dx_with_dir(struct widget_data *sc_data, int *dir)
+{
+       Evas_Coord x, w;
+
+       LIST_ITEM_GEO_GET(sc_data->curlist, &x, NULL, &w, NULL);
+       sc_data->sc_anim_dx = 0;
+
+       if (*dir < 0) {
+               DbgPrint("MOVE to LEFT\n");
+               if (x < sc_data->clip_bx) {
+                       (*dir)++;
+
+                       if (sc_data->tolist == sc_data->item_list) {
+                               if (!sc_data->is_loop) {
+                                       *dir = 0;
+                                       DbgPrint("Looping is disabled\n");
+                                       return -EINVAL;
+                               }
+                       }
+
+                       sc_data->tolist = LIST_PREV(sc_data->tolist);
+                       sc_data->sc_anim_dx = sc_data->clip_bx - x /*- w*/;
+               } else {
+                       sc_data->sc_anim_dx = sc_data->clip_bx - x;
+               }
+       } else if (*dir > 0) {
+               DbgPrint("MOVE to RIGHT\n");
+               if (x < sc_data->clip_bx) {
+                       sc_data->sc_anim_dx = sc_data->clip_bx - x;
+               } else if (x > sc_data->clip_bx) {
+                       struct item_list_entry *newlist;
+
+                       (*dir)--;
+                       newlist = LIST_NEXT(sc_data->tolist);
+                       if (newlist == sc_data->item_list) {
+                               if (!sc_data->is_loop) {
+                                       *dir = 0;
+                                       DbgPrint("Looping is disabled\n");
+                                       return -EINVAL;
+                               }
+                       }
+                       sc_data->tolist = newlist;
+                       sc_data->sc_anim_dx = sc_data->clip_bx - x; /*(sc_data->clip_bx + sc_data->clip_bw) - x;*/
+               }
+       }
+
+       return 0;
+}
+
+static inline void move_item(struct widget_data *sc_data, struct item_list_entry *ilist, int x, int y, int w, int h)
+{
+       struct live_sc_move_info info;
+
+       info.item = LIST_DATA(ilist);
+
+       info.relx = ((double)x - (double)sc_data->clip_bx) / (double)sc_data->clip_bw;
+
+       LIST_ITEM_GEO_SET(ilist, x, y, w, h);
+       info.x = x;
+       info.y = y;
+       info.w = w;
+       info.h = h;
+
+       evas_object_smart_callback_call(sc_data->scroller, "item,moved", &info);
+}
+
+static struct item_list_entry *update_items_geo(struct widget_data *sc_data, int dx)
+{
+       Evas_Coord sx, sw;
+       Evas_Coord y, w, h;
+       struct item_list_entry *ilist;
+       struct item_list_entry *newlist;
+       struct item_list_entry *boundary;
+       int bx_bw;
+       register int x;
+
+       LIST_ITEM_GEO_GET(sc_data->curlist, &sx, &y, &sw, &h);
+
+       bx_bw = sc_data->clip_bx + sc_data->clip_bw;
+
+       sx += dx;
+       move_item(sc_data, sc_data->curlist, sx, y, sw, h);
+
+       newlist = NULL;
+
+       if (sc_data->item_cnt < 3) {
+               ilist = LIST_NEXT(sc_data->curlist);
+               LIST_ITEM_GEO_GET(ilist, NULL, &y, &w, &h);
+
+               if (sx + sw < bx_bw) {
+                       x = sx + sw;
+                       move_item(sc_data, ilist, x, y, w, h);
+                       if (x == sc_data->clip_bx || (x < sc_data->clip_bx && (x + w) > sc_data->clip_bx))
+                               newlist = ilist;
+               } else if (sx > 0) {
+                       x = sx - w;
+                       move_item(sc_data, ilist, x, y, w, h);
+                       if (x == sc_data->clip_bx || (x > sc_data->clip_bx && x < bx_bw)) {
+                               newlist = ilist;
+                       }
+               }
+
+               goto out;
+       }
+
+       x = sx;
+       boundary = NULL;
+       ilist = sc_data->curlist;
+       do {
+               if (!sc_data->is_loop && ilist == sc_data->item_list)
+                       break;
+
+               ilist = LIST_PREV(ilist);
+               if (!ilist)
+                       break;
+
+               LIST_ITEM_GEO_GET(ilist, NULL, &y, &w, &h);
+               x -= w;
+               move_item(sc_data, ilist, x, y, w, h);
+
+               if (dx > 0 && !newlist) {
+                       if ((x == sc_data->clip_bx) || (x > sc_data->clip_bx && x < bx_bw))
+                               newlist = ilist;
+               }
+
+               boundary = ilist;
+       } while (x > sc_data->clip_bx);
+
+       x = sx;
+       w = sw;
+       ilist = sc_data->curlist;
+       do {
+               ilist = LIST_NEXT(ilist);
+               if (!ilist || (!sc_data->is_loop && ilist == sc_data->item_list) || ilist == boundary)
+                       break;
+
+               x += w;
+               LIST_ITEM_GEO_GET(ilist, NULL, &y, &w, &h);
+               move_item(sc_data, ilist, x, y, w, h);
+
+               if (dx < 0 && !newlist) {
+                       if ((x == sc_data->clip_bx) || (x < sc_data->clip_bx && (x + w) > sc_data->clip_bx))
+                               newlist = ilist;
+               }
+       } while (x < bx_bw);
+
+out:
+       if (newlist)
+               sc_data->curlist = newlist;
+               
+       return newlist;
+}
+
+static Eina_Bool emulate_evt(void *data)
+{
+       PROFILE_START();
+       struct widget_data *sc_data;
+       Evas_Coord x;
+       Evas_Coord dx;
+       struct item_list_entry *newlist;
+
+       sc_data = data;
+
+       x = get_evt_avg(&sc_data->evtq);
+       if (x == sc_data->old_x) {
+               PROFILE_END();
+               return ECORE_CALLBACK_RENEW;
+       }
+       
+       dx = x - sc_data->old_x;
+       sc_data->old_x = x;
+
+       newlist = update_items_geo(sc_data, dx);
+       if (newlist) {
+               int idx;
+
+               idx = list_item_idx(sc_data, newlist);
+               evas_object_smart_callback_call(sc_data->scroller, "page,changed", (void *)idx);
+       }
+       PROFILE_END();
+       return ECORE_CALLBACK_RENEW;
+}
+
+static void evt_mouse_down_cb(void *data, Evas *e, Evas_Object *evt_layer, void *event_info)
+{
+       Evas_Event_Mouse_Down *down;
+       struct widget_data *sc_data;
+
+       sc_data = data;
+       down = event_info;
+
+       sc_data->is_pressed = EINA_TRUE;
+       sc_data->press_x = down->canvas.x;
+       sc_data->press_y = down->canvas.y;
+       sc_data->old_x = down->canvas.x;
+
+       if (!sc_data->is_freezed) {
+               init_evtq(&sc_data->evtq);
+               enq_evt(&sc_data->evtq, down->canvas.x, down->timestamp);
+       }
+}
+
+static void evt_mouse_up_cb(void *data, Evas *e, Evas_Object *evt_layer, void *event_info)
+{
+       Evas_Event_Mouse_Up *up;
+       struct widget_data *sc_data;
+       struct live_sc_drag_info info;
+
+       sc_data = data;
+
+       if (!sc_data->is_pressed)
+               return;
+
+       sc_data->is_pressed = EINA_FALSE;
+
+       if (sc_data->evt_emulator) {
+               ecore_timer_del(sc_data->evt_emulator);
+               sc_data->evt_emulator = NULL;
+       }
+
+       if (sc_data->drag_started == EINA_FALSE) {
+               DbgPrint("drag is not started\n");
+               return;
+       }
+
+       up = event_info;
+
+       info.dx = up->canvas.x - sc_data->press_x;
+       info.dy = up->canvas.y - sc_data->press_y;
+
+       sc_data->drag_started = EINA_FALSE;
+
+       evas_object_smart_callback_call(sc_data->scroller, "drag,stop", &info);
+}
+
+static void evt_mouse_move_cb(void *data, Evas *e, Evas_Object *evt_layer, void *event_info)
+{
+       struct widget_data *sc_data;
+       Evas_Event_Mouse_Move *move;
+
+       sc_data = data;
+       
+       if (sc_data->is_pressed == EINA_FALSE)
+               return;
+
+       if (sc_data->item_cnt <= 1)
+               return;
+
+       if (sc_data->is_freezed)
+               return;
+
+       move = event_info;
+
+       if (sc_data->drag_started == EINA_FALSE) {
+               if (abs(move->cur.canvas.x - sc_data->press_x) < DRAG_SENS)
+                       return;
+
+               if (sc_data->sc_anim_timer) {
+                       ecore_timer_del(sc_data->sc_anim_timer);
+                       sc_data->sc_anim_timer = NULL;
+               }
+
+               evas_object_smart_callback_call(sc_data->scroller, "drag,start", NULL);
+               sc_data->drag_started = EINA_TRUE;
+       }
+
+       sc_data->prev_timestamp = move->timestamp;
+       enq_evt(&sc_data->evtq, move->cur.canvas.x, move->timestamp);
+       if (!sc_data->evt_emulator) {
+               if (!sc_data->curlist)
+                       sc_data->curlist = sc_data->item_list;
+
+               sc_data->evt_emulator = ecore_timer_add(EVT_PERIOD, emulate_evt, sc_data);
+       }
+}
+
+static inline int prepare_evt_layer(struct widget_data *sc_data)
+{
+       Evas *e;
+
+       e = evas_object_evas_get(sc_data->scroller);
+       if (!e)
+               return -EFAULT;
+
+       sc_data->evt_layer = evas_object_rectangle_add(e);
+       if (!sc_data->evt_layer)
+               return -EFAULT;
+
+       evas_object_smart_member_add(sc_data->evt_layer, sc_data->scroller);
+
+       evas_object_color_set(sc_data->evt_layer, 255, 255, 255, 0);
+       evas_object_show(sc_data->evt_layer);
+       evas_object_repeat_events_set(sc_data->evt_layer, EINA_TRUE);
+
+       evas_object_event_callback_add(sc_data->evt_layer,
+                       EVAS_CALLBACK_MOUSE_DOWN, evt_mouse_down_cb, sc_data);
+
+       evas_object_event_callback_add(sc_data->evt_layer,
+                       EVAS_CALLBACK_MOUSE_UP, evt_mouse_up_cb, sc_data);
+
+       evas_object_event_callback_add(sc_data->evt_layer,
+                       EVAS_CALLBACK_MOUSE_MOVE, evt_mouse_move_cb, sc_data);
+
+       evas_object_clip_set(sc_data->evt_layer, sc_data->clip);
+       return 0;
+}
+
+static void live_add(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+       Evas *e;
+       int ret;
+
+       sc_data = calloc(1, sizeof(*sc_data));
+       if (!sc_data)
+               return;
+
+       e = evas_object_evas_get(scroller);
+       if (!e) {
+               free(sc_data);
+               return;
+       }
+
+       evas_object_smart_data_set(scroller, sc_data);
+
+       sc_data->clip = evas_object_rectangle_add(e);
+       if (!sc_data->clip) {
+               free(sc_data);
+               return;
+       }
+
+       sc_data->is_pressed = EINA_FALSE;
+       sc_data->drag_started = EINA_FALSE;
+       sc_data->tolist = NULL;
+       sc_data->curlist = NULL;
+       sc_data->item_list = NULL;
+       sc_data->scroller = scroller;
+
+       evas_object_smart_member_add(sc_data->clip, sc_data->scroller);
+
+       ret = prepare_evt_layer(sc_data);
+       if (ret < 0) {
+               evas_object_del(sc_data->clip);
+               free(sc_data);
+       }
+
+       return;
+}
+
+static void live_del(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+       Evas_Object *item;
+       struct item_list_entry *ilist;
+       struct item_list_entry *next;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       ilist = sc_data->item_list;
+       if (ilist) {
+               do {
+                       next = LIST_NEXT(ilist);
+                       item = LIST_DATA(ilist);
+                       evas_object_clip_unset(item);
+                       evas_object_smart_member_del(item);
+                       free(ilist);
+                       ilist = next;
+               } while (ilist != sc_data->item_list);
+       }
+
+       evas_object_del(sc_data->evt_layer);
+       evas_object_del(sc_data->clip);
+       free(sc_data);
+}
+
+static void live_move(Evas_Object *scroller, Evas_Coord bx, Evas_Coord by)
+{
+       struct widget_data *sc_data;
+       Evas_Coord x, y, w, h;
+       Evas_Coord bw;
+
+       Evas_Coord dx;
+       Evas_Coord dy;
+
+       struct item_list_entry *n;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_geometry_get(sc_data->clip, &x, &y, &bw, NULL);
+
+       evas_object_move(sc_data->evt_layer, bx, by);
+       evas_object_move(sc_data->clip, bx, by);
+       sc_data->clip_bx = bx;
+       sc_data->clip_bw = bw;
+
+       dx = bx - x;
+       dy = by - y;
+
+       if (sc_data->item_list) {
+               n = sc_data->item_list;
+               do {
+                       evas_object_move(LIST_DATA(n), bx, by);
+
+                       LIST_ITEM_GEO_GET(n, &x, &y, &w, &h);
+                       x += dx;
+                       y += dy;
+                       move_item(sc_data, n, x, y, w, h);
+                       n = LIST_NEXT(n);
+               } while (n != sc_data->item_list);
+       }
+}
+
+static void live_resize(Evas_Object *scroller, Evas_Coord w, Evas_Coord h)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_resize(sc_data->clip, w, h);
+       evas_object_resize(sc_data->evt_layer, w, h);
+
+       sc_data->clip_bw = w;
+}
+
+static void live_show(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_show(sc_data->clip);
+}
+
+static void live_hide(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_hide(sc_data->clip);
+}
+
+static void live_set_color(Evas_Object *scroller, int r, int g, int b, int a)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_color_set(sc_data->clip, r, g, b, a);
+}
+
+static void live_set_clip(Evas_Object *scroller, Evas_Object *clip)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_clip_set(sc_data->clip, clip);
+}
+
+static void live_unset_clip(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return;
+       }
+
+       evas_object_clip_unset(sc_data->clip);
+}
+
+static inline void rearrange_items(struct widget_data *sc_data)
+{
+       struct item_list_entry *ilist;
+       Evas_Coord x, y, w, h;
+       Evas_Coord sw;
+
+       LIST_ITEM_GEO_GET(sc_data->curlist, NULL, &y, &sw, &h);
+       move_item(sc_data, sc_data->curlist, sc_data->clip_bx, y, sw, h);
+
+       x = sc_data->clip_bx;
+       ilist = sc_data->curlist;
+       while (ilist != sc_data->item_list) {
+               ilist = LIST_PREV(ilist);
+               LIST_ITEM_GEO_GET(ilist, NULL, &y, &w, &h);
+               x -= w;
+               move_item(sc_data, ilist, x, y, w, h);
+       }
+
+       w = sw;
+       x = sc_data->clip_bx;
+       ilist = LIST_NEXT(sc_data->curlist);
+       while (ilist != sc_data->item_list) {
+               x += w;
+               LIST_ITEM_GEO_GET(ilist, NULL, &y, &w, &h);
+               move_item(sc_data, ilist, x, y, w, h);
+               ilist = LIST_NEXT(ilist);
+       }
+}
+
+static Eina_Bool sc_anim_cb(void *data)
+{
+       PROFILE_START();
+       struct widget_data *sc_data;
+       Evas_Coord sx, sw;
+       Evas_Coord y;
+       Evas_Coord dx;
+       struct item_list_entry *ilist;
+
+       sc_data = data;
+
+       if (!sc_data->curlist || !sc_data->tolist) {
+               DbgPrint("cur_list: %p, tolist: %p\n", sc_data->curlist, sc_data->tolist);
+               goto clean_out;
+       }
+
+       ilist = sc_data->curlist;
+       if (sc_data->curlist != sc_data->tolist) {
+               if (sc_data->sc_anim_dx > 0)
+                       ilist = LIST_PREV(ilist);
+               else
+                       ilist = LIST_NEXT(ilist);
+       }
+
+       LIST_ITEM_GEO_GET(ilist, &sx, &y, &sw, NULL);
+       if (ilist == sc_data->tolist) {
+               DbgPrint("next list == tolist\n");
+               dx = abs(sx - sc_data->clip_bx);
+               DbgPrint("sx: %d, clip_bx: %d --> %d\n", sx, sc_data->clip_bx, dx);
+               if (dx < abs(sc_data->sc_anim_dx)) {
+                       if (sc_data->sc_anim_dx < 0)
+                               dx = -dx;
+               } else {
+                       dx = sc_data->sc_anim_dx;
+               }
+       } else {
+               dx = sc_data->sc_anim_dx;
+               DbgPrint("dx: %d\n", dx);
+       }
+
+       if (!dx) {
+               DbgPrint("dx is 0\n");
+               goto clean_out;
+       }
+
+       ilist = update_items_geo(sc_data, dx);
+       if (ilist) {
+               int idx;
+
+               idx = list_item_idx(sc_data, ilist);
+               evas_object_smart_callback_call(sc_data->scroller,"page,changed", (void *)idx);
+       }
+       PROFILE_END();
+       return ECORE_CALLBACK_RENEW;
+
+clean_out:
+       PROFILE_END();
+       evas_object_smart_callback_call(sc_data->scroller, "anim,stop", NULL);
+       sc_data->sc_anim_timer = NULL;
+       return ECORE_CALLBACK_CANCEL;
+}
+
+Evas_Object *live_scroller_add(Evas_Object *parent)
+{
+       static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("live,scroller");
+       static Evas_Smart *smart = NULL;
+       Evas_Object *scroller;
+       Evas *e;
+
+       if (!parent)
+               return NULL;
+
+       e = evas_object_evas_get(parent);
+       if (!e)
+               return NULL;
+
+       if (!smart) {
+               sc.add = live_add;
+               sc.del = live_del;
+               sc.move = live_move;
+               sc.resize = live_resize;
+               sc.show = live_show;
+               sc.hide = live_hide;
+               sc.color_set = live_set_color;
+               sc.clip_set = live_set_clip;
+               sc.clip_unset = live_unset_clip;
+
+               smart = evas_smart_class_new(&sc);
+       }
+
+       scroller = evas_object_smart_add(e, smart);
+
+       return scroller;
+}
+
+int live_scroller_append(Evas_Object *scroller, Evas_Object *item)
+{
+       Evas_Coord x, y, w, h;
+       Evas_Coord bx, by, bw, bh;
+       struct widget_data *sc_data;
+       struct item_list_entry *tmplist;
+       Evas_Coord start_x = 0;
+       Evas_Coord start_w = 0;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       evas_object_geometry_get(sc_data->clip, &bx, &by, &bw, &bh);
+
+       if (sc_data->item_list)
+               LIST_ITEM_GEO_GET(sc_data->item_list, &start_x, NULL, &start_w, NULL);
+
+       tmplist = list_item_last_list(sc_data->item_list);
+       if (tmplist) {
+               LIST_ITEM_GEO_GET(tmplist, &x, NULL, &w, NULL);
+               if (x + w == start_x) {
+                       x = start_x - w;
+               } else {
+                       x += w;
+               }
+       } else {
+               x = bx;
+       }
+       
+       evas_object_geometry_get(item, NULL, NULL, &w, &h);
+       evas_object_smart_member_add(item, sc_data->scroller);
+
+       y = by + ((bh - h) >> 1);
+
+       tmplist = list_item_append(sc_data->item_list, item);
+       if (sc_data->item_list == sc_data->curlist)
+               sc_data->curlist = tmplist;
+       if (sc_data->item_list == sc_data->tolist)
+               sc_data->tolist = tmplist;
+       sc_data->item_list = tmplist;
+
+       sc_data->item_cnt++;
+       evas_object_clip_set(item, sc_data->clip);
+       evas_object_stack_below(item, sc_data->clip);
+
+       evas_object_move(item, bx, by);
+       move_item(sc_data, list_item_find(sc_data->item_list, item), x, y, w, h);
+
+       return 0;
+}
+
+int live_scroller_remove_by_obj(Evas_Object *scroller, Evas_Object *obj)
+{
+       struct widget_data *sc_data;
+       struct item_list_entry *tmplist;
+       Evas_Object *item;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       if (sc_data->curlist) {
+               if (LIST_DATA(sc_data->curlist) == obj) {
+                       sc_data->curlist = sc_data->item_list;
+                       DbgPrint("Reset curlist\n");
+               }
+       }
+
+       if (sc_data->tolist) {
+               if (LIST_DATA(sc_data->tolist) == obj) {
+                       sc_data->tolist = sc_data->item_list;
+                       DbgPrint("Reset tolist\n");
+               }
+       }
+
+       tmplist = list_item_remove(sc_data->item_list, obj);
+       if (sc_data->item_list == sc_data->curlist) {
+               sc_data->curlist = tmplist;
+               DbgPrint("Update curlist\n");
+       }
+       if (sc_data->item_list == sc_data->tolist) {
+               sc_data->tolist = tmplist;
+               DbgPrint("Update tolist\n");
+       }
+       sc_data->item_list = tmplist;
+
+       sc_data->item_cnt--;
+       evas_object_clip_unset(obj);
+       evas_object_smart_member_del(obj);
+       DbgPrint("Count of items: %d\n", sc_data->item_cnt);
+
+       item = LIST_DATA(sc_data->curlist);
+       if (item) {
+               Evas_Coord y, w, h;
+               int idx;
+
+               LIST_ITEM_GEO_GET(sc_data->curlist, NULL, &y, &w, &h);
+               DbgPrint("Current GEO: %d, %dx%d\n", y, w, h);
+               LIST_ITEM_GEO_SET(sc_data->curlist, sc_data->clip_bx, y, w, h);
+               DbgPrint("sc_data->curlist : %p\n", sc_data->curlist);
+               update_items_geo(sc_data, 0);
+               DbgPrint("sc_data->curlist : %p\n", sc_data->curlist);
+
+               idx = list_item_idx(sc_data, sc_data->curlist);
+               evas_object_smart_callback_call(sc_data->scroller, "page,changed", (void *)idx);
+       }
+
+       return 0;
+}
+
+Evas_Object *live_scroller_remove(Evas_Object *scroller, int idx)
+{
+       struct widget_data *sc_data;
+       struct item_list_entry *tmplist;
+       Evas_Object *ret;
+       Evas_Object *item;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return NULL;
+       }
+
+       if (idx < 0 || idx >= sc_data->item_cnt)
+               return NULL;
+
+       ret = list_item_nth(sc_data->item_list, idx);
+       if (!ret)
+               return NULL;
+
+       if (list_item_nth_list(sc_data->item_list, idx) == sc_data->curlist) {
+               DbgPrint("Reset curlist\n");
+               sc_data->curlist = sc_data->item_list;
+       }
+
+       if (list_item_nth_list(sc_data->item_list, idx) == sc_data->tolist) {
+               DbgPrint("Reset tolist\n");
+               sc_data->tolist = sc_data->item_list;
+       }
+
+       tmplist = list_item_remove(sc_data->item_list, ret);
+       if (sc_data->item_list == sc_data->curlist)
+               sc_data->curlist = tmplist;
+       if (sc_data->item_list == sc_data->tolist)
+               sc_data->tolist = tmplist;
+       sc_data->item_list = tmplist;
+
+       sc_data->item_cnt--;
+       evas_object_clip_unset(ret);
+       evas_object_smart_member_del(ret);
+
+       item = LIST_DATA(sc_data->curlist);
+       if (item) {
+               Evas_Coord y, w, h;
+               int idx;
+               LIST_ITEM_GEO_GET(sc_data->curlist, NULL, &y, &w, &h);
+               LIST_ITEM_GEO_SET(sc_data->curlist, sc_data->clip_bx, y, w, h);
+               update_items_geo(sc_data, 0);
+               idx = list_item_idx(sc_data, sc_data->curlist);
+               evas_object_smart_callback_call(sc_data->scroller, "page,changed", (void *)idx);
+       }
+       return ret;
+}
+
+Evas_Object *live_scroller_get_item(Evas_Object *scroller, int idx)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return NULL;
+       }
+
+       if (idx < 0 || idx >= sc_data->item_cnt)
+               return NULL;
+
+       return list_item_nth(sc_data->item_list, idx);
+}
+
+int live_scroller_get_current(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+       struct item_list_entry *ilist;
+       int idx;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       ilist = sc_data->curlist;
+       idx = 0;
+       if (ilist) {
+               while (ilist != sc_data->item_list) {
+                       idx++;
+                       ilist = LIST_PREV(ilist);
+               }
+       }
+
+       return idx;
+}
+
+int live_scroller_loop_set(Evas_Object *scroller, int is_loop)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       if (is_loop == EINA_FALSE && sc_data->is_loop == EINA_TRUE)
+               rearrange_items(sc_data);
+
+       sc_data->is_loop = is_loop;
+       return 0;
+}
+
+int live_scroller_freeze(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       sc_data->is_freezed = EINA_TRUE;
+       return 0;
+}
+
+int live_scroller_thaw(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       sc_data->is_freezed = EINA_FALSE;
+       return 0;
+}
+
+int live_scroller_anim_to(Evas_Object *scroller, double sec, int offset)
+{
+       PROFILE_START();
+       struct widget_data *sc_data;
+       Evas_Coord sx, sw;
+       Evas_Coord y;
+       struct live_sc_event_info info;
+       struct item_list_entry *ilist;
+       double ftmp;
+       int ret;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               ret = -EINVAL;
+               goto out;
+       }
+       
+       if (sc_data->is_freezed) {
+               ErrPrint("Scroller is freezed\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (!sc_data->curlist)
+               sc_data->curlist = sc_data->item_list;
+
+       if (!sc_data->curlist) {
+               ErrPrint("List is empty\n");
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (sc_data->sc_anim_timer) {
+               ecore_timer_del(sc_data->sc_anim_timer);
+               sc_data->sc_anim_timer = NULL;
+               evas_object_smart_callback_call(sc_data->scroller, "anim,stop", NULL);
+       } else {
+               sc_data->tolist = sc_data->curlist;
+       }
+
+       LIST_ITEM_GEO_GET(sc_data->curlist, &sx, &y, &sw, NULL);
+
+       if (!offset) {
+               sc_data->sc_anim_dx = sc_data->clip_bx - sx;
+               DbgPrint("offset==0, dx: %d\n", sc_data->sc_anim_dx);
+       } else {
+               Evas_Coord tw;
+               struct item_list_entry *tmplist;
+
+               calc_anim_dx_with_dir(sc_data, &offset);
+               DbgPrint("Offset: %d\n", offset);
+
+               ilist = sc_data->curlist;
+               while (offset < 0) {
+                       if (!sc_data->is_loop && ilist == sc_data->item_list) {
+                               DbgPrint("Loop is disabled\n");
+                               break;
+                       }
+
+                       LIST_ITEM_GEO_GET(ilist, NULL, NULL, &tw, NULL);
+                       ilist = LIST_PREV(ilist);
+
+                       sc_data->sc_anim_dx += tw;
+                       DbgPrint("tw: %d (%d)\n", tw, sc_data->sc_anim_dx);
+
+                       offset++;
+                       if (sc_data->tolist == sc_data->item_list) {
+                               if (!sc_data->is_loop) {
+                                       DbgPrint("Looping disabled\n");
+                                       break;
+                               }
+                       }
+                       sc_data->tolist = LIST_PREV(sc_data->tolist);
+               }
+               
+               while (offset > 0) {
+                       LIST_ITEM_GEO_GET(ilist, NULL, NULL, &tw, NULL);
+                       ilist = LIST_NEXT(ilist);
+
+                       sc_data->sc_anim_dx -= tw;
+                       DbgPrint("tw: %d (%d)\n", tw, sc_data->sc_anim_dx);
+
+                       offset--;
+                       tmplist = LIST_NEXT(sc_data->tolist);
+                       if (tmplist == sc_data->item_list) {
+                               if (!sc_data->is_loop) {
+                                       DbgPrint("Looping disabled\n");
+                                       break;
+                               }
+                       }
+                       sc_data->tolist = tmplist;
+
+                       if (!sc_data->is_loop && ilist == sc_data->item_list) {
+                               DbgPrint("Destination arrived or loop is disabled");
+                               break;
+                       }
+               }
+       }
+
+       if (abs(sc_data->sc_anim_dx) > ANIM_MIN) {
+               ftmp = (double)sc_data->sc_anim_dx / ANIM_UNIT;
+               DbgPrint("ftmp: %lf\n", ftmp);
+               if (fabs(ftmp) < ANIM_MIN || fabs(ftmp) > abs(sc_data->sc_anim_dx))
+                       sc_data->sc_anim_dx = ftmp < 0 ? -ANIM_MIN : ANIM_MIN;
+               else
+                       sc_data->sc_anim_dx = (int)ftmp;
+               DbgPrint("Result: %d\n", sc_data->sc_anim_dx);
+       }
+
+       sc_data->sc_anim_timer = ecore_timer_add(sec, sc_anim_cb, sc_data);
+       if (!sc_data->sc_anim_timer) {
+               ErrPrint("Failed to add a animator\n");
+               ret = -EFAULT;
+               goto out;
+       }
+
+       info.curidx = list_item_idx(sc_data, sc_data->curlist);
+       info.toidx = list_item_idx(sc_data, sc_data->tolist);
+       DbgPrint("Current index: %d, To index: %d\n", info.curidx, info.toidx);
+
+       evas_object_smart_callback_call(sc_data->scroller, "anim,start", &info);
+       ret = 0;
+
+out:
+       PROFILE_END();
+       return ret;
+}
+
+int live_scroller_go_to(Evas_Object *scroller, int idx)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       if (sc_data->is_freezed)
+               return -EBUSY;
+
+       if (idx < 0 || idx >= sc_data->item_cnt)
+               return -EINVAL;
+
+       sc_data->curlist = list_item_nth_list(sc_data->item_list, idx);
+       if (!sc_data->curlist)
+               return -EFAULT;
+
+       rearrange_items(sc_data);
+       evas_object_smart_callback_call(sc_data->scroller, "page,changed", (void *)idx);
+
+       return 0;
+}
+
+int live_scroller_update(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+       struct item_list_entry *n;
+       Evas_Object *item;
+       Evas_Coord x, y, w, h;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       if (sc_data->item_list) {
+               n = sc_data->item_list;
+               do {
+                       item = LIST_DATA(n);
+                       LIST_ITEM_GEO_GET(n, &x, &y, &w, &h);
+                       move_item(sc_data, n, x, y, w, h);
+                       n = LIST_NEXT(n);
+               } while (n != sc_data->item_list);
+       }
+
+       return 0;
+}
+
+int live_scroller_get_item_count(Evas_Object *scroller)
+{
+       struct widget_data *sc_data;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return 0;
+       }
+
+       return list_item_count(sc_data->item_list);
+}
+
+int live_scroller_get_item_index(Evas_Object *scroller, Evas_Object *item)
+{
+       struct widget_data *sc_data;
+       struct item_list_entry *n;
+       Evas_Object *tmp;
+       int idx;
+
+       sc_data = evas_object_smart_data_get(scroller);
+       if (!sc_data) {
+               ErrPrint("sc_data is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!sc_data->item_list)
+               return -ENOENT;
+
+       idx = 0;
+       n = sc_data->item_list;
+       do {
+               tmp = LIST_DATA(n);
+               n = LIST_NEXT(n);
+
+               if (tmp == item)
+                       return idx;
+
+               idx++;
+       } while (n != sc_data->item_list);
+
+       return -ENOENT;
+}
+
+/* End of a file */
diff --git a/live.viewer/src/main.c b/live.viewer/src/main.c
new file mode 100644 (file)
index 0000000..362cf3f
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <dlog.h>
+#include <ail.h>
+#include <app.h>
+#include <bundle.h>
+
+#include <livebox.h>
+#include <livebox-service.h>
+
+#include "main.h"
+#include "util.h"
+#include "debug.h"
+#include "scroller.h"
+#include "lb.h"
+
+static struct info {
+       Evas_Object *window;
+       Evas_Object *scroller;
+} s_info = {
+       .window = NULL,
+       .scroller = NULL,
+};
+
+Evas_Object *main_get_window(void)
+{
+       return s_info.window;
+}
+
+static void click_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       Elm_Object_Item *item;
+       const char *label;
+
+       item = elm_list_selected_item_get(obj);
+       if (!item)
+               return;
+
+       label = elm_object_item_part_text_get(item, NULL);
+       if (!label)
+               return;
+
+       DbgPrint("Label: %s (%s)\n", label, data);
+       if (lb_add(s_info.scroller, data) < 0)
+               ErrPrint("Failed to add a new livebox\n");
+}
+
+static int append_livebox_cb(const char *appid, const char *lbid, int is_prime, void *data)
+{
+       char *name;
+
+       DbgPrint("%s - %s\n", appid, lbid);
+
+       name = livebox_service_i18n_name(lbid, NULL);
+       if (!name) {
+               name = strdup(lbid);
+               if (!name) {
+                       ErrPrint("Heap: %s\n", strerror(errno));
+                       return 0;
+               }
+       }
+
+       DbgPrint("Name: %s\n", name);
+       elm_list_item_append(data, name, NULL, NULL, click_cb, strdup(lbid));
+       free(name);
+       return 0;
+}
+
+static inline void livebox_list_create(void)
+{
+       Evas_Object *list;
+
+       list = elm_list_add(s_info.window);
+       if (!list) {
+               ErrPrint("Failed to create a list\n");
+               return;
+       }
+
+       evas_object_resize(list, 720, 1280);
+       evas_object_show(list);
+
+       DbgPrint("Get Package list\n");
+       livebox_service_get_pkglist(append_livebox_cb, list);
+       elm_list_go(list);
+
+       scroller_append(s_info.scroller, list);
+}
+
+static bool app_create(void *data)
+{
+       Evas_Object *bg;
+       DbgPrint("create");
+       lb_init();
+
+       s_info.window = elm_win_add(NULL, "Box viewer", ELM_WIN_BASIC);
+       if (!s_info.window) {
+               ErrPrint("Failed to create a window\n");
+               return false;
+       }
+       elm_win_autodel_set(s_info.window, EINA_TRUE);
+
+       evas_object_resize(s_info.window, 720, 1280);
+       evas_object_show(s_info.window);
+
+       bg = elm_bg_add(s_info.window);
+       elm_win_resize_object_add(s_info.window, bg);
+       elm_bg_color_set(bg, 0, 0, 255);
+       evas_object_show(bg);
+
+       s_info.scroller = scroller_create(s_info.window);
+       if (!s_info.scroller) {
+               evas_object_del(s_info.window);
+               s_info.window = NULL;
+               ErrPrint("Failed to create a scroller\n");
+               return false;
+       }
+
+       evas_object_resize(s_info.scroller, 720, 1280);
+       evas_object_show(s_info.scroller);
+
+       livebox_list_create();
+
+       return true;
+}
+
+static void app_terminate(void *data)
+{
+       DbgPrint("terminate");
+       lb_fini();
+       /*!
+        * \TODO
+        * Delete all objects from the scroller.
+        */
+
+       scroller_destroy(s_info.scroller);
+       evas_object_del(s_info.window);
+       s_info.window = NULL;
+}
+
+static void app_pause(void *data)
+{
+       DbgPrint("pause");
+}
+
+static void app_resume(void *data)
+{
+       DbgPrint("resume");
+}
+
+static void app_reset(service_h service, void *data)
+{
+       DbgPrint("reset");
+}
+
+int main(int argc, char *argv[])
+{
+       app_event_callback_s event_callback;
+
+       setenv("ELM_ENGINE", "gl", 0);
+       event_callback.create = app_create;
+       event_callback.terminate = app_terminate;
+       event_callback.pause = app_pause;
+       event_callback.resume = app_resume;
+       event_callback.service = app_reset;
+       event_callback.low_memory = NULL;
+       event_callback.low_battery = NULL;
+       event_callback.device_orientation = NULL;
+       event_callback.language_changed = NULL;
+
+       return app_efl_main(&argc, &argv, &event_callback, NULL);
+}
+
+/* End of a file */
diff --git a/live.viewer/src/scroller.c b/live.viewer/src/scroller.c
new file mode 100644 (file)
index 0000000..8eca311
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <dlog.h>
+
+#include "util.h"
+#include "live_scroller.h"
+#include "scroller.h"
+#include "debug.h"
+
+#define FOCAL_DIST 800
+#define FLICK_COND 100
+
+struct cb_item {
+       int (*cb)(Evas_Object *sc, void *data);
+       void *data;
+};
+
+struct scroll_info {
+       int locked;
+       Eina_Bool scrolling;
+       int focal;
+       Eina_Bool quick;
+
+       Evas_Map *map;
+
+       Ecore_Idler *bg_changer;
+       Eina_List *cb_list;
+};
+
+void scroller_lock(Evas_Object *sc)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+
+       if (!scinfo->locked)
+               live_scroller_freeze(sc);
+
+       scinfo->locked++;
+}
+
+void scroller_unlock(Evas_Object *sc)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+
+       if (scinfo->locked == 0)
+               return;
+
+       scinfo->locked--;
+
+       if (scinfo->locked == 0)
+               live_scroller_thaw(sc);
+}
+
+static void sc_anim_stop(void *data, Evas_Object *obj, void *event_info)
+{
+       Eina_List *l;
+       Eina_List *tmp;
+       struct cb_item *item;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(obj, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+       /*!
+        * \TODO
+        * Do what you want at here when the scroller is stopped
+        */
+
+       scinfo->scrolling = EINA_FALSE;
+       EINA_LIST_FOREACH_SAFE(scinfo->cb_list, l, tmp, item) {
+               if (item->cb(obj, item->data) == ECORE_CALLBACK_CANCEL) {
+                       if (eina_list_data_find(scinfo->cb_list, item)) {
+                               scinfo->cb_list = eina_list_remove(scinfo->cb_list, item);
+                               free(item);
+                       }
+               }
+       }
+}
+
+static inline void sc_drag_start(void *data, Evas_Object *obj, void *event_info)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(obj, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+
+       scinfo->scrolling = EINA_TRUE;
+}
+
+static inline void sc_drag_stop(void *data, Evas_Object *scroller, void *event_info)
+{
+       struct live_sc_drag_info *info;
+       int offset = 0;
+       int ret;
+
+       info = event_info;
+
+       if (info->dx > FLICK_COND)
+               offset = -1;
+       else if (info->dx < -FLICK_COND)
+               offset = 1;
+
+       ret = live_scroller_anim_to(scroller, 0.016f, offset);
+       if (ret < 0) {
+               struct scroll_info *scinfo;
+               scinfo = evas_object_data_get(scroller, "scinfo");
+               if (scinfo)
+                       scinfo->scrolling = EINA_FALSE;
+       }
+}
+
+static Eina_Bool bg_change_cb(void *data)
+{
+       Evas_Object *sc = data;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (scinfo)
+               scinfo->bg_changer = NULL;
+
+       /*!
+        * \note:
+        *  Here,
+        *  Filename of background image handling code is only
+        *  used to demonstrates UX concept and estimates its perfomance.
+        *  So, I'll change this if it should be appled to
+        *  main branch.
+        */
+       DbgPrint("Change the background image (%p)\n", sc);
+       return ECORE_CALLBACK_CANCEL;
+}
+
+static void sc_anim_start(void *data, Evas_Object *obj, void *event_info)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(obj, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+
+       /*!
+        * \note
+        * without drag,start
+        * anim start can be invoked by the scroller_anim_to
+        */
+       scinfo->scrolling = EINA_TRUE;
+
+       if (scinfo->bg_changer)
+               ecore_idler_del(scinfo->bg_changer);
+
+       scinfo->bg_changer = ecore_idler_add(bg_change_cb, obj);
+       if (!scinfo->bg_changer)
+               DbgPrint("Failed to add an idler\n");
+}
+
+static void sc_item_moved(void *data, Evas_Object *obj, void *event_info)
+{
+       struct live_sc_move_info *evt = event_info;
+       int color;
+       int focal;
+       Evas_Coord y, sx, sw;
+       double ftmp;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(obj, "scinfo");
+       if (!scinfo) {
+               ErrPrint("Has no scinfo\n");
+               return;
+       }
+
+       ftmp = fabsl(evt->relx);
+       if (ftmp >= 1.0f) {
+               evas_object_map_enable_set(evt->item, EINA_FALSE);
+               evas_object_hide(evt->item);
+               return;
+       }
+
+       color = 255 * (1.0f - ftmp);
+       if (scinfo->quick) {
+               if (color < 100)
+                       color = 100;
+
+               focal = scinfo->focal;
+       } else {
+               if (color == 0) {
+                       evas_object_map_enable_set(evt->item, EINA_FALSE);
+                       evas_object_hide(evt->item);
+                       return;
+               }
+
+               focal = -ftmp * 200.0f + scinfo->focal;
+       }
+
+       evas_object_geometry_get(data, &sx, NULL, &sw, NULL);
+       
+       /* LEFT */
+       evas_map_point_coord_set(scinfo->map, 0, evt->x, evt->y, 0);
+       evas_map_point_image_uv_set(scinfo->map, 0, 0, 0);
+       evas_map_point_color_set(scinfo->map, 0, color, color, color, color);
+
+       /* RIGHT */
+       evas_map_point_coord_set(scinfo->map, 1, evt->x + evt->w, evt->y, 0);
+       evas_map_point_image_uv_set(scinfo->map, 1, evt->w, 0);
+       evas_map_point_color_set(scinfo->map, 1, color, color, color, color);
+
+       /* BOTTOM-RIGHT */
+       evas_map_point_coord_set(scinfo->map, 2, evt->x + evt->w, evt->y + evt->h, 0);
+       evas_map_point_image_uv_set(scinfo->map, 2, evt->w, evt->h);
+       evas_map_point_color_set(scinfo->map, 2, color, color, color, color);
+
+       /* BOTTOM-LEFT */
+       evas_map_point_coord_set(scinfo->map, 3, evt->x, evt->y + evt->h, 0);
+       evas_map_point_image_uv_set(scinfo->map, 3, 0, evt->h);
+       evas_map_point_color_set(scinfo->map, 3, color, color, color, color);
+
+       y = evt->y + (evt->h >> 1);
+       evas_map_util_3d_rotate(scinfo->map, 0.0f, -30.0f * evt->relx, 0.0f, evt->x + (evt->w >> 1), y, 0);
+       evas_map_util_3d_perspective(scinfo->map, sx + (sw >> 1), y, focal, FOCAL_DIST);
+       evas_object_map_set(evt->item, scinfo->map);
+       evas_object_map_enable_set(evt->item, EINA_TRUE);
+       evas_object_show(evt->item);
+       return;
+}
+
+static void sc_page_changed(void *data, Evas_Object *obj, void *event_info)
+{
+       DbgPrint("Page is changed %d\n", (int)event_info);
+}
+
+int scroller_add_stop_cb(Evas_Object *scroller,
+                       int (*cb)(Evas_Object *sc, void *data), void *data)
+{
+       struct cb_item *item;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(scroller, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return -EINVAL;
+       }
+
+       item = calloc(1, sizeof(*item));
+       if (!item) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       item->cb = cb;
+       item->data = data;
+
+       scinfo->cb_list = eina_list_append(scinfo->cb_list, item);
+       return EXIT_SUCCESS;
+}
+
+void scroller_del_stop_cb(Evas_Object *scroller,
+                       int (*cb)(Evas_Object *sc, void *data), void *data)
+{
+       struct cb_item *item;
+       Eina_List *l;
+       Eina_List *tmp;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(scroller, "scinfo");
+       if (!scinfo) {
+               ErrPrint("Failed to get scinfo\n");
+               return;
+       }
+
+       EINA_LIST_FOREACH_SAFE(scinfo->cb_list, l, tmp, item) {
+               if (item->cb == cb && item->data == data) {
+                       scinfo->cb_list = eina_list_remove(scinfo->cb_list, item);
+                       free(item);
+                       break;
+               }
+       }
+}
+
+Evas_Object *scroller_create(Evas_Object *ctrl)
+{
+       Evas_Object *sc;
+       struct scroll_info *scinfo;
+
+       scinfo = calloc(1, sizeof(*scinfo));
+       if (!scinfo) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       sc = live_scroller_add(ctrl);
+       if (!sc) {
+               DbgPrint("Failed to create flip object\n");
+               free(scinfo);
+               return NULL;
+       }
+
+       evas_object_data_set(sc, "scinfo", scinfo);
+
+       scinfo->map = evas_map_new(4);
+       if (!scinfo->map) {
+               ErrPrint("Failed to create a map object\n");
+               evas_object_del(sc);
+               free(scinfo);
+               return NULL;
+       }
+
+       evas_map_smooth_set(scinfo->map, EINA_TRUE);
+       evas_map_alpha_set(scinfo->map, EINA_TRUE);
+
+       evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_smart_callback_add(sc, "drag,start", sc_drag_start, NULL);
+       evas_object_smart_callback_add(sc, "drag,stop", sc_drag_stop, NULL);
+       evas_object_smart_callback_add(sc, "anim,stop", sc_anim_stop, NULL);
+       evas_object_smart_callback_add(sc, "anim,start", sc_anim_start, NULL);
+       evas_object_smart_callback_add(sc, "page,changed", sc_page_changed, NULL);
+       evas_object_smart_callback_add(sc, "item,moved", sc_item_moved, NULL);
+       live_scroller_loop_set(sc, EINA_TRUE);
+       evas_object_show(sc);
+
+       return sc;
+}
+
+int scroller_append(Evas_Object *sc, Evas_Object *child)
+{
+       return live_scroller_append(sc, child);
+}
+
+int scroller_get_page_index(Evas_Object *sc, Evas_Object *page)
+{
+       return live_scroller_get_item_index(sc, page);
+}
+
+Evas_Object *scroller_get_page(Evas_Object *sc, int idx)
+{
+       return live_scroller_get_item(sc, idx);
+}
+
+Evas_Object *scroller_peek_by_idx(Evas_Object *sc, int idx)
+{
+       return live_scroller_remove(sc, idx);
+}
+
+int scroller_peek_by_obj(Evas_Object *sc, Evas_Object *page)
+{
+       return live_scroller_remove_by_obj(sc, page);
+}
+
+int scroller_get_current_idx(Evas_Object *sc)
+{
+       return live_scroller_get_current(sc);
+}
+
+int scroller_is_scrolling(Evas_Object *sc)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return -EINVAL;
+       }
+
+       return scinfo->scrolling;
+}
+
+int scroller_get_page_count(Evas_Object *sc)
+{
+       return live_scroller_get_item_count(sc);
+}
+
+int scroller_scroll_to(Evas_Object *sc, int idx)
+{
+       int curidx;
+       int cnt;
+       register int i;
+       int next_offset;
+       int prev_offset;
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return -EINVAL;
+       }
+
+       if (scinfo->scrolling) {
+               DbgPrint("Scroller is scrolling\n");
+               return -EINVAL;
+       }
+
+       curidx = live_scroller_get_current(sc);
+       cnt = live_scroller_get_item_count(sc);
+
+       i = curidx;
+       next_offset = 0;
+       while (i != idx && i >= 0 && i < cnt) {
+               i++;
+               if (i >= cnt)
+                       i = 0;
+
+               next_offset++;
+       }
+
+       i = curidx;
+       prev_offset = 0;
+       while (i != idx && i >= 0 && i < cnt) {
+               i--;
+               if (i < 0)
+                       i = cnt - 1;
+
+               prev_offset--;
+       }
+
+       idx = next_offset < -prev_offset ? next_offset : prev_offset;
+       live_scroller_anim_to(sc, 0.016f, idx);
+       return 0;
+}
+
+int scroller_jump_to(Evas_Object *sc, int idx)
+{
+       live_scroller_go_to(sc, idx);
+       return 0;
+}
+
+int scroller_destroy(Evas_Object *sc)
+{
+       int cnt;
+       struct scroll_info *scinfo;
+       struct cb_item *item;
+
+       scinfo = evas_object_data_del(sc, "scinfo");
+       if (!scinfo)
+               return -EFAULT;
+
+       if (scinfo->bg_changer)
+               ecore_idler_del(scinfo->bg_changer);
+
+       EINA_LIST_FREE(scinfo->cb_list, item) {
+               free(item);
+       }
+
+       cnt = live_scroller_get_item_count(sc);
+       if (cnt)
+               DbgPrint("Children is not cleared (%d)\n", cnt);
+
+       evas_object_del(sc);
+       evas_map_free(scinfo->map);
+       free(scinfo);
+       return 0;
+}
+
+int scroller_update(Evas_Object *sc, void *data)
+{
+       struct scroll_info *scinfo;
+
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return -EFAULT;
+       }
+
+       scinfo->focal = (int)data;
+       live_scroller_update(sc);
+       return EXIT_SUCCESS;
+}
+
+int scroller_fast_scroll(Evas_Object *sc, int idx)
+{
+       idx -= scroller_get_current_idx(sc);
+       live_scroller_anim_to(sc, 0.016f, idx);
+       return 0;
+}
+
+void scroller_loop_set(Evas_Object *sc, Eina_Bool val)
+{
+       live_scroller_loop_set(sc, val);
+}
+
+void scroller_quick_navi(Evas_Object *sc, Eina_Bool val)
+{
+       struct scroll_info *scinfo;
+       scinfo = evas_object_data_get(sc, "scinfo");
+       if (!scinfo) {
+               ErrPrint("scinfo is not valid\n");
+               return;
+       }
+
+       scinfo->quick = val;
+}
+
+/* End of a file */
diff --git a/live.viewer/src/util.c b/live.viewer/src/util.c
new file mode 100644 (file)
index 0000000..73bca58
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <dlog.h>
+
+#include "debug.h"
+#include "util.h"
+
+int errno;
+
+const char *util_basename(const char *name)
+{
+       int length;
+       length = name ? strlen(name) : 0;
+       if (!length)
+               return ".";
+
+       while (--length > 0 && name[length] != '/');
+
+       return length <= 0 ? name : name + length + (name[length] == '/');
+}
+
+/* End of a file */
diff --git a/livebox-viewer.pc.in b/livebox-viewer.pc.in
new file mode 100644 (file)
index 0000000..06f4891
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: livebox-viewer
+Description: livebox supporting library
+Version: @VERSION@
+Libs: -L${libdir} -llivebox-viewer
+Cflags: -I${includedir}
+cppflags: -I${includedir}
diff --git a/packaging/liblivebox-viewer.spec b/packaging/liblivebox-viewer.spec
new file mode 100644 (file)
index 0000000..a76e45f
--- /dev/null
@@ -0,0 +1,57 @@
+Name: liblivebox-viewer
+Summary: Library for developing the application.
+Version: 0.9.12
+Release: 1
+Group: framework/livebox
+License: Flora License
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: cmake, gettext-tools, coreutils
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(com-core)
+BuildRequires: pkgconfig(x11)
+BuildRequires: pkgconfig(xext)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(db-util)
+BuildRequires: pkgconfig(livebox-service)
+
+%description
+API for creating a new instance of the livebox and managing its life-cycle.
+
+%package devel
+Summary: Header and package configuration files for the livebox viewer development.
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Livebox viewer development library (dev)
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/%{_datarootdir}/license
+
+%post
+
+%files -n liblivebox-viewer
+%manifest liblivebox-viewer.manifest
+%defattr(-,root,root,-)
+%{_libdir}/*.so*
+%{_datarootdir}/license/*
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/livebox-viewer/livebox.h
+%{_datarootdir}/doc/livebox-viewer/livebox-viewer_PG.h
+%{_libdir}/pkgconfig/*.pc
+
+# End of a file
diff --git a/src/client.c b/src/client.c
new file mode 100644 (file)
index 0000000..79fca92
--- /dev/null
@@ -0,0 +1,995 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dlog.h>
+#include <glib.h>
+
+#include <packet.h>
+#include <com-core.h>
+#include <com-core_packet.h>
+
+#include "debug.h"
+#include "client.h"
+#include "livebox.h"
+#include "livebox_internal.h"
+#include "desc_parser.h"
+#include "fb.h"
+#include "util.h"
+#include "master_rpc.h"
+#include "conf.h"
+#include "critical_log.h"
+
+static inline void make_connection(void);
+
+static struct info {
+       int fd;
+       guint reconnector;
+} s_info = {
+       .fd = -1,
+       .reconnector = 0,
+};
+
+static struct packet *master_fault_package(pid_t pid, int handle, const struct packet *packet)
+{
+       const char *pkgname;
+       const char *id;
+       const char *function;
+
+       if (packet_get(packet, "sss", &pkgname, &id, &function) != 3) {
+               ErrPrint("Invalid arguments\n");
+               return NULL;
+       }
+
+       master_rpc_clear_fault_package(pkgname);
+       lb_invoke_fault_handler(LB_FAULT_DEACTIVATED, pkgname, id, function);
+       DbgPrint("%s(%s) is deactivated\n", pkgname, id);
+       return NULL;
+}
+
+static struct packet *master_pinup(pid_t pid, int handle, const struct packet *packet)
+{
+       const char *pkgname;
+       const char *id;
+       const char *content;
+       struct livebox *handler;
+       char *new_content;
+       int ret;
+       int pinup;
+
+       ret = packet_get(packet, "iisss", &ret, &pinup, &pkgname, &id, &content);
+       if (ret != 5) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (ret == 0) {
+               new_content = strdup(content);
+               if (new_content) {
+                       free(handler->content);
+                       handler->content = new_content;
+                       handler->is_pinned_up = pinup;
+               } else {
+                       ErrPrint("Heap: %s\n", strerror(errno));
+                       ret = -ENOMEM;
+               }
+       }
+
+       if (handler->pinup_cb) {
+               handler->pinup_cb(handler, ret, handler->pinup_cbdata);
+
+               handler->pinup_cb = NULL; /*!< Reset pinup cb */
+               handler->pinup_cbdata = NULL;
+       } else {
+               lb_invoke_event_handler(handler, LB_EVENT_PINUP_CHANGED);
+       }
+
+       ret = 0;
+out:
+       return NULL;
+}
+
+static struct packet *master_deleted(pid_t pid, int handle, const struct packet *packet)
+{
+       const char *pkgname;
+       const char *id;
+       double timestamp;
+       struct livebox *handler;
+
+       if (packet_get(packet, "ssd", &pkgname, &id, &timestamp) != 3) {
+               ErrPrint("Invalid arguemnt\n");
+               goto out;
+       }
+
+       handler = lb_find_livebox_by_timestamp(timestamp);
+       if (!handler) {
+               /*!
+                * \note
+                * This can be happens only if the user delete a livebox
+                * right after create it before receive created event.
+                */
+               goto out;
+       }
+
+       /*!< Check validity of this "handler" */
+       if (handler->state != CREATE) {
+               if (handler->state != DELETE) {
+                       /*!
+                        * \note
+                        * This is not possible
+                        */
+                       CRITICAL_LOG("Already deleted handler (%s - %s)\n", pkgname, id);
+                       return NULL;
+               }
+       }
+
+       if (handler->created_cb) {
+               /*!
+                * \note
+                *
+                * "if (handler->id == NULL)"
+                *
+                * The instance is not created yet.
+                * But the master forcely destroy it and send destroyed event to this
+                * without the created event.
+                *
+                * It could be destroyed when a slave has critical error(fault)
+                * before creating an instance successfully.
+                */
+               if (handler->created_cb == handler->deleted_cb) {
+                       if (handler->created_cbdata != handler->deleted_cbdata)
+                               DbgPrint("cb is same but cbdata is different (%s - %s)\n", pkgname, id);
+
+                       handler->deleted_cb = NULL;
+                       handler->deleted_cbdata = NULL;
+               }
+
+               DbgPrint("Call the created cb with -ECANCELED\n");
+               handler->created_cb(handler, -ECANCELED, handler->created_cbdata);
+               handler->created_cb = NULL;
+               handler->created_cbdata = NULL;
+       } else if (handler->id) {
+               if (handler->deleted_cb) {
+                       DbgPrint("Call the deleted cb\n");
+                       handler->deleted_cb(handler, 0, handler->deleted_cbdata);
+
+                       handler->deleted_cb = NULL;
+                       handler->deleted_cbdata = NULL;
+               } else {
+                       DbgPrint("Call the lb,deleted\n");
+                       lb_invoke_event_handler(handler, LB_EVENT_DELETED);
+               }
+       }
+
+       DbgPrint("[%p] %s(%s) is deleted\n", handler, pkgname, id);
+
+       /* Just try to delete it, if a user didn't remove it from the live box list */
+       lb_unref(handler);
+
+out:
+       return NULL;
+}
+
+static struct packet *master_lb_updated(pid_t pid, int handle, const struct packet *packet)
+{
+       const char *pkgname;
+       const char *id;
+       const char *fbfile;
+       const char *content;
+       const char *title;
+       struct livebox *handler;
+       int lb_w;
+       int lb_h;
+       double priority;
+       int ret;
+
+       ret = packet_get(packet, "sssiidss",
+                               &pkgname, &id,
+                               &fbfile, &lb_w, &lb_h,
+                               &priority, &content, &title);
+       if (ret != 8) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               /*!
+                * \note
+                * Already deleted by the user.
+                * Don't try to notice anything with this, Just ignore all events
+                * Beacuse the user doesn't wants know about this anymore
+                */
+               ret = -EPERM;
+               goto out;
+       }
+
+       lb_set_priority(handler, priority);
+       lb_set_content(handler, content);
+       lb_set_title(handler, title);
+
+       if (lb_text_lb(handler)) {
+               lb_set_size(handler, lb_w, lb_h);
+               ret = parse_desc(handler, livebox_filename(handler), 0);
+               /*!
+                * \note
+                * DESC parser will call the "text event callback".
+                */
+               goto out;
+       } else if (lb_get_lb_fb(handler)) {
+               lb_set_size(handler, lb_w, lb_h);
+               lb_set_lb_fb(handler, fbfile);
+               ret = fb_sync(lb_get_lb_fb(handler));
+               if (ret < 0)
+                       ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+       } else {
+               lb_set_size(handler, lb_w, lb_h);
+               ret = 0;
+       }
+
+       if (ret == 0)
+               lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATED);
+
+out:
+       return NULL;
+}
+
+static struct packet *master_pd_created(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       const char *buf_id;
+       int width;
+       int height;
+       int ret;
+       int status;
+
+       ret = packet_get(packet, "sssiii", &pkgname, &id, &buf_id, &width, &height, &status);
+       if (ret != 6) {
+               ErrPrint("Invalid argument\n");
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       lb_set_pdsize(handler, width, height);
+       if (lb_text_pd(handler)) {
+               DbgPrint("Text TYPE does not need to handle this\n");
+       } else {
+               (void)lb_set_pd_fb(handler, buf_id);
+               ret = fb_sync(lb_get_pd_fb(handler));
+               if (ret < 0) {
+                       ErrPrint("Failed to do sync FB (%s - %s)\n",
+                                       pkgname,
+                                       util_basename(util_uri_to_path(id)));
+               }
+       }
+
+       handler->is_pd_created = (status == 0);
+
+       if (handler->pd_created_cb) {
+               DbgPrint("pd_created_cb (%s) - %d\n", buf_id, status);
+               handler->pd_created_cb(handler, status, handler->pd_created_cbdata);
+
+               handler->pd_created_cb = NULL;
+               handler->pd_created_cbdata = NULL;
+       } else if (status == 0) {
+               DbgPrint("LB_EVENT_PD_CREATED (%s) - %d\n", buf_id, status);
+               lb_invoke_event_handler(handler, LB_EVENT_PD_CREATED);
+       }
+
+       ret = 0;
+out:
+       return NULL;
+}
+
+static struct packet *master_pd_destroyed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       int status;
+
+       ret = packet_get(packet, "ssi", &pkgname, &id, &status);
+       if (ret != 3) {
+               ErrPrint("Invalid argument\n");
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       handler->is_pd_created = 0;
+
+       if (handler->pd_destroyed_cb) {
+               DbgPrint("Invoke the PD Destroyed CB\n");
+               handler->pd_destroyed_cb(handler, status, handler->pd_destroyed_cbdata);
+
+               handler->pd_destroyed_cb = NULL;
+               handler->pd_destroyed_cbdata = NULL;
+       } else if (status == 0) {
+               DbgPrint("Invoke the LB_EVENT_PD_DESTROYED event\n");
+               lb_invoke_event_handler(handler, LB_EVENT_PD_DESTROYED);
+       }
+
+       ret = 0;
+out:
+       return NULL;
+}
+
+static struct packet *master_pd_updated(pid_t pid, int handle, const struct packet *packet)
+{
+       const char *pkgname;
+       const char *id;
+       const char *descfile;
+       const char *fbfile;
+       int ret;
+       struct livebox *handler;
+       int pd_w;
+       int pd_h;
+
+       ret = packet_get(packet, "ssssii",
+                               &pkgname, &id,
+                               &descfile, &fbfile,
+                               &pd_w, &pd_h);
+       if (ret != 6) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               /*!
+                * \note
+                * This handler is already deleted by the user.
+                * So don't try to notice anything about this anymore.
+                * Just ignore all events.
+                */
+               ret = -EPERM;
+               goto out;
+       }
+
+       lb_set_pdsize(handler, pd_w, pd_h);
+
+       if (lb_text_pd(handler)) {
+               ret = parse_desc(handler, descfile, 1);
+       } else {
+               (void)lb_set_pd_fb(handler, fbfile);
+
+               ret = fb_sync(lb_get_pd_fb(handler));
+               if (ret < 0) {
+                       ErrPrint("Failed to do sync FB (%s - %s)\n",
+                                       pkgname,
+                                       util_basename(util_uri_to_path(id)));
+                       goto out;
+               }
+
+               lb_invoke_event_handler(handler, LB_EVENT_PD_UPDATED);
+               ret = 0;
+       }
+
+out:
+       return NULL;
+}
+
+static struct packet *master_size_changed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int status;
+       int ret;
+       int w;
+       int h;
+       int is_pd;
+
+       if (!packet) {
+               ErrPrint("Invalid packet\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = packet_get(packet, "ssiiii", &pkgname, &id, &is_pd, &w, &h, &status);
+       if (ret != 6) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       DbgPrint("Size is changed: %dx%d (%s)\n", w, h, id);
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ErrPrint("Livebox(%s - %s) is not found\n", pkgname, id);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Hander is not created yet\n");
+               ret = -EPERM;
+               goto out;
+       }
+
+       if (is_pd) {
+               DbgPrint("PD is resized\n");
+               /*!
+                * \NOTE
+                * PD is not able to resized by the client.
+                * PD is only can be managed by the provider.
+                * So the PD has no private resized event handler.
+                * Notify it via global event handler.
+                */
+               if (status == 0) {
+                       lb_set_pdsize(handler, w, h);
+                       lb_invoke_event_handler(handler, LB_EVENT_PD_SIZE_CHANGED);
+               } else {
+                       ErrPrint("This is not possible. PD Size is changed but the return value is not ZERO\n");
+               }
+       } else {
+               DbgPrint("LB is resized\n");
+               if (status == 0) {
+                       DbgPrint("Livebox size is updated (%dx%d)\n", w, h);
+                       lb_set_size(handler, w, h);
+
+                       /*!
+                        * If there is a created LB FB, 
+                        * Update it too
+                        */
+                       if (lb_get_lb_fb(handler))
+                               lb_set_lb_fb(handler, id);
+
+                       if (handler->size_changed_cb) {
+                               DbgPrint("Call the size changed callback\n");
+                               handler->size_changed_cb(handler, status, handler->size_cbdata);
+
+                               handler->size_changed_cb = NULL;
+                               handler->size_cbdata = NULL;
+                       } else {
+                               DbgPrint("Call the global size changed callback\n");
+                               lb_invoke_event_handler(handler, LB_EVENT_LB_SIZE_CHANGED);
+                               DbgPrint("Size changed callback done\n");
+                       }
+               } else {
+                       DbgPrint("Livebox size is not changed: %dx%d, %d\n", w, h, status);
+               }
+       }
+
+out:
+       return NULL;
+}
+
+static struct packet *master_period_changed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       double period;
+       int status;
+
+       ret = packet_get(packet, "idss", &status, &period, &pkgname, &id);
+       if (ret != 4) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ErrPrint("Livebox(%s - %s) is not found\n", pkgname, id);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       if (status == 0)
+               lb_set_period(handler, period);
+
+       if (handler->period_changed_cb) {
+               handler->period_changed_cb(handler, status, handler->group_cbdata);
+
+               handler->period_changed_cb = NULL;
+               handler->period_cbdata = NULL;
+       } else {
+               lb_invoke_event_handler(handler, LB_EVENT_PERIOD_CHANGED);
+       }
+
+       ret = 0;
+
+out:
+       return NULL;
+}
+
+static struct packet *master_group_changed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       const char *cluster;
+       const char *category;
+       int status;
+
+       ret = packet_get(packet, "ssiss", &pkgname, &id, &status, &cluster, &category);
+       if (ret != 5) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               /*!
+                * \note
+                * Do no access this handler,
+                * You cannot believe this handler anymore.
+                */
+               ret = -EPERM;
+               goto out;
+       }
+
+       if (status == 0)
+               lb_set_group(handler, cluster, category);
+
+       if (handler->group_changed_cb) {
+               handler->group_changed_cb(handler, status, handler->group_cbdata);
+
+               handler->group_changed_cb = NULL;
+               handler->group_cbdata = NULL;
+       } else {
+               lb_invoke_event_handler(handler, LB_EVENT_GROUP_CHANGED);
+       }
+
+       ret = 0;
+
+out:
+       return NULL;
+}
+
+static struct packet *master_created(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+
+       int lb_w;
+       int lb_h;
+       int pd_w;
+       int pd_h;
+       const char *pkgname;
+       const char *id;
+
+       const char *content;
+       const char *cluster;
+       const char *category;
+       const char *lb_fname;
+       const char *pd_fname;
+       const char *title;
+
+       double timestamp;
+       const char *auto_launch;
+       double priority;
+       int size_list;
+       int user;
+       int pinup_supported;
+       enum lb_type lb_type;
+       enum pd_type pd_type;
+       double period;
+       int is_pinned_up;
+
+       int old_state = DESTROYED;
+
+       int ret;
+
+       ret = packet_get(packet, "dsssiiiisssssdiiiiidsi",
+                       &timestamp,
+                       &pkgname, &id, &content,
+                       &lb_w, &lb_h, &pd_w, &pd_h,
+                       &cluster, &category, &lb_fname, &pd_fname,
+                       &auto_launch, &priority, &size_list, &user, &pinup_supported,
+                       &lb_type, &pd_type, &period, &title, &is_pinned_up);
+       if (ret != 22) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ErrPrint("[%lf] pkgname: %s, id: %s, content: %s, "
+               "pd_w: %d, pd_h: %d, lb_w: %d, lb_h: %d, "
+               "cluster: %s, category: %s, lb_fname: \"%s\", pd_fname: \"%s\", "
+               "auto_launch: %s, priority: %lf, size_list: %d, user: %d, pinup: %d, "
+               "lb_type: %d, pd_type: %d, period: %lf, title: [%s], is_pinned_up: %d\n",
+               timestamp, pkgname, id, content,
+               pd_w, pd_h, lb_w, lb_h,
+               cluster, category, lb_fname, pd_fname,
+               auto_launch, priority, size_list, user, pinup_supported,
+               lb_type, pd_type, period, title, is_pinned_up);
+
+       handler = lb_find_livebox_by_timestamp(timestamp);
+       if (!handler) {
+               handler = lb_new_livebox(pkgname, id, timestamp);
+               if (!handler) {
+                       ErrPrint("Failed to create a new livebox\n");
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               old_state = handler->state;
+       } else {
+               if (handler->state != CREATE) {
+                       if (handler->state != DELETE) {
+                               /*!
+                                * \note
+                                * This is not possible!!!
+                                */
+                               ErrPrint("Invalid handler\n");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       /*!
+                        * \note
+                        * After get the delete states,
+                        * call the create callback with deleted result.
+                        */
+               }
+
+               old_state = handler->state;
+
+               if (handler->id) {
+                       ErrPrint("Already created: timestamp[%lf] "
+                               "pkgname[%s], id[%s] content[%s] "
+                               "cluster[%s] category[%s] lb_fname[%s] pd_fname[%s]\n",
+                                       timestamp, pkgname, id,
+                                       content, cluster, category,
+                                       lb_fname, pd_fname);
+
+                       ret = -EALREADY;
+                       goto out;
+               }
+
+               lb_set_id(handler, id);
+       }
+
+       lb_set_size(handler, lb_w, lb_h);
+       handler->lb.type = lb_type;
+       handler->is_pinned_up = is_pinned_up;
+
+       switch (lb_type) {
+       case _LB_TYPE_FILE:
+               break;
+       case _LB_TYPE_SCRIPT:
+       case _LB_TYPE_BUFFER:
+               if (!strlen(lb_fname))
+                       break;
+               lb_set_lb_fb(handler, lb_fname);
+               ret = fb_sync(lb_get_lb_fb(handler));
+               if (ret < 0)
+                       ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+               break;
+       case _LB_TYPE_TEXT:
+               lb_set_text_lb(handler);
+               break;
+       default:
+               break;
+       }
+
+       handler->pd.type = pd_type;
+       lb_set_pdsize(handler, pd_w, pd_h);
+       lb_set_default_pdsize(handler, pd_w, pd_h);
+       switch (pd_type) {
+       case _PD_TYPE_SCRIPT:
+       case _PD_TYPE_BUFFER:
+               if (!strlen(pd_fname))
+                       break;
+
+               lb_set_pd_fb(handler, pd_fname);
+               ret = fb_sync(lb_get_pd_fb(handler));
+               if (ret < 0)
+                       ErrPrint("Failed to do sync FB (%s - %s)\n", pkgname, util_basename(util_uri_to_path(id)));
+               break;
+       case _PD_TYPE_TEXT:
+               lb_set_text_pd(handler);
+               break;
+       default:
+               break;
+       }
+
+       lb_set_priority(handler, priority);
+
+       lb_set_size_list(handler, size_list);
+       lb_set_group(handler, cluster, category);
+
+       lb_set_content(handler, content);
+       lb_set_title(handler, title);
+
+       lb_set_user(handler, user);
+
+       lb_set_auto_launch(handler, auto_launch);
+       lb_set_pinup(handler, pinup_supported);
+
+       lb_set_period(handler, period);
+
+       ret = 0;
+
+       if (handler->state == CREATE) {
+               /*!
+                * \note
+                * These callback can change the handler->state.
+                * So we have to use the "old_state" which stored state before call these callbacks
+                */
+
+               if (handler->created_cb) {
+                       DbgPrint("Invoke the created_cb\n");
+                       handler->created_cb(handler, ret, handler->created_cbdata);
+
+                       handler->created_cb = NULL;
+                       handler->created_cbdata = NULL;
+               } else {
+                       DbgPrint("Invoke the lb,created\n");
+                       lb_invoke_event_handler(handler, LB_EVENT_CREATED);
+               }
+       }
+
+out:
+       if (ret == 0 && old_state == DELETE) {
+               DbgPrint("Send the delete request\n");
+               lb_send_delete(handler, handler->created_cb, handler->created_cbdata);
+
+               /*!
+                * \note
+                * handler->created_cb = NULL;
+                * handler->created_cbdata = NULL;
+                *
+                * Do not clear this to use this from the deleted event callback.
+                * if this value is not cleared when the deleted event callback check it,
+                * it means that the created function is not called yet.
+                * Then the call the deleted event callback with -ECANCELED errno.
+                */
+       }
+
+       return NULL;
+}
+
+static struct method s_table[] = {
+       {
+               .cmd = "lb_updated", /* pkgname, id, lb_w, lb_h, priority, ret */
+               .handler = master_lb_updated,
+       },
+       {
+               .cmd = "pd_updated", /* pkgname, id, descfile, pd_w, pd_h, ret */
+               .handler = master_pd_updated,
+       },
+       {
+               .cmd = "pd_created",
+               .handler = master_pd_created,
+       },
+       {
+               .cmd = "pd_destroyed",
+               .handler = master_pd_destroyed,
+       },
+       {
+               .cmd = "fault_package", /* pkgname, id, function, ret */
+               .handler = master_fault_package,
+       },
+       {
+               .cmd = "deleted", /* pkgname, id, timestamp, ret */
+               .handler = master_deleted,
+       },
+       {
+               .cmd = "created", /* timestamp, pkgname, id, content, lb_w, lb_h, pd_w, pd_h, cluster, category, lb_file, pd_file, auto_launch, priority, size_list, is_user, pinup_supported, text_lb, text_pd, period, ret */
+               .handler = master_created,
+       },
+       {
+               .cmd = "group_changed",
+               .handler = master_group_changed,
+       },
+       {
+               .cmd = "period_changed",
+               .handler = master_period_changed,
+       },
+       {
+               .cmd = "size_changed",
+               .handler = master_size_changed,
+       },
+       {
+               .cmd = "pinup",
+               .handler = master_pinup,
+       },
+       {
+               .cmd = NULL,
+               .handler = NULL,
+       },
+};
+
+static void acquire_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       if (!result) {
+               DbgPrint("Result packet is not valid\n");
+       } else {
+               int ret;
+
+               if (packet_get(result, "i", &ret) != 1)
+                       ErrPrint("Invalid argument\n");
+               else
+                       DbgPrint("Acquire returns: %d\n", ret);
+       }
+
+       return;
+}
+
+static gboolean connector_cb(gpointer user_data)
+{
+       s_info.reconnector = 0;
+
+       if (s_info.fd > 0) {
+               DbgPrint("Connection is already made\n");
+               return FALSE;
+       }
+
+       make_connection();
+       return FALSE;
+}
+
+static inline void make_connection(void)
+{
+       struct packet *packet;
+       int ret;
+
+       DbgPrint("Let's making connection!\n");
+
+       s_info.fd = com_core_packet_client_init(CLIENT_SOCKET, 0, s_table);
+       if (s_info.fd < 0) {
+               /*!< After 10 secs later, try to connect again */
+               s_info.reconnector = g_timeout_add(RECONNECT_PERIOD, connector_cb, NULL);
+               if (s_info.reconnector == 0)
+                       ErrPrint("Failed to fire the reconnector\n");
+
+               ErrPrint("Try this again 10 secs later\n");
+               return;
+       }
+
+       packet = packet_create("acquire", "d", util_timestamp());
+       if (!packet) {
+               com_core_packet_client_fini(s_info.fd);
+               s_info.fd = -1;
+               return;
+       }
+
+       ret = master_rpc_async_request(NULL, packet, 1, acquire_cb, NULL);
+       if (ret < 0) {
+               ErrPrint("Master RPC returns %d\n", ret);
+               com_core_packet_client_fini(s_info.fd);
+               s_info.fd = -1;
+       }
+
+}
+
+static int connected_cb(int handle, void *data)
+{
+       master_rpc_check_and_fire_consumer();
+       return 0;
+}
+
+static int disconnected_cb(int handle, void *data)
+{
+       if (s_info.fd != handle) {
+               /*!< This handle is not my favor */
+               return 0;
+       }
+
+       s_info.fd = -1; /*!< Disconnected */
+
+       if (s_info.reconnector > 0) {
+               DbgPrint("Reconnector already fired\n");
+               return 0;
+       }
+
+       /*!< After 10 secs later, try to connect again */
+       s_info.reconnector = g_timeout_add(RECONNECT_PERIOD, connector_cb, NULL);
+       if (s_info.reconnector == 0) {
+               ErrPrint("Failed to fire the reconnector\n");
+               make_connection();
+       }
+
+       master_rpc_clear_all_request();
+       lb_invoke_fault_handler(LB_FAULT_PROVIDER_DISCONNECTED, MASTER_PKGNAME, "default", "disconnected");
+
+       lb_delete_all();
+       return 0;
+}
+
+int client_init(void)
+{
+       com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+       com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
+       make_connection();
+       return 0;
+}
+
+int client_fd(void)
+{
+       return s_info.fd;
+}
+
+const char *client_addr(void)
+{
+       return CLIENT_SOCKET;
+}
+
+int client_fini(void)
+{
+       com_core_packet_client_fini(s_info.fd);
+       com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+       com_core_del_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
+       s_info.fd = -1;
+       return 0;
+}
+
+/* End of a file */
+
+
diff --git a/src/critical_log.c b/src/critical_log.c
new file mode 100644 (file)
index 0000000..8b626c5
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <dlog.h>
+
+#include "conf.h"
+#include "debug.h"
+#include "util.h"
+#include "critical_log.h"
+
+static struct {
+       FILE *fp;
+       int file_id;
+       int nr_of_lines;
+       char *filename;
+} s_info = {
+       .fp = NULL,
+       .file_id = 0,
+       .nr_of_lines = 0,
+       .filename = NULL,
+};
+
+
+
+int critical_log(const char *func, int line, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+       struct timeval tv;
+
+       if (!s_info.fp)
+               return -EIO;
+
+       gettimeofday(&tv, NULL);
+       fprintf(s_info.fp, "%d %lu.%lu [%s:%d] ", getpid(), tv.tv_sec, tv.tv_usec, util_basename((char *)func), line);
+
+       va_start(ap, fmt);
+       ret = vfprintf(s_info.fp, fmt, ap);
+       va_end(ap);
+
+       s_info.nr_of_lines++;
+       if (s_info.nr_of_lines == MAX_LOG_LINE) {
+               char *filename;
+               int namelen;
+
+               s_info.file_id = (s_info.file_id + 1) % MAX_LOG_FILE;
+
+               namelen = strlen(s_info.filename) + strlen(SLAVE_LOG_PATH) + 20;
+               filename = malloc(namelen);
+               if (filename) {
+                       snprintf(filename, namelen, "%s/%d_%s", SLAVE_LOG_PATH, s_info.file_id, s_info.filename);
+
+                       if (s_info.fp)
+                               fclose(s_info.fp);
+
+                       s_info.fp = fopen(filename, "w+");
+                       if (!s_info.fp)
+                               ErrPrint("Failed to open a file: %s\n", filename);
+
+                       free(filename);
+               }
+
+               s_info.nr_of_lines = 0;
+       }
+       return ret;
+}
+
+
+
+int critical_log_init(const char *name)
+{
+       int namelen;
+       char *filename;
+
+       if (s_info.fp)
+               return 0;
+
+       s_info.filename = strdup(name);
+       if (!s_info.filename) {
+               ErrPrint("Failed to create a log file\n");
+               return -ENOMEM;
+       }
+
+       namelen = strlen(name) + strlen(SLAVE_LOG_PATH) + 20;
+
+       filename = malloc(namelen);
+       if (!filename) {
+               ErrPrint("Failed to create a log file\n");
+               free(s_info.filename);
+               s_info.filename = NULL;
+               return -ENOMEM;
+       }
+
+       snprintf(filename, namelen, "%s/%d_%s", SLAVE_LOG_PATH, s_info.file_id, name);
+
+       s_info.fp = fopen(filename, "w+");
+       if (!s_info.fp) {
+               ErrPrint("Failed to open log: %s\n", strerror(errno));
+               free(s_info.filename);
+               s_info.filename = NULL;
+               free(filename);
+               return -EIO;
+       }
+
+       free(filename);
+       return 0;
+}
+
+
+
+int critical_log_fini(void)
+{
+       if (s_info.filename) {
+               free(s_info.filename);
+               s_info.filename = NULL;
+       }
+
+       if (s_info.fp) {
+               fclose(s_info.fp);
+               s_info.fp = NULL;
+       }
+
+       return 0;
+}
+
+
+
+/* End of a file */
diff --git a/src/desc_parser.c b/src/desc_parser.c
new file mode 100644 (file)
index 0000000..25595c0
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <errno.h>
+#include <stdlib.h> /* malloc */
+#include <string.h> /* strdup */
+#include <ctype.h>
+
+#include <dlog.h>
+
+#include "debug.h"
+#include "livebox.h"
+#include "livebox_internal.h"
+#include "desc_parser.h"
+#include "dlist.h"
+#include "util.h"
+#include "critical_log.h"
+
+#define TYPE_TEXT "text"
+#define TYPE_IMAGE "image"
+#define TYPE_EDJE "edje"
+#define TYPE_SIGNAL "signal"
+#define TYPE_INFO "info"
+#define TYPE_DRAG "drag"
+
+#define INFO_SIZE "size"
+#define INFO_CATEGORY "category"
+
+struct block {
+       char *type;
+       int type_len;
+
+       char *part;
+       int part_len;
+
+       char *data;
+       int data_len;
+
+       char *file;
+       int file_len;
+
+       char *group;
+       int group_len;
+
+       char *id;
+       int id_len;
+};
+
+static int update_text(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       if (!block || !block->part || !block->data) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+       if (ops->update_text)
+               ops->update_text(handle, (const char *)block->id, (const char *)block->part, (const char *)block->data);
+
+       return 0;
+}
+
+static int update_image(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+       if (!block || !block->part) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+       if (ops->update_image)
+               ops->update_image(handle, block->id, block->part, block->data);
+
+       return 0;
+}
+
+static int update_script(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+       if (!block || !block->part) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+       if (ops->update_script)
+               ops->update_script(handle, block->id, block->part, block->data, block->group);
+
+       return 0;
+}
+
+static int update_signal(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       if (!block) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+       if (ops->update_signal)
+               ops->update_signal(handle, block->id, block->data, block->part);
+
+       return 0;
+}
+
+static int update_drag(struct livebox *handle, struct block *block, int is_pd)
+{
+       double dx, dy;
+       struct livebox_script_operators *ops;
+
+       if (!block || !block->data || !block->part) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+
+       if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
+               ErrPrint("Invalid format of data\n");
+               return -EINVAL;
+       }
+
+       if (ops->update_drag)
+               ops->update_drag(handle, block->id, block->part, dx, dy);
+
+       return 0;
+}
+
+static int update_info(struct livebox *handle, struct block *block, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       if (!block || !block->part || !block->data) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+
+       if (!strcasecmp(block->part, INFO_SIZE)) {
+               int w, h;
+
+               if (sscanf(block->data, "%dx%d", &w, &h) != 2) {
+                       ErrPrint("Invalid format (%s)\n", block->data);
+                       return -EINVAL;
+               }
+
+               if (ops->update_info_size)
+                       ops->update_info_size(handle, block->id, w, h);
+
+       } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
+               if (ops->update_info_category)
+                       ops->update_info_category(handle, block->id, block->data);
+       }
+
+       return 0;
+}
+
+static inline int update_begin(struct livebox *handle, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+
+       if (ops->update_begin)
+               ops->update_begin(handle);
+
+       return 0;
+}
+
+static inline int update_end(struct livebox *handle, int is_pd)
+{
+       struct livebox_script_operators *ops;
+
+       ops = is_pd ? &handle->pd.data.ops : &handle->lb.data.ops;
+
+       if (ops->update_end)
+               ops->update_end(handle);
+
+       return 0;
+}
+
+int parse_desc(struct livebox *handle, const char *descfile, int is_pd)
+{
+       FILE *fp;
+       int ch;
+       enum state {
+               UNKNOWN = 0x10,
+               BLOCK_OPEN = 0x11,
+               FIELD = 0x12,
+               VALUE = 0x13,
+               BLOCK_CLOSE = 0x14,
+
+               VALUE_TYPE = 0x00,
+               VALUE_PART = 0x01,
+               VALUE_DATA = 0x02,
+               VALUE_FILE = 0x03,
+               VALUE_GROUP = 0x04,
+               VALUE_ID = 0x05,
+       };
+       const char *field_name[] = {
+               "type",
+               "part",
+               "data",
+               "file",
+               "group",
+               "id",
+               NULL
+       };
+       enum state state;
+       register int field_idx;
+       register int idx = 0;
+       register int i;
+       struct block *block;
+       struct {
+               const char *type;
+               int (*handler)(struct livebox *handle, struct block *block, int is_pd);
+       } handlers[] = {
+               {
+                       .type = TYPE_TEXT,
+                       .handler = update_text,
+               },
+               {
+                       .type = TYPE_IMAGE,
+                       .handler = update_image,
+               },
+               {
+                       .type = TYPE_EDJE,
+                       .handler = update_script,
+               },
+               {
+                       .type = TYPE_SIGNAL,
+                       .handler = update_signal,
+               },
+               {
+                       .type = TYPE_DRAG,
+                       .handler = update_drag,
+               },
+               {
+                       .type = TYPE_INFO,
+                       .handler = update_info,
+               },
+               {
+                       .type = NULL,
+                       .handler = NULL,
+               },
+       };
+
+       fp = fopen(descfile, "rt");
+       if (!fp) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               return -EIO;
+       }
+
+       update_begin(handle, is_pd);
+
+       state = UNKNOWN;
+       field_idx = 0;
+
+       block = NULL;
+       while (!feof(fp)) {
+               ch = getc(fp);
+
+               switch (state) {
+               case UNKNOWN:
+                       if (ch == '{') {
+                               state = BLOCK_OPEN;
+                               break;
+                       }
+
+                       if (!isspace(ch)) {
+                               update_end(handle, is_pd);
+                               fclose(fp);
+                               return -EINVAL;
+                       }
+                       break;
+
+               case BLOCK_OPEN:
+                       if (isblank(ch))
+                               break;
+
+                       if (ch != '\n')
+                               goto errout;
+
+                       block = calloc(1, sizeof(*block));
+                       if (!block) {
+                               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                               update_end(handle, is_pd);
+                               fclose(fp);
+                               return -ENOMEM;
+                       }
+
+                       state = FIELD;
+                       idx = 0;
+                       field_idx = 0;
+                       break;
+
+               case FIELD:
+                       if (isspace(ch))
+                               break;
+
+                       if (ch == '}') {
+                               state = BLOCK_CLOSE;
+                               break;
+                       }
+
+                       if (ch == '=') {
+                               if (field_name[field_idx][idx] != '\0')
+                                       goto errout;
+
+                               switch (field_idx) {
+                               case 0:
+                                       state = VALUE_TYPE;
+                                       if (block->type) {
+                                               free(block->type);
+                                               block->type = NULL;
+                                               block->type_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               case 1:
+                                       state = VALUE_PART;
+                                       if (block->part) {
+                                               free(block->part);
+                                               block->part = NULL;
+                                               block->part_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               case 2:
+                                       state = VALUE_DATA;
+                                       if (block->data) {
+                                               free(block->data);
+                                               block->data = NULL;
+                                               block->data_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               case 3:
+                                       state = VALUE_FILE;
+                                       if (block->file) {
+                                               free(block->file);
+                                               block->file = NULL;
+                                               block->file_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               case 4:
+                                       state = VALUE_GROUP;
+                                       if (block->group) {
+                                               free(block->group);
+                                               block->group = NULL;
+                                               block->group_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               case 5:
+                                       state = VALUE_ID;
+                                       if (block->id) {
+                                               free(block->id);
+                                               block->id = NULL;
+                                               block->id_len = 0;
+                                       }
+                                       idx = 0;
+                                       break;
+                               default:
+                                       goto errout;
+                               }
+
+                               break;
+                       }
+
+                       if (ch == '\n')
+                               goto errout;
+
+                       if (field_name[field_idx][idx] != ch) {
+                               ungetc(ch, fp);
+                               while (--idx >= 0)
+                                       ungetc(field_name[field_idx][idx], fp);
+
+                               field_idx++;
+                               if (field_name[field_idx] == NULL)
+                                       goto errout;
+
+                               idx = 0;
+                               break;
+                       }
+
+                       idx++;
+                       break;
+
+               case VALUE_TYPE:
+                       if (idx == block->type_len) {
+                               block->type_len += 256;
+                               block->type = realloc(block->type, block->type_len);
+                               if (!block->type) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->type[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->type[idx] = ch;
+                       idx++;
+                       break;
+
+               case VALUE_PART:
+                       if (idx == block->part_len) {
+                               block->part_len += 256;
+                               block->part = realloc(block->part, block->part_len);
+                               if (!block->part) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->part[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->part[idx] = ch;
+                       idx++;
+                       break;
+
+               case VALUE_DATA:
+                       if (idx == block->data_len) {
+                               block->data_len += 256;
+                               block->data = realloc(block->data, block->data_len);
+                               if (!block->data) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->data[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->data[idx] = ch;
+                       idx++;
+                       break;
+
+               case VALUE_FILE:
+                       if (idx == block->file_len) {
+                               block->file_len += 256;
+                               block->file = realloc(block->file, block->file_len);
+                               if (!block->file) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->file[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->file[idx] = ch;
+                       idx++;
+                       break;
+
+               case VALUE_GROUP:
+                       if (idx == block->group_len) {
+                               block->group_len += 256;
+                               block->group = realloc(block->group, block->group_len);
+                               if (!block->group) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->group[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->group[idx] = ch;
+                       idx++;
+                       break;
+               case VALUE_ID:
+                       if (idx == block->id_len) {
+                               block->id_len += 256;
+                               block->id = realloc(block->id, block->id_len);
+                               if (!block->id) {
+                                       CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                                       goto errout;
+                               }
+                       }
+
+                       if (ch == '\n') {
+                               block->id[idx] = '\0';
+                               state = FIELD;
+                               idx = 0;
+                               field_idx = 0;
+                               break;
+                       }
+
+                       block->id[idx] = ch;
+                       idx++;
+                       break;
+               case BLOCK_CLOSE:
+                       if (!block->file) {
+                               block->file = strdup(util_uri_to_path(handle->id));
+                               if (!block->file)
+                                       goto errout;
+                       }
+
+                       i = 0;
+                       while (handlers[i].type) {
+                               if (!strcasecmp(handlers[i].type, block->type)) {
+                                       handlers[i].handler(handle, block, is_pd);
+                                       break;
+                               }
+                               i++;
+                       }
+
+                       if (!handlers[i].type)
+                               ErrPrint("Unknown block type: %s\n", block->type);
+
+                       free(block->file);
+                       free(block->type);
+                       free(block->part);
+                       free(block->data);
+                       free(block->group);
+                       free(block->id);
+                       free(block);
+                       block = NULL;
+
+                       state = UNKNOWN;
+                       break;
+
+               default:
+                       break;
+               } /* switch */
+       } /* while */
+
+       if (state != UNKNOWN)
+               goto errout;
+
+       update_end(handle, is_pd);
+
+       fclose(fp);
+       return 0;
+
+errout:
+       ErrPrint("Parse error\n");
+       if (block) {
+               free(block->file);
+               free(block->type);
+               free(block->part);
+               free(block->data);
+               free(block->group);
+               free(block->id);
+               free(block);
+       }
+
+       update_end(handle, is_pd);
+
+       fclose(fp);
+       return -EINVAL;
+}
+
+/* End of a file */
diff --git a/src/dlist.c b/src/dlist.c
new file mode 100644 (file)
index 0000000..56ff060
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <stdlib.h>
+#include <assert.h>
+
+#include "dlist.h"
+
+/*!
+ * \brief
+ * This dlist is called Modified Doubly Linked List.
+ *
+ * Noramlly, The dobule linked list contains address of previous and next element.
+ * This dlist also contains them, but the tail element only contains prev address.
+ *
+ * The head element's prev pointer indicates the last element.
+ * But the last element's next pointer indicates NIL.
+ *
+ * So we can find the last element while crawling this DList
+ * But we have to remember the address of the head element.
+ */
+
+struct dlist {
+       struct dlist *next;
+       struct dlist *prev;
+       void *data;
+};
+
+struct dlist *dlist_append(struct dlist *list, void *data)
+{
+       struct dlist *item;
+
+       item = malloc(sizeof(*item));
+       if (!item)
+               return NULL;
+
+       item->next = NULL;
+       item->data = data;
+
+       if (!list) {
+               item->prev = item;
+
+               list = item;
+       } else {
+               item->prev = list->prev;
+               item->prev->next = item;
+               list->prev = item;
+       }
+
+       assert(!list->prev->next && "item NEXT");
+
+       return list;
+}
+
+struct dlist *dlist_prepend(struct dlist *list, void *data)
+{
+       struct dlist *item;
+
+       item = malloc(sizeof(*item));
+       if (!item)
+               return NULL;
+
+       item->data = data;
+
+       if (!list) {
+               item->prev = item;
+               item->next = NULL;
+       } else {
+               if (list->prev->next)
+                       list->prev->next = item;
+
+               item->prev = list->prev;
+               item->next = list;
+
+               list->prev = item;
+
+       }
+
+       return item;
+}
+
+struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
+{
+       if (!list || !l)
+               return NULL;
+
+       if (l == list)
+               list = l->next;
+       else
+               l->prev->next = l->next;
+
+       if (l->next)
+               l->next->prev = l->prev;
+       /*!
+        * \note
+        * If the removed entry 'l' has no next element, it is the last element.
+        * In this case, check the existence of the list first,
+        * and if the list is not empty, update the 'prev' of the list (which is a head element of the list) 
+        *
+        * If we didn't care about this, the head element(list) can indicates the invalid element.
+        */
+       else if (list)
+               list->prev = l->prev;
+
+       free(l);
+       return list;
+}
+
+struct dlist *dlist_find_data(struct dlist *list, void *data)
+{
+       struct dlist *l;
+       void *_data;
+
+       dlist_foreach(list, l, _data) {
+               if (data == _data)
+                       return l;
+       }
+
+       return NULL;
+}
+
+void *dlist_data(struct dlist *l)
+{
+       return l ? l->data : NULL;
+}
+
+struct dlist *dlist_next(struct dlist *l)
+{
+       return l ? l->next : NULL;
+}
+
+struct dlist *dlist_prev(struct dlist *l)
+{
+       return l ? l->prev : NULL;
+}
+
+int dlist_count(struct dlist *l)
+{
+       register int i;
+       struct dlist *n;
+       void *data;
+
+       i = 0;
+       dlist_foreach(l, n, data) {
+               i++;
+       }
+
+       return i;
+}
+
+struct dlist *dlist_nth(struct dlist *l, int nth)
+{
+       register int i;
+       struct dlist *n;
+
+       i = 0;
+       for (n = l; n; n = n->next) {
+               if (i == nth)
+                       return n;
+               i++;
+       }
+
+       return NULL;
+}
+
+/* End of a file */
diff --git a/src/fb.c b/src/fb.c
new file mode 100644 (file)
index 0000000..1e687ef
--- /dev/null
+++ b/src/fb.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <errno.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+#include <X11/Xutil.h>
+
+#include <dlog.h>
+
+#include "debug.h"
+#include "util.h"
+#include "fb.h"
+#include "critical_log.h"
+
+int errno;
+
+struct fb_info {
+       char *id;
+       int w;
+       int h;
+       int bufsz;
+       void *buffer;
+
+       int handle;
+};
+
+struct buffer { /*!< Must has to be sync with slave & provider */
+       enum {
+               CREATED = 0x00beef00,
+               DESTROYED = 0x00dead00,
+       } state;
+       enum buffer_type type;
+       int refcnt;
+       void *info;
+       char data[];
+};
+
+static struct {
+       Display *disp;
+       int screen;
+       int depth;
+       Visual *visual;
+       int disp_is_opened;
+} s_info = {
+       .disp = NULL,
+       .disp_is_opened = 0,
+       .screen = -1,
+       .depth = 0,
+       .visual = NULL,
+};
+
+int fb_init(void *disp)
+{
+       s_info.disp = disp;
+       if (s_info.disp) {
+               Screen *screen;
+
+               screen = DefaultScreenOfDisplay(s_info.disp);
+
+               s_info.screen = DefaultScreen(s_info.disp);
+               s_info.visual = DefaultVisualOfScreen(screen);
+       }
+
+       s_info.depth = sizeof(int); //DefaultDepthOfScreen(screen);
+       return 0;
+}
+
+int fb_fini(void)
+{
+       if (s_info.disp_is_opened && s_info.disp) {
+               XCloseDisplay(s_info.disp);
+       }
+
+       s_info.disp = NULL;
+       s_info.disp_is_opened = 0;
+       s_info.visual = NULL;
+       s_info.screen = -1;
+       s_info.depth = 0;
+       return 0;
+}
+
+static inline int sync_for_file(struct fb_info *info)
+{
+       int fd;
+       struct buffer *buffer;
+
+       buffer = info->buffer;
+
+       if (!buffer) /* Ignore this sync request */
+               return 0;
+
+       if (buffer->state != CREATED) {
+               ErrPrint("Invalid state of a FB\n");
+               return -EINVAL;
+       }
+
+       if (buffer->type != BUFFER_TYPE_FILE) {
+               DbgPrint("Invalid buffer\n");
+               return 0;
+       }
+
+       fd = open(util_uri_to_path(info->id), O_RDONLY);
+       if (fd < 0) {
+               ErrPrint("Failed to open a file (%s) because of (%s)\n",
+                                       util_uri_to_path(info->id), strerror(errno));
+
+               /*!
+                * \note
+                * But return ZERO, even if we couldn't get a buffer file,
+                * the viewer can draw empty screen.
+                *
+                * and then update it after it gots update events
+                */
+               return 0;
+       }
+
+       if (read(fd, buffer->data, info->bufsz) != info->bufsz) {
+               ErrPrint("read: %s\n", strerror(errno));
+               close(fd);
+
+               /*!
+                * \note
+                * But return ZERO, even if we couldn't get a buffer file,
+                * the viewer can draw empty screen.
+                *
+                * and then update it after it gots update events
+                */
+               return 0;
+       }
+
+       close(fd);
+       return 0;
+}
+
+static inline __attribute__((always_inline)) int sync_for_pixmap(struct fb_info *info)
+{
+       struct buffer *buffer;
+       XShmSegmentInfo si;
+       XImage *xim;
+
+       buffer = info->buffer;
+       if (!buffer) /*!< Ignore this sync request */
+               return 0;
+
+       if (buffer->state != CREATED) {
+               ErrPrint("Invalid state of a FB\n");
+               return -EINVAL;
+       }
+
+       if (buffer->type != BUFFER_TYPE_PIXMAP) {
+               DbgPrint("Invalid buffer\n");
+               return 0;
+       }
+
+       if (!s_info.disp) {
+               s_info.disp = XOpenDisplay(NULL);
+               if (s_info.disp) {
+                       Screen *screen;
+
+                       s_info.disp_is_opened = 1;
+
+                       screen = DefaultScreenOfDisplay(s_info.disp);
+
+                       s_info.screen = DefaultScreen(s_info.disp);
+                       s_info.visual = DefaultVisualOfScreen(screen);
+               } else {
+                       ErrPrint("Failed to open a display\n");
+                       return -EFAULT;
+               }
+       }
+
+       if (info->handle == 0) {
+               DbgPrint("Pixmap ID is not valid\n");
+               return -EINVAL;
+       }
+
+       if (info->bufsz == 0) {
+               DbgPrint("Nothing can be sync\n");
+               return 0;
+       }
+
+       si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
+       if (si.shmid < 0) {
+               ErrPrint("shmget: %s\n", strerror(errno));
+               return -EFAULT;
+       }
+
+       si.readOnly = False;
+       si.shmaddr = shmat(si.shmid, NULL, 0);
+       if (si.shmaddr == (void *)-1) {
+
+               if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+                       ErrPrint("shmctl: %s\n", strerror(errno));
+
+               return -EFAULT;
+       }
+
+       /*!
+        * \NOTE
+        * Use the 24 bits Pixmap for Video player
+        */
+       xim = XShmCreateImage(s_info.disp, s_info.visual,
+                               24 /* (s_info.depth << 3) */, ZPixmap, NULL,
+                               &si,
+                               info->w, info->h);
+       if (xim == NULL) {
+               if (shmdt(si.shmaddr) < 0)
+                       ErrPrint("shmdt: %s\n", strerror(errno));
+
+               if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+                       ErrPrint("shmctl: %s\n", strerror(errno));
+
+               return -EFAULT;
+       }
+
+       xim->data = si.shmaddr;
+       XShmAttach(s_info.disp, &si);
+
+       XShmGetImage(s_info.disp, info->handle, xim, 0, 0, 0xFFFFFFFF);
+       XSync(s_info.disp, False);
+
+       memcpy(buffer->data, xim->data, info->bufsz);
+
+       XShmDetach(s_info.disp, &si);
+       XDestroyImage(xim);
+
+       if (shmdt(si.shmaddr) < 0)
+               ErrPrint("shmdt: %s\n", strerror(errno));
+
+       if (shmctl(si.shmid, IPC_RMID, 0) < 0)
+               ErrPrint("shmctl: %s\n", strerror(errno));
+
+       return 0;
+}
+
+int fb_sync(struct fb_info *info)
+{
+       if (!info) {
+               ErrPrint("FB Handle is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!info->id || info->id[0] == '\0') {
+               DbgPrint("Ingore sync\n");
+               return 0;
+       }
+
+       if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
+               return sync_for_file(info);
+       } else if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
+               return sync_for_pixmap(info);
+       } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
+               /* No need to do sync */ 
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+struct fb_info *fb_create(const char *id, int w, int h)
+{
+       struct fb_info *info;
+
+       if (!id || id[0] == '\0') {
+               ErrPrint("Invalid ID\n");
+               return NULL;
+       }
+
+       info = calloc(1, sizeof(*info));
+       if (!info) {
+               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       info->id = strdup(id);
+       if (!info->id) {
+               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+               free(info);
+               return NULL;
+       }
+
+       if (sscanf(info->id, SCHEMA_SHM "%d", &info->handle) == 1) {
+               DbgPrint("SHMID: %d is gotten\n", info->handle);
+       } else if (sscanf(info->id, SCHEMA_PIXMAP "%d", &info->handle) == 1) {
+               DbgPrint("PIXMAP-SHMID: %d is gotten\n", info->handle);
+       } else {
+               info->handle = -EINVAL;
+       }
+
+       info->bufsz = 0;
+       info->buffer = NULL;
+       info->w = w;
+       info->h = h;
+
+       return info;
+}
+
+int fb_destroy(struct fb_info *info)
+{
+       if (!info) {
+               ErrPrint("Handle is not valid\n");
+               return -EINVAL;
+       }
+
+       if (info->buffer) {
+               struct buffer *buffer;
+               buffer = info->buffer;
+
+               buffer->info = NULL;
+       }
+
+       free(info->id);
+       free(info);
+       return 0;
+}
+
+int fb_is_created(struct fb_info *info)
+{
+       if (!info) {
+               ErrPrint("Handle is not valid\n");
+               return 0;
+       }
+
+       if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->handle != 0) {
+               return 1;
+       } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM)) && info->handle > 0) {
+               return 1;
+       } else {
+               const char *path;
+               path = util_uri_to_path(info->id);
+               if (path && access(path, F_OK | R_OK) == 0) {
+                       return 1;
+               } else {
+                       ErrPrint("access: %s (%s)\n", strerror(errno), path);
+               }
+       }
+
+       return 0;
+}
+
+void *fb_acquire_buffer(struct fb_info *info)
+{
+       struct buffer *buffer;
+
+       if (!info) {
+               ErrPrint("info == NIL\n");
+               return NULL;
+       }
+
+       if (!info->buffer) {
+               if (!strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) {
+                       info->bufsz = info->w * info->h * s_info.depth;
+                       buffer = calloc(1, sizeof(*buffer) + info->bufsz);
+                       if (!buffer) {
+                               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                               info->bufsz = 0;
+                               return NULL;
+                       }
+
+                       buffer->type = BUFFER_TYPE_PIXMAP;
+                       buffer->refcnt = 0;
+                       buffer->state = CREATED;
+                       buffer->info = info;
+                       info->buffer = buffer;
+
+                       /*!
+                        * \note
+                        * Just update from here.
+                        */
+                       sync_for_pixmap(info);
+               } else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
+                       info->bufsz = info->w * info->h * s_info.depth;
+                       buffer = calloc(1, sizeof(*buffer) + info->bufsz);
+                       if (!buffer) {
+                               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+                               info->bufsz = 0;
+                               return NULL;
+                       }
+
+                       buffer->type = BUFFER_TYPE_FILE;
+                       buffer->refcnt = 0;
+                       buffer->state = CREATED;
+                       buffer->info = info;
+                       info->buffer = buffer;
+
+                       sync_for_file(info);
+               } else if (!strncasecmp(info->id, SCHEMA_SHM, strlen(SCHEMA_SHM))) {
+                       buffer = shmat(info->handle, NULL, 0);
+                       if (buffer == (void *)-1) {
+                               ErrPrint("shmat: %s\n", strerror(errno));
+                               return NULL;
+                       }
+
+                       return buffer->data;
+               } else {
+                       ErrPrint("Buffer is not created (%s)\n", info->id);
+                       return NULL;
+               }
+       }
+
+       buffer = info->buffer;
+
+       switch (buffer->type) {
+       case BUFFER_TYPE_PIXMAP:
+               buffer->refcnt++;
+               break;
+       case BUFFER_TYPE_FILE:
+               buffer->refcnt++;
+               break;
+       default:
+               DbgPrint("Unknwon FP: %d\n", buffer->type);
+               break;
+       }
+
+       return buffer->data;
+}
+
+int fb_release_buffer(void *data)
+{
+       struct buffer *buffer;
+
+       if (!data) {
+               DbgPrint("buffer data == NIL\n");
+               return 0;
+       }
+
+       buffer = container_of(data, struct buffer, data);
+
+       if (buffer->state != CREATED) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       switch (buffer->type) {
+       case BUFFER_TYPE_SHM:
+               if (shmdt(buffer) < 0)
+                       ErrPrint("shmdt: %s\n", strerror(errno));
+               break;
+       case BUFFER_TYPE_PIXMAP:
+               buffer->refcnt--;
+               if (buffer->refcnt == 0) {
+                       struct fb_info *info;
+                       info = buffer->info;
+
+                       buffer->state = DESTROYED;
+                       free(buffer);
+               
+                       if (info && info->buffer == buffer)
+                               info->buffer = NULL;
+               }
+               break;
+       case BUFFER_TYPE_FILE:
+               buffer->refcnt--;
+               if (buffer->refcnt == 0) {
+                       struct fb_info *info;
+                       info = buffer->info;
+
+                       buffer->state = DESTROYED;
+                       free(buffer);
+
+                       if (info && info->buffer == buffer)
+                               info->buffer = NULL;
+               }
+               break;
+       default:
+               ErrPrint("Unknwon buffer type\n");
+               break;
+       }
+
+       return 0;
+}
+
+int fb_refcnt(void *data)
+{
+       struct buffer *buffer;
+       struct shmid_ds buf;
+       int ret;
+
+       if (!data)
+               return -EINVAL;
+
+       buffer = container_of(data, struct buffer, data);
+
+       if (buffer->state != CREATED) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       switch (buffer->type) {
+       case BUFFER_TYPE_SHM:
+               if (shmctl(buffer->refcnt, IPC_STAT, &buf) < 0) {
+                       ErrPrint("Error: %s\n", strerror(errno));
+                       return -EFAULT;
+               }
+
+               ret = buf.shm_nattch;
+               break;
+       case BUFFER_TYPE_PIXMAP:
+               ret = buffer->refcnt;
+               break;
+       case BUFFER_TYPE_FILE:
+               ret = buffer->refcnt;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+const char *fb_id(struct fb_info *info)
+{
+       return info ? info->id : NULL;
+}
+
+int fb_get_size(struct fb_info *info, int *w, int *h)
+{
+       if (!info) {
+               ErrPrint("Handle is not valid\n");
+               return -EINVAL;
+       }
+
+       *w = info->w;
+       *h = info->h;
+       return 0;
+}
+
+int fb_size(struct fb_info *info)
+{
+       info->bufsz = info->w * info->h * s_info.depth;
+       return info ? info->bufsz : 0;
+}
+
+/* End of a file */
diff --git a/src/livebox.c b/src/livebox.c
new file mode 100644 (file)
index 0000000..d880101
--- /dev/null
@@ -0,0 +1,2590 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <errno.h>
+#include <stdlib.h> /* malloc */
+#include <string.h> /* strdup */
+#include <math.h>
+
+#include <aul.h>
+#include <dlog.h>
+
+#include <com-core_packet.h>
+#include <packet.h>
+#include <livebox-service.h>
+
+#include "debug.h"
+#include "fb.h"
+#include "livebox.h"
+#include "livebox_internal.h"
+#include "dlist.h"
+#include "util.h"
+#include "master_rpc.h"
+#include "client.h"
+#include "critical_log.h"
+
+#define EAPI __attribute__((visibility("default")))
+#define MINIMUM_EVENT  s_info.event_filter
+
+#if defined(FLOG)
+FILE *__file_log_fp;
+#endif
+
+static struct info {
+       struct dlist *livebox_list;
+       struct dlist *event_list;
+       struct dlist *fault_list;
+       int init_count;
+       int prevent_overwrite;
+       double event_filter;
+} s_info = {
+       .livebox_list = NULL,
+       .event_list = NULL,
+       .fault_list = NULL,
+       .init_count = 0,
+       .prevent_overwrite = 0,
+       .event_filter = 0.02f,
+};
+
+struct cb_info {
+       ret_cb_t cb;
+       void *data;
+};
+
+struct event_info {
+       int (*handler)(struct livebox *handler, enum livebox_event_type event, void *data);
+       void *user_data;
+};
+
+struct fault_info {
+       int (*handler)(enum livebox_fault_type event, const char *pkgname, const char *filename, const char *func, void *data);
+       void *user_data;
+};
+
+static inline void default_create_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default created event handler: %d\n", ret);
+}
+
+static inline void default_delete_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default deleted event handler: %d\n", ret);
+}
+
+static inline void default_pinup_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default pinup event handler: %d\n", ret);
+}
+
+static inline void default_group_changed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default group changed event handler: %d\n", ret);
+}
+
+static inline void default_period_changed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default period changed event handler: %d\n", ret);
+}
+
+static inline void default_pd_created_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default PD created event handler: %d\n", ret);
+}
+
+static inline void default_pd_destroyed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default PD destroyed event handler: %d\n", ret);
+}
+
+static inline void default_lb_size_changed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default LB size changed event handler: %d\n", ret);
+}
+
+static inline __attribute__((always_inline)) struct cb_info *create_cb_info(ret_cb_t cb, void *data)
+{
+       struct cb_info *info;
+
+       info = malloc(sizeof(*info));
+       if (!info) {
+               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       info->cb = cb;
+       info->data = data;
+       return info;
+}
+
+static inline void destroy_cb_info(struct cb_info *info)
+{
+       free(info);
+}
+
+static void resize_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       struct cb_info *info = data;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+       }
+
+       /*!
+        * \note
+        * In case of resize request,
+        * The livebox handler will not have resized value right after this callback,
+        * It can only get the new size when it makes updates.
+        *
+        * So the user can only get the resized value(result) from the first update event
+        * after this request.
+        */
+       if (ret == 0) {
+               DbgPrint("Resize request is done, prepare the size changed event\n");
+               handler->size_changed_cb = cb;
+               handler->size_cbdata = cbdata;
+       } else {
+               DbgPrint("Resize request is failed: %d\n", ret);
+               cb(handler, ret, cbdata);
+       }
+}
+
+static void text_signal_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       void *cbdata;
+       struct cb_info *info = data;
+       ret_cb_t cb;
+
+       cbdata = info->data;
+       cb = info->cb;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+       }
+
+       if (cb)
+               cb(handler, ret, cbdata);
+       return;
+}
+
+static void set_group_ret_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       void *cbdata;
+       ret_cb_t cb;
+       struct cb_info *info = data;
+
+       cbdata = info->data;
+       cb = info->cb;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+       }
+
+       if (ret == 0) { /*!< Group information is successfully changed */
+               handler->group_changed_cb = cb;
+               handler->group_cbdata = cbdata;
+       } else if (cb) {
+               cb(handler, ret, cbdata);
+       }
+
+       return;
+}
+
+static void period_ret_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       struct cb_info *info = data;
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+       }
+
+       if (ret == 0) {
+               handler->period_changed_cb = cb;
+               handler->period_cbdata = cbdata;
+       } else if (cb) {
+               cb(handler, ret, cbdata);
+       }
+}
+
+static void del_ret_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       struct cb_info *info = data;
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ErrPrint("Connection lost?\n");
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+       }
+
+       if (ret == 0) {
+               DbgPrint("Returns %d (waiting deleted event)\n", ret);
+               handler->deleted_cb = cb;
+               handler->deleted_cbdata = cbdata;
+       } else if (cb) {
+               cb(handler, ret, cbdata);
+       }
+
+       /*!
+        * \note
+        * Do not call the deleted callback from here.
+        * master will send the "deleted" event.
+        * Then invoke this callback.
+        *
+        * if (handler->deleted_cb)
+        *      handler->deleted_cb(handler, ret, handler->deleted_cbdata);
+        */
+}
+
+static void new_ret_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       struct cb_info *info = data;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ret = -EINVAL;
+       }
+
+       if (ret >= 0) {
+               DbgPrint("new request is sent, just waiting the created event\n");
+               handler->created_cb = cb;
+               handler->created_cbdata = cbdata;
+
+               /*!
+                * \note
+                * Don't go anymore ;)
+                */
+               return;
+       } else if (cb) {
+               /*!
+                * \note
+                * It means the current instance is not created,
+                * so user has to know about this.
+                * notice it to user using "deleted" event.
+                */
+               cb(handler, ret, cbdata);
+       }
+
+       lb_unref(handler);
+}
+
+static void pd_create_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       struct cb_info *info = data;
+       void *cbdata;
+       ret_cb_t cb;
+       int ret;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(data);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ret = -EINVAL;
+       }
+
+       if (ret == 0) {
+               DbgPrint("PD Created event handler prepared\n");
+               handler->pd_created_cb = cb;
+               handler->pd_created_cbdata = cbdata;
+       } else if (cb) {
+               DbgPrint("Failed to create a PD\n");
+               cb(handler, ret, cbdata);
+       }
+}
+
+static void activated_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       struct cb_info *info = data;
+       void *cbdata;
+       ret_cb_t cb;
+       const char *pkgname = "";
+
+       cbdata = info->data;
+       cb = info->cb;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "is", &ret, &pkgname) != 2) {
+               ret = -EINVAL;
+       }
+
+       if (cb)
+               cb(handler, ret, cbdata);
+}
+
+static void pd_destroy_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+       struct cb_info *info = data;
+
+       cbdata = info->data;
+       cb = info->cb;
+       destroy_cb_info(info);
+
+       if (!result) {
+               DbgPrint("Result is NIL (may connection lost)\n");
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               DbgPrint("Invalid parameter\n");
+               ret = -EINVAL;
+       }
+
+       if (ret == 0) {
+               DbgPrint("PD Destroyed callback prepared\n");
+               handler->pd_destroyed_cb = cb;
+               handler->pd_destroyed_cbdata = cbdata;
+       } else if (cb) {
+               DbgPrint("PD is not desroyed (forcely reset, pd flag)\n");
+               handler->is_pd_created = 0;
+               cb(handler, ret, cbdata);
+       }
+}
+
+static void delete_cluster_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       struct cb_info *info = data;
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result) {
+               ret = -EFAULT;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ret = -EINVAL;
+       }
+
+       DbgPrint("Delete category returns: %d\n", ret);
+
+       if (cb)
+               cb(handler, ret, cbdata);
+}
+
+static void delete_category_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       struct cb_info *info = data;
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result)
+               ret = -EFAULT;
+       else if (packet_get(result, "i", &ret) != 1)
+               ret = -EINVAL;
+
+       DbgPrint("Delete category returns: %d\n", ret);
+
+       if (cb)
+               cb(handler, ret, cbdata);
+}
+
+static void pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+       struct cb_info *info = data;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result)
+               ret = 0; /* PIXMAP 0 means error */
+       else if (packet_get(result, "i", &ret) != 1)
+               ret = 0;
+
+       if (cb)
+               cb(handler, ret, cbdata);
+}
+
+static void pinup_done_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+       ret_cb_t cb;
+       void *cbdata;
+       struct cb_info *info = data;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
+
+       if (!result)
+               ret = -EFAULT;
+       else if (packet_get(result, "i", &ret) != 1)
+               ret = -EINVAL;
+
+       if (ret == 0) {
+               handler->pinup_cb = cb;
+               handler->pinup_cbdata = cbdata;
+       } else if (cb) {
+               cb(handler, ret, cbdata);
+       }
+}
+
+static int send_mouse_event(struct livebox *handler, const char *event, double x, double y, int w, int h)
+{
+       struct packet *packet;
+       double timestamp;
+
+       timestamp = util_timestamp();
+       packet = packet_create_noack(event, "ssiiddd", handler->pkgname, handler->id, w, h,
+                                               timestamp, x, y);
+       if (!packet) {
+               ErrPrint("Failed to build param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(handler, packet);
+}
+
+EAPI int livebox_init(void *disp)
+{
+       const char *env;
+
+       if (s_info.init_count > 0) {
+               s_info.init_count++;
+               return 0;
+       }
+       env = getenv("PROVIDER_DISABLE_PREVENT_OVERWRITE");
+       if (env && !strcasecmp(env, "true"))
+               s_info.prevent_overwrite = 1;
+
+       env = getenv("PROVIDER_EVENT_FILTER");
+       if (env)
+               sscanf(env, "%lf", &MINIMUM_EVENT);
+
+#if defined(FLOG)
+       char filename[BUFSIZ];
+       snprintf(filename, sizeof(filename), "/tmp/%d.box.log", getpid());
+       __file_log_fp = fopen(filename, "w+t");
+       if (!__file_log_fp)
+               __file_log_fp = fdopen(1, "w+t");
+#endif
+       critical_log_init("viewer");
+       livebox_service_init();
+       fb_init(disp);
+
+       client_init();
+
+       s_info.init_count++;
+       return 0;
+}
+
+EAPI int livebox_fini(void)
+{
+       if (s_info.init_count <= 0) {
+               DbgPrint("Didn't initialized\n");
+               return -EINVAL;
+       }
+
+       s_info.init_count--;
+       if (s_info.init_count > 0) {
+               DbgPrint("init count : %d\n", s_info.init_count);
+               return 0;
+       }
+
+       client_fini();
+       fb_fini();
+       livebox_service_fini();
+       critical_log_fini();
+       return 0;
+}
+
+static inline char *lb_pkgname(const char *pkgname)
+{
+       char *lb;
+
+       lb = livebox_service_pkgname(pkgname);
+       if (!lb) {
+               if (util_validate_livebox_package(pkgname) == 0)
+                       return strdup(pkgname);
+       }
+
+       return lb;
+}
+
+/*!
+ * Just wrapping the livebox_add_with_size function.
+ */
+EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const char *cluster, const char *category, double period, ret_cb_t cb, void *data)
+{
+       return livebox_add_with_size(pkgname, content, cluster, category, period, LB_SIZE_TYPE_UNKNOWN, cb, data);
+}
+
+EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *content, const char *cluster, const char *category, double period, int type, ret_cb_t cb, void *data)
+{
+       struct livebox *handler;
+       struct packet *packet;
+       int ret;
+       int width = 0;
+       int height = 0;
+
+       if (!pkgname || !cluster || !category || width < 0 || height < 0) {
+               ErrPrint("Invalid arguments: pkgname[%p], cluster[%p], category[%p]\n",
+                                                               pkgname, cluster, category);
+               return NULL;
+       }
+
+       if (type != LB_SIZE_TYPE_UNKNOWN)
+               livebox_service_get_size(type, &width, &height);
+
+       handler = calloc(1, sizeof(*handler));
+       if (!handler) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       handler->pkgname = lb_pkgname(pkgname);
+       if (!handler->pkgname) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               free(handler);
+               return NULL;
+       }
+
+       if (livebox_service_is_enabled(handler->pkgname) == 0) {
+               DbgPrint("Livebox [%s](%s) is disabled package\n", handler->pkgname, pkgname);
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       if (content) {
+               handler->content = strdup(content);
+               if (!handler->content) {
+                       ErrPrint("Error: %s\n", strerror(errno));
+                       free(handler->pkgname);
+                       free(handler);
+                       return NULL;
+               }
+       } else {
+               handler->content = livebox_service_content(handler->pkgname);
+       }
+
+       handler->cluster = strdup(cluster);
+       if (!handler->cluster) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               free(handler->content);
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       handler->category = strdup(category);
+       if (!handler->category) {
+               ErrPrint("Error: %s\n", strerror(errno));
+               free(handler->cluster);
+               free(handler->content);
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       if (!cb)
+               cb = default_create_cb;
+
+       /* Data provider will set this */
+       handler->lb.type = _LB_TYPE_FILE;
+       handler->pd.type = _PD_TYPE_SCRIPT;
+       handler->lb.period = period;
+
+       /* Used for handling the mouse event on a box */
+       handler->lb.mouse_event = livebox_service_mouse_event(handler->pkgname);
+
+       /* Cluster infomration is not determined yet */
+       handler->nr_of_sizes = 0x01;
+
+       handler->timestamp = util_timestamp();
+       handler->is_user = 1;
+       handler->visible = LB_SHOW;
+
+       s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
+
+       packet = packet_create("new", "dssssdii", handler->timestamp, handler->pkgname, handler->content, cluster, category, period, width, height);
+       if (!packet) {
+               ErrPrint("Failed to create a new packet\n");
+               free(handler->category);
+               free(handler->cluster);
+               free(handler->content);
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       ret = master_rpc_async_request(handler, packet, 0, new_ret_cb, create_cb_info(cb, data));
+       if (ret < 0) {
+               ErrPrint("Failed to send a new packet\n");
+               free(handler->category);
+               free(handler->cluster);
+               free(handler->content);
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       DbgPrint("Successfully sent a new request ([%lf] %s)\n", handler->timestamp, handler->pkgname);
+       handler->state = CREATE;
+       return lb_ref(handler);
+}
+
+EAPI double livebox_period(struct livebox *handler)
+{
+       if (!handler || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return 0.0f;
+       }
+
+       return handler->lb.period;
+}
+
+EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!handler->is_user) {
+               ErrPrint("CA Livebox is not able to change the period\n");
+               return -EPERM;
+       }
+
+       if (handler->lb.period == period) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
+
+       if (handler->period_changed_cb)
+               DbgPrint("Already requested\n");
+
+       packet = packet_create("set_period", "ssd", handler->pkgname, handler->id, period);
+       if (!packet) {
+               ErrPrint("Failed to build a packet %s\n", handler->pkgname);
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_period_changed_cb;
+
+       return master_rpc_async_request(handler, packet, 0, period_ret_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Handler is already deleted\n");
+               return -EINVAL;
+       }
+
+       handler->state = DELETE;
+
+       if (!handler->id) {
+               /*!
+                * \note
+                * The id is not determined yet.
+                * It means a user didn't receive created event yet.
+                * Then just stop to delete procedure from here.
+                * Because the "created" event handler will release this.
+                * By the way, if the user adds any callback for getting return status of this,
+                * call it at here.
+                */
+               if (cb)
+                       cb(handler, 0, data);
+               return 0;
+       }
+
+       if (!cb)
+               cb = default_delete_cb;
+
+       return lb_send_delete(handler, cb, data);
+}
+
+EAPI int livebox_set_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *), void *data)
+{
+       struct fault_info *info;
+
+       if (!cb)
+               return -EINVAL;
+
+       info = malloc(sizeof(*info));
+       if (!info) {
+               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       info->handler = cb;
+       info->user_data = data;
+
+       s_info.fault_list = dlist_append(s_info.fault_list, info);
+       return 0;
+}
+
+EAPI void *livebox_unset_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *))
+{
+       struct fault_info *info;
+       struct dlist *l;
+
+       dlist_foreach(s_info.fault_list, l, info) {
+               if (info->handler == cb) {
+                       void *data;
+                       s_info.fault_list = dlist_remove(s_info.fault_list, l);
+                       data = info->user_data;
+                       free(info);
+
+                       return data;
+               }
+       }
+
+       return NULL;
+}
+
+EAPI int livebox_set_event_handler(int (*cb)(struct livebox *, enum livebox_event_type, void *), void *data)
+{
+       struct event_info *info;
+
+       if (!cb) {
+               ErrPrint("Invalid argument cb is nil\n");
+               return -EINVAL;
+       }
+
+       info = malloc(sizeof(*info));
+       if (!info) {
+               CRITICAL_LOG("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       info->handler = cb;
+       info->user_data = data;
+
+       s_info.event_list = dlist_append(s_info.event_list, info);
+       return 0;
+}
+
+EAPI void *livebox_unset_event_handler(int (*cb)(struct livebox *, enum livebox_event_type, void *))
+{
+       struct event_info *info;
+       struct dlist *l;
+
+       dlist_foreach(s_info.event_list, l, info) {
+               if (info->handler == cb) {
+                       void *data;
+
+                       s_info.event_list = dlist_remove(s_info.event_list, l);
+                       data = info->user_data;
+                       free(info);
+
+                       return data;
+               }
+       }
+
+       return NULL;
+}
+
+EAPI int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+       int w;
+       int h;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!handler->is_user) {
+               ErrPrint("CA Livebox is not able to be resized\n");
+               return -EPERM;
+       }
+
+       if (livebox_service_get_size(type, &w, &h) != 0) {
+               ErrPrint("Invalid size type\n");
+               return -EINVAL;
+       }
+
+       if (handler->lb.width == w && handler->lb.height == h) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
+
+       if (handler->size_changed_cb)
+               DbgPrint("Already pended\n");
+
+       packet = packet_create("resize", "ssii", handler->pkgname, handler->id, w, h);
+       if (!packet) {
+               ErrPrint("Failed to build param\n");
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_lb_size_changed_cb;
+
+       return master_rpc_async_request(handler, packet, 0, resize_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_click(struct livebox *handler, double x, double y)
+{
+       struct packet *packet;
+       double timestamp;
+       int ret;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (handler->lb.auto_launch)
+               if (aul_launch_app(handler->lb.auto_launch, NULL) < 0)
+                       ErrPrint("Failed to launch app %s\n", handler->lb.auto_launch);
+
+       timestamp = util_timestamp();
+       packet = packet_create_noack("clicked", "sssddd", handler->pkgname, handler->id, "clicked", timestamp, x, y);
+       if (!packet) {
+               ErrPrint("Failed to build param\n");
+               return -EFAULT;
+       }
+
+       ret = master_rpc_request_only(handler, packet);
+
+       if (!handler->lb.mouse_event && (handler->lb.type == _LB_TYPE_BUFFER || handler->lb.type == _LB_TYPE_SCRIPT)) {
+               int ret; /* Shadow variable */
+               ret = send_mouse_event(handler, "lb_mouse_down", x, y, handler->lb.width, handler->lb.height);
+               if (ret < 0)
+                       DbgPrint("Failed to send Down: %d\n", ret);
+
+               ret = send_mouse_event(handler, "lb_mouse_move", x, y, handler->lb.width, handler->lb.height);
+               if (ret < 0)
+                       DbgPrint("Failed to send Move: %d\n", ret);
+
+               ret = send_mouse_event(handler, "lb_mouse_up", x, y, handler->lb.width, handler->lb.height);
+               if (ret < 0)
+                       DbgPrint("Failed to send Up: %d\n", ret);
+       }
+
+       return ret;
+}
+
+EAPI int livebox_has_pd(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       return !!handler->pd.data.fb;
+}
+
+EAPI int livebox_pd_is_created(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       return handler->is_pd_created;
+}
+
+EAPI int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       return livebox_create_pd_with_position(handler, -1.0, -1.0, cb, data);
+}
+
+EAPI int livebox_create_pd_with_position(struct livebox *handler, double x, double y, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (handler->is_pd_created == 1) {
+               DbgPrint("PD already created\n");
+               return 0;
+       }
+
+       packet = packet_create("create_pd", "ssdd", handler->pkgname, handler->id, x, y);
+       if (!packet) {
+               ErrPrint("Failed to build param\n");
+               return -EFAULT;
+       }
+
+       if (!cb)
+               handler->pd_created_cb = default_pd_created_cb;
+
+       return master_rpc_async_request(handler, packet, 0, pd_create_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_move_pd(struct livebox *handler, double x, double y)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!handler->is_pd_created) {
+               DbgPrint("PD is not created\n");
+               return -EINVAL;
+       }
+
+       packet = packet_create_noack("pd_move", "ssdd", handler->pkgname, handler->id, x, y);
+       if (!packet) {
+               ErrPrint("Failed to build param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(handler, packet);
+}
+
+EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!pkgname)
+               return -EINVAL;
+
+       packet = packet_create("activate_package", "s", pkgname);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(NULL, packet, 0, activated_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!handler->is_pd_created) {
+               ErrPrint("PD is not created\n");
+               return -EINVAL;
+       }
+
+       packet = packet_create("destroy_pd", "ss", handler->pkgname, handler->id);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_pd_destroyed_cb;
+
+       return master_rpc_async_request(handler, packet, 0, pd_destroy_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y)
+{
+       int w;
+       int h;
+       char cmd[20] = { '\0', };
+       char *ptr = cmd;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (type & CONTENT_EVENT_PD_MASK) {
+               if (!handler->is_pd_created) {
+                       ErrPrint("PD is not created\n");
+                       return -EINVAL;
+               }
+
+               if (type & CONTENT_EVENT_MOUSE_MASK) {
+                       if (!handler->pd.data.fb) {
+                               ErrPrint("Handler is not valid\n");
+                               return -EINVAL;
+                       }
+
+                       if (type & CONTENT_EVENT_MOUSE_MOVE) {
+                               if (fabs(x - handler->pd.x) < MINIMUM_EVENT && fabs(y - handler->pd.y) < MINIMUM_EVENT)
+                                       return -EBUSY;
+                       }
+               }
+
+               w = handler->pd.width;
+               h = handler->pd.height;
+               handler->pd.x = x;
+               handler->pd.y = y;
+               *ptr++ = 'p';
+               *ptr++ = 'd';
+       } else {
+               if (type & CONTENT_EVENT_MOUSE_MASK) {
+                       if (!handler->lb.mouse_event) {
+                               ErrPrint("Box is not support the mouse event\n");
+                               return -EINVAL;
+                       }
+
+                       if (!handler->lb.data.fb) {
+                               ErrPrint("Handler is not valid\n");
+                               return -EINVAL;
+                       }
+
+                       if (type & CONTENT_EVENT_MOUSE_MOVE) {
+                               if (fabs(x - handler->lb.x) < MINIMUM_EVENT && fabs(y - handler->lb.y) < MINIMUM_EVENT)
+                                       return -EBUSY;
+                       }
+               }
+
+               w = handler->lb.width;
+               h = handler->lb.height;
+               handler->lb.x = x;
+               handler->lb.y = y;
+               *ptr++ = 'l';
+               *ptr++ = 'b';
+       }
+
+       switch ((type & ~CONTENT_EVENT_PD_MASK)) {
+       case CONTENT_EVENT_ACCESS_READ | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_read");
+               break;
+       case CONTENT_EVENT_ACCESS_READ_PREV | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_read_prev");
+               break;
+       case CONTENT_EVENT_ACCESS_READ_NEXT | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_read_next");
+               break;
+       case CONTENT_EVENT_ACCESS_ACTIVATE | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_activate");
+               break;
+       case CONTENT_EVENT_ACCESS_UP | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_up");
+               break;
+       case CONTENT_EVENT_ACCESS_DOWN | CONTENT_EVENT_ACCESS_MASK:
+               strcpy(ptr, "_access_down");
+               break;
+       case CONTENT_EVENT_MOUSE_ENTER | CONTENT_EVENT_MOUSE_MASK:
+               strcpy(ptr, "_mouse_enter");
+               break;
+       case CONTENT_EVENT_MOUSE_LEAVE | CONTENT_EVENT_MOUSE_MASK:
+               strcpy(ptr, "_mouse_leave");
+               break;
+       case CONTENT_EVENT_MOUSE_UP | CONTENT_EVENT_MOUSE_MASK:
+               strcpy(ptr, "_mouse_up");
+               break;
+       case CONTENT_EVENT_MOUSE_DOWN | CONTENT_EVENT_MOUSE_MASK:
+               strcpy(ptr, "_mouse_down");
+               break;
+       case CONTENT_EVENT_MOUSE_MOVE | CONTENT_EVENT_MOUSE_MASK:
+               strcpy(ptr, "_mouse_move");
+               break;
+       case CONTENT_EVENT_KEY_DOWN | CONTENT_EVENT_KEY_MASK:
+               strcpy(ptr, "_key_down");
+               break;
+       case CONTENT_EVENT_KEY_UP | CONTENT_EVENT_KEY_MASK:
+               strcpy(ptr, "_key_up");
+               break;
+       default:
+               ErrPrint("Invalid event type\n");
+               return -EINVAL;
+       }
+
+       return send_mouse_event(handler, cmd, x, y, w, h);
+}
+
+EAPI const char *livebox_filename(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return NULL;
+       }
+
+       if (handler->filename)
+               return handler->filename;
+
+       /* Oooops */
+       return util_uri_to_path(handler->id);
+}
+
+EAPI int livebox_get_pdsize(struct livebox *handler, int *w, int *h)
+{
+       int _w;
+       int _h;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!w)
+               w = &_w;
+       if (!h)
+               h = &_h;
+
+       if (!handler->is_pd_created) {
+               DbgPrint("Buffer is not created yet [%dx%d]\n", *w, *h);
+               *w = handler->pd.default_width;
+               *h = handler->pd.default_height;
+       } else {
+               *w = handler->pd.width;
+               *h = handler->pd.height;
+       }
+
+       return 0;
+}
+
+EAPI int livebox_size(struct livebox *handler)
+{
+       int w;
+       int h;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       w = handler->lb.width;
+       h = handler->lb.height;
+
+       switch (handler->lb.type) {
+       case _LB_TYPE_BUFFER:
+       case _LB_TYPE_SCRIPT:
+               if (!fb_is_created(handler->lb.data.fb)) {
+                       DbgPrint("Buffer is not created yet - reset size\n");
+                       w = 0;
+                       h = 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return livebox_service_size_type(w, h);
+}
+
+EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const char *category, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!cluster || !category || handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       if (!handler->is_user) {
+               ErrPrint("CA Livebox is not able to change the group\n");
+               return -EPERM;
+       }
+
+       if (!strcmp(handler->cluster, cluster) && !strcmp(handler->category, category)) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
+
+       if (handler->group_changed_cb)
+               DbgPrint("Already sent\n");
+
+       packet = packet_create("change_group", "ssss", handler->pkgname, handler->id, cluster, category);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_group_changed_cb;
+
+       return master_rpc_async_request(handler, packet, 0, set_group_ret_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (!cluster || !category || handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       *cluster = handler->cluster;
+       *category = handler->category;
+       return 0;
+}
+
+EAPI int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *size_list)
+{
+       register int i;
+       register int j;
+
+       if (!handler || !size_list) {
+               ErrPrint("Invalid argument, handler(%p), size_list(%p)\n", handler, size_list);
+               return -EINVAL;
+       }
+
+       if (!cnt || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       for (j = i = 0; i < NR_OF_SIZE_LIST; i++) {
+               if (handler->lb.size_list & (0x01 << i)) {
+                       if (j == *cnt)
+                               break;
+
+                       size_list[j++] = (0x01 << i);
+               }
+       }
+
+       *cnt = j;
+       return 0;
+}
+
+EAPI const char *livebox_pkgname(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Handler is not valid\n");
+               return NULL;
+       }
+
+       return handler->pkgname;
+}
+
+EAPI double livebox_priority(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return 0.0f;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid (%p)\n", handler);
+               return -1.0f;
+       }
+
+       return handler->lb.priority;
+}
+
+EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       packet = packet_create("delete_cluster", "s", cluster);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(NULL, packet, 0, delete_cluster_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_delete_category(const char *cluster, const char *category, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       packet = packet_create("delete_category", "ss", cluster, category);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(NULL, packet, 0, delete_category_cb, create_cb_info(cb, data));
+}
+
+EAPI enum livebox_lb_type livebox_lb_type(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return LB_TYPE_INVALID;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return LB_TYPE_INVALID;
+       }
+
+       switch (handler->lb.type) {
+       case _LB_TYPE_FILE:
+               return LB_TYPE_IMAGE;
+       case _LB_TYPE_BUFFER:
+       case _LB_TYPE_SCRIPT:
+               {
+                       const char *id;
+                       id = fb_id(handler->lb.data.fb);
+                       if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
+                               return LB_TYPE_PIXMAP;
+               }
+               return LB_TYPE_BUFFER;
+       case _LB_TYPE_TEXT:
+               return LB_TYPE_TEXT;
+       default:
+               break;
+       }
+
+       return LB_TYPE_INVALID;
+}
+
+EAPI enum livebox_pd_type livebox_pd_type(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return PD_TYPE_INVALID;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return PD_TYPE_INVALID;
+       }
+
+       switch (handler->pd.type) {
+       case _PD_TYPE_TEXT:
+               return PD_TYPE_TEXT;
+       case _PD_TYPE_BUFFER:
+       case _PD_TYPE_SCRIPT:
+               {
+                       const char *id;
+                       id = fb_id(handler->pd.data.fb);
+                       if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
+                               return PD_TYPE_PIXMAP;
+               }
+               return PD_TYPE_BUFFER;
+       default:
+               break;
+       }
+
+       return PD_TYPE_INVALID;
+}
+
+EAPI int livebox_set_pd_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       memcpy(&handler->pd.data.ops, ops, sizeof(*ops));
+       return 0;
+}
+
+EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       memcpy(&handler->lb.data.ops, ops, sizeof(*ops));
+       return 0;
+}
+
+EAPI int livebox_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+       const char *id;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return -EINVAL;
+       }
+
+       id = fb_id(handler->lb.data.fb);
+       if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
+               return -EINVAL;
+
+       packet = packet_create("lb_acquire_pixmap", "ss", handler->pkgname, handler->id);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_release_lb_pixmap(struct livebox *handler, int pixmap)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return -EINVAL;
+       }
+
+       packet = packet_create_noack("lb_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(handler, packet);
+}
+
+EAPI int livebox_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+       const char *id;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return -EINVAL;
+       }
+
+       id = fb_id(handler->pd.data.fb);
+       if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
+               return -EINVAL;
+
+       packet = packet_create("pd_acquire_pixmap", "ss", handler->pkgname, handler->id);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_pd_pixmap(const struct livebox *handler)
+{
+       const char *id;
+       int pixmap = 0;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return 0;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handler\n");
+               return 0;
+       }
+
+       if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
+               ErrPrint("Invalid handler\n");
+               return 0;
+       }
+
+       id = fb_id(handler->pd.data.fb);
+       if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) {
+               ErrPrint("PIXMAP Id is not valid\n");
+               return 0;
+       }
+
+       return pixmap;
+}
+
+EAPI int livebox_lb_pixmap(const struct livebox *handler)
+{
+       const char *id;
+       int pixmap = 0;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return 0;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handler\n");
+               return 0;
+       }
+
+       if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
+               ErrPrint("Invalid handler\n");
+               return 0;
+       }
+
+       id = fb_id(handler->lb.data.fb);
+       if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) {
+               ErrPrint("PIXMAP Id is not valid\n");
+               return 0;
+       }
+
+       return pixmap;
+}
+
+EAPI int livebox_release_pd_pixmap(struct livebox *handler, int pixmap)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handle\n");
+               return -EINVAL;
+       }
+
+       if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return -EINVAL;
+       }
+
+       packet = packet_create_noack("pd_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(handler, packet);
+}
+
+EAPI void *livebox_acquire_fb(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handle\n");
+               return NULL;
+       }
+
+       if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return NULL;
+       }
+
+       return fb_acquire_buffer(handler->lb.data.fb);
+}
+
+EAPI int livebox_release_fb(void *buffer)
+{
+       return fb_release_buffer(buffer);
+}
+
+EAPI int livebox_fb_refcnt(void *buffer)
+{
+       return fb_refcnt(buffer);
+}
+
+EAPI void *livebox_acquire_pdfb(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Invalid handler\n");
+               return NULL;
+       }
+
+       if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
+               ErrPrint("Handler is not valid type\n");
+               return NULL;
+       }
+
+       return fb_acquire_buffer(handler->pd.data.fb);
+}
+
+EAPI int livebox_release_pdfb(void *buffer)
+{
+       return fb_release_buffer(buffer);
+}
+
+EAPI int livebox_pdfb_refcnt(void *buffer)
+{
+       return fb_refcnt(buffer);
+}
+
+EAPI int livebox_pdfb_bufsz(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       return fb_size(handler->pd.data.fb);
+}
+
+EAPI int livebox_lbfb_bufsz(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       return fb_size(handler->lb.data.fb);
+}
+
+EAPI int livebox_is_user(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE) {
+               ErrPrint("Handler is invalid\n");
+               return -EINVAL;
+       }
+
+       return handler->is_user;
+}
+
+EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (handler->is_pinned_up == flag) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
+
+       if (handler->pinup_cb)
+               DbgPrint("Already sent\n");
+
+       packet = packet_create("pinup_changed", "ssi", handler->pkgname, handler->id, flag);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_pinup_cb;
+
+       return master_rpc_async_request(handler, packet, 0, pinup_done_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_is_pinned_up(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id)
+               return -EINVAL;
+
+       return handler->is_pinned_up;
+}
+
+EAPI int livebox_has_pinup(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id)
+               return -EINVAL;
+
+       return handler->lb.pinup_supported;
+}
+
+EAPI int livebox_set_data(struct livebox *handler, void *data)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE)
+               return -EINVAL;
+
+       handler->data = data;
+       return 0;
+}
+
+EAPI void *livebox_get_data(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE)
+               return NULL;
+
+       return handler->data;
+}
+
+EAPI int livebox_is_exists(const char *pkgname)
+{
+       char *lb;
+
+       lb = lb_pkgname(pkgname);
+       if (lb) {
+               free(lb);
+               return 1;
+       }
+
+       return 0;
+}
+
+EAPI const char *livebox_content(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE)
+               return NULL;
+
+       return handler->content;
+}
+
+EAPI const char *livebox_category_title(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return NULL;
+       }
+
+       if (handler->state != CREATE)
+               return NULL;
+
+       return handler->title;
+}
+
+EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission, const char *source, double sx, double sy, double ex, double ey, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if ((handler->lb.type != _LB_TYPE_TEXT && handler->pd.type != _PD_TYPE_TEXT) || handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return -EINVAL;
+       }
+
+       if (!emission)
+               emission = "";
+
+       if (!source)
+               source = "";
+
+       packet = packet_create("text_signal", "ssssdddd",
+                               handler->pkgname, handler->id, emission, source, sx, sy, ex, ey);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_async_request(handler, packet, 0, text_signal_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_subscribe_group(const char *cluster, const char *category)
+{
+       struct packet *packet;
+
+       /*!
+        * \TODO
+        * Validate the group info using DB
+        * If the group info is not valid, do not send this request
+        */
+
+       packet = packet_create_noack("subscribe", "ss", cluster ? cluster : "", category ? category : "");
+       if (!packet) {
+               ErrPrint("Failed to create a packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(NULL, packet);
+}
+
+EAPI int livebox_unsubscribe_group(const char *cluster, const char *category)
+{
+       struct packet *packet;
+
+       /*!
+        * \TODO
+        * Validate the group info using DB
+        * If the group info is not valid, do not send this request
+        * AND Check the subscribed or not too
+        */
+
+       packet = packet_create_noack("unsubscribe", "ss", cluster ? cluster : "", category ? category : "");
+       if (!packet) {
+               ErrPrint("Failed to create a packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(NULL, packet);
+}
+
+EAPI int livebox_refresh(struct livebox *handler)
+{
+       struct packet *packet;
+
+       if (!handler) {
+               ErrPrint("Hnalder is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id)
+               return -EINVAL;
+
+       packet = packet_create_noack("update", "ss", handler->pkgname, handler->id);
+       if (!packet) {
+               ErrPrint("Failed to create a packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(handler, packet);
+}
+
+EAPI int livebox_refresh_group(const char *cluster, const char *category)
+{
+       struct packet *packet;
+
+       if (!cluster || !category) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       packet = packet_create_noack("refresh_group", "ss", cluster, category);
+       if (!packet) {
+               ErrPrint("Failed to create a packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(NULL, packet);
+}
+
+EAPI int livebox_set_visibility(struct livebox *handler, enum livebox_visible_state state)
+{
+       struct packet *packet;
+       int ret;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return -EINVAL;
+       }
+
+       if (handler->state != CREATE || !handler->id)
+               return -EINVAL;
+
+       if (!handler->is_user) {
+               /* System cluster livebox cannot be changed its visible states */
+               if (state == LB_HIDE_WITH_PAUSE) {
+                       ErrPrint("CA Livebox is not able to change the visibility\n");
+                       return -EPERM;
+               }
+       }
+
+       if (handler->visible == state)
+               return 0;
+
+       packet = packet_create_noack("change,visibility", "ssi", handler->pkgname, handler->id, (int)state);
+       if (!packet) {
+               ErrPrint("Failed to create a packet\n");
+               return -EFAULT;
+       }
+
+       ret = master_rpc_request_only(handler, packet);
+       if (ret == 0)
+               handler->visible = state;
+
+       return ret;
+}
+
+EAPI enum livebox_visible_state livebox_visibility(struct livebox *handler)
+{
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return LB_VISIBLE_ERROR;
+       }
+
+       if (handler->state != CREATE)
+               return LB_VISIBLE_ERROR;
+
+       return handler->visible;
+}
+
+int lb_set_group(struct livebox *handler, const char *cluster, const char *category)
+{
+       void *pc = NULL;
+       void *ps = NULL;
+
+       if (cluster) {
+               pc = strdup(cluster);
+               if (!pc) {
+                       CRITICAL_LOG("Heap: %s (cluster: %s)\n", strerror(errno), cluster);
+                       return -ENOMEM;
+               }
+       }
+
+       if (category) {
+               ps = strdup(category);
+               if (!ps) {
+                       CRITICAL_LOG("Heap: %s (category: %s)\n", strerror(errno), category);
+                       free(pc);
+                       return -ENOMEM;
+               }
+       }
+
+       if (handler->cluster)
+               free(handler->cluster);
+
+       if (handler->category)
+               free(handler->category);
+
+       handler->cluster = pc;
+       handler->category = ps;
+
+       return 0;
+}
+
+void lb_set_size(struct livebox *handler, int w, int h)
+{
+       handler->lb.width = w;
+       handler->lb.height = h;
+}
+
+void lb_set_pdsize(struct livebox *handler, int w, int h)
+{
+       handler->pd.width = w;
+       handler->pd.height = h;
+}
+
+void lb_set_default_pdsize(struct livebox *handler, int w, int h)
+{
+       handler->pd.default_width = w;
+       handler->pd.default_height = h;
+}
+
+void lb_invoke_fault_handler(enum livebox_fault_type event, const char *pkgname, const char *file, const char *func)
+{
+       struct dlist *l;
+       struct dlist *n;
+       struct fault_info *info;
+
+       dlist_foreach_safe(s_info.fault_list, l, n, info) {
+               if (info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE)
+                       s_info.fault_list = dlist_remove(s_info.fault_list, l);
+       }
+}
+
+void lb_invoke_event_handler(struct livebox *handler, enum livebox_event_type event)
+{
+       struct dlist *l;
+       struct dlist *n;
+       struct event_info *info;
+
+       dlist_foreach_safe(s_info.event_list, l, n, info) {
+               if (info->handler(handler, event, info->user_data) == EXIT_FAILURE)
+                       s_info.event_list = dlist_remove(s_info.event_list, l);
+       }
+}
+
+struct livebox *lb_find_livebox(const char *pkgname, const char *id)
+{
+       struct dlist *l;
+       struct livebox *handler;
+
+       dlist_foreach(s_info.livebox_list, l, handler) {
+               if (!handler->id)
+                       continue;
+
+               if (!strcmp(handler->pkgname, pkgname) && !strcmp(handler->id, id))
+                       return handler;
+       }
+
+       return NULL;
+}
+
+struct livebox *lb_find_livebox_by_timestamp(double timestamp)
+{
+       struct dlist *l;
+       struct livebox *handler;
+
+       dlist_foreach(s_info.livebox_list, l, handler) {
+               if (handler->timestamp == timestamp)
+                       return handler;
+       }
+
+       return NULL;
+}
+
+static inline char *get_file_kept_in_safe(const char *id)
+{
+       const char *path;
+       char *new_path;
+       int len;
+       int base_idx;
+
+       path = util_uri_to_path(id);
+       if (!path) {
+               ErrPrint("Invalid URI(%s)\n", id);
+               return NULL;
+       }
+
+       /*!
+        * \TODO: REMOVE ME
+        */
+       if (s_info.prevent_overwrite) {
+               new_path = strdup(path);
+               if (!new_path)
+                       ErrPrint("Heap: %s\n", strerror(errno));
+
+               return new_path;
+       }
+
+
+       len = strlen(path);
+       base_idx = len - 1;
+
+       while (base_idx > 0 && path[base_idx] != '/') base_idx--;
+       base_idx += (path[base_idx] == '/');
+
+       new_path = malloc(len + 10);
+       if (!new_path) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       strncpy(new_path, path, base_idx);
+       snprintf(new_path + base_idx, len + 10 - base_idx, "reader/%s", path + base_idx);
+       return new_path;
+}
+
+struct livebox *lb_new_livebox(const char *pkgname, const char *id, double timestamp)
+{
+       struct livebox *handler;
+
+       handler = calloc(1, sizeof(*handler));
+       if (!handler) {
+               ErrPrint("Failed to create a new livebox\n");
+               return NULL;
+       }
+
+       handler->pkgname = strdup(pkgname);
+       if (!handler->pkgname) {
+               ErrPrint("%s\n", strerror(errno));
+               free(handler);
+               return NULL;
+       }
+
+       handler->id = strdup(id);
+       if (!handler->id) {
+               ErrPrint("%s\n", strerror(errno));
+               free(handler->pkgname);
+               free(handler);
+               return NULL;
+       }
+
+       handler->filename = get_file_kept_in_safe(id);
+       if (!handler->filename) {
+               handler->filename = strdup(util_uri_to_path(id));
+               if (!handler->filename)
+                       ErrPrint("Error: %s\n", strerror(errno));
+       }
+
+       handler->timestamp = timestamp;
+       handler->lb.type = _LB_TYPE_FILE;
+       handler->pd.type = _PD_TYPE_SCRIPT;
+       handler->state = CREATE;
+       handler->visible = LB_SHOW;
+
+       s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
+       lb_ref(handler);
+       return handler;
+}
+
+int lb_delete_all(void)
+{
+       struct dlist *l;
+       struct dlist *n;
+       struct livebox *handler;
+
+       dlist_foreach_safe(s_info.livebox_list, l, n, handler) {
+               lb_invoke_event_handler(handler, LB_EVENT_DELETED);
+               lb_unref(handler);
+       }
+
+       return 0;
+}
+
+int lb_set_content(struct livebox *handler, const char *content)
+{
+       if (handler->content) {
+               free(handler->content);
+               handler->content = NULL;
+       }
+
+       if (content) {
+               handler->content = strdup(content);
+               if (!handler->content) {
+                       CRITICAL_LOG("Heap: %s (content: %s)\n", strerror(errno), content);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+int lb_set_title(struct livebox *handler, const char *title)
+{
+       if (handler->title) {
+               free(handler->title);
+               handler->title = NULL;
+       }
+
+       if (title) {
+               handler->title = strdup(title);
+               if (!handler->title) {
+                       CRITICAL_LOG("Heap: %s (title: %s)\n", strerror(errno), title);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+void lb_set_size_list(struct livebox *handler, int size_list)
+{
+       handler->lb.size_list = size_list;
+}
+
+void lb_set_auto_launch(struct livebox *handler, const char *auto_launch)
+{
+       if (!strlen(auto_launch))
+               return;
+
+       handler->lb.auto_launch = strdup(auto_launch);
+       if (!handler->lb.auto_launch)
+               ErrPrint("Heap: %s\n", strerror(errno));
+}
+
+void lb_set_priority(struct livebox *handler, double priority)
+{
+       handler->lb.priority = priority;
+}
+
+void lb_set_id(struct livebox *handler, const char *id)
+{
+       if (handler->id)
+               free(handler->id);
+
+       handler->id = strdup(id);
+       if (!handler->id)
+               ErrPrint("Error: %s\n", strerror(errno));
+
+       if (handler->filename)
+               free(handler->filename);
+
+       handler->filename = get_file_kept_in_safe(id);
+       if (!handler->filename) {
+               handler->filename = strdup(util_uri_to_path(id));
+               if (!handler->filename)
+                       ErrPrint("Error: %s\n", strerror(errno));
+       }
+}
+
+int lb_set_lb_fb(struct livebox *handler, const char *filename)
+{
+       struct fb_info *fb;
+
+       if (!handler)
+               return -EINVAL;
+
+       fb = handler->lb.data.fb;
+       if (fb && !strcmp(fb_id(fb), filename)) /*!< BUFFER is not changed, */
+               return 0;
+
+       handler->lb.data.fb = NULL;
+
+       if (!filename || filename[0] == '\0') {
+               if (fb)
+                       fb_destroy(fb);
+               return 0;
+       }
+
+       handler->lb.data.fb = fb_create(filename, handler->lb.width, handler->lb.height);
+       if (!handler->lb.data.fb) {
+               ErrPrint("Faield to create a FB\n");
+               if (fb)
+                       fb_destroy(fb);
+               return -EFAULT;
+       }
+
+       if (fb)
+               fb_destroy(fb);
+
+       return 0;
+}
+
+int lb_set_pd_fb(struct livebox *handler, const char *filename)
+{
+       struct fb_info *fb;
+
+       if (!handler)
+               return -EINVAL;
+
+       fb = handler->pd.data.fb;
+       if (fb && !strcmp(fb_id(fb), filename)) {
+               /* BUFFER is not changed, just update the content */
+               return -EEXIST;
+       }
+       handler->pd.data.fb = NULL;
+
+       if (!filename || filename[0] == '\0') {
+               if (fb)
+                       fb_destroy(fb);
+               return 0;
+       }
+
+       handler->pd.data.fb = fb_create(filename, handler->pd.width, handler->pd.height);
+       if (!handler->pd.data.fb) {
+               ErrPrint("Failed to create a FB\n");
+               if (fb)
+                       fb_destroy(fb);
+               return -EFAULT;
+       }
+
+       if (fb)
+               fb_destroy(fb);
+       return 0;
+}
+
+struct fb_info *lb_get_lb_fb(struct livebox *handler)
+{
+       return handler->lb.data.fb;
+}
+
+struct fb_info *lb_get_pd_fb(struct livebox *handler)
+{
+       return handler->pd.data.fb;
+}
+
+void lb_set_user(struct livebox *handler, int user)
+{
+       handler->is_user = user;
+}
+
+void lb_set_pinup(struct livebox *handler, int pinup_supported)
+{
+       handler->lb.pinup_supported = pinup_supported;
+}
+
+void lb_set_text_lb(struct livebox *handler)
+{
+       handler->lb.type = _LB_TYPE_TEXT;
+}
+
+void lb_set_text_pd(struct livebox *handler)
+{
+       handler->pd.type = _PD_TYPE_TEXT;
+}
+
+int lb_text_lb(struct livebox *handler)
+{
+       return handler->lb.type == _LB_TYPE_TEXT;
+}
+
+int lb_text_pd(struct livebox *handler)
+{
+       return handler->pd.type == _PD_TYPE_TEXT;
+}
+
+void lb_set_period(struct livebox *handler, double period)
+{
+       handler->lb.period = period;
+}
+
+struct livebox *lb_ref(struct livebox *handler)
+{
+       if (!handler)
+               return NULL;
+
+       handler->refcnt++;
+       return handler;
+}
+
+struct livebox *lb_unref(struct livebox *handler)
+{
+       if (!handler)
+               return NULL;
+
+       handler->refcnt--;
+       if (handler->refcnt > 0)
+               return handler;
+
+       dlist_remove_data(s_info.livebox_list, handler);
+
+       handler->state = DESTROYED;
+       free(handler->cluster);
+       free(handler->category);
+       free(handler->id);
+       free(handler->pkgname);
+       free(handler->filename);
+       free(handler->lb.auto_launch);
+
+       if (handler->lb.data.fb) {
+               fb_destroy(handler->lb.data.fb);
+               handler->lb.data.fb = NULL;
+       }
+
+       if (handler->pd.data.fb) {
+               fb_destroy(handler->pd.data.fb);
+               handler->pd.data.fb = NULL;
+       }
+
+       free(handler);
+       return NULL;
+}
+
+int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data)
+{
+       struct packet *packet;
+
+       if (!cb && !!data) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       if (handler->deleted_cb) {
+               ErrPrint("Already in-progress\n");
+               return -EINPROGRESS;
+       }
+
+       packet = packet_create("delete", "ss", handler->pkgname, handler->id);
+       if (!packet) {
+               ErrPrint("Failed to build a param\n");
+               if (cb)
+                       cb(handler, -EFAULT, data);
+
+               return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_delete_cb;
+
+       return master_rpc_async_request(handler, packet, 0, del_ret_cb, create_cb_info(cb, data));
+}
+
+EAPI int livebox_client_paused(void)
+{
+       struct packet *packet;
+
+       packet = packet_create_noack("client_paused", "d", util_timestamp());
+       if (!packet) {
+               ErrPrint("Failed to create a pause packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(NULL, packet);
+}
+
+EAPI int livebox_client_resumed(void)
+{
+       struct packet *packet;
+
+       packet = packet_create_noack("client_resumed", "d", util_timestamp());
+       if (!packet) {
+               ErrPrint("Failed to create a resume packet\n");
+               return -EFAULT;
+       }
+
+       return master_rpc_request_only(NULL, packet);
+}
+
+/* End of a file */
diff --git a/src/master_rpc.c b/src/master_rpc.c
new file mode 100644 (file)
index 0000000..d3b68e1
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <gio/gio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dlog.h>
+
+#include <packet.h>
+#include <com-core_packet.h>
+
+#include "debug.h"
+#include "dlist.h"
+#include "livebox.h"
+#include "livebox_internal.h"
+#include "master_rpc.h"
+#include "client.h"
+#include "util.h"
+
+#define DEFAULT_TTL 10
+#define REQUEST_DELAY 10
+
+struct command {
+       int ttl;
+       struct packet *packet;
+       struct livebox *handler;
+       void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data);
+       void *data;
+       enum {
+               TYPE_ACK,
+               TYPE_NOACK,
+       } type;
+};
+
+int errno;
+
+static struct {
+       guint cmd_timer;
+       struct dlist *cmd_list;
+} s_info = {
+       .cmd_timer = 0,
+       .cmd_list = NULL,
+};
+
+static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data);
+
+static inline struct command *pop_command(void)
+{
+       struct dlist *l;
+       struct command *command;
+
+       l = dlist_nth(s_info.cmd_list, 0);
+       if (!l)
+               return NULL;
+
+       command = dlist_data(l);
+       s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
+       return command;
+}
+
+static inline struct command *create_command(struct livebox *handler, struct packet *packet)
+{
+       struct command *command;
+
+       command = malloc(sizeof(*command));
+       if (!command) {
+               ErrPrint("Failed to allocate mem for command\n");
+               return NULL;
+       }
+
+       command->handler = lb_ref(handler);
+       command->packet = packet_ref(packet);
+       return command;
+}
+
+static inline void destroy_command(struct command *command)
+{
+       packet_unref(command->packet);
+       lb_unref(command->handler);
+       free(command);
+}
+
+static gboolean cmd_consumer(gpointer user_data)
+{
+       struct command *command;
+
+       command = pop_command();
+       if (!command) {
+               s_info.cmd_timer = 0;
+               return FALSE;
+       }
+
+       /*!
+        * \NOTE:
+        * Item will be deleted in the "done_cb"
+        *
+        * item->param be release by the g_dbus_proxy_call
+        * so to use it again from the done_cb function,
+        * increate the reference counter of the item->param
+        */
+       if (command->type == TYPE_NOACK) {
+               if (com_core_packet_send_only(client_fd(), command->packet) < 0)
+                       ErrPrint("Failed to send a packet to master\n");
+
+               destroy_command(command);
+       } else {
+               if (com_core_packet_async_send(client_fd(), command->packet, 0u, done_cb, command) < 0) {
+                       DbgPrint("Failed to send a packet to master\n");
+                       if (command->ret_cb)
+                               command->ret_cb(command->handler, NULL, command->data);
+                       destroy_command(command);
+               }
+       }
+       return TRUE;
+}
+
+static inline void prepend_command(struct command *command)
+{
+       s_info.cmd_list = dlist_prepend(s_info.cmd_list, command);
+       master_rpc_check_and_fire_consumer();
+}
+
+void master_rpc_check_and_fire_consumer(void)
+{
+       if (!s_info.cmd_list || s_info.cmd_timer || client_fd() < 0)
+               return;
+
+       s_info.cmd_timer = g_timeout_add(REQUEST_DELAY, cmd_consumer, NULL);
+       if (!s_info.cmd_timer)
+               ErrPrint("Failed to add timer\n");
+}
+
+static int done_cb(pid_t pid, int handle, const struct packet *packet, void *data)
+{
+       struct command *command;
+       int ret;
+
+       command = data;
+
+       if (!packet) {
+               /*! \NOTE:
+                * Release resource even if
+                * we failed to finish the method call
+                */
+               command->ttl--;
+               if (command->ttl > 0) {
+                       prepend_command(command);
+                       return 0;
+               }
+
+               goto out;
+       }
+
+       if (packet_get(packet, "i", &ret) != 1) {
+               ErrPrint("Invalid result packet\n");
+               ret = -EINVAL;
+       }
+
+       DbgPrint("[%s] Returns: %d\n", packet_command(packet), ret);
+
+out:
+       if (command->ret_cb)
+               command->ret_cb(command->handler, packet, command->data);
+
+       destroy_command(command);
+       return 0;
+}
+
+static inline void push_command(struct command *command)
+{
+       s_info.cmd_list = dlist_append(s_info.cmd_list, command);
+       master_rpc_check_and_fire_consumer();
+}
+
+/*!
+ * \note
+ * "handler" could be NULL
+ */
+int master_rpc_async_request(struct livebox *handler, struct packet *packet, int urgent, void (*ret_cb)(struct livebox *handler, const struct packet *result, void *data), void *data)
+{
+       struct command *command;
+
+       command = create_command(handler, packet);
+       if (!command) {
+               ErrPrint("Failed to create a command\n");
+               if (ret_cb)
+                       ret_cb(handler, NULL, data);
+
+               packet_unref(packet);
+               return -EFAULT;
+       }
+
+       command->ret_cb = ret_cb;
+       command->data = data;
+       command->ttl = DEFAULT_TTL;
+       command->type = TYPE_ACK;
+
+       if (urgent)
+               prepend_command(command);
+       else
+               push_command(command);
+
+       packet_unref(packet);
+       return 0;
+}
+
+int master_rpc_request_only(struct livebox *handler, struct packet *packet)
+{
+       struct command *command;
+
+       command = create_command(handler, packet);
+       if (!command) {
+               ErrPrint("Failed to create a command\n");
+               packet_unref(packet);
+               return -EFAULT;
+       }
+
+       command->ret_cb = NULL;
+       command->data = NULL;
+       command->ttl = 0;
+       command->type = TYPE_NOACK;
+
+       push_command(command);
+       packet_unref(packet);
+       return 0;
+}
+
+int master_rpc_clear_fault_package(const char *pkgname)
+{
+       struct dlist *l;
+       struct dlist *n;
+       struct command *command;
+
+       if (!pkgname)
+               return -EINVAL;
+
+       DbgPrint("Clear requests of the fault package(%s)\n", pkgname);
+
+       dlist_foreach_safe(s_info.cmd_list, l, n, command) {
+               if (!command->handler)
+                       continue;
+
+               if (!strcmp(command->handler->pkgname, pkgname)) {
+                       s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
+                       if (command->ret_cb)
+                               command->ret_cb(command->handler, NULL, command->data);
+
+                       destroy_command(command);
+               }
+       }
+
+       return 0;
+}
+
+int master_rpc_clear_all_request(void)
+{
+       struct command *command;
+       struct dlist *l;
+       struct dlist *n;
+
+       DbgPrint("Clear all pended requests\n");
+
+       dlist_foreach_safe(s_info.cmd_list, l, n, command) {
+               s_info.cmd_list = dlist_remove(s_info.cmd_list, l);
+
+               if (command->ret_cb)
+                       command->ret_cb(command->handler, NULL, command->data);
+
+               destroy_command(command);
+       }
+
+       return 0;
+}
+
+int master_rpc_sync_request(struct packet *packet)
+{
+       struct packet *result;
+       int ret;
+
+       result = com_core_packet_oneshot_send(client_addr(), packet, 0.0f);
+       if (result) {
+               if (packet_get(result, "i", &ret) != 1) {
+                       ErrPrint("Invalid result packet\n");
+                       ret = -EINVAL;
+               }
+
+               packet_unref(result);
+       } else {
+               ErrPrint("Failed to send a sync request\n");
+               ret = -EFAULT;
+       }
+
+       packet_unref(packet);
+       return ret;
+}
+
+/* End of a file */
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..a62a7d0
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2012  Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <dlog.h>
+
+#include "debug.h"
+#include "util.h"
+
+int errno;
+
+int util_check_extension(const char *filename, const char *check_ptr)
+{
+       int name_len;
+
+       name_len = strlen(filename);
+       while (--name_len >= 0 && *check_ptr) {
+               if (filename[name_len] != *check_ptr)
+                       return -EINVAL;
+
+               check_ptr ++;
+       }
+
+       return 0;
+}
+
+double util_timestamp(void)
+{
+       struct timeval tv;
+
+       gettimeofday(&tv, NULL);
+
+       return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
+}
+
+const char *util_basename(const char *name)
+{
+       int length;
+       length = name ? strlen(name) : 0;
+       if (!length)
+               return ".";
+
+       while (--length > 0 && name[length] != '/');
+
+       return length <= 0 ? name : name + length + (name[length] == '/');
+}
+
+static inline int check_native_livebox(const char *pkgname)
+{
+       int len;
+       char *path;
+
+       len = strlen(pkgname) * 2;
+       len += strlen("/opt/usr/live/%s/libexec/liblive-%s.so");
+
+       path = malloc(len + 1);
+       if (!path) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       snprintf(path, len, "/opt/usr/live/%s/libexec/liblive-%s.so", pkgname, pkgname);
+       if (access(path, F_OK | R_OK) != 0) {
+               ErrPrint("%s is not a valid package\n", pkgname);
+               free(path);
+               return -EINVAL;
+       }
+
+       free(path);
+       return 0;
+}
+
+static inline int check_web_livebox(const char *pkgname)
+{
+       int len;
+       char *path;
+
+       len = strlen(pkgname) * 2;
+       len += strlen("/opt/usr/apps/%s/res/wgt/livebox/index.html");
+
+       path = malloc(len + 1);
+       if (!path) {
+               ErrPrint("Heap: %s\n", strerror(errno));
+               return -ENOMEM;
+       }
+
+       snprintf(path, len, "/opt/usr/apps/%s/res/wgt/livebox/index.html", pkgname);
+       if (access(path, F_OK | R_OK) != 0) {
+               ErrPrint("%s is not a valid package\n", pkgname);
+               free(path);
+               return -EINVAL;
+       }
+
+       free(path);
+       return 0;
+}
+
+int util_validate_livebox_package(const char *pkgname)
+{
+       if (!pkgname) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       if (!check_native_livebox(pkgname) || !check_web_livebox(pkgname))
+               return 0;
+
+       return -EINVAL;
+}
+
+const char *util_uri_to_path(const char *uri)
+{
+       int len;
+
+       len = strlen(SCHEMA_FILE);
+       if (strncasecmp(uri, SCHEMA_FILE, len))
+               return NULL;
+
+       return uri + len;
+}
+
+/* End of a file */