From 110215ad40cd0c24ed5ae70430e45304d5c60fe1 Mon Sep 17 00:00:00 2001 From: zheng_wenlong Date: Wed, 14 Nov 2018 12:49:40 +0900 Subject: Add waltham server for horizontal mode. Add waltham server for horizontal mode. This application is used for receive video from waltham transmitter. Change-Id: I794abf014eb014a4f0b42175093bf5c898e261f5 Signed-off-by: zheng_wenlong --- demo3/README.md | 3 +- demo3/horizontal/waltham-server/CMakeLists.txt | 111 ++ demo3/horizontal/waltham-server/README.md | 71 ++ .../horizontal/waltham-server/config/pipeline.cfg | 1 + demo3/horizontal/waltham-server/include/bitmap.h | 35 + .../horizontal/waltham-server/include/hmi-debug.h | 70 ++ .../waltham-server/include/os-compatibility.h | 58 + .../include/wth-server-waltham-comm.h | 524 ++++++++ .../waltham-server/include/wth-server-weston.h | 99 ++ .../horizontal/waltham-server/orig/CMakeLists.txt | 93 ++ demo3/horizontal/waltham-server/orig/README | 76 ++ .../waltham-server/orig/include/bitmap.h | 35 + .../waltham-server/orig/include/os-compatibility.h | 58 + .../orig/include/wth-server-waltham-comm.h | 524 ++++++++ .../orig/include/wth-server-weston.h | 99 ++ .../orig/protocol/ivi-application.xml | 100 ++ .../waltham-server/orig/src/utils/bitmap.c | 107 ++ .../orig/src/utils/os-compatibility.c | 204 +++ .../waltham-server/orig/src/wth-server-gst.c | 1151 +++++++++++++++++ .../waltham-server/orig/src/wth-server-main.c | 344 +++++ .../orig/src/wth-server-waltham-comm.c | 1179 +++++++++++++++++ .../waltham-server/orig/src/wth-server-weston.c | 811 ++++++++++++ .../waltham-server/package/receiver/config.xml | 17 + .../waltham-server/package/receiver/icon.svg | 279 ++++ .../waltham-server/package/root/config.xml | 17 + .../waltham-server/package/root/icon.svg | 279 ++++ .../waltham-server/protocol/ivi-application.xml | 100 ++ .../waltham-server/screenshot/waltham-server.png | Bin 0 -> 293268 bytes demo3/horizontal/waltham-server/src/utils/bitmap.c | 107 ++ .../waltham-server/src/utils/os-compatibility.c | 204 +++ .../waltham-server/src/wth-server-gst.cpp | 1326 ++++++++++++++++++++ .../waltham-server/src/wth-server-main.cpp | 372 ++++++ .../waltham-server/src/wth-server-waltham-comm.cpp | 1202 ++++++++++++++++++ .../waltham-server/src/wth-server-weston.c | 811 ++++++++++++ 34 files changed, 10466 insertions(+), 1 deletion(-) create mode 100644 demo3/horizontal/waltham-server/CMakeLists.txt create mode 100644 demo3/horizontal/waltham-server/README.md create mode 100644 demo3/horizontal/waltham-server/config/pipeline.cfg create mode 100644 demo3/horizontal/waltham-server/include/bitmap.h create mode 100644 demo3/horizontal/waltham-server/include/hmi-debug.h create mode 100644 demo3/horizontal/waltham-server/include/os-compatibility.h create mode 100644 demo3/horizontal/waltham-server/include/wth-server-waltham-comm.h create mode 100644 demo3/horizontal/waltham-server/include/wth-server-weston.h create mode 100644 demo3/horizontal/waltham-server/orig/CMakeLists.txt create mode 100644 demo3/horizontal/waltham-server/orig/README create mode 100644 demo3/horizontal/waltham-server/orig/include/bitmap.h create mode 100644 demo3/horizontal/waltham-server/orig/include/os-compatibility.h create mode 100644 demo3/horizontal/waltham-server/orig/include/wth-server-waltham-comm.h create mode 100644 demo3/horizontal/waltham-server/orig/include/wth-server-weston.h create mode 100644 demo3/horizontal/waltham-server/orig/protocol/ivi-application.xml create mode 100644 demo3/horizontal/waltham-server/orig/src/utils/bitmap.c create mode 100644 demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-gst.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-main.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c create mode 100644 demo3/horizontal/waltham-server/orig/src/wth-server-weston.c create mode 100644 demo3/horizontal/waltham-server/package/receiver/config.xml create mode 100644 demo3/horizontal/waltham-server/package/receiver/icon.svg create mode 100644 demo3/horizontal/waltham-server/package/root/config.xml create mode 100644 demo3/horizontal/waltham-server/package/root/icon.svg create mode 100644 demo3/horizontal/waltham-server/protocol/ivi-application.xml create mode 100644 demo3/horizontal/waltham-server/screenshot/waltham-server.png create mode 100644 demo3/horizontal/waltham-server/src/utils/bitmap.c create mode 100644 demo3/horizontal/waltham-server/src/utils/os-compatibility.c create mode 100644 demo3/horizontal/waltham-server/src/wth-server-gst.cpp create mode 100644 demo3/horizontal/waltham-server/src/wth-server-main.cpp create mode 100644 demo3/horizontal/waltham-server/src/wth-server-waltham-comm.cpp create mode 100644 demo3/horizontal/waltham-server/src/wth-server-weston.c diff --git a/demo3/README.md b/demo3/README.md index 096098a..3727f9a 100644 --- a/demo3/README.md +++ b/demo3/README.md @@ -16,7 +16,8 @@
sandbox branch : [ces2019_horizontal](https://gerrit.automotivelinux.org/gerrit/gitweb?p=apps%2Fals-meter-demo.git;a=shortlog;h=refs%2Fheads%2Fsandbox%2Fzheng_wenlong%2Fces2019_horizontal) - camapp
sandbox branch : [camapp](https://gerrit.automotivelinux.org/gerrit/gitweb?p=apps%2Fals-meter-demo.git;a=shortlog;h=refs%2Fheads%2Fsandbox%2Fzheng_wenlong%2Fcamapp) -- ... +- waltham-server +
Used for receive video from waltham transmitter. Needs waltham weston. ## vertical (IVI mode) - homescreen
sandbox branch : [ces2019_vertical](https://gerrit.automotivelinux.org/gerrit/gitweb?p=apps%2Fhomescreen.git;a=shortlog;h=refs%2Fheads%2Fsandbox%2Fzheng_wenlong%2Fces2019_vertical) diff --git a/demo3/horizontal/waltham-server/CMakeLists.txt b/demo3/horizontal/waltham-server/CMakeLists.txt new file mode 100644 index 0000000..2f8d74e --- /dev/null +++ b/demo3/horizontal/waltham-server/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required( VERSION 2.8.5 ) + +project (waltham-server) + +set(CMAKE_CXX_FLAGS "-Wall -fpermissive") + +find_package(PkgConfig) +find_package (Threads) +pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED) +pkg_check_modules(WAYLAND_CURSOR wayland-cursor REQUIRED) +pkg_check_modules(WALTHAM waltham REQUIRED) +pkg_check_modules(GLESv2 glesv2 REQUIRED) +pkg_check_modules(WAYLAND_EGL wayland-egl REQUIRED) +pkg_search_module(EGL egl required) +pkg_search_module(GSTREAMER gstreamer-1.0 required) +pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required) +pkg_search_module(DRM libdrm required) + +find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) +find_library(GST_ALLOCATOR NAMES gstallocators-1.0 PATHs /usr/lib64) +find_library(GST_VIDEO NAMES gstvideo-1.0 PATHs /usr/lib64) +add_custom_command( + OUTPUT ivi-application-client-protocol.h + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header + < ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-client-protocol.h + DEPENDS ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml +) + +add_custom_command( + OUTPUT ivi-application-protocol.c + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code + < ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c + DEPENDS ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml +) + +include_directories( + ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CURSOR_INCLUDE_DIR} + ${WALTHAM_INCLUDE_DIRS} + ${DRM_INCLUDE_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMER_INCLUDE_DIRS} + ${GSTREAMERAPP_INCLUDE_DIRS} + ${EGL_INCLUDE_DIRS} + ${WAYLAND_EGL_INCLUDE_DIR} + ${GLESv2_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/include/ + ${CMAKE_SOURCE_DIR}/waltham-renderer +) + +link_directories( + ${WAYLAND_CLIENT_LIBRARY_DIRS} + ${WAYLAND_CURSOR_LIBRARY_DIRS} + ${WALTHAM_LIBRARY_DIRS} + ${EGL_LIBRARY_DIRS} + ${WAYLAND_EGL_LIBRAY_DIRS} + ${GLESv2_LIBRARY_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMERAPP_LIBRARY_DIRS} +) + +SET(LIBS + ${CMAKE_THREAD_LIBS_INIT} + ${WAYLAND_CLIENT_LIBRARIES} + ${WAYLAND_CURSOR_LIBRARIES} + ${WALTHAM_LIBRARIES} + ${EGL_LIBRARIES} + ${WAYLAND_EGL_LIBRARIES} + ${GLESv2_LIBRARIES} + ${GSTREAMER_LIBRARIES} + ${GSTREAMERAPP_LIBRARIES} + ${GST_ALLOCATOR} + ${GST_VIDEO} + libwindowmanager.so + libjson-c.so + libhomescreen.so +) + +SET(SRC_FILES + src/wth-server-main.cpp + src/wth-server-waltham-comm.cpp + src/wth-server-gst.cpp + src/utils/bitmap.c + src/utils/os-compatibility.c + ivi-application-protocol.c + ivi-application-client-protocol.h +) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) + +add_definitions(${EGL_CFLAGS}) + +target_link_libraries(${PROJECT_NAME} ${LIBS}) + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/package ${PROJECT_BINARY_DIR} + COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/bin + COMMAND cp -rf ${PROJECT_BINARY_DIR}/${PROJECT_NAME} ${PROJECT_BINARY_DIR}/package/root/bin) + +add_custom_target(widget DEPENDS ${PROJECT_BINARY_DIR}/package/root + COMMAND wgtpkg-pack -f -o ${PROJECT_BINARY_DIR}/package/${PROJECT_NAME}.wgt ${PROJECT_BINARY_DIR}/package/root) + +add_custom_target(receiver DEPENDS ${PROJECT_BINARY_DIR}/package/root + COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/receiver/bin + COMMAND cp -rf ${PROJECT_BINARY_DIR}/${PROJECT_NAME} ${PROJECT_BINARY_DIR}/package/receiver/bin/receiver + COMMAND wgtpkg-pack -f -o ${PROJECT_BINARY_DIR}/package/receiver.wgt ${PROJECT_BINARY_DIR}/package/receiver) + +install (TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/demo3/horizontal/waltham-server/README.md b/demo3/horizontal/waltham-server/README.md new file mode 100644 index 0000000..0b48aa4 --- /dev/null +++ b/demo3/horizontal/waltham-server/README.md @@ -0,0 +1,71 @@ +**Overview** + +This application receives transmitted data by waltham-transmitter. +This application is implemented based on waltham-server. +The original source code of waltham-server is in `./orig`. + +**Download** + +Download souce code and SDK from gitlab. + +``` +$ git clone http://oss-project.tmc-tokai.jp/gitlab/WindowManager/waltham-server.git +``` + +*NOTE* + +This application uses waltham protocol, therefore waltham librarys is necessary. +The downloaded SDK includes the libraries. +If build this application, please use this SDK. + +**Install SDK** + +1. Install SDK which is in `./sdk`. +``` +$ cd ./sdk +$ ./poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-aarch64-toolchain-6.0.0.sh +``` + +1. Copy gstglconfig.h +This SDK has gstglconfig.h +but it exists in `/sysroots/aarch64-agl-linux/usr/lib` +and it occures build error. +Therefore copy it to `/sysroots/aarch64-agl-linux/usr/include`. +``` +$ cd /sysroots/aarch64-agl-linux/ +$ cp usr/lib/gstreamer-1.0/include/gst/gl/gstglconfig.h usr/include/gstreamer-1.0/gst/gl/ +``` + +**Build application** + +Source SDK envirment and make. +``` +$ source /environment-setup-aarch64-agl-linux +$ cd waltham-server +$ mkdir build +$ cd build +$ cmake .. +$ make +$ make receiver +``` + +**Install wgt and config file** + +``` +[On host] +$ scp build/package/receiver.wgt root@ +$ scp config/pipeline.cfg root@:/etc/xdg/weston +$ ssh root@ + +[On target] +# afm-util install receiver.wgt +# sync +``` + +**NOTE** + +This application uses port 34400 by default. +If change it, please modify the followings: + +- In `config/pipeline.cfg`, value of `port` at line 1. +- In `src/wth-server-main.cpp`, value of `tcp_port` at line 49. diff --git a/demo3/horizontal/waltham-server/config/pipeline.cfg b/demo3/horizontal/waltham-server/config/pipeline.cfg new file mode 100644 index 0000000..536540b --- /dev/null +++ b/demo3/horizontal/waltham-server/config/pipeline.cfg @@ -0,0 +1 @@ +udpsrc port=34400 caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)JPEG,payload=(int)26" ! rtpjpegdepay ! jpegdec ! videoconvert ! video/x-raw,format=RGBA ! appsink name=sink sync=true diff --git a/demo3/horizontal/waltham-server/include/bitmap.h b/demo3/horizontal/waltham-server/include/bitmap.h new file mode 100644 index 0000000..3cef52d --- /dev/null +++ b/demo3/horizontal/waltham-server/include/bitmap.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef IVICONTROLLER_BITMAP_H_ +#define IVICONTROLLER_BITMAP_H_ + +#include + +int save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp + ); + +#endif /* IVICONTROLLER_BITMAP_H_*/ diff --git a/demo3/horizontal/waltham-server/include/hmi-debug.h b/demo3/horizontal/waltham-server/include/hmi-debug.h new file mode 100644 index 0000000..2a744ba --- /dev/null +++ b/demo3/horizontal/waltham-server/include/hmi-debug.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HMI_DEBUG_H__ +#define __HMI_DEBUG_H__ + +#include +#include +#include +#include +#include + +enum LOG_LEVEL{ + LOG_LEVEL_NONE = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARNING, + LOG_LEVEL_NOTICE, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG, + LOG_LEVEL_MAX = LOG_LEVEL_DEBUG +}; + +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) + +#define HMI_ERROR(prefix, args,...) _HMI_LOG(LOG_LEVEL_ERROR, __FILENAME__, __FUNCTION__, __LINE__, prefix, args, ##__VA_ARGS__) +#define HMI_WARNING(prefix, args,...) _HMI_LOG(LOG_LEVEL_WARNING, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_NOTICE(prefix, args,...) _HMI_LOG(LOG_LEVEL_NOTICE, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_INFO(prefix, args,...) _HMI_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_DEBUG(prefix, args,...) _HMI_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) + +static char ERROR_FLAG[6][20] = {"NONE", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"}; + +static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, const char* prefix, const char* log, ...) +{ + const int log_level = (getenv("USE_HMI_DEBUG") == NULL)?LOG_LEVEL_ERROR:atoi(getenv("USE_HMI_DEBUG")); + if(log_level < level) + { + return; + } + + char *message; + struct timespec tp; + unsigned int time; + + clock_gettime(CLOCK_REALTIME, &tp); + time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); + + va_list args; + va_start(args, log); + if (log == NULL || vasprintf(&message, log, args) < 0) + message = NULL; + fprintf(stderr, "[%10.3f] [%s %s] [%s, %s(), Line:%d] >>> %s \n", time / 1000.0, prefix, ERROR_FLAG[level], file, func, line, message); + va_end(args); + free(message); +} + +#endif //__HMI_DEBUG_H__ \ No newline at end of file diff --git a/demo3/horizontal/waltham-server/include/os-compatibility.h b/demo3/horizontal/waltham-server/include/os-compatibility.h new file mode 100644 index 0000000..690f229 --- /dev/null +++ b/demo3/horizontal/waltham-server/include/os-compatibility.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef OS_COMPATIBILITY_H +#define OS_COMPATIBILITY_H + +#include + +#ifdef HAVE_EXECINFO_H +#include +#else +static inline int +backtrace(void **buffer, int size) +{ + return 0; +} +#endif + +int +os_fd_set_cloexec(int fd); + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv); + +int +os_epoll_create_cloexec(void); + +int +os_create_anonymous_file(off_t size); + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c); +#endif + +#endif /* OS_COMPATIBILITY_H */ diff --git a/demo3/horizontal/waltham-server/include/wth-server-waltham-comm.h b/demo3/horizontal/waltham-server/include/wth-server-waltham-comm.h new file mode 100644 index 0000000..1d58dde --- /dev/null +++ b/demo3/horizontal/waltham-server/include/wth-server-waltham-comm.h @@ -0,0 +1,524 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc, ** +** required to interface with waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WTH_SERVER_WALTHAM_COMM_H_ +#define WTH_SERVER_WALTHAM_COMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct server; +struct client; +struct window; +struct pointer; +struct touch; +/* +pthread_mutex_t g_mutex; +pthread_cond_t g_cond; +int go_to_wait; +*/ +extern const struct wth_display_interface display_implementation; + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_accept_client(struct server *srv); + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_flush_clients(struct server *srv); + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void client_destroy(struct client *c); + +/** +* waltham_pointer_enter +* +* Send pointer enter event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* serial - serial number of the enter event +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_leave +* +* Send pointer leave event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* @param value window - window information +* serial - serial number of the leave event +* @return none +*/ +void waltham_pointer_leave(struct window *window, uint32_t serial); + +/** +* waltham_pointer_motion +* +* Send pointer motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* time - timestamp with millisecond granularity +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_button +* +* Send pointer button event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* uint32_t button +* uint32_t state +* @param value window - window information +* serial - serial number of the button event +* time - timestamp with millisecond granularity +* button - button that produced the event +* state - physical state of the button +* @return none +*/ +void waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state); + +/** +* waltham_pointer_axis +* +* Send pointer axis event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* uint32_t axis +* wl_fixed_t value +* @param value window - window information +* time - timestamp with millisecond granularity +* axis - axis type +* value - length of vector in surface-local coordinate space +* @return none +*/ +void waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value); + +/** +* waltham_touch_down +* +* Send touch down event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* serial - serial number of the touch down event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_up +* +* Send touch up event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* @param value window - window information +* serial - serial number of the touch up event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* @return none +*/ +void waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id); + +/** +* waltham_touch_motion +* +* Send touch motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_frame +* +* Send touch frame event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_frame(struct window *window); + +/** +* waltham_touch_cancel +* +* Send touch cancel event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_cancel(struct window *window); + + +/***** macros *******/ +#define MAX_EPOLL_WATCHES 2 + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define wl_list_last_until_empty(pos, head, member) \ + while (!wl_list_empty(head) && \ + (pos = wl_container_of((head)->prev, pos, member), 1)) + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#endif + +#ifndef pr_fmt +# define pr_fmt(fmt) fmt +#endif + +#ifndef USE_STDOUT +# define PRINT_OUT stderr +#else +# define PRINT_OUT stdout +#endif + +#define wth_error(fmt, ...) \ + ({ fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); }) +#define wth_verbose(fmt, ...) \ + ({ if (get_verbosity()) { fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); } }) + +/****** incline functions *****/ +static inline void * +zalloc(size_t size) +{ + return calloc(1, size); +} + + +/***** Data types *****/ +/* wthp_region protocol object */ +struct region { + struct wthp_region *obj; + /* pixman_region32_t region; */ + struct wl_list link; /* struct client::region_list */ +}; + +/* wthp_compositor protocol object */ +struct compositor { + struct wthp_compositor *obj; + struct client *client; + struct wl_list link; /* struct client::compositor_list */ +}; + +/* wthp_blob_factory protocol object */ +struct blob_factory { + struct wthp_blob_factory *obj; + struct client *client; + struct wl_list link; /* struct client::blob_factory_list */ +}; + +/* wthp_buffer protocol object */ +struct buffer { + struct wthp_buffer *obj; + uint32_t data_sz; + void *data; + int32_t width; + int32_t height; + int32_t stride; + uint32_t format; + struct wl_list link; /* struct client::buffer_list */ +}; + +/* wthp_seat protocol object */ +struct seat { + struct wthp_seat *obj; + struct client *client; + struct pointer *pointer; + struct keyboard *keyboard; + struct touch *touch; + struct wl_list link; /* struct client::seat_list */ +}; + +/* wthp_pointer protocol object */ +struct pointer { + struct wthp_pointer *obj; + struct seat *seat; + struct wl_list link; /* struct client::pointer_list */ +}; + +/* wthp_keyboard protocol object */ +struct keyboard { + struct wthp_keyboard *obj; + struct seat *seat; + struct wl_list link; /* struct client::keyboard_list */ +}; + +/* wthp_touch protocol object */ +struct touch { + struct wthp_touch *obj; + struct seat *seat; + struct wl_list link; /* struct client::touch_list */ +}; + +/* wthp_surface protocol object */ +struct surface { + struct wthp_surface *obj; + uint32_t ivi_id; + struct ivisurface3 *ivisurf; + struct wthp_callback *cb; + struct window *shm_window; + struct wl_list link; /* struct client::surface_list */ +}; +/* wthp_ivi_surface protocol object */ +struct ivisurface { + struct wthp_ivi_surface *obj; + struct wthp_callback *cb; + struct wl_list link; /* struct client::surface_list */ + struct surface *surf; +}; + +/* wthp_ivi_application protocol object */ +struct application { + struct wthp_ivi_application *obj; + struct client *client; + struct wl_list link; /* struct client::surface_list */ +}; + +/* wthp_registry protocol object */ +struct registry { + struct wthp_registry *obj; + struct client *client; + struct wl_list link; /* struct client::registry_list */ +}; + +enum wthp_seat_capability { + /** + * the seat has pointer devices + */ + WTHP_SEAT_CAPABILITY_POINTER = 1, + /** + * the seat has one or more keyboards + */ + WTHP_SEAT_CAPABILITY_KEYBOARD = 2, + /** + * the seat has touch devices + */ + WTHP_SEAT_CAPABILITY_TOUCH = 4, +}; + +/* epoll structure */ +struct watch { + struct server *server; + int fd; + void (*cb)(struct watch *w, uint32_t events); +}; + +struct client { + struct wl_list link; /* struct server::client_list */ + struct server *server; + + struct wth_connection *connection; + struct watch conn_watch; + + /* client object lists for clean-up on disconnection */ + struct wl_list registry_list; /* struct registry::link */ + struct wl_list compositor_list; /* struct compositor::link */ + struct wl_list region_list; /* struct region::link */ + struct wl_list surface_list; /* struct surface::link */ + struct wl_list buffer_list; /* struct buffer::link */ + struct wl_list seat_list; /* struct seat::link */ + struct wl_list pointer_list; /* struct pointer::link */ + struct wl_list touch_list; /* struct touch::link */ +}; + +/* server structure */ +struct server { + int listen_fd; + struct watch listen_watch; + + bool running; + int epoll_fd; + + struct wl_list client_list; /* struct client::link */ +}; + +struct shm_buffer { + struct wl_buffer *buffer; + void *shm_data; + int busy; +}; + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shm *shm; + bool has_xrgb; + struct ivi_application *ivi_application; + + struct wl_seat *seat; + struct wl_pointer *wl_pointer; + struct wl_keyboard *wl_keyboard; + struct wl_touch *wl_touch; + struct window *window; + struct { + EGLDisplay dpy; + EGLContext ctx; + EGLConfig conf; + + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_texture_2d; + } egl; + struct { + GLuint vertex_shader; + GLuint fragment_shader; + GLuint program_object; + GLuint texture; + } gl; +}; + +struct window { + struct display *display; + struct { + GLuint rotation_uniform; + GLuint pos; + GLuint col; + } gl; + int width, height; + struct wl_surface *surface; + struct ivi_surface *ivi_surface; + struct shm_buffer buffers[2]; + struct shm_buffer *prev_buffer; + struct wl_callback *callback; + uint32_t window_frames; + uint32_t window_benchmark_time; + int wait; + struct surface *server_surf; + struct wl_egl_window *native; + EGLSurface egl_surface; + EGLImageKHR egl_img; + struct seat *server_seat; + struct pointer *server_pointer; + bool ready; + uint32_t id_ivisurf; +}; + + +#endif diff --git a/demo3/horizontal/waltham-server/include/wth-server-weston.h b/demo3/horizontal/waltham-server/include/wth-server-weston.h new file mode 100644 index 0000000..50e1b2c --- /dev/null +++ b/demo3/horizontal/waltham-server/include/wth-server-weston.h @@ -0,0 +1,99 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc ** +** required to interface with weston compositor at server side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WALTHAM_SHM_H_ +#define WALTHAM_SHM_H_ + +#include "wth-server-waltham-comm.h" +/** +* wth_server_weston_shm_attach +* +* attach waltham surface data to weston surface +* +* @param names struct window *window +* uint32_t data_sz +* void * data +* int32_t width +* int32_t height +* int32_t stride +* uint32_t format +* @param value struct window *window - window info pointer +* uint32_t data_sz - buffer data size +* void * data - buffer pointer +* int32_t width - width +* int32_t height -height +* int32_t stride -stride information +* uint32_t format - buffer data format +* @return none +*/ +void wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); + +/** +* wth_server_weston_shm_damage +* +* Send weston surface damage +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_damage(struct window *window); + +/** +* wth_server_weston_shm_commit +* +* Commit weston surface data +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_commit(struct window *window); + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int wth_server_weston_main(void *data); + + +#endif diff --git a/demo3/horizontal/waltham-server/orig/CMakeLists.txt b/demo3/horizontal/waltham-server/orig/CMakeLists.txt new file mode 100644 index 0000000..5ea80bc --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required( VERSION 2.8.5 ) + +project (waltham-server) + +find_package(PkgConfig) +find_package (Threads) +pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED) +pkg_check_modules(WAYLAND_CURSOR wayland-cursor REQUIRED) +pkg_check_modules(WALTHAM waltham REQUIRED) +pkg_check_modules(GLESv2 glesv2 REQUIRED) +pkg_check_modules(WAYLAND_EGL wayland-egl REQUIRED) +pkg_search_module(EGL egl required) +pkg_search_module(GSTREAMER gstreamer-1.0 required) +pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required) +pkg_search_module(DRM libdrm required) + +find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) +find_library(GST_ALLOCATOR NAMES gstallocators-1.0 PATHs /usr/lib64) +find_library(GST_VIDEO NAMES gstvideo-1.0 PATHs /usr/lib64) +add_custom_command( + OUTPUT ivi-application-client-protocol.h + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header + < ${CMAKE_SOURCE_DIR}/waltham-server/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-client-protocol.h + DEPENDS ${CMAKE_SOURCE_DIR}/waltham-server/protocol/ivi-application.xml +) + +add_custom_command( + OUTPUT ivi-application-protocol.c + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code + < ${CMAKE_SOURCE_DIR}/waltham-server/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c + DEPENDS ${CMAKE_SOURCE_DIR}/waltham-server/protocol/ivi-application.xml +) + +include_directories( + ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CURSOR_INCLUDE_DIR} + ${WALTHAM_INCLUDE_DIRS} + ${DRM_INCLUDE_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMER_INCLUDE_DIRS} + ${GSTREAMERAPP_INCLUDE_DIRS} + ${EGL_INCLUDE_DIRS} + ${WAYLAND_EGL_INCLUDE_DIR} + ${GLESv2_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/waltham-server/include/ + ${CMAKE_SOURCE_DIR}/waltham-renderer +) + +link_directories( + ${WAYLAND_CLIENT_LIBRARY_DIRS} + ${WAYLAND_CURSOR_LIBRARY_DIRS} + ${WALTHAM_LIBRARY_DIRS} + ${EGL_LIBRARY_DIRS} + ${WAYLAND_EGL_LIBRAY_DIRS} + ${GLESv2_LIBRARY_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMERAPP_LIBRARY_DIRS} +) + +SET(LIBS + ${CMAKE_THREAD_LIBS_INIT} + ${WAYLAND_CLIENT_LIBRARIES} + ${WAYLAND_CURSOR_LIBRARIES} + ${WALTHAM_LIBRARIES} + ${EGL_LIBRARIES} + ${WAYLAND_EGL_LIBRARIES} + ${GLESv2_LIBRARIES} + ${GSTREAMER_LIBRARIES} + ${GSTREAMERAPP_LIBRARIES} + ${GST_ALLOCATOR} + ${GST_VIDEO} +) + +SET(SRC_FILES + src/wth-server-main.c + src/wth-server-waltham-comm.c + src/wth-server-gst.c + src/utils/bitmap.c + src/utils/os-compatibility.c + ivi-application-protocol.c + ivi-application-client-protocol.h +) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) + +add_definitions(${EGL_CFLAGS}) + +target_link_libraries(${PROJECT_NAME} ${LIBS}) + +install (TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/demo3/horizontal/waltham-server/orig/README b/demo3/horizontal/waltham-server/orig/README new file mode 100644 index 0000000..f20c1e6 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/README @@ -0,0 +1,76 @@ +Component Name: +============ +waltham-server + +Description +============ +waltham-server component is a server side implementation for using +Waltham IPC library to obtain and process remote output received from +waltham-transmitter + +This component is designed to be used for evaluating the functionalities of +waltham-transmitter plugin. + +This component also acts as weston client application to display/handle various +requests from actual weston client at transmitter side. + +Build Steps +=========== +Currently built for HOST environment + +1. Prerequisite before building +weston, wayland and waltham should be built and available in HOST machine +Refer below link to build on Ubuntu HOST machie +https://wayland.freedesktop.org/ubuntu16.04.html + +2. In waltham-server directory, create build directory +# cd waltham-server +# mkdir build + +3. Run cmake +# cmake .. + +4. waltham-server binary should be availaible in build directory + +Features supported +================== +1. Connection establishment with waltham-transmitter +2. Create surface sent by waltham-transmitter +3. Handle pointer events from weston at server side +4. Transmit pointer events from weston at server side to transmitter + +Basic test steps +================= +1. Start weston at server side +# weston + +2. Run waltham-server +#waltham-server -p -v + +3. Start weston with transmitter plugin at transmitter side +#weston + +###############Connection established -Server side logs ################ +set_sigint_handler >>> + <<< set_sigint_handler +server_listen >>> + <<< server_listen +watch_ctl >>> + <<< watch_ctl +Waltham server listening on TCP port 34400... +server_mainloop >>> +server_flush_clients >>> + <<< server_flush_clients +listen_socket_handle_data >>> +EPOLLIN evnet received. +server_accept_client >>> +client_create >>> +watch_ctl >>> +Client 0xb6c20930 connected. + + +Limitation/Workarounds if any +============================== +1. Currently server does not display framed data received from the transmitter, +instead frame data created in local buffer is used. +2. Pointer events are also tested with local buffer data. diff --git a/demo3/horizontal/waltham-server/orig/include/bitmap.h b/demo3/horizontal/waltham-server/orig/include/bitmap.h new file mode 100644 index 0000000..3cef52d --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/include/bitmap.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef IVICONTROLLER_BITMAP_H_ +#define IVICONTROLLER_BITMAP_H_ + +#include + +int save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp + ); + +#endif /* IVICONTROLLER_BITMAP_H_*/ diff --git a/demo3/horizontal/waltham-server/orig/include/os-compatibility.h b/demo3/horizontal/waltham-server/orig/include/os-compatibility.h new file mode 100644 index 0000000..690f229 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/include/os-compatibility.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef OS_COMPATIBILITY_H +#define OS_COMPATIBILITY_H + +#include + +#ifdef HAVE_EXECINFO_H +#include +#else +static inline int +backtrace(void **buffer, int size) +{ + return 0; +} +#endif + +int +os_fd_set_cloexec(int fd); + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv); + +int +os_epoll_create_cloexec(void); + +int +os_create_anonymous_file(off_t size); + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c); +#endif + +#endif /* OS_COMPATIBILITY_H */ diff --git a/demo3/horizontal/waltham-server/orig/include/wth-server-waltham-comm.h b/demo3/horizontal/waltham-server/orig/include/wth-server-waltham-comm.h new file mode 100644 index 0000000..05f3810 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/include/wth-server-waltham-comm.h @@ -0,0 +1,524 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc, ** +** required to interface with waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WTH_SERVER_WALTHAM_COMM_H_ +#define WTH_SERVER_WALTHAM_COMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct server; +struct client; +struct window; +struct pointer; +struct touch; + +pthread_mutex_t g_mutex; +pthread_cond_t g_cond; +int go_to_wait; + +const struct wth_display_interface display_implementation; + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_accept_client(struct server *srv); + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_flush_clients(struct server *srv); + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void client_destroy(struct client *c); + +/** +* waltham_pointer_enter +* +* Send pointer enter event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* serial - serial number of the enter event +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_leave +* +* Send pointer leave event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* @param value window - window information +* serial - serial number of the leave event +* @return none +*/ +void waltham_pointer_leave(struct window *window, uint32_t serial); + +/** +* waltham_pointer_motion +* +* Send pointer motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* time - timestamp with millisecond granularity +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_button +* +* Send pointer button event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* uint32_t button +* uint32_t state +* @param value window - window information +* serial - serial number of the button event +* time - timestamp with millisecond granularity +* button - button that produced the event +* state - physical state of the button +* @return none +*/ +void waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state); + +/** +* waltham_pointer_axis +* +* Send pointer axis event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* uint32_t axis +* wl_fixed_t value +* @param value window - window information +* time - timestamp with millisecond granularity +* axis - axis type +* value - length of vector in surface-local coordinate space +* @return none +*/ +void waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value); + +/** +* waltham_touch_down +* +* Send touch down event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* serial - serial number of the touch down event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_up +* +* Send touch up event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* @param value window - window information +* serial - serial number of the touch up event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* @return none +*/ +void waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id); + +/** +* waltham_touch_motion +* +* Send touch motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_frame +* +* Send touch frame event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_frame(struct window *window); + +/** +* waltham_touch_cancel +* +* Send touch cancel event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_cancel(struct window *window); + + +/***** macros *******/ +#define MAX_EPOLL_WATCHES 2 + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define wl_list_last_until_empty(pos, head, member) \ + while (!wl_list_empty(head) && \ + (pos = wl_container_of((head)->prev, pos, member), 1)) + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#endif + +#ifndef pr_fmt +# define pr_fmt(fmt) fmt +#endif + +#ifndef USE_STDOUT +# define PRINT_OUT stderr +#else +# define PRINT_OUT stdout +#endif + +#define wth_error(fmt, ...) \ + ({ fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); }) +#define wth_verbose(fmt, ...) \ + ({ if (get_verbosity()) { fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); } }) + +/****** incline functions *****/ +static inline void * +zalloc(size_t size) +{ + return calloc(1, size); +} + + +/***** Data types *****/ +/* wthp_region protocol object */ +struct region { + struct wthp_region *obj; + /* pixman_region32_t region; */ + struct wl_list link; /* struct client::region_list */ +}; + +/* wthp_compositor protocol object */ +struct compositor { + struct wthp_compositor *obj; + struct client *client; + struct wl_list link; /* struct client::compositor_list */ +}; + +/* wthp_blob_factory protocol object */ +struct blob_factory { + struct wthp_blob_factory *obj; + struct client *client; + struct wl_list link; /* struct client::blob_factory_list */ +}; + +/* wthp_buffer protocol object */ +struct buffer { + struct wthp_buffer *obj; + uint32_t data_sz; + void *data; + int32_t width; + int32_t height; + int32_t stride; + uint32_t format; + struct wl_list link; /* struct client::buffer_list */ +}; + +/* wthp_seat protocol object */ +struct seat { + struct wthp_seat *obj; + struct client *client; + struct pointer *pointer; + struct keyboard *keyboard; + struct touch *touch; + struct wl_list link; /* struct client::seat_list */ +}; + +/* wthp_pointer protocol object */ +struct pointer { + struct wthp_pointer *obj; + struct seat *seat; + struct wl_list link; /* struct client::pointer_list */ +}; + +/* wthp_keyboard protocol object */ +struct keyboard { + struct wthp_keyboard *obj; + struct seat *seat; + struct wl_list link; /* struct client::keyboard_list */ +}; + +/* wthp_touch protocol object */ +struct touch { + struct wthp_touch *obj; + struct seat *seat; + struct wl_list link; /* struct client::touch_list */ +}; + +/* wthp_surface protocol object */ +struct surface { + struct wthp_surface *obj; + uint32_t ivi_id; + struct ivisurface3 *ivisurf; + struct wthp_callback *cb; + struct window *shm_window; + struct wl_list link; /* struct client::surface_list */ +}; +/* wthp_ivi_surface protocol object */ +struct ivisurface { + struct wthp_ivi_surface *obj; + struct wthp_callback *cb; + struct wl_list link; /* struct client::surface_list */ + struct surface *surf; +}; + +/* wthp_ivi_application protocol object */ +struct application { + struct wthp_ivi_application *obj; + struct client *client; + struct wl_list link; /* struct client::surface_list */ +}; + +/* wthp_registry protocol object */ +struct registry { + struct wthp_registry *obj; + struct client *client; + struct wl_list link; /* struct client::registry_list */ +}; + +enum wthp_seat_capability { + /** + * the seat has pointer devices + */ + WTHP_SEAT_CAPABILITY_POINTER = 1, + /** + * the seat has one or more keyboards + */ + WTHP_SEAT_CAPABILITY_KEYBOARD = 2, + /** + * the seat has touch devices + */ + WTHP_SEAT_CAPABILITY_TOUCH = 4, +}; + +/* epoll structure */ +struct watch { + struct server *server; + int fd; + void (*cb)(struct watch *w, uint32_t events); +}; + +struct client { + struct wl_list link; /* struct server::client_list */ + struct server *server; + + struct wth_connection *connection; + struct watch conn_watch; + + /* client object lists for clean-up on disconnection */ + struct wl_list registry_list; /* struct registry::link */ + struct wl_list compositor_list; /* struct compositor::link */ + struct wl_list region_list; /* struct region::link */ + struct wl_list surface_list; /* struct surface::link */ + struct wl_list buffer_list; /* struct buffer::link */ + struct wl_list seat_list; /* struct seat::link */ + struct wl_list pointer_list; /* struct pointer::link */ + struct wl_list touch_list; /* struct touch::link */ +}; + +/* server structure */ +struct server { + int listen_fd; + struct watch listen_watch; + + bool running; + int epoll_fd; + + struct wl_list client_list; /* struct client::link */ +}; + +struct shm_buffer { + struct wl_buffer *buffer; + void *shm_data; + int busy; +}; + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shm *shm; + bool has_xrgb; + struct ivi_application *ivi_application; + + struct wl_seat *seat; + struct wl_pointer *wl_pointer; + struct wl_keyboard *wl_keyboard; + struct wl_touch *wl_touch; + struct window *window; + struct { + EGLDisplay dpy; + EGLContext ctx; + EGLConfig conf; + + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_texture_2d; + } egl; + struct { + GLuint vertex_shader; + GLuint fragment_shader; + GLuint program_object; + GLuint texture; + } gl; +}; + +struct window { + struct display *display; + struct { + GLuint rotation_uniform; + GLuint pos; + GLuint col; + } gl; + int width, height; + struct wl_surface *surface; + struct ivi_surface *ivi_surface; + struct shm_buffer buffers[2]; + struct shm_buffer *prev_buffer; + struct wl_callback *callback; + uint32_t window_frames; + uint32_t window_benchmark_time; + int wait; + struct surface *server_surf; + struct wl_egl_window *native; + EGLSurface egl_surface; + EGLImageKHR egl_img; + struct seat *server_seat; + struct pointer *server_pointer; + bool ready; + uint32_t id_ivisurf; +}; + + +#endif diff --git a/demo3/horizontal/waltham-server/orig/include/wth-server-weston.h b/demo3/horizontal/waltham-server/orig/include/wth-server-weston.h new file mode 100644 index 0000000..50e1b2c --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/include/wth-server-weston.h @@ -0,0 +1,99 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc ** +** required to interface with weston compositor at server side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WALTHAM_SHM_H_ +#define WALTHAM_SHM_H_ + +#include "wth-server-waltham-comm.h" +/** +* wth_server_weston_shm_attach +* +* attach waltham surface data to weston surface +* +* @param names struct window *window +* uint32_t data_sz +* void * data +* int32_t width +* int32_t height +* int32_t stride +* uint32_t format +* @param value struct window *window - window info pointer +* uint32_t data_sz - buffer data size +* void * data - buffer pointer +* int32_t width - width +* int32_t height -height +* int32_t stride -stride information +* uint32_t format - buffer data format +* @return none +*/ +void wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); + +/** +* wth_server_weston_shm_damage +* +* Send weston surface damage +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_damage(struct window *window); + +/** +* wth_server_weston_shm_commit +* +* Commit weston surface data +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_commit(struct window *window); + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int wth_server_weston_main(void *data); + + +#endif diff --git a/demo3/horizontal/waltham-server/orig/protocol/ivi-application.xml b/demo3/horizontal/waltham-server/orig/protocol/ivi-application.xml new file mode 100644 index 0000000..78e2569 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/protocol/ivi-application.xml @@ -0,0 +1,100 @@ + + + + + Copyright (C) 2013 DENSO CORPORATION + Copyright (c) 2013 BMW Car IT GmbH + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + + + This removes link from ivi_id to wl_surface and destroys ivi_surface. + The ID, ivi_id, is free and can be used for surface_create again. + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface-local coordinates. + + + + + + + + + This interface is exposed as a global singleton. + This interface is implemented by servers that provide IVI-style user interfaces. + It allows clients to associate a ivi_surface with wl_surface. + + + + + + + + + + This request gives the wl_surface the role of an IVI Surface. Creating more than + one ivi_surface for a wl_surface is not allowed. Note, that this still allows the + following example: + + 1. create a wl_surface + 2. create ivi_surface for the wl_surface + 3. destroy the ivi_surface + 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) + + surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + ivi compositor. These ivi_ids are defined as unique in the system to identify + it inside of ivi compositor. The ivi compositor implements business logic how to + set properties of the surface with ivi_id according to status of the system. + E.g. a unique ID for Car Navigation application is used for implementing special + logic of the application about where it shall be located. + The server regards following cases as protocol errors and disconnects the client. + - wl_surface already has an nother role. + - ivi_id is already assigned to an another wl_surface. + + If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, + ivi_id which is assigned to the ivi_surface is free for reuse. + + + + + + + + + diff --git a/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c b/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c new file mode 100644 index 0000000..2c7fdb5 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/utils/bitmap.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "bitmap.h" +#include + +struct __attribute__ ((__packed__)) BITMAPFILEHEADER { + char bfType[2]; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; + +struct __attribute__ ((__packed__)) BITMAPINFOHEADER { + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPixPerMeter; + uint32_t biYPixPerMeter; + uint32_t biClrUsed; + uint32_t biClrImporant; +}; + +static void +create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size) +{ + file_header->bfType[0] = 'B'; + file_header->bfType[1] = 'M'; + file_header->bfSize = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER) + + image_size; + file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER); +} + +static void +create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp) +{ + info_header->biSize = sizeof(struct BITMAPINFOHEADER); + info_header->biWidth = width; + info_header->biHeight = height; + info_header->biPlanes = 1; + info_header->biBitCount = bpp; + info_header->biSizeImage = image_size; +} + +static int +write_bitmap(const char *filename, + const struct BITMAPFILEHEADER *file_header, + const struct BITMAPINFOHEADER *info_header, + const char *buffer) +{ + FILE *fp = fopen(filename, "w"); + if (fp == NULL) { + return -1; + } + + fwrite(file_header, sizeof(struct BITMAPFILEHEADER), 1, fp); + fwrite(info_header, sizeof(struct BITMAPINFOHEADER), 1, fp); + fwrite(buffer, info_header->biSizeImage, 1, fp); + + fclose(fp); + return 0; +} + +int +save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp) +{ + if ((filename == NULL) || (buffer == NULL)) { + return -1; + } + + struct BITMAPFILEHEADER file_header = {}; + struct BITMAPINFOHEADER info_header = {}; + + create_file_header(&file_header, image_size); + create_info_header(&info_header, image_size, width, height, bpp); + return write_bitmap(filename, &file_header, &info_header, buffer); +} diff --git a/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c b/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c new file mode 100644 index 0000000..d9502e5 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/utils/os-compatibility.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os-compatibility.h" + +int +os_fd_set_cloexec(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + return -1; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + return -1; + + return 0; +} + +static int +set_cloexec_or_close(int fd) +{ + if (os_fd_set_cloexec(fd) != 0) { + close(fd); + return -1; + } + return fd; +} + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (ret == 0 || errno != EINVAL) + return ret; +#endif + + ret = socketpair(domain, type, protocol, sv); + if (ret < 0) + return ret; + + sv[0] = set_cloexec_or_close(sv[0]); + sv[1] = set_cloexec_or_close(sv[1]); + + if (sv[0] != -1 && sv[1] != -1) + return 0; + + close(sv[0]); + close(sv[1]); + return -1; +} + +int +os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + return (char *)s; +} +#endif diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c b/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c new file mode 100644 index 0000000..572a04d --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-gst.c @@ -0,0 +1,1151 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* + ** ** + ** SRC-MODULE: ** + ** ** + ** TARGET : linux ** + ** ** + ** PROJECT : waltham-server ** + ** ** + ** AUTHOR : ** + ** ** + ** ** + ** ** + ** PURPOSE : This file is acts as interface to weston compositor at server ** + ** side ** + ** ** + ** REMARKS : ** + ** ** + ** PLATFORM DEPENDANT [yes/no]: yes ** + ** ** + ** TO BE CHANGED BY USER [yes/no]: no ** + ** ** + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "wth-server-waltham-comm.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; + +typedef struct _GstAppContext +{ + GMainLoop *loop; + GstBus *bus; + GstElement *pipeline; + GstElement *sink; + GstSample *sample; + GstBuffer *gstbuffer; + GstVideoMeta *vmeta; + + int dma_fd[2]; + + struct display *display; + struct window *window; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int wait; + + GstVideoInfo info; + uint32_t format; + bool no_dma_buf; +}GstAppContext; + +static const gchar *vertex_shader_str = +"attribute vec4 a_position; \n" +"attribute vec2 a_texCoord; \n" +"varying vec2 v_texCoord; \n" +"void main() \n" +"{ \n" +" gl_Position = a_position; \n" +" v_texCoord = a_texCoord; \n" +"} \n"; + +static const gchar *fragment_shader_str = +"#ifdef GL_ES \n" +"precision mediump float; \n" +"#endif \n" +"varying vec2 v_texCoord; \n" +"uniform sampler2D tex; \n" +"void main() \n" +"{ \n" +"vec2 uv; \n" +"uv = v_texCoord.xy; \n" +"vec4 c = texture2D(tex, uv); \n" +"gl_FragColor = c; \n" +"} \n"; + +/* + * pointer callbcak functions + */ + static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +static int +drm_fourcc_from_gst_format(GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + return DRM_FORMAT_RGB565; + + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + return DRM_FORMAT_BGR888; + + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_AYUV: + return DRM_FORMAT_ARGB8888; + + case GST_VIDEO_FORMAT_GRAY8: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + return DRM_FORMAT_GR88; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_NV12: + return DRM_FORMAT_NV12; + + default: + return -1; + } +} + +gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) +{ + GstAppContext *gstctx = p; + + fprintf(stderr, "mesage: %s\n", GST_MESSAGE_TYPE_NAME(message)); + + switch( GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + { + GError *err; + gchar *debug; + + gst_message_parse_error(message, &err, &debug); + g_print("ERROR: %s\n", err->message); + + g_error_free(err); + g_free(debug); + g_main_loop_quit(gstctx->loop); + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate, newstate; + + gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); + fprintf(stderr, "#%s state changed\n", GST_MESSAGE_SRC_NAME(message)); + switch (newstate){ + case GST_STATE_NULL: + fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_READY: + fprintf(stderr, "%s: state is READY\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PAUSED: + fprintf(stderr, "%s: state is PAUSED\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PLAYING: + fprintf(stderr, "%s: state is PLAYING\n", GST_MESSAGE_SRC_NAME(message)); + break; + } + break; + } + default: + fprintf(stderr, "Unhandled message\n"); + break; + } + fprintf(stderr, "-----------------\n"); +} + +EGLImageKHR create_eglImage(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + + uint32_t n_planes = vmeta->n_planes; + EGLint attribs[30]; + int fourcc; + int atti = 0; + + fourcc = drm_fourcc_from_gst_format(vmeta->format); + + n_planes = GST_VIDEO_INFO_N_PLANES(&(gstctx->info)); + + int width = GST_VIDEO_INFO_WIDTH(&(gstctx->info)); + int height = GST_VIDEO_INFO_HEIGHT(&(gstctx->info)); + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = vmeta->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = vmeta->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = fourcc; + + /* + * Offset value for both the planes i.e Y and UV is "0" + * The omxdec gives the output is 2 different memory blocks, + * One for Y -> dmafd[0] and other for UV -> dmafd[1] + */ + + if (n_planes > 0) { + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = gstctx->dma_fd[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = vmeta->stride[0]; + } + + if (n_planes > 1) { + attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; + attribs[atti++] = gstctx->dma_fd[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; + attribs[atti++] = vmeta->stride[1]; + } + + attribs[atti++] = EGL_NONE; + + return display->egl.create_image(display->egl.dpy, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, + attribs); +} + +static int +redraw(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + struct window *window = display->window; + GLfloat vVertices[] = { -1.0f, 1.0f, 1.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -1.0f, -1.0f, 1.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 1.0f, -1.0f, 1.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 1.0f, 1.0f, 1.0f, // Position 3, skewed a bit + 1.0f, 0.0f // TexCoord 3 + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + glViewport(0,0,vmeta->width,vmeta->height); + wl_egl_window_resize(window->native,vmeta->width,vmeta->height,0,0); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(display->gl.program_object); + + /* Load the vertex position */ + GLint positionLoc = glGetAttribLocation(display->gl.program_object, "a_position"); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + /* Load the texture coordinate */ + GLint texCoordLoc = glGetAttribLocation(display->gl.program_object, "a_texCoord"); + glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + glEnableVertexAttribArray(positionLoc); + glEnableVertexAttribArray(texCoordLoc); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, display->gl.texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if(gstctx->no_dma_buf == false && window->egl_img != NULL ) + { + display->egl.image_texture_2d(GL_TEXTURE_2D, window->egl_img); + } + else + { + GstMapInfo map; + gst_buffer_map(gstctx->gstbuffer, &map, GST_MAP_READ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, vmeta->width, vmeta->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)map.data); + gst_buffer_unmap(gstctx->gstbuffer, &map); + } + + /* Set the texture sampler to texture unit 0 */ + GLint tex = glGetUniformLocation(display->gl.program_object, "tex"); + glUniform1i(tex, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); +} + +static GstFlowReturn +appsink_callback(GstElement *object, gpointer *data) +{ + wth_verbose("%s >>> \n",__func__); + int ret; + GstAppContext *gstctx = (struct gstApplContext *)data; + GstSample *sample; + GstBuffer *gstbuffer; + GstMemory *mem; + int i; + int n_mem; + + sample = gst_app_sink_pull_sample((GstAppSink*)((void*)object)); + if(sample == NULL) { + wth_error("No frame received\n"); + return -1; + } + else { + wth_verbose("Frame received\n"); + } + + /* get dmabuf fd from gstbuffer */ + gstbuffer = gst_sample_get_buffer(sample); + if(!gstbuffer){ + wth_error("Cannot get buffer from sample\n"); + } + gstctx->vmeta = gst_buffer_get_video_meta(gstbuffer); + if(gstctx->vmeta==NULL){ + wth_error("no metadata on buffer\n"); + } + + n_mem = gst_buffer_n_memory(gstbuffer); + if (n_mem < 1) { + wth_error("Buffer with no mem!\n"); + } + + for (i = 0; i < n_mem; i++) { + /* get dmabuf fd from gstbuffer */ + mem = gst_buffer_peek_memory (gstbuffer, i); + if (!gst_is_dmabuf_memory(mem)) { + wth_verbose("Memory is not of dmabuf type \n"); + gstctx->no_dma_buf = true; + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; + } + gstctx->dma_fd[i] = gst_dmabuf_memory_get_fd(mem); + } + + if (gstctx->dma_fd[0] < 0 || gstctx->dma_fd[1] < 0 ) { + wth_error("dma fd is null \n"); + return GST_FLOW_ERROR; + } + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + /* stub */ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + /* stub */ +} +void +wth_server_weston_shm_damage(struct window *window) +{ + /* stub */ +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + /* stub */ +} + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +init_egl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint major, minor, count; + EGLBoolean ret; + + display->egl.dpy = eglGetDisplay(display->display); + assert(display->egl.dpy); + + ret = eglInitialize(display->egl.dpy, &major, &minor); + assert(ret == EGL_TRUE); + ret = eglBindAPI(EGL_OPENGL_ES_API); + assert(ret == EGL_TRUE); + + ret = eglChooseConfig(display->egl.dpy, config_attribs, + &display->egl.conf, 1, &count); + assert(ret && count >= 1); + + display->egl.ctx = eglCreateContext(display->egl.dpy, + display->egl.conf, + EGL_NO_CONTEXT, context_attribs); + assert(display->egl.ctx); + + eglSwapInterval(display->egl.dpy, 1); + + display->egl.create_image = + (void *) eglGetProcAddress("eglCreateImageKHR"); + assert(display->egl.create_image); + + display->egl.image_texture_2d = + (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); + assert(display->egl.image_texture_2d); + + display->egl.destroy_image = + (void *) eglGetProcAddress("eglDestroyImageKHR"); + assert(display->egl.destroy_image); +} + +GLuint load_shader(GLenum type, const char *shaderSrc) +{ + wth_verbose("%s >>> \n",__func__); + GLuint shader; + GLint compiled; + + /* Create the shader object */ + shader = glCreateShader(type); + if (shader == 0) + { + printf("\n Failed to create shader \n"); + return 0; + } + /* Load the shader source */ + glShaderSource(shader, 1, &shaderSrc, NULL); + /* Compile the shader */ + glCompileShader(shader); + /* Check the compile status */ + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc (sizeof(char) * infoLen ); + glGetShaderInfoLog(shader, infoLen, NULL, infoLog); + fprintf(stderr, "Error compiling shader:%s\n",infoLog); + free(infoLog); + } + glDeleteShader(shader); + return 0; + } + return shader; +} + +void init_gl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + GLint linked; + + /* load vertext/fragment shader */ + display->gl.vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_shader_str); + display->gl.fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_shader_str); + + /* Create the program object */ + display->gl.program_object = glCreateProgram(); + if (display->gl.program_object == 0) + { + fprintf(stderr, "error program object\n"); + return; + } + + glAttachShader(display->gl.program_object, display->gl.vertex_shader); + glAttachShader(display->gl.program_object, display->gl.fragment_shader); + /* Bind vPosition to attribute 0 */ + glBindAttribLocation(display->gl.program_object, 0, "a_position"); + /* Link the program */ + glLinkProgram(display->gl.program_object); + /* Check the link status */ + glGetProgramiv(display->gl.program_object, GL_LINK_STATUS, &linked); + if (!linked) + { + GLint infoLen = 0; + glGetProgramiv(display->gl.program_object, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc(sizeof(char) * infoLen); + glGetProgramInfoLog(display->gl.program_object, infoLen, NULL, infoLog); + fprintf(stderr, "Error linking program:%s\n", infoLog); + free(infoLog); + } + glDeleteProgram(display->gl.program_object); + } + + glGenTextures(1, &display->gl.texture); + + return; +} + +static void +create_surface(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct display *display = window->display; + int ret; + + window->surface = wl_compositor_create_surface(display->compositor); + assert(window->surface); + + window->native = wl_egl_window_create(window->surface, + window->width, window->height); + assert(window->native); + + window->egl_surface = eglCreateWindowSurface(display->egl.dpy, + display->egl.conf, + (NativeWindowType)window->native, NULL); + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + } else { + assert(0); + } + ret = eglMakeCurrent(display->egl.dpy, window->egl_surface, + window->egl_surface, display->egl.ctx); + assert(ret == EGL_TRUE); + + glClearColor(0.5, 0.5, 0.5, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + + window->display = display; + window->width = width; + window->height = height; + window->window_frames = 0; + window->window_benchmark_time = 0; + + create_surface(window); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +void *stream_thread(void *data) +{ + wth_verbose("%s >>> \n",__func__); + GMainLoop *loop = data; + g_main_loop_run(loop); + wth_verbose(" <<< %s \n",__func__); +} + + + +static GstPadProbeReturn +pad_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + wth_verbose("%s >>> \n",__func__); + GstAppContext *dec = user_data; + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + GstCaps *caps; + + (void)pad; + + if (GST_EVENT_TYPE(event) != GST_EVENT_CAPS) + return GST_PAD_PROBE_OK; + + gst_event_parse_caps(event, &caps); + + if (!caps) { + GST_ERROR("caps event without caps"); + return GST_PAD_PROBE_OK; + } + + if (!gst_video_info_from_caps(&dec->info, caps)) { + GST_ERROR("caps event with invalid video caps"); + return GST_PAD_PROBE_OK; + } + + switch (GST_VIDEO_INFO_FORMAT(&(dec->info))) { + case GST_VIDEO_FORMAT_I420: + dec->format = DRM_FORMAT_YUV420; + break; + case GST_VIDEO_FORMAT_NV12: + dec->format = DRM_FORMAT_NV12; + break; + case GST_VIDEO_FORMAT_YUY2: + dec->format = DRM_FORMAT_YUYV; + break; + default: + GST_ERROR("unknown format\n"); + return GST_PAD_PROBE_OK; + } + wth_verbose(" <<< %s \n",__func__); + return GST_PAD_PROBE_OK; +} + +/** + * wth_server_weston_main + * + * This is the main function which will handle connection to the compositor at server side + * + * @param names void *data + * @param value struct window data + * @return 0 on success, -1 on error + */ +int +wth_server_weston_main(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct sigaction sigint; + pthread_t pthread; + GstAppContext gstctx; + int ret = 0; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + memset(&gstctx, 0, sizeof(gstctx)); + /* Initialization for window creation */ + gstctx.display = create_display(); + init_egl(gstctx.display); + /* ToDo: fix the hardcoded value of width, height */ + create_window(window, gstctx.display,1920,1080); + init_gl(gstctx.display); + gstctx.window = window; + + gstctx.display->window = window; + + wth_verbose("display %p\n", gstctx.display); + wth_verbose("display->window %p\n", gstctx.display->window); + wth_verbose("window %p\n", window); + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* create gstreamer pipeline */ + gst_init(NULL, NULL); + gstctx.loop = g_main_loop_new(NULL, FALSE); + + /* Read pipeline from file */ + pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); + if (pFile==NULL){ + fprintf(stderr, "failed to open file\n"); + return -1; + } + + /* obtain file size */ + fseek (pFile , 0 , SEEK_END); + lSize = ftell (pFile); + rewind (pFile); + + /* allocate memory to contain the whole file */ + pipe = (char*) zalloc (sizeof(char)*lSize); + if (pipe == NULL){ + fprintf(stderr,"Cannot allocate memory\n"); + return -1; + } + + /* copy the file into the buffer */ + res = fread (pipe,1,lSize,pFile); + if (res != lSize){ + fprintf(stderr,"File read error\n"); + return -1; + } + + wth_verbose("Gst Pipeline=%s",pipe); + /* close file */ + fclose (pFile); + + /* parse the pipeline */ + gstctx.pipeline = gst_parse_launch(pipe, &gerror); + + if(!gstctx.pipeline) + fprintf(stderr,"Could not create gstreamer pipeline.\n"); + free(pipe); + + gstctx.bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx.pipeline)); + gst_bus_add_watch(gstctx.bus, bus_message, &gstctx); + fprintf(stderr, "registered bus signal\n"); + + gstctx.sink = gst_bin_get_by_name(GST_BIN(gstctx.pipeline), "sink"); + g_object_set(G_OBJECT(gstctx.sink), "emit-signals", TRUE, NULL); + g_signal_connect(gstctx.sink, "new-sample", G_CALLBACK(appsink_callback), &gstctx); + g_object_set(G_OBJECT(gstctx.sink), "drop", TRUE, "max-buffers",-1, NULL); + gst_pad_add_probe(gst_element_get_static_pad(gstctx.sink, "sink"), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + pad_probe, &gstctx, NULL); + + fprintf(stderr, "set state as playing\n"); + gst_element_set_state((GstElement*)((void*)gstctx.pipeline), GST_STATE_PLAYING); + + pthread_mutex_init(&gstctx.mutex, NULL); + pthread_cond_init(&gstctx.cond, NULL); + + pthread_create(&pthread, NULL, &stream_thread, gstctx.loop); + + fprintf(stderr, "rendering part\n"); + + gstctx.wait = 1; + pthread_mutex_lock(&gstctx.mutex); + + while (running && ret != -1) { + wth_verbose("in render loop\n"); + ret = wl_display_dispatch(gstctx.display->display); + if(gstctx.wait == 1) { + wth_verbose("cond wait\n"); + pthread_cond_wait(&gstctx.cond, &gstctx.mutex); + } + + if(gstctx.no_dma_buf == false) + { + wth_verbose("create egl image\n"); + window->egl_img = create_eglImage(&gstctx); + } + + wth_verbose("redraw\n"); + redraw(&gstctx); + wth_verbose("fin redraw\n"); + gstctx.display->egl.destroy_image(gstctx.display->egl.dpy, window->egl_img); + gst_buffer_unref(gstctx.gstbuffer); + gst_sample_unref(gstctx.sample); + gstctx.wait = 1; + } + pthread_mutex_unlock(&gstctx.mutex); + + wth_verbose("wth_server_gst_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(gstctx.display); + + wth_verbose(" <<< %s \n",__func__); + + return 0; +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-main.c b/demo3/horizontal/waltham-server/orig/src/wth-server-main.c new file mode 100644 index 0000000..4bbf399 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-main.c @@ -0,0 +1,344 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file handles connection with remote-client ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include "wth-server-waltham-comm.h" + +#define MAX_EPOLL_WATCHES 2 + +int verbose=0; +uint16_t tcp_port; + + + +/** get verbosity + */ +bool +get_verbosity() +{ + if (verbose == 1) + { + return true; + } + else + { + return false; + } +} + +/** Print out the application help + */ +static void usage(void) +{ + printf("Usage: waltham server [options]\n"); + printf("Options:\n"); + printf(" -p --port number TCP port number\n"); + printf(" -h --help Usage\n"); + printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); +} + +static struct option long_options[] = { + {"port", required_argument, 0, 'p'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} +}; + +/** + * parse_args + * + * Parses the application arguments + * The arguments are parsed and saved in static structure for future use. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +static int parse_args(int argc, char *argv[]) +{ + int c = -1; + int long_index = 0; + + while ((c = getopt_long(argc, + argv, + "p:vh", + long_options, + &long_index)) != -1) + { + switch (c) + { + case 'p': + tcp_port = atoi(optarg); + break; + case 'v': + verbose=1; + break; + case 'h': + usage(); + return -1; + default: + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + if (tcp_port == 0) + { + wth_error("TCP port not set \n"); + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + + return 0; +} + +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +/** +* listen_socket_handle_data +* +* Handles all incoming events on socket +* +* @param names struct watch *w ,uint32_t events +* @param value pointer to watch connection it holds server information, Incoming events information +* @return none +*/ +static void +listen_socket_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct server *srv = container_of(w, struct server, listen_watch); + + if (events & EPOLLERR) { + wth_error("Listening socket errored out.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLHUP) { + wth_error("Listening socket hung up.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLIN) + { + wth_verbose("EPOLLIN evnet received. \n"); + server_accept_client(srv); + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_mainloop +* +* This is the main loop, which will flush all pending clients requests and +* listen to input events from socket +* +* @param names void *data +* @param value pointer to server struct - +* struct holds the client connection information +* @return none +*/ +static void +server_mainloop(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + + struct epoll_event ee[MAX_EPOLL_WATCHES]; + struct watch *w; + int count; + int i; + + srv->running = true; + + while (srv->running) { + /* Run any idle tasks at this point. */ + + server_flush_clients(srv); + + /* Wait for events or signals */ + count = epoll_wait(srv->epoll_fd, + ee, ARRAY_LENGTH(ee), -1); + if (count < 0 && errno != EINTR) { + perror("Error with epoll_wait"); + break; + } + + /* Handle all fds, both the listening socket + * (see listen_socket_handle_data()) and clients + * (see connection_handle_data()). + */ + for (i = 0; i < count; i++) { + w = ee[i].data.ptr; + w->cb(w, ee[i].events); + } + } + wth_verbose(" <<< %s \n",__func__); +} + +static int +server_listen(uint16_t tcp_port) +{ + wth_verbose("%s >>> \n",__func__); + int fd; + int reuse = 1; + struct sockaddr_in addr; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(tcp_port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse); + + if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + wth_error("Failed to bind to port %d", tcp_port); + close(fd); + return -1; + } + + if (listen(fd, 1024) < 0) { + wth_error("Failed to listen to port %d", tcp_port); + close (fd); + return -1; + } + + wth_verbose(" <<< %s \n",__func__); + return fd; +} + +static bool *signal_int_handler_run_flag; + +static void +signal_int_handler(int signum) +{ + wth_verbose("%s >>> \n",__func__); + if (!*signal_int_handler_run_flag) + abort(); + + *signal_int_handler_run_flag = false; + wth_verbose(" <<< %s \n",__func__); +} + +static void +set_sigint_handler(bool *running) +{ + wth_verbose("%s >>> \n",__func__); + struct sigaction sigint; + + signal_int_handler_run_flag = running; + sigint.sa_handler = signal_int_handler; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* main +* +* waltham server main function, it accepts tcp port number as argument. +* Establishes connection on the port and listen to port for incoming connection +* request from waltham clients +* +* @param names argv - argument list and argc -argument count +* @param value tcp port number as argument +* @return 0 on success, -1 on error +*/ +int +main(int argc, char *argv[]) +{ + struct server srv = { 0 }; + struct client *c; + + wth_verbose("%s >>> \n",__func__); + + /* Get command line arguments */ + if (parse_args(argc, argv) != 0) + { + return -1; + } + + set_sigint_handler(&srv.running); + + wl_list_init(&srv.client_list); + + srv.epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (srv.epoll_fd == -1) { + perror("Error on epoll_create1"); + exit(1); + } + + srv.listen_fd = server_listen(tcp_port); + if (srv.listen_fd < 0) { + perror("Error setting up listening socket"); + exit(1); + } + + srv.listen_watch.server = &srv; + srv.listen_watch.cb = listen_socket_handle_data; + srv.listen_watch.fd = srv.listen_fd; + if (watch_ctl(&srv.listen_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + perror("Error setting up listen polling"); + exit(1); + } + + wth_verbose("Waltham server listening on TCP port %u...\n",tcp_port); + + + server_mainloop(&srv); + + /* destroy all things */ + wl_list_last_until_empty(c, &srv.client_list, link) + client_destroy(c); + + close(srv.listen_fd); + close(srv.epoll_fd); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c b/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c new file mode 100644 index 0000000..bcd2cd4 --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-waltham-comm.c @@ -0,0 +1,1179 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file acts as interface to waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include "wth-server-waltham-comm.h" + +extern int wth_server_weston_main(struct window *); + +extern void wth_server_weston_shm_attach(struct window *, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); +extern void wth_server_weston_shm_damage(struct window *); +extern void wth_server_weston_shm_commit(struct window *); + +extern bool get_verbosity(void); +extern int verbose; + +/* + * utility functions + */ +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +static void +client_post_out_of_memory(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct wth_display *disp; + + disp = wth_connection_get_display(c->connection); + wth_object_post_error((struct wth_object *)disp, 1, + "out of memory"); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham surface implementation + */ +static void +surface_destroy(struct surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("surface %p destroy\n", surface->obj); + + wthp_surface_free(surface->obj); + wl_list_remove(&surface->link); + free(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_destroy(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + + assert(wthp_surface == surface->obj); + + surface_destroy(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_attach(struct wthp_surface *wthp_surface, + struct wthp_buffer *wthp_buffer, int32_t x, int32_t y) +{ + wth_verbose("%s >>> \n",__func__); + struct buffer *buffr = wth_object_get_user_data((struct wth_object *)wthp_buffer); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + struct buffer *buf = NULL; + + buf = container_of(wthp_buffer, struct buffer, obj); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_attach(surf->shm_window, + buf->data_sz, + buf->data, + buf->width, + buf->height, + buf->stride, + buf->format); + + wthp_buffer_send_complete(wthp_buffer, 0); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_damage(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("surface %p damage(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_damage(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_frame(struct wthp_surface *wthp_surface, + struct wthp_callback *callback) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("surface %p callback(%p)\n",wthp_surface, callback); + + surf->cb = callback; + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_opaque_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_opaque_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_set_input_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_input_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_commit(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("commit %p\n",wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_commit(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_buffer_transform(struct wthp_surface *wthp_surface, + int32_t transform) +{ + wth_verbose("surface %p et_buffer_transform(%d)\n", + wthp_surface, transform); +} + +static void +surface_handle_set_buffer_scale(struct wthp_surface *wthp_surface, + int32_t scale) +{ + wth_verbose("surface %p set_buffer_scale(%d)\n", + wthp_surface, scale); +} + +static void +surface_handle_damage_buffer(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("surface %p damage_buffer(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); +} + +static const struct wthp_surface_interface surface_implementation = { + surface_handle_destroy, + surface_handle_attach, + surface_handle_damage, + surface_handle_frame, + surface_handle_set_opaque_region, + surface_handle_set_input_region, + surface_handle_commit, + surface_handle_set_buffer_transform, + surface_handle_set_buffer_scale, + surface_handle_damage_buffer +}; + + +/* BEGIN wthp_region implementation */ + +static void +buffer_handle_destroy(struct wthp_buffer *wthp_buffer) +{ + struct buffer *buf = wth_object_get_user_data((struct wth_object *)wthp_buffer); + + wthp_buffer_free(wthp_buffer); + wl_list_remove(&buf->link); + free(buf); +} + +static const struct wthp_buffer_interface buffer_implementation = { + buffer_handle_destroy +}; + +/* END wthp_region implementation */ + +/* BEGIN wthp_blob_factory implementation */ + +static void +blob_factory_create_buffer(struct wthp_blob_factory *blob_factory, + struct wthp_buffer *wthp_buffer, uint32_t data_sz, void *data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + struct blob_factory *blob = wth_object_get_user_data((struct wth_object *)blob_factory); + struct buffer *buffer; + + + wth_verbose("wthp_blob_factory %p create_buffer(%p, %d, %p, %d, %d, %d, %d)\n", + blob_factory, wthp_buffer, data_sz, data, width, height, stride, format); + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + client_post_out_of_memory(blob->client); + return; + } + + wl_list_insert(&blob->client->buffer_list, &buffer->link); + + buffer->data_sz = data_sz; + buffer->data = data; + buffer->width = width; + buffer->height = height; + buffer->stride = stride; + buffer->format = format; + buffer->obj = wthp_buffer; + + wthp_buffer_set_interface(wthp_buffer, &buffer_implementation, buffer); +} + +static const struct wthp_blob_factory_interface blob_factory_implementation = { + blob_factory_create_buffer +}; + +static void +client_bind_blob_factory(struct client *c, struct wthp_blob_factory *obj) +{ + struct blob_factory *blob; + + blob = zalloc(sizeof *blob); + if (!blob) { + client_post_out_of_memory(c); + return; + } + + blob->obj = obj; + blob->client = c; + wl_list_insert(&c->compositor_list, &blob->link); + + wthp_blob_factory_set_interface(obj, &blob_factory_implementation, + blob); + fprintf(stderr, "client %p bound wthp_blob_factory\n", c); +} + +/* + * waltam ivi surface implementation + */ +static void +wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); + free(ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_surface_interface wthp_ivi_surface_implementation = { + wthp_ivi_surface_destroy, +}; + + +/* + * waltham ivi application implementation + */ +static void +wthp_ivi_application_surface_create(struct wthp_ivi_application * ivi_application, uint32_t ivi_id, + struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("ivi_application %p surface_create(%d, %p, %p)\n", + ivi_application, ivi_id, wthp_surface, obj); + struct application *app = wth_object_get_user_data((struct wth_object *)ivi_application); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("----------------------------------\n\n\n"); + wth_verbose("surface [%p]\n", surface); + wth_verbose("shm_window [%p]\n\n\n", surface->shm_window); + wth_verbose("----------------------------------\n"); + + surface->ivi_id = ivi_id + 100; + surface->shm_window->id_ivisurf = surface->ivi_id; + struct ivisurface *ivisurf; + + ivisurf = zalloc(sizeof *ivisurf); + if (!ivisurf) { + return; + } + + ivisurf->obj = obj; + ivisurf->surf = surface; + + wth_server_weston_main(surface->shm_window); + + while (!surface->shm_window->ready) + usleep(1); + + wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, + ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_application_interface wthp_ivi_application_implementation = { + wthp_ivi_application_surface_create, +}; + +static void +client_bind_wthp_ivi_application(struct client *c, struct wthp_ivi_application *obj) +{ + wth_verbose("%s >>> \n",__func__); + + struct application *app; + + app = zalloc(sizeof *app); + if (!app) { + client_post_out_of_memory(c); + return; + } + + app->obj = obj; + app->client = c; + wl_list_insert(&c->compositor_list, &app->link); + + wthp_ivi_application_set_interface(obj, &wthp_ivi_application_implementation, + app); + wth_verbose("client %p bound wthp_ivi_application\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * APIs to send pointer events to waltham client + */ + +void +waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_enter [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_enter (pointer->obj, serial, surface->obj, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_leave(struct window *window, uint32_t serial) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_leave [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_leave (pointer->obj, serial, surface->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_motion (pointer->obj, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_button (pointer->obj, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_axis (pointer->obj, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham pointer implementation + */ +static void +pointer_set_cursor(struct wthp_pointer *wthp_pointer, int32_t serial, struct wthp_surface *surface, + int32_t hotspot_x, int32_t hotspot_y) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p (%d, %p, %d, %d)\n", + wthp_pointer, serial, surface, hotspot_x, hotspot_y); + +} + +static void +pointer_release(struct wthp_pointer *wthp_pointer) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p\n",wthp_pointer); +} + +static const struct wthp_pointer_interface pointer_implementation = { + pointer_set_cursor, + pointer_release +}; + +/* + * APIs to send touch events to waltham client + */ + +void +waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wth_verbose("touch_handle_down surface [%d]\n", surface->ivi_id); + wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_up(touch->obj, serial, time, id); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_frame(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_frame(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_cancel(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_cancel(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham touch implementation + */ +static void +touch_release(struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + struct touch *touch = wth_object_get_user_data((struct wth_object *)wthp_touch); + + wth_verbose("%p\n",wthp_touch); +} + +static const struct wthp_touch_interface touch_implementation = { + touch_release, +}; + +/* + * waltham seat implementation + */ +static void +seat_get_pointer(struct wthp_seat *wthp_seat, struct wthp_pointer *wthp_pointer) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("wthp_seat %p get_pointer(%p)\n", + wthp_seat, wthp_pointer); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct pointer *pointer; + + pointer = zalloc(sizeof *pointer); + if (!pointer) { + client_post_out_of_memory(seat->client); + return; + } + + pointer->obj = wthp_pointer; + pointer->seat = seat; + seat->pointer = pointer; + wl_list_insert(&seat->client->pointer_list, &pointer->link); + + wthp_pointer_set_interface(wthp_pointer, &pointer_implementation, pointer); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_get_touch(struct wthp_seat *wthp_seat, struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("wthp_seat %p get_touch(%p)\n", + wthp_seat, wthp_touch); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct touch *touch; + + touch = zalloc(sizeof *touch); + if (!touch) { + client_post_out_of_memory(seat->client); + return; + } + + touch->obj = wthp_touch; + touch->seat = seat; + seat->touch = touch; + wl_list_insert(&seat->client->touch_list, &touch->link); + + wthp_touch_set_interface(wthp_touch, &touch_implementation, touch); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_release(struct wthp_seat *wthp_seat) +{ +} + +static const struct wthp_seat_interface seat_implementation = { + seat_get_pointer, + NULL, + seat_get_touch, + seat_release, + NULL +}; + +static void +seat_send_updated_caps(struct seat *seat) +{ + wth_verbose("%s >>> \n",__func__); + enum wthp_seat_capability caps = 0; + + caps |= WTHP_SEAT_CAPABILITY_POINTER; + wth_verbose("WTHP_SEAT_CAPABILITY_POINTER %d\n", caps); + + caps |= WTHP_SEAT_CAPABILITY_TOUCH; + wth_verbose("WTHP_SEAT_CAPABILITY_TOUCH %d\n", caps); + + wthp_seat_send_capabilities(seat->obj, caps); + wth_verbose(" <<< %s \n",__func__); +} + +static void +client_bind_seat(struct client *c, struct wthp_seat *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat; + + seat = zalloc(sizeof *seat); + if (!seat) { + client_post_out_of_memory(c); + return; + } + + seat->obj = obj; + seat->client = c; + wl_list_insert(&c->seat_list, &seat->link); + wth_verbose("wthp_seat object=%p and seat=%p\n",obj,seat); + wthp_seat_set_interface(obj, &seat_implementation, + seat); + wth_verbose("client %p bound wthp_seat\n", c); + seat_send_updated_caps(seat); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham region implementation + */ + +static void +region_destroy(struct region *region) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("region %p destroy\n", region->obj); + + wthp_region_free(region->obj); + wl_list_remove(®ion->link); + free(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_destroy(struct wthp_region *wthp_region) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region = wth_object_get_user_data((struct wth_object *)wthp_region); + + assert(wthp_region == region->obj); + + region_destroy(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_add(struct wthp_region *wthp_region, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("region %p add(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static void +region_handle_subtract(struct wthp_region *wthp_region, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + wth_verbose("region %p subtract(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static const struct wthp_region_interface region_implementation = { + region_handle_destroy, + region_handle_add, + region_handle_subtract +}; + +/* + * waltham compositor implementation + */ +static void +compositor_destroy(struct compositor *comp) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, comp->obj); + + wthp_compositor_free(comp->obj); + wl_list_remove(&comp->link); + free(comp); + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_surface(struct wthp_compositor *compositor, + struct wthp_surface *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct client *client = comp->client; + struct surface *surface; + struct seat *seat, *tmp; + + wth_verbose("client %p create surface %p\n", + comp->client, id); + + surface = zalloc(sizeof *surface); + if (!surface) { + client_post_out_of_memory(comp->client); + return; + } + + surface->obj = id; + wl_list_insert(&comp->client->surface_list, &surface->link); + + wthp_surface_set_interface(id, &surface_implementation, surface); + + surface->shm_window = calloc(1, sizeof *surface->shm_window); + if (!surface->shm_window) + return; + + surface->shm_window->server_surf = surface; + surface->shm_window->ready = false; + surface->ivi_id = 0; + + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + surface->shm_window->server_seat = seat; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_region(struct wthp_compositor *compositor, + struct wthp_region *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct region *region; + + wth_verbose("client %p create region %p\n", + comp->client, id); + + region = zalloc(sizeof *region); + if (!region) { + client_post_out_of_memory(comp->client); + return; + } + + region->obj = id; + wl_list_insert(&comp->client->region_list, ®ion->link); + + wthp_region_set_interface(id, ®ion_implementation, region); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_compositor_interface compositor_implementation = { + compositor_handle_create_surface, + compositor_handle_create_region +}; + +static void +client_bind_compositor(struct client *c, struct wthp_compositor *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp; + + comp = zalloc(sizeof *comp); + if (!comp) { + client_post_out_of_memory(c); + return; + } + + comp->obj = obj; + comp->client = c; + wl_list_insert(&c->compositor_list, &comp->link); + + wthp_compositor_set_interface(obj, &compositor_implementation, + comp); + wth_verbose("client %p bound wthp_compositor\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham registry implementation + */ +static void +registry_destroy(struct registry *reg) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, reg->obj); + + wthp_registry_free(reg->obj); + wl_list_remove(®->link); + free(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_destroy(struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + + registry_destroy(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_bind(struct wthp_registry *registry, + uint32_t name, + struct wth_object *id, + const char *interface, + uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + wth_verbose("Recieved registry : %s\n", interface); + + if (strcmp(interface, "wthp_compositor") == 0) { + client_bind_compositor(reg->client, (struct wthp_compositor *)id); + } else if (strcmp(interface, "wthp_blob_factory") == 0) { + client_bind_blob_factory(reg->client, (struct wthp_blob_factory *)id); + struct client *client = reg->client; + struct seat *seat, *tmp,*get_seat; + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + get_seat = seat; + } + wth_verbose("get_seat : %p\n", get_seat); + seat_send_updated_caps(get_seat); + } else if (strcmp(interface, "wthp_ivi_application") == 0) { + client_bind_wthp_ivi_application(reg->client, (struct wthp_ivi_application *)id); + } else if (strcmp(interface, "wthp_seat") == 0) { + client_bind_seat(reg->client, (struct wthp_seat *)id); + } else { + wth_object_post_error((struct wth_object *)registry, 0, + "%s: unknown name %u", __func__, name); + wth_object_delete(id); + } + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_registry_interface registry_implementation = { + registry_handle_destroy, + registry_handle_bind +}; + +/* + * waltham display implementation + */ + +static void +display_handle_client_version(struct wth_display *wth_display, + uint32_t client_version) +{ + wth_verbose("%s >>> \n",__func__); + wth_object_post_error((struct wth_object *)wth_display, 0, + "unimplemented: %s", __func__); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_sync(struct wth_display * wth_display, struct wthp_callback * callback) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + + wth_verbose("Client %p requested wth_display.sync\n", c); + wthp_callback_send_done(callback, 0); + wthp_callback_free(callback); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_get_registry(struct wth_display *wth_display, + struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + struct registry *reg; + + reg = zalloc(sizeof *reg); + if (!reg) { + client_post_out_of_memory(c); + return; + } + + reg->obj = registry; + reg->client = c; + wl_list_insert(&c->registry_list, ®->link); + wthp_registry_set_interface(registry, + ®istry_implementation, reg); + + wthp_registry_send_global(registry, 1, "wthp_compositor", 4); + wthp_registry_send_global(registry, 1, "wthp_ivi_application", 1); + wthp_registry_send_global(registry, 1, "wthp_seat", 4); + wthp_registry_send_global(registry, 1, "wthp_blob_factory", 4); + wth_verbose(" <<< %s \n",__func__); +} + +const struct wth_display_interface display_implementation = { + display_handle_client_version, + display_handle_sync, + display_handle_get_registry +}; + +/* + * functions to handle waltham client connections + */ +static void +connection_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = container_of(w, struct client, conn_watch); + int ret; + + if (events & EPOLLERR) { + wth_error("Client %p errored out.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLHUP) { + wth_error("Client %p hung up.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLOUT) { + ret = wth_connection_flush(c->connection); + if (ret == 0) + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN); + else if (ret < 0 && errno != EAGAIN){ + wth_error("Client %p flush error.\n", c); + client_destroy(c); + + return; + } + } + + if (events & EPOLLIN) { + ret = wth_connection_read(c->connection); + if (ret < 0) { + wth_error("Client %p read error.\n", c); + client_destroy(c); + + return; + } + + ret = wth_connection_dispatch(c->connection); + if (ret < 0 && errno != EPROTO) { + wth_error("Client %p dispatch error.\n", c); + client_destroy(c); + + return; + } + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* client_create +* +* Create new client connection +* +* @param srv Server structure +* @param wth_connection Waltham connection handle +* @return Pointer to client structure +*/ +static struct client * +client_create(struct server *srv, struct wth_connection *conn) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c; + struct wth_display *disp; + + c = zalloc(sizeof *c); + if (!c) + return NULL; + + c->server = srv; + c->connection = conn; + + c->conn_watch.server = srv; + c->conn_watch.fd = wth_connection_get_fd(conn); + c->conn_watch.cb = connection_handle_data; + if (watch_ctl(&c->conn_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + free(c); + return NULL; + } + + wth_verbose("Client %p connected.\n", c); + + wl_list_insert(&srv->client_list, &c->link); + + wl_list_init(&c->registry_list); + wl_list_init(&c->compositor_list); + wl_list_init(&c->seat_list); + wl_list_init(&c->pointer_list); + wl_list_init(&c->touch_list); + wl_list_init(&c->region_list); + wl_list_init(&c->surface_list); + wl_list_init(&c->buffer_list); + + disp = wth_connection_get_display(c->connection); + wth_display_set_interface(disp, &display_implementation, c); + + wth_verbose(" <<< %s \n",__func__); + return c; +} + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void +client_destroy(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region; + struct compositor *comp; + struct registry *reg; + struct surface *surface; + + wth_verbose("Client %p disconnected.\n", c); + + /* clean up remaining client resources in case the client + * did not. + */ + wl_list_last_until_empty(region, &c->region_list, link) + region_destroy(region); + + wl_list_last_until_empty(comp, &c->compositor_list, link) + compositor_destroy(comp); + + wl_list_last_until_empty(reg, &c->registry_list, link) + registry_destroy(reg); + + wl_list_last_until_empty(surface, &c->surface_list, link) + surface_destroy(surface); + + wl_list_remove(&c->link); + watch_ctl(&c->conn_watch, EPOLL_CTL_DEL, 0); + wth_connection_destroy(c->connection); + free(c); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_flush_clients(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c, *tmp; + int ret; + + wl_list_for_each_safe(c, tmp, &srv->client_list, link) { + /* Flush out buffered requests. If the Waltham socket is + * full, poll it for writable too. + */ + ret = wth_connection_flush(c->connection); + if (ret < 0 && errno == EAGAIN) { + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN | EPOLLOUT); + } else if (ret < 0) { + perror("Connection flush failed"); + client_destroy(c); + return; + } + } + + wth_verbose(" <<< %s \n",__func__); + +} + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_accept_client(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *client; + struct wth_connection *conn; + struct sockaddr_in addr; + socklen_t len; + + len = sizeof addr; + conn = wth_accept(srv->listen_fd, (struct sockaddr *)&addr, &len); + if (!conn) { + wth_error("Failed to accept a connection.\n"); + return; + } + + client = client_create(srv, conn); + if (!client) { + wth_error("Failed client_create().\n"); + return; + } + wth_verbose(" <<< %s \n",__func__); +} diff --git a/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c b/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c new file mode 100644 index 0000000..6cc309c --- /dev/null +++ b/demo3/horizontal/waltham-server/orig/src/wth-server-weston.c @@ -0,0 +1,811 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file is acts as interface to weston compositor at server ** +** side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include +#include + +#include "wth-server-weston.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; +/* + * buffer callback + */ +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct shm_buffer *mybuf = data; + + wth_verbose("%s >>> \n",__func__); + + mybuf->busy = 0; + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct display *display, struct shm_buffer *buffer, + int width, int height, uint32_t format) +{ + struct wl_shm_pool *pool; + int fd, size, stride; + void *data; + + wth_verbose("%s >>> \n",__func__); + stride = width * 4; + size = stride * height; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + wth_error("creating a buffer file for %d B failed: %m\n", + size); + return -1; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + wth_error("mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, + stride, format); + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + wl_shm_pool_destroy(pool); + close(fd); + + buffer->shm_data = data; + + wth_verbose(" <<< %s \n",__func__); + return 0; +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->surface = wl_compositor_create_surface(display->compositor); + window->window_frames = 0; + window->window_benchmark_time = 0; + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + + } else { + assert(0); + } + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static struct shm_buffer * +window_next_buffer(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct shm_buffer *buffer; + int ret = 0; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else { + window->buffers[0].busy = 0; + window->buffers[0].busy = 1; + buffer = &window->buffers[0]; + } + + if (!buffer->buffer) { + ret = create_shm_buffer(window->display, buffer, + window->width, window->height, + WL_SHM_FORMAT_XRGB8888); + + if (ret < 0) + return NULL; + + /* paint the padding */ + memset(buffer->shm_data, 0xff, + window->width * window->height * 4); + } + + wth_verbose(" <<< %s \n",__func__); + return buffer; +} + +static void +paint_pixels(void *image, int padding, int width, int height, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + const int halfh = padding + (height - padding * 2) / 2; + const int halfw = padding + (width - padding * 2) / 2; + int ir, or; + uint32_t *pixel = image; + int y; + + /* squared radii thresholds */ + or = (halfw < halfh ? halfw : halfh) - 8; + ir = or - 32; + or *= or; + ir *= ir; + + pixel += padding * width; + for (y = padding; y < height - padding; y++) { + int x; + int y2 = (y - halfh) * (y - halfh); + + pixel += padding; + for (x = padding; x < width - padding; x++) { + uint32_t v; + + /* squared distance from center */ + int r2 = (x - halfw) * (x - halfw) + y2; + + if (r2 < ir) + v = (r2 / 32 + time / 64) * 0x0080401; + else if (r2 < or) + v = (y + time / 32) * 0x0080401; + else + v = (x + time / 16) * 0x0080401; + v &= 0x00ffffff; + + /* cross if compositor uses X from XRGB as alpha */ + if (abs(x - y) > 6 && abs(x + y - height) > 6) + v |= 0xff000000; + + *pixel++ = v; + } + + pixel += padding; + } + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct timeval tv; + uint32_t time; + struct shm_buffer *buffer; + static int ss_count = 0; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + buffer = window_next_buffer(window); + if (!buffer) { + wth_error("Both buffers busy at redraw().\n"); + return; + } + + char *bitmap; + bitmap = getenv("BITMAP"); + if (bitmap) { + if (!strcmp(bitmap, "1")) { + int len; + const char *path = "/tmp/bitmap"; + len = strlen(path); + char *filename; + filename = (char *)malloc(len + 10); + sprintf(filename, "%s%d.bmp", path, ss_count); + wth_verbose("%s\n", filename); + + save_as_bitmap(filename, data, data_sz, width, height, format); + ss_count++; + free(filename); + } + } + buffer->shm_data = data; + window->width = width; + window->height = height; + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_damage(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + wl_surface_damage(window->surface, + 0, 0, window->width, window->height); + + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + static const uint32_t benchmark_interval = 5; + struct timeval tv; + uint32_t time; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (window->window_frames == 0) + window->window_benchmark_time = time; + if (time - window->window_benchmark_time > (benchmark_interval * 1000)) { + wth_verbose("-------------------------------%d frames in %d seconds: %f fps\n", + window->window_frames, + benchmark_interval, + (float) window->window_frames / benchmark_interval); + + window->window_benchmark_time = time; + window->window_frames = 0; + } + + wl_surface_commit(window->surface); + + wl_display_flush(window->display->display); + + if (window->wait) + window->wait = 0; + + window->window_frames++; + wth_verbose(" <<< %s \n",__func__); +} + +/* + * frame callback function - this function will display buffer to surface + */ + +static const struct wl_callback_listener frame_listener; +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = data; + struct shm_buffer *buffer; + + buffer = window_next_buffer(window); + if (!buffer) { + if(!callback) + { + wth_error("Failed to create the first buffer.\n"); + } + else + { + wth_error("Both buffers busy at redraw(). Server bug?\n"); + } + abort(); + } + + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, + 20, 20, window->width - 40, window->height - 40); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +/* + * shm callbcak function + */ + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (format == WL_SHM_FORMAT_XRGB8888) + d->has_xrgb = true; + + wth_verbose(" <<< %s \n",__func__); +} + +struct wl_shm_listener shm_listener = { + shm_format +}; + +/* + * pointer callbcak functions + */ +static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->shm == NULL) { + wth_error("No wl_shm global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (!display->has_xrgb) { + wth_error("WL_SHM_FORMAT_XRGB32 not available\n"); + exit(1); + } + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->shm) + wl_shm_destroy(display->shm); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int +wth_server_weston_main(void *data) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = (struct window *) data; + struct sigaction sigint; + struct display *display; + int ret = 0; + + display = create_display(); + create_window(window, display, 400, 400); + if (!window) + return -1; + wl_display_roundtrip(display->display); + wth_verbose("data %p\n", data); + wth_verbose("window %p\n", window); + + display->window = window; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, + window->width, window->height); + + redraw(window, NULL, 0); + + window->wait = 1; + window->ready = true; + while (window->wait) + { + ret = wl_display_dispatch(display->display); + usleep(1); + } + wth_verbose("debug\n"); + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + wth_verbose("wth_server_weston_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(display); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} diff --git a/demo3/horizontal/waltham-server/package/receiver/config.xml b/demo3/horizontal/waltham-server/package/receiver/config.xml new file mode 100644 index 0000000..640108a --- /dev/null +++ b/demo3/horizontal/waltham-server/package/receiver/config.xml @@ -0,0 +1,17 @@ + + + receiver + + + This is a demo application for waltham-server + TOYOA + APL 2.0 + MIT + + + + + + + + + diff --git a/demo3/horizontal/waltham-server/package/receiver/icon.svg b/demo3/horizontal/waltham-server/package/receiver/icon.svg new file mode 100644 index 0000000..91661a7 --- /dev/null +++ b/demo3/horizontal/waltham-server/package/receiver/icon.svg @@ -0,0 +1,279 @@ + + + +image/svg+xmlMULTIMEDIA + \ No newline at end of file diff --git a/demo3/horizontal/waltham-server/package/root/config.xml b/demo3/horizontal/waltham-server/package/root/config.xml new file mode 100644 index 0000000..41f49ca --- /dev/null +++ b/demo3/horizontal/waltham-server/package/root/config.xml @@ -0,0 +1,17 @@ + + + WALTHAM-SERVER + + + This is a demo application for waltham-server + TOYOA + APL 2.0 + MIT + + + + + + + + + diff --git a/demo3/horizontal/waltham-server/package/root/icon.svg b/demo3/horizontal/waltham-server/package/root/icon.svg new file mode 100644 index 0000000..91661a7 --- /dev/null +++ b/demo3/horizontal/waltham-server/package/root/icon.svg @@ -0,0 +1,279 @@ + + + +image/svg+xmlMULTIMEDIA + \ No newline at end of file diff --git a/demo3/horizontal/waltham-server/protocol/ivi-application.xml b/demo3/horizontal/waltham-server/protocol/ivi-application.xml new file mode 100644 index 0000000..78e2569 --- /dev/null +++ b/demo3/horizontal/waltham-server/protocol/ivi-application.xml @@ -0,0 +1,100 @@ + + + + + Copyright (C) 2013 DENSO CORPORATION + Copyright (c) 2013 BMW Car IT GmbH + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + + + This removes link from ivi_id to wl_surface and destroys ivi_surface. + The ID, ivi_id, is free and can be used for surface_create again. + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface-local coordinates. + + + + + + + + + This interface is exposed as a global singleton. + This interface is implemented by servers that provide IVI-style user interfaces. + It allows clients to associate a ivi_surface with wl_surface. + + + + + + + + + + This request gives the wl_surface the role of an IVI Surface. Creating more than + one ivi_surface for a wl_surface is not allowed. Note, that this still allows the + following example: + + 1. create a wl_surface + 2. create ivi_surface for the wl_surface + 3. destroy the ivi_surface + 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) + + surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + ivi compositor. These ivi_ids are defined as unique in the system to identify + it inside of ivi compositor. The ivi compositor implements business logic how to + set properties of the surface with ivi_id according to status of the system. + E.g. a unique ID for Car Navigation application is used for implementing special + logic of the application about where it shall be located. + The server regards following cases as protocol errors and disconnects the client. + - wl_surface already has an nother role. + - ivi_id is already assigned to an another wl_surface. + + If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, + ivi_id which is assigned to the ivi_surface is free for reuse. + + + + + + + + + diff --git a/demo3/horizontal/waltham-server/screenshot/waltham-server.png b/demo3/horizontal/waltham-server/screenshot/waltham-server.png new file mode 100644 index 0000000..75b892c Binary files /dev/null and b/demo3/horizontal/waltham-server/screenshot/waltham-server.png differ diff --git a/demo3/horizontal/waltham-server/src/utils/bitmap.c b/demo3/horizontal/waltham-server/src/utils/bitmap.c new file mode 100644 index 0000000..2c7fdb5 --- /dev/null +++ b/demo3/horizontal/waltham-server/src/utils/bitmap.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "bitmap.h" +#include + +struct __attribute__ ((__packed__)) BITMAPFILEHEADER { + char bfType[2]; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; + +struct __attribute__ ((__packed__)) BITMAPINFOHEADER { + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPixPerMeter; + uint32_t biYPixPerMeter; + uint32_t biClrUsed; + uint32_t biClrImporant; +}; + +static void +create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size) +{ + file_header->bfType[0] = 'B'; + file_header->bfType[1] = 'M'; + file_header->bfSize = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER) + + image_size; + file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER); +} + +static void +create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp) +{ + info_header->biSize = sizeof(struct BITMAPINFOHEADER); + info_header->biWidth = width; + info_header->biHeight = height; + info_header->biPlanes = 1; + info_header->biBitCount = bpp; + info_header->biSizeImage = image_size; +} + +static int +write_bitmap(const char *filename, + const struct BITMAPFILEHEADER *file_header, + const struct BITMAPINFOHEADER *info_header, + const char *buffer) +{ + FILE *fp = fopen(filename, "w"); + if (fp == NULL) { + return -1; + } + + fwrite(file_header, sizeof(struct BITMAPFILEHEADER), 1, fp); + fwrite(info_header, sizeof(struct BITMAPINFOHEADER), 1, fp); + fwrite(buffer, info_header->biSizeImage, 1, fp); + + fclose(fp); + return 0; +} + +int +save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp) +{ + if ((filename == NULL) || (buffer == NULL)) { + return -1; + } + + struct BITMAPFILEHEADER file_header = {}; + struct BITMAPINFOHEADER info_header = {}; + + create_file_header(&file_header, image_size); + create_info_header(&info_header, image_size, width, height, bpp); + return write_bitmap(filename, &file_header, &info_header, buffer); +} diff --git a/demo3/horizontal/waltham-server/src/utils/os-compatibility.c b/demo3/horizontal/waltham-server/src/utils/os-compatibility.c new file mode 100644 index 0000000..d9502e5 --- /dev/null +++ b/demo3/horizontal/waltham-server/src/utils/os-compatibility.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os-compatibility.h" + +int +os_fd_set_cloexec(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + return -1; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + return -1; + + return 0; +} + +static int +set_cloexec_or_close(int fd) +{ + if (os_fd_set_cloexec(fd) != 0) { + close(fd); + return -1; + } + return fd; +} + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (ret == 0 || errno != EINVAL) + return ret; +#endif + + ret = socketpair(domain, type, protocol, sv); + if (ret < 0) + return ret; + + sv[0] = set_cloexec_or_close(sv[0]); + sv[1] = set_cloexec_or_close(sv[1]); + + if (sv[0] != -1 && sv[1] != -1) + return 0; + + close(sv[0]); + close(sv[1]); + return -1; +} + +int +os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + return (char *)s; +} +#endif diff --git a/demo3/horizontal/waltham-server/src/wth-server-gst.cpp b/demo3/horizontal/waltham-server/src/wth-server-gst.cpp new file mode 100644 index 0000000..c282773 --- /dev/null +++ b/demo3/horizontal/waltham-server/src/wth-server-gst.cpp @@ -0,0 +1,1326 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* + ** ** + ** SRC-MODULE: ** + ** ** + ** TARGET : linux ** + ** ** + ** PROJECT : waltham-server ** + ** ** + ** AUTHOR : ** + ** ** + ** ** + ** ** + ** PURPOSE : This file is acts as interface to weston compositor at server ** + ** side ** + ** ** + ** REMARKS : ** + ** ** + ** PLATFORM DEPENDANT [yes/no]: yes ** + ** ** + ** TO BE CHANGED BY USER [yes/no]: no ** + ** ** + *******************************************************************************/ + +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +// Error avoidance for dual declaration of strchrnul() +#define HAVE_STRCHRNUL 1 + +extern "C" { +#include "wth-server-waltham-comm.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" +} + +// Applied to Windowmanager, HomeScreen +#include "libwindowmanager.h" +#include +#include "hmi-debug.h" + + +LibHomeScreen* hs; +LibWindowmanager *wm; +extern bool gIsDraw; +extern uint32_t g_id_ivisurf; + +long port = 1700; +std::string token = "wm"; +std::string app_name = "receiver"; + +static int running = 1; + +extern bool get_verbosity(void); +extern int verbose; + +typedef struct _GstAppContext +{ + GMainLoop *loop; + GstBus *bus; + GstElement *pipeline; + GstElement *sink; + GstSample *sample; + GstBuffer *gstbuffer; + GstVideoMeta *vmeta; + + int dma_fd[2]; + + struct display *display; + struct window *window; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int wait; + + GstVideoInfo info; + uint32_t format; + bool no_dma_buf; +}GstAppContext; + +static const gchar *vertex_shader_str = +"attribute vec4 a_position; \n" +"attribute vec2 a_texCoord; \n" +"varying vec2 v_texCoord; \n" +"void main() \n" +"{ \n" +" gl_Position = a_position; \n" +" v_texCoord = a_texCoord; \n" +"} \n"; + +static const gchar *fragment_shader_str = +"#ifdef GL_ES \n" +"precision mediump float; \n" +"#endif \n" +"varying vec2 v_texCoord; \n" +"uniform sampler2D tex; \n" +"void main() \n" +"{ \n" +"vec2 uv; \n" +"uv = v_texCoord.xy; \n" +"vec4 c = texture2D(tex, uv); \n" +"gl_FragColor = c; \n" +"} \n"; + +/* + * pointer callbcak functions + */ + static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +static int +drm_fourcc_from_gst_format(GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + return DRM_FORMAT_RGB565; + + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + return DRM_FORMAT_BGR888; + + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_AYUV: + return DRM_FORMAT_ARGB8888; + + case GST_VIDEO_FORMAT_GRAY8: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + return DRM_FORMAT_GR88; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_NV12: + return DRM_FORMAT_NV12; + + default: + return -1; + } +} + +gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) +{ + GstAppContext *gstctx = p; + + fprintf(stderr, "mesage: %s\n", GST_MESSAGE_TYPE_NAME(message)); + + switch( GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + { + GError *err; + gchar *debug; + + gst_message_parse_error(message, &err, &debug); + g_print("ERROR: %s\n", err->message); + + g_error_free(err); + g_free(debug); + g_main_loop_quit(gstctx->loop); + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate, newstate; + + gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); + fprintf(stderr, "#%s state changed\n", GST_MESSAGE_SRC_NAME(message)); + switch (newstate){ + case GST_STATE_NULL: + fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_READY: + fprintf(stderr, "%s: state is READY\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PAUSED: + fprintf(stderr, "%s: state is PAUSED\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PLAYING: + fprintf(stderr, "%s: state is PLAYING\n", GST_MESSAGE_SRC_NAME(message)); + break; + } + break; + } + default: + fprintf(stderr, "Unhandled message\n"); + break; + } + fprintf(stderr, "-----------------\n"); +} + +EGLImageKHR create_eglImage(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + + uint32_t n_planes = vmeta->n_planes; + EGLint attribs[30]; + int fourcc; + int atti = 0; + + fourcc = drm_fourcc_from_gst_format(vmeta->format); + + n_planes = GST_VIDEO_INFO_N_PLANES(&(gstctx->info)); + + int width = GST_VIDEO_INFO_WIDTH(&(gstctx->info)); + int height = GST_VIDEO_INFO_HEIGHT(&(gstctx->info)); + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = vmeta->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = vmeta->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = fourcc; + + /* + * Offset value for both the planes i.e Y and UV is "0" + * The omxdec gives the output is 2 different memory blocks, + * One for Y -> dmafd[0] and other for UV -> dmafd[1] + */ + + if (n_planes > 0) { + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = gstctx->dma_fd[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = vmeta->stride[0]; + } + + if (n_planes > 1) { + attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; + attribs[atti++] = gstctx->dma_fd[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; + attribs[atti++] = vmeta->stride[1]; + } + + attribs[atti++] = EGL_NONE; + + return display->egl.create_image(display->egl.dpy, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, + attribs); +} + +static int +redraw(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + struct window *window = display->window; + GLfloat vVertices[] = { -1.0f, 1.0f, 1.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -1.0f, -1.0f, 1.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 1.0f, -1.0f, 1.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 1.0f, 1.0f, 1.0f, // Position 3, skewed a bit + 1.0f, 0.0f // TexCoord 3 + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + glViewport(0,0,vmeta->width,vmeta->height); + wl_egl_window_resize(window->native,vmeta->width,vmeta->height,0,0); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(display->gl.program_object); + + /* Load the vertex position */ + GLint positionLoc = glGetAttribLocation(display->gl.program_object, "a_position"); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + /* Load the texture coordinate */ + GLint texCoordLoc = glGetAttribLocation(display->gl.program_object, "a_texCoord"); + glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + glEnableVertexAttribArray(positionLoc); + glEnableVertexAttribArray(texCoordLoc); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, display->gl.texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if(gstctx->no_dma_buf == false && window->egl_img != NULL ) + { + display->egl.image_texture_2d(GL_TEXTURE_2D, window->egl_img); + } + else + { + GstMapInfo map; + gst_buffer_map(gstctx->gstbuffer, &map, GST_MAP_READ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, vmeta->width, vmeta->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)map.data); + gst_buffer_unmap(gstctx->gstbuffer, &map); + } + + /* Set the texture sampler to texture unit 0 */ + GLint tex = glGetUniformLocation(display->gl.program_object, "tex"); + glUniform1i(tex, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); +} + +static GstFlowReturn +appsink_callback(GstElement *object, gpointer *data) +{ + wth_verbose("%s >>> \n",__func__); + int ret; + //GstAppContext *gstctx = (struct gstApplContext *)data; + GstAppContext *gstctx = (GstAppContext *)data; + GstSample *sample; + GstBuffer *gstbuffer; + GstMemory *mem; + int i; + int n_mem; + + sample = gst_app_sink_pull_sample((GstAppSink*)((void*)object)); + if(sample == NULL) { + wth_error("No frame received\n"); + return -1; + } + else { + wth_verbose("Frame received\n"); + } + + /* get dmabuf fd from gstbuffer */ + gstbuffer = gst_sample_get_buffer(sample); + if(!gstbuffer){ + wth_error("Cannot get buffer from sample\n"); + } + gstctx->vmeta = gst_buffer_get_video_meta(gstbuffer); + if(gstctx->vmeta==NULL){ + wth_error("no metadata on buffer\n"); + } + + n_mem = gst_buffer_n_memory(gstbuffer); + if (n_mem < 1) { + wth_error("Buffer with no mem!\n"); + } + + for (i = 0; i < n_mem; i++) { + /* get dmabuf fd from gstbuffer */ + mem = gst_buffer_peek_memory (gstbuffer, i); + if (!gst_is_dmabuf_memory(mem)) { + wth_verbose("Memory is not of dmabuf type \n"); + gstctx->no_dma_buf = true; + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; + } + gstctx->dma_fd[i] = gst_dmabuf_memory_get_fd(mem); + } + + if (gstctx->dma_fd[0] < 0 || gstctx->dma_fd[1] < 0 ) { + wth_error("dma fd is null \n"); + return GST_FLOW_ERROR; + } + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + /* stub */ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + /* stub */ +} +void +wth_server_weston_shm_damage(struct window *window) +{ + /* stub */ +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + /* stub */ +} + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +init_egl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint major, minor, count; + EGLBoolean ret; + + display->egl.dpy = eglGetDisplay(display->display); + assert(display->egl.dpy); + + ret = eglInitialize(display->egl.dpy, &major, &minor); + assert(ret == EGL_TRUE); + ret = eglBindAPI(EGL_OPENGL_ES_API); + assert(ret == EGL_TRUE); + + ret = eglChooseConfig(display->egl.dpy, config_attribs, + &display->egl.conf, 1, &count); + assert(ret && count >= 1); + + display->egl.ctx = eglCreateContext(display->egl.dpy, + display->egl.conf, + EGL_NO_CONTEXT, context_attribs); + assert(display->egl.ctx); + + eglSwapInterval(display->egl.dpy, 1); + + display->egl.create_image = + (void *) eglGetProcAddress("eglCreateImageKHR"); + assert(display->egl.create_image); + + display->egl.image_texture_2d = + (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); + assert(display->egl.image_texture_2d); + + display->egl.destroy_image = + (void *) eglGetProcAddress("eglDestroyImageKHR"); + assert(display->egl.destroy_image); +} + +GLuint load_shader(GLenum type, const char *shaderSrc) +{ + wth_verbose("%s >>> \n",__func__); + GLuint shader; + GLint compiled; + + /* Create the shader object */ + shader = glCreateShader(type); + if (shader == 0) + { + printf("\n Failed to create shader \n"); + return 0; + } + /* Load the shader source */ + glShaderSource(shader, 1, &shaderSrc, NULL); + /* Compile the shader */ + glCompileShader(shader); + /* Check the compile status */ + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc (sizeof(char) * infoLen ); + glGetShaderInfoLog(shader, infoLen, NULL, infoLog); + fprintf(stderr, "Error compiling shader:%s\n",infoLog); + free(infoLog); + } + glDeleteShader(shader); + return 0; + } + return shader; +} + +void init_gl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + GLint linked; + + /* load vertext/fragment shader */ + display->gl.vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_shader_str); + display->gl.fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_shader_str); + + /* Create the program object */ + display->gl.program_object = glCreateProgram(); + if (display->gl.program_object == 0) + { + fprintf(stderr, "error program object\n"); + return; + } + + glAttachShader(display->gl.program_object, display->gl.vertex_shader); + glAttachShader(display->gl.program_object, display->gl.fragment_shader); + /* Bind vPosition to attribute 0 */ + glBindAttribLocation(display->gl.program_object, 0, "a_position"); + /* Link the program */ + glLinkProgram(display->gl.program_object); + /* Check the link status */ + glGetProgramiv(display->gl.program_object, GL_LINK_STATUS, &linked); + if (!linked) + { + GLint infoLen = 0; + glGetProgramiv(display->gl.program_object, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc(sizeof(char) * infoLen); + glGetProgramInfoLog(display->gl.program_object, infoLen, NULL, infoLog); + fprintf(stderr, "Error linking program:%s\n", infoLog); + free(infoLog); + } + glDeleteProgram(display->gl.program_object); + } + + glGenTextures(1, &display->gl.texture); + + return; +} + +static void +create_surface(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct display *display = window->display; + int ret; + + window->surface = wl_compositor_create_surface(display->compositor); + assert(window->surface); + + window->native = wl_egl_window_create(window->surface, + window->width, window->height); + assert(window->native); + + window->egl_surface = eglCreateWindowSurface(display->egl.dpy, + display->egl.conf, + (NativeWindowType)window->native, NULL); + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = g_id_ivisurf; //window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + } else { + assert(0); + } + ret = eglMakeCurrent(display->egl.dpy, window->egl_surface, + window->egl_surface, display->egl.ctx); + assert(ret == EGL_TRUE); + + glClearColor(0.5, 0.5, 0.5, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + + window->display = display; + window->width = width; + window->height = height; + window->window_frames = 0; + window->window_benchmark_time = 0; + + create_surface(window); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +void *stream_thread(void *data) +{ + wth_verbose("%s >>> \n",__func__); + GMainLoop *loop = data; + g_main_loop_run(loop); + wth_verbose(" <<< %s \n",__func__); +} + + + +static GstPadProbeReturn +pad_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + wth_verbose("%s >>> \n",__func__); + GstAppContext *dec = user_data; + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + GstCaps *caps; + + (void)pad; + + if (GST_EVENT_TYPE(event) != GST_EVENT_CAPS) + return GST_PAD_PROBE_OK; + + gst_event_parse_caps(event, &caps); + + if (!caps) { + GST_ERROR("caps event without caps"); + return GST_PAD_PROBE_OK; + } + + if (!gst_video_info_from_caps(&dec->info, caps)) { + GST_ERROR("caps event with invalid video caps"); + return GST_PAD_PROBE_OK; + } + + switch (GST_VIDEO_INFO_FORMAT(&(dec->info))) { + case GST_VIDEO_FORMAT_I420: + dec->format = DRM_FORMAT_YUV420; + break; + case GST_VIDEO_FORMAT_NV12: + dec->format = DRM_FORMAT_NV12; + break; + case GST_VIDEO_FORMAT_YUY2: + dec->format = DRM_FORMAT_YUYV; + break; + default: + GST_ERROR("unknown format\n"); + return GST_PAD_PROBE_OK; + } + wth_verbose(" <<< %s \n",__func__); + return GST_PAD_PROBE_OK; +} + +// Applied to WM, HS +int +init_wm(LibWindowmanager *wm, struct window *window) +{ + HMI_DEBUG("waltham-server","called"); + char* surfaceIdStr; + + wth_verbose("app:%s port:%d token:%s \n", app_name.c_str(), port, token.c_str()); + + if (wm->init(port, token.c_str()) != 0) { + HMI_ERROR("waltham-server","wm init failed. "); + return -1; + } + + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + g_id_ivisurf = wm->requestSurface(obj); + if(g_id_ivisurf < 0) + { + HMI_ERROR("waltham-server","requestSurface failed: %d ", g_id_ivisurf); + return -1; + } + HMI_DEBUG("waltham-server","IVI_SURFACE_ID: %d ", g_id_ivisurf); + + wm->set_event_handler(LibWindowmanager::Event_Active, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got activated! ", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Inactive, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got inactivated!", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Visible, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got visibled!", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Invisible, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got invisibled!", label); + gIsDraw = false; + }); + + wm->set_event_handler(LibWindowmanager::Event_SyncDraw, [wm, window](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + const char *area = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingArea)); + + HMI_DEBUG("waltham-server","Layout:%s x:%d y:%d w:%d h:%d ", area, 0, 0, 640, 720); + wl_egl_window_resize(window->native, 640, 720, 0, 0); + window->width = 640; + window->height = 720; + //if (!window->fullscreen) + // window->window_size = window->geometry; + gIsDraw = true; + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + wm->endDraw(obj); + }); + + wm->set_event_handler(LibWindowmanager::Event_FlushDraw, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got flushdraw! ", label); + }); + + return 0; +} + +int +init_hs(LibHomeScreen* hs) +{ + if(hs->init(port, token)!=0) + { + HMI_ERROR("waltham-server","homescreen init failed. "); + return -1; + } + + hs->set_event_handler(LibHomeScreen::Event_TapShortcut, [](json_object *object){ + const char *application_name = json_object_get_string( + json_object_object_get(object, "application_name")); + HMI_DEBUG("waltham-server","Event_TapShortcut application_name = %s ", application_name); + if(strcmp(application_name, app_name.c_str()) == 0) + { + HMI_DEBUG("waltham-server","try to activesurface %s ", app_name.c_str()); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("split.sub")); + gIsDraw = false; + fprintf(stderr, "@@@@@ called activate in tapshortcut handler\n"); + wm->activateWindow(obj); + } + }); + + hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, [](json_object *object){ + const char *display_message = json_object_get_string( + json_object_object_get(object, "display_message")); + HMI_DEBUG("waltham-server","Event_OnScreenMessage display_message = %s ", display_message); + }); + + return 0; +} + +GstAppContext gstctx; // @@@@@ +void init_receiver(struct window *window) +{ + struct sigaction sigint; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + memset(&gstctx, 0, sizeof(gstctx)); + /* Initialization for window creation */ + gstctx.display = create_display(); + init_egl(gstctx.display); + + /* windowmanager, homescreen */ + wm = new LibWindowmanager(); + hs = new LibHomeScreen(); + + if(init_wm(wm, window)!=0){ + // error process + wth_verbose("Error in init_wm.\n"); + return -1; + } + + if(init_hs(hs)!=0){ + // error process + wth_verbose("Error in init_hs.\n"); + return -1; + } + + /* ToDo: fix the hardcoded value of width, height */ +// create_window(window, gstctx.display,1920,1080); + create_window(window, gstctx.display,640,720); + init_gl(gstctx.display); + gstctx.window = window; + + gstctx.display->window = window; + + wth_verbose("display %p\n", gstctx.display); + wth_verbose("display->window %p\n", gstctx.display->window); + wth_verbose("window %p\n", window); + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* create gstreamer pipeline */ + gst_init(NULL, NULL); + gstctx.loop = g_main_loop_new(NULL, FALSE); + + /* Read pipeline from file */ + pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); + if (pFile==NULL){ + fprintf(stderr, "failed to open file\n"); + return -1; + } + + /* obtain file size */ + fseek (pFile , 0 , SEEK_END); + lSize = ftell (pFile); + rewind (pFile); + + /* allocate memory to contain the whole file */ + pipe = (char*) zalloc (sizeof(char)*lSize); + if (pipe == NULL){ + fprintf(stderr,"Cannot allocate memory\n"); + return -1; + } + + /* copy the file into the buffer */ + res = fread (pipe,1,lSize,pFile); + if (res != lSize){ + fprintf(stderr,"File read error\n"); + return -1; + } + + wth_verbose("Gst Pipeline=%s",pipe); + /* close file */ + fclose (pFile); + + /* parse the pipeline */ + gstctx.pipeline = gst_parse_launch(pipe, &gerror); + + if(!gstctx.pipeline) + fprintf(stderr,"Could not create gstreamer pipeline.\n"); + free(pipe); + + gstctx.bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx.pipeline)); + gst_bus_add_watch(gstctx.bus, bus_message, &gstctx); + fprintf(stderr, "registered bus signal\n"); + + gstctx.sink = gst_bin_get_by_name(GST_BIN(gstctx.pipeline), "sink"); + g_object_set(G_OBJECT(gstctx.sink), "emit-signals", TRUE, NULL); + g_signal_connect(gstctx.sink, "new-sample", G_CALLBACK(appsink_callback), &gstctx); + g_object_set(G_OBJECT(gstctx.sink), "drop", TRUE, "max-buffers",-1, NULL); + gst_pad_add_probe(gst_element_get_static_pad(gstctx.sink, "sink"), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + pad_probe, &gstctx, NULL); + + fprintf(stderr, "set state as playing\n"); + gst_element_set_state((GstElement*)((void*)gstctx.pipeline), GST_STATE_PLAYING); + + wth_verbose("wl_display_dispatch_pending >>>\n"); + wl_display_dispatch_pending(gstctx.display->display); + wth_verbose("<<< wl_display_dispatch_pending; redraw >>>\n"); + //redraw(&gstctx); + wth_verbose("<<< redraw\n"); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("normal.full")); + wth_verbose("activateWindow >>>\n"); + fprintf(stderr, "@@@@@ called activate in init_receiver\n"); + wm->activateWindow(obj); +} + +/** + * wth_server_weston_main + * + * This is the main function which will handle connection to the compositor at server side + * + * @param names void *data + * @param value struct window data + * @return 0 on success, -1 on error + */ +int +wth_server_weston_main(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct sigaction sigint; + pthread_t pthread; +// GstAppContext gstctx; + int ret = 0; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + pthread_mutex_init(&gstctx.mutex, NULL); + pthread_cond_init(&gstctx.cond, NULL); + + pthread_create(&pthread, NULL, &stream_thread, gstctx.loop); + + fprintf(stderr, "rendering part\n"); + + gstctx.wait = 1; + pthread_mutex_lock(&gstctx.mutex); + + while (running && ret != -1) { + wth_verbose("in render loop\n"); + ret = wl_display_dispatch(gstctx.display->display); + if(gstctx.wait == 1) { + wth_verbose("cond wait\n"); + pthread_cond_wait(&gstctx.cond, &gstctx.mutex); + } + + if(gstctx.no_dma_buf == false) + { + wth_verbose("create egl image\n"); + window->egl_img = create_eglImage(&gstctx); + } + + wth_verbose("redraw\n"); + redraw(&gstctx); + wth_verbose("fin redraw\n"); + gstctx.display->egl.destroy_image(gstctx.display->egl.dpy, window->egl_img); + gst_buffer_unref(gstctx.gstbuffer); + gst_sample_unref(gstctx.sample); + gstctx.wait = 1; + } + pthread_mutex_unlock(&gstctx.mutex); + + wth_verbose("wth_server_gst_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(gstctx.display); + + wth_verbose(" <<< %s \n",__func__); + + return 0; +} diff --git a/demo3/horizontal/waltham-server/src/wth-server-main.cpp b/demo3/horizontal/waltham-server/src/wth-server-main.cpp new file mode 100644 index 0000000..ab86304 --- /dev/null +++ b/demo3/horizontal/waltham-server/src/wth-server-main.cpp @@ -0,0 +1,372 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file handles connection with remote-client ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +extern "C" { +#include "wth-server-waltham-comm.h" +} +#include + +// Applied to Windowmanager, HomeScreen +#include "libwindowmanager.h" +#include + +#define MAX_EPOLL_WATCHES 2 + +extern long port; +extern std::string token; +extern std::string app_name; + +int verbose = 0; +uint16_t tcp_port = 34400; + +bool gIsDraw = false; + +uint32_t g_id_ivisurf = 9009; + +/** get verbosity + */ +bool +get_verbosity() +{ + if (verbose == 1) + { + return true; + } + else + { + return false; + } +} + +/** Print out the application help + */ +static void usage(void) +{ + printf("Usage: waltham server [options]\n"); + printf("Options:\n"); + printf(" -p --port number TCP port number\n"); + printf(" -h --help Usage\n"); + printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); +} + +static struct option long_options[] = { + {"port", required_argument, 0, 'p'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} +}; + +/** + * parse_args + * + * Parses the application arguments + * The arguments are parsed and saved in static structure for future use. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +static int parse_args(int argc, char *argv[]) +{ + int c = -1; + int long_index = 0; + + while ((c = getopt_long(argc, + argv, + "p:vh", + long_options, + &long_index)) != -1) + { + switch (c) + { + case 'p': + tcp_port = atoi(optarg); + break; + case 'v': + verbose=1; + break; + case 'h': + usage(); + return -1; + default: + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + if (tcp_port == 0) + { + wth_error("TCP port not set \n"); + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + + return 0; +} + +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +/** +* listen_socket_handle_data +* +* Handles all incoming events on socket +* +* @param names struct watch *w ,uint32_t events +* @param value pointer to watch connection it holds server information, Incoming events information +* @return none +*/ +static void +listen_socket_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct server *srv = container_of(w, struct server, listen_watch); + + if (events & EPOLLERR) { + wth_error("Listening socket errored out.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLHUP) { + wth_error("Listening socket hung up.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLIN) + { + wth_verbose("EPOLLIN evnet received. \n"); + server_accept_client(srv); + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_mainloop +* +* This is the main loop, which will flush all pending clients requests and +* listen to input events from socket +* +* @param names void *data +* @param value pointer to server struct - +* struct holds the client connection information +* @return none +*/ +static void +server_mainloop(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + + struct epoll_event ee[MAX_EPOLL_WATCHES]; + struct watch *w; + int count; + int i; + + srv->running = true; + + while (srv->running) { + /* Run any idle tasks at this point. */ + + server_flush_clients(srv); + + /* Wait for events or signals */ + count = epoll_wait(srv->epoll_fd, + ee, ARRAY_LENGTH(ee), -1); + if (count < 0 && errno != EINTR) { + perror("Error with epoll_wait"); + break; + } + + /* Handle all fds, both the listening socket + * (see listen_socket_handle_data()) and clients + * (see connection_handle_data()). + */ + for (i = 0; i < count; i++) { + w = ee[i].data.ptr; + w->cb(w, ee[i].events); + } + } + wth_verbose(" <<< %s \n",__func__); +} + +static int +server_listen(uint16_t tcp_port) +{ + wth_verbose("%s >>> \n",__func__); + int fd; + int reuse = 1; + struct sockaddr_in addr; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(tcp_port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse); + + if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + wth_error("Failed to bind to port %d", tcp_port); + close(fd); + return -1; + } + + if (listen(fd, 1024) < 0) { + wth_error("Failed to listen to port %d", tcp_port); + close (fd); + return -1; + } + + wth_verbose(" <<< %s \n",__func__); + return fd; +} + +static bool *signal_int_handler_run_flag; + +static void +signal_int_handler(int signum) +{ + wth_verbose("%s >>> \n",__func__); + if (!*signal_int_handler_run_flag) + abort(); + + *signal_int_handler_run_flag = false; + wth_verbose(" <<< %s \n",__func__); +} + +static void +set_sigint_handler(bool *running) +{ + wth_verbose("%s >>> \n",__func__); + struct sigaction sigint; + + signal_int_handler_run_flag = running; + sigint.sa_handler = signal_int_handler; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + wth_verbose(" <<< %s \n",__func__); +} + + +struct window g_window; // @@@@@ +extern void init_receiver(struct window *window);// @@@@@ +/** +* main +* +* waltham server main function, it accepts tcp port number as argument. +* Establishes connection on the port and listen to port for incoming connection +* request from waltham clients +* +* @param names argv - argument list and argc -argument count +* @param value tcp port number as argument +* @return 0 on success, -1 on error +*/ +int +main(int argc, char *argv[]) +{ + struct server srv = { 0 }; + struct client *c; + + wth_verbose("%s >>> \n",__func__); + + if(argc > 2) + { + if(std::string(argv[0]).find("receiver") != std::string::npos) + app_name = std::string("receiver"); + port = strtol(argv[1], NULL, 10); + token = argv[2]; + } + + wth_verbose("app:%s port:%d token:%s \n", app_name.c_str(), port, token.c_str()); +#if 0 + /* Get command line arguments */ + if (parse_args(argc, argv) != 0) + { + return -1; + } +#endif + + set_sigint_handler(&srv.running); + + wl_list_init(&srv.client_list); + + srv.epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (srv.epoll_fd == -1) { + perror("Error on epoll_create1"); + exit(1); + } + + srv.listen_fd = server_listen(tcp_port); + if (srv.listen_fd < 0) { + perror("Error setting up listening socket"); + exit(1); + } + + srv.listen_watch.server = &srv; + srv.listen_watch.cb = listen_socket_handle_data; + srv.listen_watch.fd = srv.listen_fd; + if (watch_ctl(&srv.listen_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + perror("Error setting up listen polling"); + exit(1); + } + + init_receiver(&g_window); + + wth_verbose("Waltham server listening on TCP port %u...\n",tcp_port); + + server_mainloop(&srv); + + /* destroy all things */ + wl_list_last_until_empty(c, &srv.client_list, link) + client_destroy(c); + + close(srv.listen_fd); + close(srv.epoll_fd); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} diff --git a/demo3/horizontal/waltham-server/src/wth-server-waltham-comm.cpp b/demo3/horizontal/waltham-server/src/wth-server-waltham-comm.cpp new file mode 100644 index 0000000..6e3b08c --- /dev/null +++ b/demo3/horizontal/waltham-server/src/wth-server-waltham-comm.cpp @@ -0,0 +1,1202 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file acts as interface to waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ +extern "C" { +#include "wth-server-waltham-comm.h" +} +extern int wth_server_weston_main(struct window *); + +extern void wth_server_weston_shm_attach(struct window *, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); +extern void wth_server_weston_shm_damage(struct window *); +extern void wth_server_weston_shm_commit(struct window *); + +extern bool get_verbosity(void); +extern int verbose; + +// container_of modified for C->C++ +/* +#undef container_of +#undef offsetof + +template +size_t offsetof(const M P::*member) +{ + return (size_t) &( reinterpret_cast(0)->*member); +} +template +P* container_of(M* ptr, const M P::*member) +{ + return (P*)( (char*)ptr - offsetof(member)); +} +*/ +typedef struct buffer Buffer; + +/* + * utility functions + */ +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +static void +client_post_out_of_memory(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct wth_display *disp; + + disp = wth_connection_get_display(c->connection); + wth_object_post_error((struct wth_object *)disp, 1, + "out of memory"); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham surface implementation + */ +static void +surface_destroy(struct surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("surface %p destroy\n", surface->obj); + + wthp_surface_free(surface->obj); + wl_list_remove(&surface->link); + free(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_destroy(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + + assert(wthp_surface == surface->obj); + + surface_destroy(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_attach(struct wthp_surface *wthp_surface, + struct wthp_buffer *wthp_buf, int32_t x, int32_t y) +{ + wth_verbose("%s >>> \n",__func__); + struct buffer *buffr = wth_object_get_user_data((struct wth_object *)wthp_buf); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + struct buffer *buf = NULL; + + //buf = container_of(wthp_buf, struct buffer, obj); + //buf = container_of(wthp_buf, &buffer::obj); + uint32_t *tmp_data_sz = (uint32_t *)wthp_buf + sizeof(struct wthp_buffer *); + buf = container_of(tmp_data_sz, struct buffer, data_sz); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_attach(surf->shm_window, + buf->data_sz, + buf->data, + buf->width, + buf->height, + buf->stride, + buf->format); + + wthp_buffer_send_complete(wthp_buf, 0); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_damage(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("surface %p damage(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_damage(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_frame(struct wthp_surface *wthp_surface, + struct wthp_callback *callback) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("surface %p callback(%p)\n",wthp_surface, callback); + + surf->cb = callback; + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_opaque_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_opaque_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_set_input_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_input_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_commit(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("commit %p\n",wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_commit(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_buffer_transform(struct wthp_surface *wthp_surface, + int32_t transform) +{ + wth_verbose("surface %p et_buffer_transform(%d)\n", + wthp_surface, transform); +} + +static void +surface_handle_set_buffer_scale(struct wthp_surface *wthp_surface, + int32_t scale) +{ + wth_verbose("surface %p set_buffer_scale(%d)\n", + wthp_surface, scale); +} + +static void +surface_handle_damage_buffer(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("surface %p damage_buffer(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); +} + +static const struct wthp_surface_interface surface_implementation = { + surface_handle_destroy, + surface_handle_attach, + surface_handle_damage, + surface_handle_frame, + surface_handle_set_opaque_region, + surface_handle_set_input_region, + surface_handle_commit, + surface_handle_set_buffer_transform, + surface_handle_set_buffer_scale, + surface_handle_damage_buffer +}; + + +/* BEGIN wthp_region implementation */ + +static void +buffer_handle_destroy(struct wthp_buffer *wthp_buffer) +{ + struct buffer *buf = wth_object_get_user_data((struct wth_object *)wthp_buffer); + + wthp_buffer_free(wthp_buffer); + wl_list_remove(&buf->link); + free(buf); +} + +static const struct wthp_buffer_interface buffer_implementation = { + buffer_handle_destroy +}; + +/* END wthp_region implementation */ + +/* BEGIN wthp_blob_factory implementation */ + +static void +blob_factory_create_buffer(struct wthp_blob_factory *blob_factory, + struct wthp_buffer *wthp_buffer, uint32_t data_sz, void *data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + struct blob_factory *blob = wth_object_get_user_data((struct wth_object *)blob_factory); + struct buffer *buffer; + + + wth_verbose("wthp_blob_factory %p create_buffer(%p, %d, %p, %d, %d, %d, %d)\n", + blob_factory, wthp_buffer, data_sz, data, width, height, stride, format); + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + client_post_out_of_memory(blob->client); + return; + } + + wl_list_insert(&blob->client->buffer_list, &buffer->link); + + buffer->data_sz = data_sz; + buffer->data = data; + buffer->width = width; + buffer->height = height; + buffer->stride = stride; + buffer->format = format; + buffer->obj = wthp_buffer; + + wthp_buffer_set_interface(wthp_buffer, &buffer_implementation, buffer); +} + +static const struct wthp_blob_factory_interface blob_factory_implementation = { + blob_factory_create_buffer +}; + +static void +client_bind_blob_factory(struct client *c, struct wthp_blob_factory *obj) +{ + struct blob_factory *blob; + + blob = zalloc(sizeof *blob); + if (!blob) { + client_post_out_of_memory(c); + return; + } + + blob->obj = obj; + blob->client = c; + wl_list_insert(&c->compositor_list, &blob->link); + + wthp_blob_factory_set_interface(obj, &blob_factory_implementation, + blob); + fprintf(stderr, "client %p bound wthp_blob_factory\n", c); +} + +/* + * waltam ivi surface implementation + */ +static void +wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); + free(ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_surface_interface wthp_ivi_surface_implementation = { + wthp_ivi_surface_destroy, +}; + + +/* + * waltham ivi application implementation + */ +static void +wthp_ivi_application_surface_create(struct wthp_ivi_application * ivi_application, uint32_t ivi_id, + struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("ivi_application %p surface_create(%d, %p, %p)\n", + ivi_application, ivi_id, wthp_surface, obj); + struct application *app = wth_object_get_user_data((struct wth_object *)ivi_application); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("----------------------------------\n\n\n"); + wth_verbose("surface [%p]\n", surface); + wth_verbose("shm_window [%p]\n\n\n", surface->shm_window); + wth_verbose("----------------------------------\n"); + + surface->ivi_id = ivi_id + 100; + surface->shm_window->id_ivisurf = surface->ivi_id; + struct ivisurface *ivisurf; + + ivisurf = zalloc(sizeof *ivisurf); + if (!ivisurf) { + return; + } + + ivisurf->obj = obj; + ivisurf->surf = surface; + + wth_server_weston_main(surface->shm_window); + + while (!surface->shm_window->ready) + usleep(1); + + wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, + ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_application_interface wthp_ivi_application_implementation = { + wthp_ivi_application_surface_create, +}; + +static void +client_bind_wthp_ivi_application(struct client *c, struct wthp_ivi_application *obj) +{ + wth_verbose("%s >>> \n",__func__); + + struct application *app; + + app = zalloc(sizeof *app); + if (!app) { + client_post_out_of_memory(c); + return; + } + + app->obj = obj; + app->client = c; + wl_list_insert(&c->compositor_list, &app->link); + + wthp_ivi_application_set_interface(obj, &wthp_ivi_application_implementation, + app); + wth_verbose("client %p bound wthp_ivi_application\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * APIs to send pointer events to waltham client + */ + +void +waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_enter [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_enter (pointer->obj, serial, surface->obj, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_leave(struct window *window, uint32_t serial) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_leave [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_leave (pointer->obj, serial, surface->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_motion (pointer->obj, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_button (pointer->obj, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_axis (pointer->obj, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham pointer implementation + */ +static void +pointer_set_cursor(struct wthp_pointer *wthp_pointer, int32_t serial, struct wthp_surface *surface, + int32_t hotspot_x, int32_t hotspot_y) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p (%d, %p, %d, %d)\n", + wthp_pointer, serial, surface, hotspot_x, hotspot_y); + +} + +static void +pointer_release(struct wthp_pointer *wthp_pointer) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p\n",wthp_pointer); +} + +static const struct wthp_pointer_interface pointer_implementation = { + pointer_set_cursor, + pointer_release +}; + +/* + * APIs to send touch events to waltham client + */ + +void +waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wth_verbose("touch_handle_down surface [%d]\n", surface->ivi_id); + wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_up(touch->obj, serial, time, id); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_frame(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_frame(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_cancel(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_cancel(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham touch implementation + */ +static void +touch_release(struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + struct touch *touch = wth_object_get_user_data((struct wth_object *)wthp_touch); + + wth_verbose("%p\n",wthp_touch); +} + +static const struct wthp_touch_interface touch_implementation = { + touch_release, +}; + +/* + * waltham seat implementation + */ +static void +seat_get_pointer(struct wthp_seat *wthp_seat, struct wthp_pointer *wthp_pointer) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("wthp_seat %p get_pointer(%p)\n", + wthp_seat, wthp_pointer); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct pointer *pointer; + + pointer = zalloc(sizeof *pointer); + if (!pointer) { + client_post_out_of_memory(seat->client); + return; + } + + pointer->obj = wthp_pointer; + pointer->seat = seat; + seat->pointer = pointer; + wl_list_insert(&seat->client->pointer_list, &pointer->link); + + wthp_pointer_set_interface(wthp_pointer, &pointer_implementation, pointer); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_get_touch(struct wthp_seat *wthp_seat, struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("wthp_seat %p get_touch(%p)\n", + wthp_seat, wthp_touch); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct touch *touch; + + touch = zalloc(sizeof *touch); + if (!touch) { + client_post_out_of_memory(seat->client); + return; + } + + touch->obj = wthp_touch; + touch->seat = seat; + seat->touch = touch; + wl_list_insert(&seat->client->touch_list, &touch->link); + + wthp_touch_set_interface(wthp_touch, &touch_implementation, touch); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_release(struct wthp_seat *wthp_seat) +{ +} + +static const struct wthp_seat_interface seat_implementation = { + seat_get_pointer, + NULL, + seat_get_touch, + seat_release //, + //NULL +}; + +static void +seat_send_updated_caps(struct seat *seat) +{ + wth_verbose("%s >>> \n",__func__); + enum wthp_seat_capability caps = 0; + + caps |= WTHP_SEAT_CAPABILITY_POINTER; + wth_verbose("WTHP_SEAT_CAPABILITY_POINTER %d\n", caps); + + caps |= WTHP_SEAT_CAPABILITY_TOUCH; + wth_verbose("WTHP_SEAT_CAPABILITY_TOUCH %d\n", caps); + + wthp_seat_send_capabilities(seat->obj, caps); + wth_verbose(" <<< %s \n",__func__); +} + +static void +client_bind_seat(struct client *c, struct wthp_seat *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat; + + seat = zalloc(sizeof *seat); + if (!seat) { + client_post_out_of_memory(c); + return; + } + + seat->obj = obj; + seat->client = c; + wl_list_insert(&c->seat_list, &seat->link); + wth_verbose("wthp_seat object=%p and seat=%p\n",obj,seat); + wthp_seat_set_interface(obj, &seat_implementation, + seat); + wth_verbose("client %p bound wthp_seat\n", c); + seat_send_updated_caps(seat); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham region implementation + */ + +static void +region_destroy(struct region *region) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("region %p destroy\n", region->obj); + + wthp_region_free(region->obj); + wl_list_remove(®ion->link); + free(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_destroy(struct wthp_region *wthp_region) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region = wth_object_get_user_data((struct wth_object *)wthp_region); + + assert(wthp_region == region->obj); + + region_destroy(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_add(struct wthp_region *wthp_region, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("region %p add(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static void +region_handle_subtract(struct wthp_region *wthp_region, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + wth_verbose("region %p subtract(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static const struct wthp_region_interface region_implementation = { + region_handle_destroy, + region_handle_add, + region_handle_subtract +}; + +/* + * waltham compositor implementation + */ +static void +compositor_destroy(struct compositor *comp) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, comp->obj); + + wthp_compositor_free(comp->obj); + wl_list_remove(&comp->link); + free(comp); + wth_verbose(" <<< %s \n",__func__); +} + +extern struct window g_window; // @@@@@ +static void +compositor_handle_create_surface(struct wthp_compositor *compositor, + struct wthp_surface *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct client *client = comp->client; + struct surface *surface; + struct seat *seat, *tmp; + + wth_verbose("client %p create surface %p\n", + comp->client, id); + + surface = zalloc(sizeof *surface); + if (!surface) { + client_post_out_of_memory(comp->client); + return; + } + + surface->obj = id; + wl_list_insert(&comp->client->surface_list, &surface->link); + + wthp_surface_set_interface(id, &surface_implementation, surface); + +// surface->shm_window = calloc(1, sizeof *surface->shm_window); + surface->shm_window = &g_window; + if (!surface->shm_window) + return; + + surface->shm_window->server_surf = surface; + surface->shm_window->ready = false; + surface->ivi_id = 0; + + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + surface->shm_window->server_seat = seat; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_region(struct wthp_compositor *compositor, + struct wthp_region *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct region *region; + + wth_verbose("client %p create region %p\n", + comp->client, id); + + region = zalloc(sizeof *region); + if (!region) { + client_post_out_of_memory(comp->client); + return; + } + + region->obj = id; + wl_list_insert(&comp->client->region_list, ®ion->link); + + wthp_region_set_interface(id, ®ion_implementation, region); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_compositor_interface compositor_implementation = { + compositor_handle_create_surface, + compositor_handle_create_region +}; + +static void +client_bind_compositor(struct client *c, struct wthp_compositor *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp; + + comp = zalloc(sizeof *comp); + if (!comp) { + client_post_out_of_memory(c); + return; + } + + comp->obj = obj; + comp->client = c; + wl_list_insert(&c->compositor_list, &comp->link); + + wthp_compositor_set_interface(obj, &compositor_implementation, + comp); + wth_verbose("client %p bound wthp_compositor\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham registry implementation + */ +static void +registry_destroy(struct registry *reg) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, reg->obj); + + wthp_registry_free(reg->obj); + wl_list_remove(®->link); + free(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_destroy(struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + + registry_destroy(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_bind(struct wthp_registry *registry, + uint32_t name, + struct wth_object *id, + const char *interface, + uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + wth_verbose("Recieved registry : %s\n", interface); + + if (strcmp(interface, "wthp_compositor") == 0) { + client_bind_compositor(reg->client, (struct wthp_compositor *)id); + } else if (strcmp(interface, "wthp_blob_factory") == 0) { + client_bind_blob_factory(reg->client, (struct wthp_blob_factory *)id); + struct client *client = reg->client; + struct seat *seat, *tmp,*get_seat; + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + get_seat = seat; + } + wth_verbose("get_seat : %p\n", get_seat); + seat_send_updated_caps(get_seat); + } else if (strcmp(interface, "wthp_ivi_application") == 0) { + client_bind_wthp_ivi_application(reg->client, (struct wthp_ivi_application *)id); + } else if (strcmp(interface, "wthp_seat") == 0) { + client_bind_seat(reg->client, (struct wthp_seat *)id); + } else { + wth_object_post_error((struct wth_object *)registry, 0, + "%s: unknown name %u", __func__, name); + wth_object_delete(id); + } + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_registry_interface registry_implementation = { + registry_handle_destroy, + registry_handle_bind +}; + +/* + * waltham display implementation + */ + +static void +display_handle_client_version(struct wth_display *wth_display, + uint32_t client_version) +{ + wth_verbose("%s >>> \n",__func__); + wth_object_post_error((struct wth_object *)wth_display, 0, + "unimplemented: %s", __func__); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_sync(struct wth_display * wth_display, struct wthp_callback * callback) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + + wth_verbose("Client %p requested wth_display.sync\n", c); + wthp_callback_send_done(callback, 0); + wthp_callback_free(callback); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_get_registry(struct wth_display *wth_display, + struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + struct registry *reg; + + reg = zalloc(sizeof *reg); + if (!reg) { + client_post_out_of_memory(c); + return; + } + + reg->obj = registry; + reg->client = c; + wl_list_insert(&c->registry_list, ®->link); + wthp_registry_set_interface(registry, + ®istry_implementation, reg); + + wthp_registry_send_global(registry, 1, "wthp_compositor", 4); + wthp_registry_send_global(registry, 1, "wthp_ivi_application", 1); + wthp_registry_send_global(registry, 1, "wthp_seat", 4); + wthp_registry_send_global(registry, 1, "wthp_blob_factory", 4); + wth_verbose(" <<< %s \n",__func__); +} + +const struct wth_display_interface display_implementation = { + display_handle_client_version, + display_handle_sync, + display_handle_get_registry +}; + +/* + * functions to handle waltham client connections + */ +static void +connection_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = container_of(w, struct client, conn_watch); + int ret; + + if (events & EPOLLERR) { + wth_error("Client %p errored out.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLHUP) { + wth_error("Client %p hung up.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLOUT) { + ret = wth_connection_flush(c->connection); + if (ret == 0) + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN); + else if (ret < 0 && errno != EAGAIN){ + wth_error("Client %p flush error.\n", c); + client_destroy(c); + + return; + } + } + + if (events & EPOLLIN) { + ret = wth_connection_read(c->connection); + if (ret < 0) { + wth_error("Client %p read error.\n", c); + client_destroy(c); + + return; + } + + ret = wth_connection_dispatch(c->connection); + if (ret < 0 && errno != EPROTO) { + wth_error("Client %p dispatch error.\n", c); + client_destroy(c); + + return; + } + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* client_create +* +* Create new client connection +* +* @param srv Server structure +* @param wth_connection Waltham connection handle +* @return Pointer to client structure +*/ +static struct client * +client_create(struct server *srv, struct wth_connection *conn) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c; + struct wth_display *disp; + + c = zalloc(sizeof *c); + if (!c) + return NULL; + + c->server = srv; + c->connection = conn; + + c->conn_watch.server = srv; + c->conn_watch.fd = wth_connection_get_fd(conn); + c->conn_watch.cb = connection_handle_data; + if (watch_ctl(&c->conn_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + free(c); + return NULL; + } + + wth_verbose("Client %p connected.\n", c); + + wl_list_insert(&srv->client_list, &c->link); + + wl_list_init(&c->registry_list); + wl_list_init(&c->compositor_list); + wl_list_init(&c->seat_list); + wl_list_init(&c->pointer_list); + wl_list_init(&c->touch_list); + wl_list_init(&c->region_list); + wl_list_init(&c->surface_list); + wl_list_init(&c->buffer_list); + + disp = wth_connection_get_display(c->connection); + wth_display_set_interface(disp, &display_implementation, c); + + wth_verbose(" <<< %s \n",__func__); + return c; +} + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void +client_destroy(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region; + struct compositor *comp; + struct registry *reg; + struct surface *surface; + + wth_verbose("Client %p disconnected.\n", c); + + /* clean up remaining client resources in case the client + * did not. + */ + wl_list_last_until_empty(region, &c->region_list, link) + region_destroy(region); + + wl_list_last_until_empty(comp, &c->compositor_list, link) + compositor_destroy(comp); + + wl_list_last_until_empty(reg, &c->registry_list, link) + registry_destroy(reg); + + wl_list_last_until_empty(surface, &c->surface_list, link) + surface_destroy(surface); + + wl_list_remove(&c->link); + watch_ctl(&c->conn_watch, EPOLL_CTL_DEL, 0); + wth_connection_destroy(c->connection); + free(c); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_flush_clients(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c, *tmp; + int ret; + + wl_list_for_each_safe(c, tmp, &srv->client_list, link) { + /* Flush out buffered requests. If the Waltham socket is + * full, poll it for writable too. + */ + ret = wth_connection_flush(c->connection); + if (ret < 0 && errno == EAGAIN) { + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN | EPOLLOUT); + } else if (ret < 0) { + perror("Connection flush failed"); + client_destroy(c); + return; + } + } + + wth_verbose(" <<< %s \n",__func__); + +} + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_accept_client(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *client; + struct wth_connection *conn; + struct sockaddr_in addr; + socklen_t len; + + len = sizeof addr; + conn = wth_accept(srv->listen_fd, (struct sockaddr *)&addr, &len); + if (!conn) { + wth_error("Failed to accept a connection.\n"); + return; + } + + client = client_create(srv, conn); + if (!client) { + wth_error("Failed client_create().\n"); + return; + } + wth_verbose(" <<< %s \n",__func__); +} diff --git a/demo3/horizontal/waltham-server/src/wth-server-weston.c b/demo3/horizontal/waltham-server/src/wth-server-weston.c new file mode 100644 index 0000000..6cc309c --- /dev/null +++ b/demo3/horizontal/waltham-server/src/wth-server-weston.c @@ -0,0 +1,811 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file is acts as interface to weston compositor at server ** +** side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include +#include + +#include "wth-server-weston.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; +/* + * buffer callback + */ +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct shm_buffer *mybuf = data; + + wth_verbose("%s >>> \n",__func__); + + mybuf->busy = 0; + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct display *display, struct shm_buffer *buffer, + int width, int height, uint32_t format) +{ + struct wl_shm_pool *pool; + int fd, size, stride; + void *data; + + wth_verbose("%s >>> \n",__func__); + stride = width * 4; + size = stride * height; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + wth_error("creating a buffer file for %d B failed: %m\n", + size); + return -1; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + wth_error("mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, + stride, format); + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + wl_shm_pool_destroy(pool); + close(fd); + + buffer->shm_data = data; + + wth_verbose(" <<< %s \n",__func__); + return 0; +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->surface = wl_compositor_create_surface(display->compositor); + window->window_frames = 0; + window->window_benchmark_time = 0; + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + + } else { + assert(0); + } + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static struct shm_buffer * +window_next_buffer(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct shm_buffer *buffer; + int ret = 0; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else { + window->buffers[0].busy = 0; + window->buffers[0].busy = 1; + buffer = &window->buffers[0]; + } + + if (!buffer->buffer) { + ret = create_shm_buffer(window->display, buffer, + window->width, window->height, + WL_SHM_FORMAT_XRGB8888); + + if (ret < 0) + return NULL; + + /* paint the padding */ + memset(buffer->shm_data, 0xff, + window->width * window->height * 4); + } + + wth_verbose(" <<< %s \n",__func__); + return buffer; +} + +static void +paint_pixels(void *image, int padding, int width, int height, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + const int halfh = padding + (height - padding * 2) / 2; + const int halfw = padding + (width - padding * 2) / 2; + int ir, or; + uint32_t *pixel = image; + int y; + + /* squared radii thresholds */ + or = (halfw < halfh ? halfw : halfh) - 8; + ir = or - 32; + or *= or; + ir *= ir; + + pixel += padding * width; + for (y = padding; y < height - padding; y++) { + int x; + int y2 = (y - halfh) * (y - halfh); + + pixel += padding; + for (x = padding; x < width - padding; x++) { + uint32_t v; + + /* squared distance from center */ + int r2 = (x - halfw) * (x - halfw) + y2; + + if (r2 < ir) + v = (r2 / 32 + time / 64) * 0x0080401; + else if (r2 < or) + v = (y + time / 32) * 0x0080401; + else + v = (x + time / 16) * 0x0080401; + v &= 0x00ffffff; + + /* cross if compositor uses X from XRGB as alpha */ + if (abs(x - y) > 6 && abs(x + y - height) > 6) + v |= 0xff000000; + + *pixel++ = v; + } + + pixel += padding; + } + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct timeval tv; + uint32_t time; + struct shm_buffer *buffer; + static int ss_count = 0; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + buffer = window_next_buffer(window); + if (!buffer) { + wth_error("Both buffers busy at redraw().\n"); + return; + } + + char *bitmap; + bitmap = getenv("BITMAP"); + if (bitmap) { + if (!strcmp(bitmap, "1")) { + int len; + const char *path = "/tmp/bitmap"; + len = strlen(path); + char *filename; + filename = (char *)malloc(len + 10); + sprintf(filename, "%s%d.bmp", path, ss_count); + wth_verbose("%s\n", filename); + + save_as_bitmap(filename, data, data_sz, width, height, format); + ss_count++; + free(filename); + } + } + buffer->shm_data = data; + window->width = width; + window->height = height; + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_damage(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + wl_surface_damage(window->surface, + 0, 0, window->width, window->height); + + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + static const uint32_t benchmark_interval = 5; + struct timeval tv; + uint32_t time; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (window->window_frames == 0) + window->window_benchmark_time = time; + if (time - window->window_benchmark_time > (benchmark_interval * 1000)) { + wth_verbose("-------------------------------%d frames in %d seconds: %f fps\n", + window->window_frames, + benchmark_interval, + (float) window->window_frames / benchmark_interval); + + window->window_benchmark_time = time; + window->window_frames = 0; + } + + wl_surface_commit(window->surface); + + wl_display_flush(window->display->display); + + if (window->wait) + window->wait = 0; + + window->window_frames++; + wth_verbose(" <<< %s \n",__func__); +} + +/* + * frame callback function - this function will display buffer to surface + */ + +static const struct wl_callback_listener frame_listener; +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = data; + struct shm_buffer *buffer; + + buffer = window_next_buffer(window); + if (!buffer) { + if(!callback) + { + wth_error("Failed to create the first buffer.\n"); + } + else + { + wth_error("Both buffers busy at redraw(). Server bug?\n"); + } + abort(); + } + + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, + 20, 20, window->width - 40, window->height - 40); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +/* + * shm callbcak function + */ + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (format == WL_SHM_FORMAT_XRGB8888) + d->has_xrgb = true; + + wth_verbose(" <<< %s \n",__func__); +} + +struct wl_shm_listener shm_listener = { + shm_format +}; + +/* + * pointer callbcak functions + */ +static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->shm == NULL) { + wth_error("No wl_shm global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (!display->has_xrgb) { + wth_error("WL_SHM_FORMAT_XRGB32 not available\n"); + exit(1); + } + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->shm) + wl_shm_destroy(display->shm); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int +wth_server_weston_main(void *data) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = (struct window *) data; + struct sigaction sigint; + struct display *display; + int ret = 0; + + display = create_display(); + create_window(window, display, 400, 400); + if (!window) + return -1; + wl_display_roundtrip(display->display); + wth_verbose("data %p\n", data); + wth_verbose("window %p\n", window); + + display->window = window; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, + window->width, window->height); + + redraw(window, NULL, 0); + + window->wait = 1; + window->ready = true; + while (window->wait) + { + ret = wl_display_dispatch(display->display); + usleep(1); + } + wth_verbose("debug\n"); + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + wth_verbose("wth_server_weston_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(display); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} -- cgit 1.2.3-korg