receiver: Introduce waltham-receiver 75/21475/2
authorVeeresh Kadasani <external.vkadasani@jp.adit-jv.com>
Fri, 31 May 2019 02:14:15 +0000 (11:14 +0900)
committerVeeresh Kadasani <external.vkadasani@jp.adit-jv.com>
Mon, 8 Jul 2019 02:12:09 +0000 (11:12 +0900)
NewFeature-AGL: SPEC-2445

waltham-receiver sample component is a receiver
side implementation for using waltham protocol to
obtain and process remote output received from
waltham-transmitter

Change-Id: I85983a0ac41c3a086f43fb5912e23f95609e3559
Signed-off-by: Veeresh Kadasani <external.vkadasani@jp.adit-jv.com>
Signed-off-by: Naoko Tanibata <tnaoko@jp.adit-jv.com>
14 files changed:
CMakeLists.txt
waltham-receiver/CMakeLists.txt [new file with mode: 0644]
waltham-receiver/README.md [new file with mode: 0644]
waltham-receiver/include/bitmap.h [new file with mode: 0644]
waltham-receiver/include/os-compatibility.h [new file with mode: 0644]
waltham-receiver/include/wth-receiver-comm.h [new file with mode: 0644]
waltham-receiver/receiver_pipeline_example_general.cfg [new file with mode: 0644]
waltham-receiver/receiver_pipeline_example_intel.cfg [new file with mode: 0644]
waltham-receiver/receiver_pipeline_example_rcar.cfg [new file with mode: 0644]
waltham-receiver/src/utils/bitmap.c [new file with mode: 0644]
waltham-receiver/src/utils/os-compatibility.c [new file with mode: 0644]
waltham-receiver/src/wth-receiver-comm.c [new file with mode: 0644]
waltham-receiver/src/wth-receiver-gst.c [new file with mode: 0644]
waltham-receiver/src/wth-receiver-main.c [new file with mode: 0644]

index 00fd14e..085d3e9 100644 (file)
@@ -1,3 +1,4 @@
 project (weston-ivi-plugins)
 
 add_subdirectory(waltham-transmitter)
+add_subdirectory(waltham-receiver)
diff --git a/waltham-receiver/CMakeLists.txt b/waltham-receiver/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fc6331e
--- /dev/null
@@ -0,0 +1,82 @@
+cmake_minimum_required( VERSION 2.8.5 )
+
+project (waltham-receiver)
+
+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)
+pkg_check_modules(IVI-APPLICATION ivi-application 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)
+find_library(GSTREAMER_WAYLANDSINK NAMES gstwayland-1.0 PATHs ${LIBS})
+
+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}
+    ${IVI-APPLICATION_INCLUDE_DIRS}
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_SOURCE_DIR}/waltham-receiver/include/
+    ${CMAKE_SOURCE_DIR}/waltham-transmitter/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}
+    ${IVI-APPLICATION_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}
+    ${IVI-APPLICATION_LIBRARIES}
+    ${GSTREAMER_WAYLANDSINK}
+)
+
+SET(SRC_FILES
+    src/wth-receiver-main.c
+    src/wth-receiver-comm.c
+    src/wth-receiver-gst.c
+    src/utils/bitmap.c
+    src/utils/os-compatibility.c
+)
+
+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/waltham-receiver/README.md b/waltham-receiver/README.md
new file mode 100644 (file)
index 0000000..d0f63cb
--- /dev/null
@@ -0,0 +1,126 @@
+# Waltham-receiver
+
+waltham-receiver component is a receiver side implementation for using
+Waltham protocol 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.
+
+###Architecture
+
+````
+
+                               ECU 1                                                                     ECU 2
+              +-----------------------------------------------------+                    +----------------------------------------------+
+              |        +-----------------+                          |                    |                                              |
+              |        | IVI-Application |                          |                    |               +-----------+-----------+      |
+              |        +-----------------+                          |                    |               | Gstreamer |           |      |
+              |                 ^                                   |    Buffer   -----------------------> (Decode)  |           |      |
+              |        wayland  |                         +----------------------/       |               +-----------+           |      |
+              |                 v                         |         |    (Ethernet)      |               |     Waltham-receiver  |      |
+              |   +----+---------------------+            |         |        ---------------------------->                       |      |
+              |   |    |  Transmitter Plugin |<-----------------------------/            |               +-----------------------+      |
+              |   |    |                     |            |         |  Waltham-Protocol  |                             ^                |
+              |   |    | +-------------------+            |         |                    |                     wayland |                |
+              |   |    | | waltham-renderer  |------------+         |                    |                             v                |
+              |   |    | |(gstreamer Encode) |                      |                    |                 +---------------------+      |
+              |   |    +-+-------------------+                      |                    |                 |                     |      |
+              |   |                          |                      |                    |                 |       WESTON        |      |
+              |   |         WESTON           |                      |                    |                 |                     |      |
+              |   +------+-------------------+                      |                    |                 +----------------+----+      |
+              |          |                                          |                    |                                  |           |
+              |          v                                          |                    |                                  v           |
+              |   +------------+                                    |                    |                            +----------+      |
+              |   |  Display   |                                    |                    |                            |  Display |      |
+              |   |            |                                    |                    |                            |          |      |
+              |   +------------+                                    |                    |                            +----------+      |
+              +-----------------------------------------------------+                    +----------------------------------------------+
+
+````
+
+###Build Steps
+
+
+1. Prerequisite before building
+
+    weston, wayland, waltham and gstreamer should be built and available.
+
+2. In waltham-receiver directory, create build directory
+
+        $cd waltham-receiver
+        $mkdir build
+        $cd build/
+
+3. Run cmake
+
+        $cmake ../
+        $cmake --build .
+
+4. waltham-receiver binary should be availaible in build directory
+
+###Configure pipeline
+You can use gstreamer pipeline as you want by configuring from "pipeline_receiver.cfg".
+This file should be in the folder "/etc/xdg/weston/".
+
+As an example, please refer to the example file named "pipeline_receiver_example*.cfg".
+
+    -pipeline_receiver_example_general.cfg : Does not use any HW decoder.
+    -pipeline_receiver_example_intel.cfg   : Use Intel's HW decoder.
+    -pipeline_receiver_example_rcar.cfg    : Use Rcar's HW decoder.
+
+Rename file as "pipeline_receiver.cfg" and put in correct place when you use them.
+
+###Connection Establishment
+
+1. Connect two board over ethernet.
+
+2. Assign IP to both the boards and check if the simple ping works.
+
+    For example:if transmitter IP: 192.168.2.51 and Waltham-Receiver IP: 192.168.2.52 then
+
+    $ping 192.168.2.52 (you can also ping vice versa)
+
+3. Make sure that IP address specified in the weston.ini under [remote-output] matches the Waltham-Receiver IP.
+
+4. Make sure that IP address in pipeline.cfg on the transmitter side match the Waltham-Receiver IP.
+
+###Basic test steps
+
+1. Start weston at receiver side
+
+    $weston &
+
+2. Run waltham-receiver
+
+    $waltham-receiver -p < port_number > -v &
+
+3. Start weston with transmitter plugin at transmitter side, run application and put it on transmitter screen.You should see the application rendered on receiver display.
+
+Connection established -receiver side logs:
+
+````
+set_sigint_handler >>>
+ <<< set_sigint_handler
+receiver_listen >>>
+ <<< receiver_listen
+watch_ctl >>>
+ <<< watch_ctl
+Waltham receiver listening on TCP port 34400...
+receiver_mainloop >>>
+receiver_flush_clients >>>
+ <<< receiver_flush_clients
+listen_socket_handle_data >>>
+EPOLLIN evnet received.
+receiver_accept_client >>>
+client_create >>>
+watch_ctl >>>
+ <<< watch_ctl
+Client 0xaaaadc4cde70 connected.
+ <<< client_create
+ <<< receiver_accept_client
+ <<< listen_socket_handle_data
+````
diff --git a/waltham-receiver/include/bitmap.h b/waltham-receiver/include/bitmap.h
new file mode 100644 (file)
index 0000000..3cef52d
--- /dev/null
@@ -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 <stdint.h>
+
+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/waltham-receiver/include/os-compatibility.h b/waltham-receiver/include/os-compatibility.h
new file mode 100644 (file)
index 0000000..690f229
--- /dev/null
@@ -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 <sys/types.h>
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#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/waltham-receiver/include/wth-receiver-comm.h b/waltham-receiver/include/wth-receiver-comm.h
new file mode 100644 (file)
index 0000000..285bacf
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * Copyright © 2019 Advanced Driver Information Technology 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.
+ */
+
+/*******************************************************************************
+**                                                                            **
+**  TARGET    : linux                                                         **
+**                                                                            **
+**  PROJECT   : waltham-receiver                                              **
+**                                                                            **
+**  PURPOSE   : Header file declare macros, extern functions, data types etc, **
+**  required to interface with waltham IPC library                            **
+**                                                                            **
+*******************************************************************************/
+
+#ifndef WTH_SERVER_WALTHAM_COMM_H_
+#define WTH_SERVER_WALTHAM_COMM_H_
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/epoll.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <assert.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <wayland-egl.h>
+#include <wayland-client.h>
+#include <waltham-server.h>
+#include <waltham-connection.h>
+
+#define DEBUG 0
+
+struct receiver;
+struct client;
+struct window;
+struct pointer;
+struct touch;
+static int verbose = 0;
+
+const struct wth_display_interface display_implementation;
+
+/**
+* receiver_accept_client
+*
+* Accepts new waltham client connection and instantiates client structure
+*
+* @param names        struct receiver *srv
+* @param value        socket connection info and client data
+* @return             none
+*/
+void receiver_accept_client(struct receiver *srv);
+
+/**
+* receiver_flush_clients
+*
+* write all the pending requests from the clients to socket
+*
+* @param names        struct receiver *srv
+* @param value        socket connection info and client data
+* @return             none
+*/
+void receiver_flush_clients(struct receiver *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);
+
+/**
+ * set verbosity
+ */
+inline void set_verbosity(int verbosity)
+{
+       verbose = verbosity;
+}
+
+/**
+ * get verbosity
+ */
+inline bool get_verbosity()
+{
+    if (verbose == 1)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/***** 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
+
+#define wth_error(fmt, ...) \
+    ({ fprintf(stderr, pr_fmt(fmt), ## __VA_ARGS__); fflush(stderr); })
+
+#if DEBUG
+#define wth_verbose(fmt, ...) \
+    ({ if (get_verbosity()) { fprintf(stdout, pr_fmt(fmt), ## __VA_ARGS__); fflush(stdout); } })
+#else
+#define wth_verbose(fmt, ...)\
+               ({})
+#endif
+
+/****** 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 ivisurface *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 receiver *receiver;
+    int fd;
+    void (*cb)(struct watch *w, uint32_t events);
+};
+
+struct client {
+    struct wl_list link; /* struct receiver::client_list */
+    struct receiver *receiver;
+
+    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 */
+};
+
+/* receiver structure */
+struct receiver {
+    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 *receiver_surf;
+    struct wl_egl_window *native;
+    EGLSurface egl_surface;
+    EGLImageKHR egl_img;
+    struct seat *receiver_seat;
+    struct pointer *receiver_pointer;
+    bool ready;
+    uint32_t id_ivisurf;
+};
+
+
+#endif
diff --git a/waltham-receiver/receiver_pipeline_example_general.cfg b/waltham-receiver/receiver_pipeline_example_general.cfg
new file mode 100644 (file)
index 0000000..be4d562
--- /dev/null
@@ -0,0 +1 @@
+  udpsrc port=YOUR_RECIEVER_PORT caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG,payload=(int)26" ! rtpjpegdepay ! jpegdec ! waylandsink name=sink sync=true
diff --git a/waltham-receiver/receiver_pipeline_example_intel.cfg b/waltham-receiver/receiver_pipeline_example_intel.cfg
new file mode 100644 (file)
index 0000000..3872f28
--- /dev/null
@@ -0,0 +1 @@
+ udpsrc port=YOUR_RECIEVER_PORT caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264,payload=(int)96" ! rtpjitterbuffer latency=0 ! rtph264depay ! h264parse config-interval=1 disable-passthrough=true ! mfxdecode ! waylandsink  name=sink sync=true
diff --git a/waltham-receiver/receiver_pipeline_example_rcar.cfg b/waltham-receiver/receiver_pipeline_example_rcar.cfg
new file mode 100644 (file)
index 0000000..15fd4ef
--- /dev/null
@@ -0,0 +1 @@
+ udpsrc port=YOUR_RECIEVER_PORT caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264,payload=(int)96" ! rtpjitterbuffer latency=0 ! rtph264depay ! h264parse config-interval=1  disable-passthrough=true ! omxh264dec no-reorder=true ! waylandsink name=sink
diff --git a/waltham-receiver/src/utils/bitmap.c b/waltham-receiver/src/utils/bitmap.c
new file mode 100644 (file)
index 0000000..2c7fdb5
--- /dev/null
@@ -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 <stdio.h>
+
+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/waltham-receiver/src/utils/os-compatibility.c b/waltham-receiver/src/utils/os-compatibility.c
new file mode 100644 (file)
index 0000000..d9502e5
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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/waltham-receiver/src/wth-receiver-comm.c b/waltham-receiver/src/wth-receiver-comm.c
new file mode 100644 (file)
index 0000000..af42f1b
--- /dev/null
@@ -0,0 +1,1176 @@
+/*
+ * Copyright © 2019 Advanced Driver Information Technology 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.
+ */
+
+/*******************************************************************************
+**                                                                            **
+**  TARGET    : linux                                                         **
+**                                                                            **
+**  PROJECT   : waltham-receiver                                              **
+**                                                                            **
+**  PURPOSE   :  This file acts as interface to waltham IPC library           **
+**                                                                            **
+**                                                                            **
+*******************************************************************************/
+
+#include "wth-receiver-comm.h"
+
+extern int wth_receiver_weston_main(struct window *);
+
+extern void wth_receiver_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_receiver_weston_shm_damage(struct window *);
+extern void wth_receiver_weston_shm_commit(struct window *);
+
+/*
+ * 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->receiver->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 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_receiver_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_receiver_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_receiver_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 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_receiver_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->receiver_surf;
+    struct seat *seat = window->receiver_seat;
+    struct pointer *pointer = seat->pointer;
+
+    wth_verbose("waltham_pointer_enter [%d]\n", window->receiver_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->receiver_surf;
+    struct seat *seat = window->receiver_seat;
+    struct pointer *pointer = seat->pointer;
+
+    wth_verbose("waltham_pointer_leave [%d]\n", window->receiver_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 seat *seat = window->receiver_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 seat *seat = window->receiver_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 seat *seat = window->receiver_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->receiver_surf;
+    struct seat *seat = window->receiver_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->receiver_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->receiver_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->receiver_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->receiver_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(&region->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->receiver_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->receiver_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, &region->link);
+
+    wthp_region_set_interface(id, &region_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(&reg->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, &reg->link);
+    wthp_registry_set_interface(registry,
+                    &registry_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                   receiver structure
+* @param wth_connection        Waltham connection handle
+* @return                      Pointer to client structure
+*/
+static struct client *
+client_create(struct receiver *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->receiver = srv;
+    c->connection = conn;
+
+    c->conn_watch.receiver = 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__);
+}
+
+/**
+* receiver_flush_clients
+*
+* write all the pending requests from the clients to socket
+*
+* @param names        struct receiver *srv
+* @param value        socket connection info and client data
+* @return             none
+*/
+void
+receiver_flush_clients(struct receiver *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__);
+
+}
+
+/**
+* receiver_accept_client
+*
+* Accepts new waltham client connection and instantiates client structure
+*
+* @param names        struct receiver *srv
+* @param value        socket connection info and client data
+* @return             none
+*/
+void
+receiver_accept_client(struct receiver *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/waltham-receiver/src/wth-receiver-gst.c b/waltham-receiver/src/wth-receiver-gst.c
new file mode 100644 (file)
index 0000000..6c5f747
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * Copyright © 2019 Advanced Driver Information Technology 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.
+ */
+
+/*******************************************************************************
+ **                                                                              **
+ **  TARGET    : linux                                                           **
+ **                                                                              **
+ **  PROJECT   : waltham-receiver                                                **
+ **                                                                              **
+ **  PURPOSE   : This file is acts as interface to weston compositor at receiver **
+ **  side                                                                        **
+ **                                                                              **
+ *******************************************************************************/
+
+#include <sys/mman.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <gst/gst.h>
+#include <GL/gl.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/allocators/gstdmabuf.h>
+#include <gst/app/gstappsink.h>
+#include <pthread.h>
+#include <gst/wayland/wayland.h>
+#include <gst/video/videooverlay.h>
+
+#include <xf86drm.h>
+#include <drm.h>
+#include <drm_fourcc.h>
+
+#include "wth-receiver-comm.h"
+#include "os-compatibility.h"
+#include "ivi-application-client-protocol.h"
+#include "bitmap.h"
+static int running = 1;
+
+typedef struct _GstAppContext
+{
+       GMainLoop *loop;
+       GstBus *bus;
+       GstElement *pipeline;
+       GstElement *sink;
+       struct display *display;
+       struct window *window;
+       GstVideoInfo info;
+}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;
+
+       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->wl_touch = NULL;
+       display->wl_keyboard = 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__);
+}
+
+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");
+}
+
+/*
+ *  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_receiver_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_receiver_weston_shm_damage(struct window *window)
+{
+       /* stub */
+}
+
+void
+wth_receiver_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,
+                       &registry_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);
+       wth_verbose("%s <<< \n",__func__);
+}
+
+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.0, 0.0, 0.0, 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;
+       }
+
+       dec->window->width=GST_VIDEO_INFO_WIDTH(&dec->info);
+       dec->window->height=GST_VIDEO_INFO_HEIGHT(&dec->info);
+       gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY (dec->sink),0,0,dec->window->width,dec->window->height);
+       wl_surface_commit(dec->window->surface);
+
+       wth_verbose(" <<< %s \n",__func__);
+       return GST_PAD_PROBE_OK;
+}
+
+/**
+ * wth_receiver_weston_main
+ *
+ * This is the main function which will handle connection to the compositor at receiver side
+ *
+ * @param names        void *data
+ * @param value        struct window data
+ * @return             0 on success, -1 on error
+ */
+int
+wth_receiver_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;
+       GstContext *context;
+
+       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/receiver_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");
+
+       /* get sink element */
+       gstctx.sink = gst_bin_get_by_name(GST_BIN(gstctx.pipeline), "sink");
+       /* get display context */
+       context = gst_wayland_display_handle_context_new(gstctx.display->display);
+       /* set external display from context to sink */
+       gst_element_set_context(gstctx.sink,context);
+       /* Attach existing surface to sink */
+       gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY (gstctx.sink),window->surface);
+
+       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_create(&pthread, NULL, &stream_thread, gstctx.loop);
+
+       fprintf(stderr, "rendering part\n");
+
+       wth_verbose("in render loop\n");
+       while (running && ret != -1)
+               ret=wl_display_dispatch_pending(gstctx.display->display);
+
+
+       wth_verbose("wth_receiver_gst_main exiting\n");
+
+       if (window->display->ivi_application) {
+               ivi_surface_destroy(window->ivi_surface);
+               ivi_application_destroy(window->display->ivi_application);
+       }
+
+       gst_element_set_state((GstElement*)((void*)gstctx.pipeline), GST_STATE_NULL);
+       destroy_window(window);
+       destroy_display(gstctx.display);
+
+       wth_verbose(" <<< %s \n",__func__);
+
+       return 0;
+}
diff --git a/waltham-receiver/src/wth-receiver-main.c b/waltham-receiver/src/wth-receiver-main.c
new file mode 100644 (file)
index 0000000..cce1e83
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright © 2019 Advanced Driver Information Technology 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.
+ */
+
+/*******************************************************************************
+**                                                                            **
+**  TARGET    : linux                                                         **
+**                                                                            **
+**  PROJECT   : waltham-receiver                                              **
+**                                                                            **
+**  PURPOSE   : This file handles connection with remote-client               **
+**                                                                            **
+*******************************************************************************/
+
+#include <signal.h>
+#include "wth-receiver-comm.h"
+
+#define MAX_EPOLL_WATCHES 2
+
+uint16_t tcp_port;
+
+/** Print out the application help
+ */
+static void usage(void)
+{
+    printf("Usage: waltham receiver [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':
+#if DEBUG
+            set_verbosity(1);
+#else
+            printf("No verbose logs for release mode");
+#endif
+            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->receiver->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 receiver information, Incoming events information
+* @return             none
+*/
+static void
+listen_socket_handle_data(struct watch *w, uint32_t events)
+{
+    wth_verbose("%s >>> \n",__func__);
+    struct receiver *srv = container_of(w, struct receiver, 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");
+        receiver_accept_client(srv);
+    }
+    wth_verbose(" <<< %s \n",__func__);
+}
+
+/**
+* receiver_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 receiver struct -
+*                     struct holds the client connection information
+* @return             none
+*/
+static void
+receiver_mainloop(struct receiver *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. */
+
+        receiver_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
+receiver_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 receiver 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 receiver 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 = receiver_listen(tcp_port);
+    if (srv.listen_fd < 0) {
+        perror("Error setting up listening socket");
+        exit(1);
+    }
+
+    srv.listen_watch.receiver = &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 receiver listening on TCP port %u...\n",tcp_port);
+
+
+    receiver_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;
+}