From: Wataru Mizuno Date: Mon, 20 Aug 2018 22:49:01 +0000 (+0900) Subject: waltham-transmitter: modify reciepe file X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=commitdiff_plain;h=90df7161b6fbefed9309125d8c24f29b7e8a1f87;p=AGL%2Fmeta-agl.git waltham-transmitter: modify reciepe file Change-Id: I2991b59ab7d84acd8cb8250ea956cdaadd9fbc9f Signed-off-by: Wataru Mizuno --- diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch deleted file mode 100644 index a27788d71..000000000 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter/0001-waltham-transmitter-initial-commit-of-waltham-transm.patch +++ /dev/null @@ -1,3932 +0,0 @@ -From 2bcc81912b92d6ba7a6d24e972e0bcce2e746cab Mon Sep 17 00:00:00 2001 -From: Wataru Mizuno -Date: Wed, 4 Jul 2018 09:09:33 +0900 -Subject: [PATCH] transmitter: initial commit for waltham-transmitter - -The waltham-transmitter is the plugin of weston to enable client -applications to share its surface between multiple domains. - -Signed-off-by: Wataru Mizuno ---- - CMakeLists.txt | 3 + - waltham-transmitter/CMakeLists.txt | 4 + - waltham-transmitter/COPYING | 30 + - .../transmitter-plugin/CMakeLists.txt | 62 + - waltham-transmitter/transmitter-plugin/README | 97 ++ - waltham-transmitter/transmitter-plugin/input.c | 1317 ++++++++++++++++++++ - waltham-transmitter/transmitter-plugin/output.c | 352 ++++++ - waltham-transmitter/transmitter-plugin/plugin.c | 940 ++++++++++++++ - waltham-transmitter/transmitter-plugin/plugin.h | 330 +++++ - .../transmitter-plugin/transmitter_api.h | 278 +++++ - .../transmitter-plugin/weston.ini.transmitter | 21 + - .../waltham-renderer/CMakeLists.txt | 59 + - .../waltham-renderer/waltham-renderer.c | 270 ++++ - .../waltham-renderer/waltham-renderer.h | 41 + - 14 files changed, 3804 insertions(+) - create mode 100644 CMakeLists.txt - create mode 100644 waltham-transmitter/CMakeLists.txt - create mode 100644 waltham-transmitter/COPYING - create mode 100644 waltham-transmitter/transmitter-plugin/CMakeLists.txt - create mode 100644 waltham-transmitter/transmitter-plugin/README - create mode 100644 waltham-transmitter/transmitter-plugin/input.c - create mode 100644 waltham-transmitter/transmitter-plugin/output.c - create mode 100644 waltham-transmitter/transmitter-plugin/plugin.c - create mode 100644 waltham-transmitter/transmitter-plugin/plugin.h - create mode 100644 waltham-transmitter/transmitter-plugin/transmitter_api.h - create mode 100644 waltham-transmitter/transmitter-plugin/weston.ini.transmitter - create mode 100644 waltham-transmitter/waltham-renderer/CMakeLists.txt - create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.c - create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.h - -diff --git a/CMakeLists.txt b/CMakeLists.txt -new file mode 100644 -index 0000000..00fd14e ---- /dev/null -+++ b/CMakeLists.txt -@@ -0,0 +1,3 @@ -+project (weston-ivi-plugins) -+ -+add_subdirectory(waltham-transmitter) -diff --git a/waltham-transmitter/CMakeLists.txt b/waltham-transmitter/CMakeLists.txt -new file mode 100644 -index 0000000..b4d1243 ---- /dev/null -+++ b/waltham-transmitter/CMakeLists.txt -@@ -0,0 +1,4 @@ -+project (transmitter) -+ -+add_subdirectory(transmitter-plugin) -+add_subdirectory(waltham-renderer) -diff --git a/waltham-transmitter/COPYING b/waltham-transmitter/COPYING -new file mode 100644 -index 0000000..faefd8f ---- /dev/null -+++ b/waltham-transmitter/COPYING -@@ -0,0 +1,30 @@ -+Copyright © 2008-2012 Kristian Høgsberg -+Copyright © 2010-2012 Intel Corporation -+Copyright © 2010-2011 Benjamin Franzke -+Copyright © 2011-2012 Collabora, Ltd. -+Copyright © 2010 Red Hat -+ -+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. -+ -+--- -+ -+The above is the version of the MIT "Expat" License used by X.org: -+ -+ http://cgit.freedesktop.org/xorg/xserver/tree/COPYING -diff --git a/waltham-transmitter/transmitter-plugin/CMakeLists.txt b/waltham-transmitter/transmitter-plugin/CMakeLists.txt -new file mode 100644 -index 0000000..a900d3b ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/CMakeLists.txt -@@ -0,0 +1,62 @@ -+project (transmitter) -+ -+find_package(PkgConfig REQUIRED) -+pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) -+pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) -+pkg_check_modules(PIXMAN pixman-1 REQUIRED) -+pkg_check_modules(WALTHAM waltham REQUIRED) -+ -+include_directories( -+ include -+ ${CMAKE_SOURCE_DIR}/waltham-transmitter/waltham-renderer -+ ${CMAKE_CURRENT_BINARY_DIR} -+ ${WAYLAND_CLIENT_INCLUDE_DIRS} -+ ${WAYLAND_SERVER_INCLUDE_DIRS} -+ ${WESTON_INCLUDE_DIRS} -+ ${PIXMAN_INCLUDE_DIRS} -+ ${WALTHAM_INCLUDE_DIRS} -+) -+ -+link_directories( -+ ${WAYLAND_SERVER_LIBRARY_DIRS} -+ ${WESTON_LIBRARY_DIRS} -+ ${PIXMAN_LIBRARY_DIRS} -+ ${WALTHAM_LIBRARY_DIRS} -+) -+ -+add_library(${PROJECT_NAME} MODULE -+ plugin.c -+ output.c -+ input.c -+ plugin.h -+ transmitter_api.h -+) -+ -+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") -+ -+set(LIBS -+ m -+ ${WAYLAND_SERVER_LIBRARIES} -+ ${WESTON_LIBRARIES} -+ ${PIXMAN_LIBRARIES} -+ ${WALTHAM_LIBRARIES} -+) -+ -+SET(SRC_FILES -+ plugin.c -+ output.c -+ input.c -+ plugin.h -+ transmitter_api.h -+) -+ -+ -+ -+add_dependencies(${PROJECT_NAME} ${LIBS}) -+ -+target_link_libraries(${PROJECT_NAME} ${LIBS}) -+ -+install ( -+ TARGETS ${PROJECT_NAME} -+ LIBRARY DESTINATION lib64/weston -+) -diff --git a/waltham-transmitter/transmitter-plugin/README b/waltham-transmitter/transmitter-plugin/README -new file mode 100644 -index 0000000..345142d ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/README -@@ -0,0 +1,97 @@ -+Transmitter plugin -+ -+The current implementation of Transmitter is a stub which interfaces to -+other Weston parts appropriately, but all networking is just a mockup. -+ -+Sections in this file describe: -+- How to build -+- How to write weston.ini -+- How to test -+ -+How to build -+============ -+Configure Weston with --enable-surface-remoting to build the Transmitter -+plugin. -+ -+How to write weston.ini -+======================= -+To load transmitter plugin to weston, add 'transmitter.so' to the 'modules' -+key under '[core]', and make sure the 'shell' is 'ivi-shell.so'. -+ -+The destination of remoting is configured in weston.ini. -+Add output name, server address, port number, output's width and height key -+under '[remote-output]'. -+You can speficy multiple [remote-output]. -+ -+In details, see 'weston.ini.transmitter'. -+ -+How to test -+=========== -+You can use server side test application in waltham-server directory. -+ -+If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can -+see the log like this: -+ -+ [13:24:08.345] Loading module '/usr/lib64/weston/transmitter.so' -+ [13:24:08.345] Registered plugin API 'transmitter_v1' of size 88 -+ [13:24:08.345] Registered plugin API 'transmitter_ivi_v1' of size 16 -+ [13:24:08.345] Transmitter initialized. -+ [13:24:08.345] Loading module '/usr/lib64/libweston-2/waltham-renderer.so' -+ [13:24:08.352] gst-setting are :--> -+ [13:24:08.352] ip = 192.168.2.52 -+ [13:24:08.352] port = 34400 -+ [13:24:08.352] bitrate = 3000000 -+ [13:24:08.352] crop = 384 x 368 -+ [13:24:08.352] width = 1920 -+ [13:24:08.352] width = 1080 -+ [13:24:08.531] open media device: platform:fe960000.vsp (fe960000.vsp) -+ [13:24:08.532] input pad setup ('fe960000.vsp rpf.0 input':'/dev/video0') -+ [13:24:08.533] output pad setup (fe960000.vsp wpf.0 output:/dev/video5) -+ [13:24:08.533] vsp-device '/dev/media0' created -+ [13:24:08.533] gst_recorder_create (1920x1080) crop 384x368 at 0,0 -+ [13:24:08.533] gst_pipeline: starting: appsrc name=src ! omxh264enc target-bitrate=3000000 control-rate=2 no-copy=k -+ [13:24:08.582] goot 1 pools -+ [13:24:08.583] pool settings size 211968, min 5, max 5 -+ [13:24:08.583] gst_recorder_create done -+ [13:24:08.583] [gst recorder] transmitter-192.168.2.52:34400-1: recorder initialized -+ [13:24:08.583] Transmitter weston_seat 0x15424630 -+ [13:24:08.583] Transmitter created pointer=0x15625df0 for seat 0x15424630 -+ [13:24:08.583] Transmitter created keyboard=0x154247c0 for seat 0x15424630 -+ [13:24:08.583] Transmitter created touch=0x15625f10 for seat 0x15424630 -+ -+The connection is established, you can see following debug messages: -+ -+ debug: wth_connection_insert_new_object: new object id: 1 -+ debug: wth_connection_insert_new_object: new object id: 2 -+ 2018-01-09T13:24:22Z 00001000030000000100000002000000 wth_display_get_registry -+ debug: wth_connection_insert_new_object: new object id: 3 -+ 2018-01-09T13:24:22Z 00001000020000000100000003000000 wth_display_sync -+ debug: Message received on conn 0x15572730: (9) 40 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 4 -+ 2018-01-09T13:24:22Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthpd -+ debug: Message received on conn 0x15572730: (9) 48 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 1) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 5 -+ 2018-01-09T13:24:22Z 000034000800000002000000010000000500000015000000777468705f6976695f6170706c69636174696f6e00010d -+ debug: Message received on conn 0x15572730: (9) 44 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 6 -+ 2018-01-09T13:24:22Z 000030000800000002000000010000000600000012000000777468705f626c6f625f666163746f72790001000000 d -+ debug: Message received on conn 0x15572730: (9) 36 bytes -+ debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called. -+ debug: wth_connection_insert_new_object: new object id: 7 -+ 2018-01-09T13:24:22Z 00002800080000000200000001000000070000000a000000777468705f736561740001000000 wthp_registry_bid -+ debug: Message received on conn 0x15572730: (11) 16 bytes -+ debug: wthp_callback_send_done(3, 0) (opcode 11) called. -+ -+Start remoting : -+- Start an IVI application. -+- Put surface on transmitter output -+ -+Weston log will indicate remoting has started: -+ -+[13:18:24.572] HMI transmitting surface 0x1c3dad0, ivi-id 0x9ff6 -+[13:18:24.572] Transmitter: update surface 0x1c3dad0 (0, 0), 0 cb -+[13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6) -+[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1 -\ No newline at end of file -diff --git a/waltham-transmitter/transmitter-plugin/input.c b/waltham-transmitter/transmitter-plugin/input.c -new file mode 100644 -index 0000000..e00546b ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/input.c -@@ -0,0 +1,1317 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture 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. -+ */ -+ -+#include -+#include -+#include -+ -+/* for fake stuff */ -+#include -+ -+#include "compositor.h" -+ -+#include "plugin.h" -+#include "transmitter_api.h" -+ -+/** @file -+ * -+ * This is an implementation of a remote input. -+ * -+ * Request wl_data_device_manager.get_data_device would need to be blocked, -+ * except maybe it's not necessary, we just "forget" to forward data to/from -+ * the remote wl_seat. It might still work inside the local compositor. -+ * -+ * weston_compositor_set_default_pointer_grab() will break our pointer -+ * implementation, but no in-tree code is calling it. -+ */ -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+static void -+pointer_focus_grab_handler(struct weston_pointer_grab *grab) -+{ -+ /* No-op: -+ * -+ * Weston internal events do not change the focus. -+ */ -+} -+ -+static void -+pointer_motion_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ struct weston_pointer_motion_event *event) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_button_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_axis_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t time, -+ struct weston_pointer_axis_event *event) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_axis_source_grab_handler(struct weston_pointer_grab *grab, -+ uint32_t source) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_frame_grab_handler(struct weston_pointer_grab *grab) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+static void -+pointer_cancel_grab_handler(struct weston_pointer_grab *grab) -+{ -+ weston_log("Unexpected! %s(pointer=%p, ...)\n", -+ __func__, grab->pointer); -+} -+ -+/* These handlers would be called from the notify_*() functions in src/input.c. -+ * However, as we do not use the low level input notify_*() functions that -+ * backends drive, these are mostly uncalled, except the focus handler which -+ * weston core generates internally. -+ */ -+static const struct weston_pointer_grab_interface pointer_grab_impl = { -+ pointer_focus_grab_handler, -+ pointer_motion_grab_handler, -+ pointer_button_grab_handler, -+ pointer_axis_grab_handler, -+ pointer_axis_source_grab_handler, -+ pointer_frame_grab_handler, -+ pointer_cancel_grab_handler, -+}; -+ -+static void -+keyboard_grab_key(struct weston_keyboard_grab *grab, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+} -+ -+static void -+keyboard_grab_modifiers(struct weston_keyboard_grab *grab, -+ uint32_t serial, -+ uint32_t mods_depressed, -+ uint32_t mods_latched, -+ uint32_t mods_locked, -+ uint32_t group) -+{ -+} -+ -+static void -+keyboard_grab_cancel(struct weston_keyboard_grab *grab) -+{ -+} -+ -+static const struct weston_keyboard_grab_interface keyborad_grab_impl = { -+ keyboard_grab_key, -+ keyboard_grab_modifiers, -+ keyboard_grab_cancel -+}; -+ -+static void -+touch_grab_down_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+} -+ -+static void -+touch_grab_up_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id) -+{ -+} -+ -+static void -+touch_grab_motion_handler(struct weston_touch_grab *grab, -+ uint32_t time, -+ int touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+} -+ -+static void -+touch_grab_frame_handler(struct weston_touch_grab *grab) -+{ -+} -+ -+static void -+touch_grab_cancel_handler(struct weston_touch_grab *grab) -+{ -+} -+ -+static const struct weston_touch_grab_interface touch_grab_impl = { -+ touch_grab_down_handler, -+ touch_grab_up_handler, -+ touch_grab_motion_handler, -+ touch_grab_frame_handler, -+ touch_grab_cancel_handler, -+}; -+ -+ -+/* The different ways to get pointer focus on a remoted surface: -+ * -+ * 1. Transmitter seat has pointer. The client has wl_pointer. Transmitter -+ * receives pointer.enter. (transmitter_seat_pointer_enter()) -+ * -+ * 2. Transmitter seat has pointer. Transmitter has received pointer.enter. -+ * The client calls wl_seat.get_pointer. => send enter only on the new -+ * wl_pointer. (seat_get_pointer_handler()) -+ * -+ * 3. Client has wl_pointer. Transmitter seat adds pointer capability. -+ * Transmitter receives pointer.enter. wl_pointer MUST NOT enter, -+ * specified by wl_seat.capabilities. -+ * -+ * By definition, Transmitter cannot receive pointer.enter without having -+ * pointer capability in the seat, so no other combinations are possible. -+ * -+ * The same applies to wl_keyboard and wl_touch. -+ */ -+ -+/* Implementor notes: -+ * -+ * The handling of all of wl_pointer, wl_keyboard and wl_touch should be -+ * similar. To make it work, we need to add a signal to each of the -+ * wl_seat.get_pointer, wl_seat.get_keyboard, and wl_seat.get_touch request -+ * handlers in Weston core. Otherwise we cannot implement the case 2 of gaining -+ * input device focus. -+ * -+ * However, weston_keyboard::focus is a weston_surface, not a weston_view, so -+ * we may be able to leverage more of the core implementation and maybe do -+ * without the wl_seat.get_keyboard signal. Weston_touch uses a weston_view, so -+ * that is similar to weston_pointer. -+ * -+ * It might be useful to convert weston_keyboard and weston_touch to use a -+ * similar thing as weston_pointer_client, in case it makes things more -+ * consistent. It might also fix issues when a client has multiple copies of a -+ * wl_keyboard or a wl_touch, but that is getting off-topic. -+ * -+ * This file shows which part of the Weston input path we skip and where we -+ * hook in. We skip everything starting from the notify_*() API used by -+ * backends, and stub out the grab handlers. Instead of actual grab handlers, -+ * we have our own network protocol events handlers. They do much of the same -+ * as normal grab handlers would do, except focus is pre-given, and we do not -+ * have weston_view for the focus surfaces, so we need to bypass core code -+ * dealing with those. -+ * -+ * Our remote seat implementation will leave many struct members unused and -+ * replicate some from weston_pointer, weston_keyboard, and weston_touch. -+ * Weston core must be kept out from the focus handling business, because we -+ * will send enter/leave events ourselves, and focus assignments are given -+ * to us from the remote, they cannot be changed at will by the local Weston. -+ */ -+ -+/** Callback from the protocol request handler for wl_seat.get_pointer -+ * -+ * The Weston core handler never sees focus set on the weston_pointer, -+ * so it won't send wl_pointer.enter nor set focus_client. It does call -+ * weston_pointer_ensure_pointer_client() though. -+ */ -+static void -+seat_get_pointer_handler(struct wl_listener *listener, void *data) -+{ -+ struct wl_resource *new_pointer = data; -+ struct weston_transmitter_seat *seat; -+ struct wl_resource *surface; -+ struct weston_pointer_client *pointer_client; -+ struct wl_client *client; -+ struct weston_pointer *pointer; -+ -+ seat = wl_container_of(listener, seat, get_pointer_listener); -+ if (!seat->pointer_focus) -+ return; -+ -+ client = wl_resource_get_client(new_pointer); -+ surface = seat->pointer_focus->surface->resource; -+ -+ if (wl_resource_get_client(surface) != client) -+ return; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); /* guaranteed by having pointer_focus */ -+ pointer_client = weston_pointer_get_pointer_client(pointer, client); -+ -+ if (!pointer->focus_client) -+ pointer->focus_client = pointer_client; -+ else -+ assert(pointer->focus_client == pointer_client); -+ -+ wl_pointer_send_enter(new_pointer, pointer->focus_serial, surface, -+ seat->pointer_surface_x, seat->pointer_surface_y); -+ -+ if (wl_resource_get_version(new_pointer) >= -+ WL_POINTER_FRAME_SINCE_VERSION) -+ wl_pointer_send_frame(new_pointer); -+} -+ -+static void -+transmitter_seat_create_pointer(struct weston_transmitter_seat *seat) -+{ -+ struct weston_pointer *pointer; -+ -+ seat->pointer_phase = 0.0; -+ seat->pointer_surface_x = wl_fixed_from_int(-1000000); -+ seat->pointer_surface_y = wl_fixed_from_int(-1000000); -+ seat->pointer_focus = NULL; -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ weston_seat_init_pointer(seat->base); -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ -+ /* not exported: -+ * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */ -+ pointer->default_grab.interface = &pointer_grab_impl; -+ -+ /* Changes to local outputs are irrelevant. */ -+ wl_list_remove(&pointer->output_destroy_listener.link); -+ wl_list_init(&pointer->output_destroy_listener.link); -+ -+ weston_log("Transmitter created pointer=%p for seat %p\n", -+ pointer, seat->base); -+} -+ -+static void -+seat_pointer_focus_destroy_handler(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs = data; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(listener, seat, pointer_focus_destroy_listener); -+ assert(seat->pointer_focus == txs); -+ -+ seat->pointer_focus = NULL; -+} -+ -+void -+transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y) -+{ -+ struct wl_client *client; -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ assert(txs->surface); -+ client = wl_resource_get_client(txs->surface->resource); -+ -+ seat->pointer_focus = txs; -+ seat->pointer_focus_destroy_listener.notify = -+ seat_pointer_focus_destroy_handler; -+ wl_signal_add(&txs->destroy_signal, -+ &seat->pointer_focus_destroy_listener); -+ -+ /* If pointer-focus gets destroyed, txs will get destroyed, the -+ * remote surface object is destroyed, and the remote will send a -+ * leave and a frame. -+ */ -+ -+ seat->pointer_surface_x = surface_x; -+ seat->pointer_surface_y = surface_y; -+ -+ pointer->focus_serial = serial; -+ -+ /* pointer->focus is not used, because it is a weston_view, while -+ * remoted surfaces have no views. -+ * -+ * pointer->x,y are not used because they are in global coordinates. -+ * Remoted surfaces are not in the global space at all, so there are -+ * no such coordinates. -+ */ -+ -+ if (!pointer->focus_client) -+ return; -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_enter(resource, -+ serial, -+ txs->surface->resource, -+ surface_x, surface_y); -+ } -+} -+ -+void -+transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *surface_resource; -+ struct wl_resource *resource; -+ -+ if (txs != seat->pointer_focus) { -+ weston_log("Transmitter Warning: pointer leave for %p, expected %p\n", -+ txs, seat->pointer_focus); -+ } -+ -+ seat->pointer_focus = NULL; -+ wl_list_remove(&seat->pointer_focus_destroy_listener.link); -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ if (!txs) -+ return; -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ if (!pointer->focus_client) -+ return; -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) -+ wl_pointer_send_leave(resource, serial, surface_resource); -+ -+ /* Do not reset pointer->focus_client, because we need to be able -+ * to send a following 'frame' event in -+ * transmitter_seat_pointer_frame(). -+ */ -+} -+ -+void -+transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ seat->pointer_surface_x = surface_x; -+ seat->pointer_surface_y = surface_y; -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_motion(resource, time, -+ surface_x, surface_y); -+ } -+} -+ -+void -+transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_button(resource, serial, time, -+ button, state); -+ } -+} -+ -+void -+transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis, -+ wl_fixed_t value) -+{ -+ struct weston_pointer *pointer; -+ struct wl_list *focus_resource_list; -+ struct wl_resource *resource; -+ struct weston_transmitter_surface *txs; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ assert(pointer); -+ -+ if (!pointer->focus_client) -+ return; -+ -+ txs = seat->pointer_focus; -+ if (txs) -+ assert(wl_resource_get_client(txs->surface->resource) == -+ pointer->focus_client->client); -+ -+ focus_resource_list = &pointer->focus_client->pointer_resources; -+ wl_resource_for_each(resource, focus_resource_list) { -+ wl_pointer_send_axis(resource, time, -+ axis, value); -+ } -+} -+ -+void -+transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat) -+{ -+ struct weston_pointer *pointer; -+ -+ pointer = weston_seat_get_pointer(seat->base); -+ if (pointer) -+ weston_pointer_send_frame(pointer); -+} -+ -+void -+transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, -+ uint32_t axis_source) -+{ -+ /* ToDo : implement axis event handling */ -+} -+ -+void -+transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis) -+{ -+ /* ToDo : implement axis event handling */ -+} -+ -+void -+transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, -+ uint32_t axis, -+ int32_t discrete) -+{ -+ /* ToDo : implement axis event handling */ -+} -+ -+static void -+transmitter_seat_create_keyboard(struct weston_transmitter_seat *seat) -+{ -+ struct weston_keyboard *keyboard; -+ -+ seat->keyboard_focus = NULL; -+ weston_seat_init_keyboard(seat->base, NULL); -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ -+ keyboard->default_grab.interface = &keyborad_grab_impl; -+ -+ weston_log("Transmitter created keyboard=%p for seat %p\n", -+ keyboard, seat->base); -+} -+ -+static void -+transmitter_seat_keyboard_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ struct wl_array *keys) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ seat->keyboard_focus = txs; -+ wl_array_copy(&keyboard->keys, keys); -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_keyboard_send_enter(resource, -+ serial, -+ surface_resource, -+ &keyboard->keys); -+ } -+ } -+} -+ -+static void -+transmitter_seat_keyboard_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_keyboard_send_leave(resource, -+ serial, -+ surface_resource); -+ } -+ } -+} -+ -+static void -+transmitter_seat_keyboard_key(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+ struct weston_keyboard *keyboard; -+ struct wl_resource *resource = NULL; -+ -+ keyboard = weston_seat_get_keyboard(seat->base); -+ assert(keyboard); -+ -+ wl_resource_for_each(resource, &keyboard->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->keyboard_focus->surface->resource)) { -+ wl_keyboard_send_key(resource, -+ serial, -+ time, -+ key, -+ state); -+ } -+ } -+} -+ -+static void -+transmitter_seat_create_touch(struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ -+ seat->touch_focus = NULL; -+ weston_seat_init_touch(seat->base); -+ -+ touch = weston_seat_get_touch(seat->base); -+ -+ touch->default_grab.interface = &touch_grab_impl; -+ -+ weston_log("Transmitter created touch=%p for seat %p\n", -+ touch, seat->base); -+} -+ -+static void -+transmitter_seat_touch_down (struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ struct weston_transmitter_surface *txs, -+ int32_t touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ struct wl_resource *surface_resource; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ assert(txs->surface); -+ surface_resource = txs->surface->resource; -+ -+ seat->touch_focus = txs; -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) { -+ wl_touch_send_down(resource, serial, time, -+ surface_resource, -+ touch_id, x, y); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_up (struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ int32_t touch_id) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_up(resource, serial, time, touch_id); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_motion (struct weston_transmitter_seat *seat, -+ uint32_t time, -+ int32_t touch_id, -+ wl_fixed_t x, -+ wl_fixed_t y) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_motion(resource, time, touch_id, x, y); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_frame (struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_frame(resource); -+ } -+ } -+} -+ -+static void -+transmitter_seat_touch_cancel (struct weston_transmitter_seat *seat) -+{ -+ struct weston_touch *touch; -+ struct wl_resource *resource = NULL; -+ -+ touch = weston_seat_get_touch(seat->base); -+ assert(touch); -+ -+ wl_resource_for_each(resource, &touch->resource_list) { -+ if (wl_resource_get_client(resource) == -+ wl_resource_get_client(seat->touch_focus->surface->resource)) { -+ wl_touch_send_cancel(resource); -+ } -+ } -+} -+ -+static char * -+make_seat_name(struct weston_transmitter_remote *remote, const char *name) -+{ -+ char *str; -+ -+ if (asprintf(&str, "transmitter-%s-%s", remote->addr, name) < 0) -+ return NULL; -+ -+ return str; -+} -+ -+void -+transmitter_seat_destroy(struct weston_transmitter_seat *seat) -+{ -+ wl_list_remove(&seat->link); -+ -+ weston_log("Transmitter destroy seat=%p\n", seat->base); -+ -+ wl_list_remove(&seat->get_pointer_listener.link); -+ wl_list_remove(&seat->pointer_focus_destroy_listener.link); -+ -+ if (seat->pointer_timer) -+ wl_event_source_remove(seat->pointer_timer); -+ -+ free(seat); -+} -+ -+static void -+pointer_handle_enter(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ struct wthp_surface *surface, -+ wth_fixed_t surface_x, -+ wth_fixed_t surface_y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ if (txs != seat->pointer_focus) -+ transmitter_seat_pointer_leave(seat, serial, seat->pointer_focus); -+ transmitter_seat_pointer_enter(seat, serial, txs, -+ surface_x, surface_y); -+ } -+ } -+} -+ -+static void -+pointer_handle_leave(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ struct wthp_surface *surface) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_pointer_leave(seat, serial, txs); -+ } -+ } -+} -+ -+static void -+pointer_handle_motion(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ wth_fixed_t surface_x, -+ wth_fixed_t surface_y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_pointer_motion(seat, time, -+ surface_x, -+ surface_y); -+} -+ -+static void -+pointer_handle_button(struct wthp_pointer *wthp_pointer, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_pointer_button(seat, serial, -+ time, button, -+ state); -+} -+ -+static void -+pointer_handle_axis(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ uint32_t axis, wth_fixed_t value) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_pointer); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_pointer_axis(seat, time, -+ axis, value); -+} -+ -+static void -+pointer_handle_frame(struct wthp_pointer *wthp_pointer) -+{ -+ /* ToDo : implement pointer handle frame */ -+} -+ -+static void -+pointer_handle_axis_source(struct wthp_pointer *wthp_pointer, -+ uint32_t axis_source) -+{ -+ /* ToDo : implement pointer handle axis source */ -+} -+ -+static void -+pointer_handle_axis_stop(struct wthp_pointer *wthp_pointer, -+ uint32_t time, -+ uint32_t axis) -+{ -+ /* ToDo : implement pointer handle axis stop */ -+} -+ -+static void -+pointer_handle_axis_discrete(struct wthp_pointer *wthp_pointer, -+ uint32_t axis, -+ int32_t discrete) -+{ -+ /* ToDo : implement pointer handle axis discrete */ -+} -+ -+static const struct wthp_pointer_listener pointer_listener = { -+ pointer_handle_enter, -+ pointer_handle_leave, -+ pointer_handle_motion, -+ pointer_handle_button, -+ pointer_handle_axis, -+ pointer_handle_frame, -+ pointer_handle_axis_source, -+ pointer_handle_axis_stop, -+ pointer_handle_axis_discrete -+}; -+ -+static void -+keyboard_handle_keymap(struct wthp_keyboard * wthp_keyboard, -+ uint32_t format, -+ uint32_t keymap_sz, -+ void * keymap) -+{ -+ /* ToDo : implement keyboard handle keymap */ -+} -+ -+static void -+keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ struct wthp_surface *surface, -+ struct wth_array *keys) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ struct wl_array *wl_key = (struct wl_array *)malloc(sizeof(struct wl_array)); -+ -+ wl_key->size = keys->size; -+ wl_key->alloc = keys->alloc; -+ wl_key->data = keys->data; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ //transmitter_seat_keyboard_enter(seat, serial, txs, keys); -+ transmitter_seat_keyboard_enter(seat, serial, txs, wl_key); -+ } -+ } -+ free(wl_key); -+} -+ -+static void -+keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ struct wthp_surface *surface) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_keyboard_leave(seat, serial, txs); -+ } -+ } -+} -+ -+static void -+keyboard_handle_key(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t key, -+ uint32_t state) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_keyboard); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_keyboard_key(seat, serial, time, key, state); -+} -+ -+static void -+keyboard_handle_modifiers(struct wthp_keyboard *wthp_keyboard, -+ uint32_t serial, -+ uint32_t mods_depressed, -+ uint32_t mods_latched, -+ uint32_t mods_locked, -+ uint32_t group) -+{ -+ weston_log("keyboard_handle_modifiers\n"); -+} -+ -+static void -+keyboard_handle_repeat_info(struct wthp_keyboard *wthp_keyboard, -+ int32_t rate, -+ int32_t delay) -+{ -+ weston_log("keyboard_handle_repeat_info\n"); -+} -+ -+static const struct wthp_keyboard_listener keyboard_listener = { -+ keyboard_handle_keymap, -+ keyboard_handle_enter, -+ keyboard_handle_leave, -+ keyboard_handle_key, -+ keyboard_handle_modifiers, -+ keyboard_handle_repeat_info -+}; -+ -+static void -+touch_handle_down (struct wthp_touch * wthp_touch, -+ uint32_t serial, -+ uint32_t time, -+ struct wthp_surface * surface, -+ int32_t id, -+ wth_fixed_t x, -+ wth_fixed_t y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ struct weston_transmitter_surface *txs; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ if (txs->wthp_surf == surface) { -+ transmitter_seat_touch_down(seat, serial, time, -+ txs, id, x, y); -+ } -+ } -+} -+ -+static void -+touch_handle_up (struct wthp_touch * wthp_touch, -+ uint32_t serial, -+ uint32_t time, -+ int32_t id) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_touch_up(seat, serial, time, id); -+} -+ -+static void -+touch_handle_motion (struct wthp_touch * wthp_touch, -+ uint32_t time, -+ int32_t id, -+ wth_fixed_t x, -+ wth_fixed_t y) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_touch_motion(seat, time, id, x, y); -+} -+ -+ -+static void -+touch_handle_frame (struct wthp_touch * wthp_touch) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_touch_frame(seat); -+} -+ -+static void -+touch_handle_cancel (struct wthp_touch * wthp_touch) -+{ -+ struct waltham_display *dpy = -+ wth_object_get_user_data((struct wth_object *)wthp_touch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ struct wl_list *seat_list = &remote->seat_list; -+ struct weston_transmitter_seat *seat; -+ -+ seat = wl_container_of(seat_list->next, seat, link); -+ -+ transmitter_seat_touch_cancel(seat); -+} -+ -+ -+static const struct wthp_touch_listener touch_listener = { -+ touch_handle_down, -+ touch_handle_up, -+ touch_handle_motion, -+ touch_handle_frame, -+ touch_handle_cancel -+}; -+ -+void -+seat_capabilities(struct wthp_seat *wthp_seat, -+ enum wthp_seat_capability caps) -+{ -+ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)wthp_seat); -+ -+ weston_log("seat_capabilities\n"); -+ -+ if ((caps & WTHP_SEAT_CAPABILITY_POINTER) && !dpy->pointer) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_POINTER\n"); -+ dpy->pointer = wthp_seat_get_pointer(dpy->seat); -+ wthp_pointer_set_listener(dpy->pointer, &pointer_listener, dpy); -+ } -+ if ((caps & WTHP_SEAT_CAPABILITY_KEYBOARD) && !dpy->keyboard) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_KEYBOARD\n"); -+ dpy->keyboard = wthp_seat_get_keyboard(dpy->seat); -+ wthp_keyboard_set_listener(dpy->keyboard, &keyboard_listener, dpy); -+ } -+ if ((caps & WTHP_SEAT_CAPABILITY_TOUCH) && !dpy->touch) -+ { -+ weston_log("WTHP_SEAT_CAPABILITY_TOUCH\n"); -+ dpy->touch = wthp_seat_get_touch(dpy->seat); -+ wthp_touch_set_listener(dpy->touch, &touch_listener, dpy); -+ } -+} -+ -+int -+transmitter_remote_create_seat(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_seat *seat = NULL; -+ char *name = NULL; -+ struct weston_seat *weston_seat = NULL; -+ -+ seat = zalloc(sizeof *seat); -+ if (!seat) -+ goto fail; -+ -+ wl_list_init(&seat->get_pointer_listener.link); -+ wl_list_init(&seat->pointer_focus_destroy_listener.link); -+ -+ /* XXX: get the name from remote */ -+ name = make_seat_name(remote, "default"); -+ if (!name) -+ goto fail; -+ -+ -+ if (wl_list_empty(&remote->transmitter->compositor->seat_list)) { -+ weston_seat = zalloc(sizeof *weston_seat); -+ if (!weston_seat) -+ goto fail; -+ -+ weston_seat_init(weston_seat, remote->transmitter->compositor, name); -+ seat->base = weston_seat; -+ weston_log("Transmitter created seat=%p \n", &seat->base); -+ } else { -+ wl_list_for_each(weston_seat, &remote->transmitter->compositor->seat_list, link) { -+ weston_log("Transmitter weston_seat %p\n", weston_seat); -+ seat->base = weston_seat; -+ } -+ } -+ -+ free(name); -+#if DEBUG -+ weston_seat_init(&seat->base, remote->transmitter->compositor, name); -+ free(name); -+ -+ /* Hide the weston_seat from the rest of Weston, there are too many -+ * things making assumptions: -+ * - backends assume they control all seats -+ * - shells assume they control all input foci -+ * We do not want either to mess with our seat. -+ */ -+ wl_list_remove(&seat->base.link); -+ wl_list_init(&seat->base.link); -+ -+ /* The weston_compositor::seat_created_signal has already been -+ * emitted. Shells use it to subscribe to focus changes, but we should -+ * never handle focus with weston core... except maybe with keyboard. -+ * text-backend.c will also act on the new seat. -+ * It is possible weston_seat_init() needs to be split to fix this -+ * properly. -+ */ -+ -+ weston_log("Transmitter created seat=%p '%s'\n", -+ &seat->base, seat->base.seat_name); -+#endif -+ -+ /* XXX: mirror remote capabilities */ -+ transmitter_seat_create_pointer(seat); -+ transmitter_seat_create_keyboard(seat); -+ transmitter_seat_create_touch(seat); -+ -+ wl_list_insert(&remote->seat_list, &seat->link); -+ -+ return 0; -+ -+fail: -+ free(seat); -+ free(name); -+ -+ return -1; -+} -+ -+static void -+fake_pointer_get_position(struct weston_transmitter_seat *seat, double step, -+ wl_fixed_t *x, wl_fixed_t *y) -+{ -+ double s, c; -+ -+ seat->pointer_phase += step; -+ while (seat->pointer_phase > 2.0 * M_PI) -+ seat->pointer_phase -= 2.0 * M_PI; -+ -+ sincos(seat->pointer_phase, &s, &c); -+ *x = wl_fixed_from_double(100.0 + 50.0 * c); -+ *y = wl_fixed_from_double(100.0 + 50.0 * s); -+} -+ -+static int -+fake_pointer_timer_handler(void *data) -+{ -+ struct weston_transmitter_seat *seat = data; -+ wl_fixed_t x, y; -+ uint32_t time; -+ -+ time = weston_compositor_get_time(); -+ -+ fake_pointer_get_position(seat, 18.0 / 180.0 * M_PI, &x, &y); -+ transmitter_seat_pointer_motion(seat, time, x, y); -+ transmitter_seat_pointer_frame(seat); -+ -+ wl_event_source_timer_update(seat->pointer_timer, 100); -+ -+ return 0; -+} -+ -+int -+transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, -+ struct weston_transmitter_surface *txs) -+{ -+ struct wl_event_loop *loop; -+ wl_fixed_t x, y; -+ uint32_t serial = 5; -+ -+ /* remove focus from earlier surface */ -+ transmitter_seat_pointer_leave(seat, serial++, seat->pointer_focus); -+ transmitter_seat_pointer_frame(seat); -+ -+ /* set pointer focus to surface */ -+ fake_pointer_get_position(seat, 0.0, &x, &y); -+ transmitter_seat_pointer_enter(seat, serial++, txs, x, y); -+ transmitter_seat_pointer_frame(seat); -+ -+ if (!seat->pointer_timer) { -+ /* schedule timer for motion */ -+ loop = wl_display_get_event_loop(seat->base->compositor->wl_display); -+ seat->pointer_timer = wl_event_loop_add_timer(loop, -+ fake_pointer_timer_handler, seat); -+ wl_event_source_timer_update(seat->pointer_timer, 100); -+ } -+ -+ /* XXX: if the now focused surface disappears, we should call -+ * transmitter_seat_pointer_leave() as part of the mockup. Otherwise -+ * you get a "Transmitter Warning: no pointer->focus_client?". -+ */ -+ -+ return 0; -+} -diff --git a/waltham-transmitter/transmitter-plugin/output.c b/waltham-transmitter/transmitter-plugin/output.c -new file mode 100644 -index 0000000..c379ce5 ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/output.c -@@ -0,0 +1,352 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture 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. -+ */ -+ -+#include -+#include -+#include -+ -+#include "compositor.h" -+#include "compositor-drm.h" -+#include "plugin-registry.h" -+ -+#include "plugin.h" -+#include "transmitter_api.h" -+#include "waltham-renderer.h" -+ -+/** @file -+ * -+ * This is an implementation of a remote output. -+ * -+ * A remote output must not be accepted as an argument to: -+ * - wl_shell_surface.set_fullscreen -+ * - wl_shell_surface.set_maximized -+ * - zwp_fullscreen_shell_v1.present_surface -+ * - zwp_fullscreen_shell_v1.present_surface_for_mode -+ * - zwp_input_panel_surface_v1.set_toplevel -+ * - xdg_surface.set_fullscreen -+ * -+ * If a remote output is an argument to the above or similar requests, -+ * it should have the same effect as NULL if possible. -+ * -+ * @todo Should we instead accept the argument and have it start remoting -+ * automatically? That would be shell-specific. -+ * -+ * In ivi-shell's case, only zwp_input_panel_surface_v1.set_toplevel is -+ * reachable from keyboard.c. That just blindly uses whatever the first -+ * output happens to be, so there is no need to check for now. -+ * -+ * @todo Add weston_output_set_remote() which sets weston_output::is_remote -+ * to true and inits weston_output::link. This should be made mutually -+ * exclusive with weston_compositor_add_output(). -+ */ -+ -+static struct waltham_renderer_interface *waltham_renderer; -+ -+static char * -+make_model(struct weston_transmitter_remote *remote, int name) -+{ -+ char *str; -+ -+ if (asprintf(&str, "transmitter-%s:%s-%d", remote->addr, remote->port, name) < 0) -+ return NULL; -+ -+ return str; -+} -+ -+static int -+make_mode_list(struct wl_list *list, -+ const struct weston_transmitter_output_info *info) -+{ -+ struct weston_mode *mode; -+ -+ mode = zalloc(sizeof *mode); -+ if (!mode) -+ return -1; -+ -+ *mode = info->mode; -+ wl_list_insert(list->prev, &mode->link); -+ -+ return 0; -+} -+ -+static struct weston_mode * -+get_current_mode(struct wl_list *mode_list) -+{ -+ struct weston_mode *mode; -+ -+ wl_list_for_each(mode, mode_list, link) -+ if (mode->flags & WL_OUTPUT_MODE_CURRENT) -+ return mode; -+ -+ assert(0); -+ return NULL; -+} -+ -+static void -+free_mode_list(struct wl_list *mode_list) -+{ -+ struct weston_mode *mode; -+ -+ while (!wl_list_empty(mode_list)) { -+ mode = wl_container_of(mode_list->next, mode, link); -+ -+ wl_list_remove(&mode->link); -+ free(mode); -+ } -+} -+ -+void -+transmitter_output_destroy(struct weston_transmitter_output *output) -+{ -+ wl_list_remove(&output->link); -+ -+ free_mode_list(&output->base.mode_list); -+ free(output->base.serial_number); -+ free(output->base.model); -+ free(output->base.make); -+ -+ weston_output_destroy(&output->base); -+ free(output); -+} -+ -+static void -+transmitter_output_destroy_(struct weston_output *base) -+{ -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); -+ -+ transmitter_output_destroy(output); -+} -+ -+ -+static void -+transmitter_start_repaint_loop(struct weston_output *base) -+{ -+ struct timespec ts; -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); -+ -+ weston_compositor_read_presentation_clock(output->base.compositor, &ts); -+ weston_output_finish_frame(&output->base, &ts, 0); -+} -+ -+static int -+transmitter_output_repaint(struct weston_output *base, -+ pixman_region32_t *damage) -+{ -+ struct weston_transmitter_output* output = wl_container_of(base, output, base); -+ struct weston_transmitter_remote* remote = output->remote; -+ struct weston_transmitter* txr = remote->transmitter; -+ struct weston_transmitter_api* transmitter_api = -+ weston_get_transmitter_api(txr->compositor); -+ struct weston_transmitter_surface* txs; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_view *view; -+ bool found_output = false; -+ struct timespec ts; -+ -+ struct weston_drm_output_api *api = -+ weston_plugin_api_get(txr->compositor, WESTON_DRM_OUTPUT_API_NAME, sizeof(api)); -+ -+ /* -+ * Pick up weston_view in transmitter_output and check weston_view's surface -+ * If the surface hasn't been conbined to weston_transmitter_surface, -+ * then call push_to_remote. -+ * If the surface has already been combined, call gather_state. -+ */ -+ if (wl_list_empty(&compositor->view_list)) -+ goto out; -+ -+ if (remote->status == WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) -+ goto out; -+ -+ wl_list_for_each_reverse(view, &compositor->view_list, link) { -+ bool found_surface = false; -+ if (view->output == &output->base) { -+ found_output = true; -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == view->surface) { -+ found_surface = true; -+ if (!txs->wthp_surf) -+ transmitter_api->surface_push_to_remote -+ (view->surface, remote, NULL); -+ -+ output->renderer->dmafd = -+ api->get_dma_fd_from_view(&output->base, view); -+ if(!output->renderer->dmafd) { -+ weston_log("Failed to get dmafd\n"); -+ goto out; -+ } -+ -+ /* -+ * Updating the width x height -+ * from surface to gst-recorder -+ */ -+ output->renderer->surface_width -+ = view->surface->width; -+ output->renderer->surface_height -+ = view->surface->height; -+ -+ output->renderer->repaint_output(output); -+ output->renderer->dmafd = NULL; -+ transmitter_api->surface_gather_state(txs); -+ weston_buffer_reference(&view->surface->buffer_ref, NULL); -+ break; -+ } -+ } -+ if (!found_surface) -+ transmitter_api->surface_push_to_remote(view->surface, -+ remote, NULL); -+ } -+ } -+ if (!found_output) -+ goto out; -+ -+ weston_compositor_read_presentation_clock(output->base.compositor, &ts); -+ weston_output_finish_frame(&output->base, &ts, 0); -+ -+ return 0; -+ -+out: -+ transmitter_start_repaint_loop(base); -+ -+ return 0; -+} -+ -+static void -+transmitter_assign_planes(struct weston_output *base) { -+ /* -+ * This function prevents compositor releasing buffer early. -+ */ -+ struct weston_transmitter_output* output = wl_container_of(base, output, base); -+ struct weston_transmitter_remote* remote = output->remote; -+ struct weston_transmitter_surface* txs; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_view *view; -+ -+ wl_list_for_each_reverse(view, &compositor->view_list, link) { -+ if (view->output == &output->base) { -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == view->surface) -+ view->surface->keep_buffer = true; -+ -+ } -+ } -+ } -+} -+ -+static void -+transmitter_output_enable(struct weston_output *base) -+{ -+ struct weston_transmitter_output *output = wl_container_of(base, output, base); -+ -+ output->base.assign_planes = transmitter_assign_planes; -+ output->base.set_backlight = NULL; -+ output->base.set_dpms = NULL; -+ output->base.switch_mode = NULL; -+} -+ -+int -+transmitter_remote_create_output(struct weston_transmitter_remote *remote, -+ const struct weston_transmitter_output_info *info) -+{ -+ struct weston_transmitter_output *output; -+ struct weston_transmitter *txr = remote->transmitter; -+ struct weston_output *def_output; -+ -+ output = zalloc(sizeof *output); -+ if (!output) -+ return -1; -+ -+ output->parent.draw_initial_frame = true; -+ -+ output->base.subpixel = info->subpixel; -+ -+ output->base.name = make_model(remote, 1); -+ output->base.make = strdup(WESTON_TRANSMITTER_OUTPUT_MAKE); -+ output->base.model = make_model(remote, 1); -+ output->base.serial_number = strdup("0"); -+ /* x and y is fake value */ -+ wl_list_init(&output->base.mode_list); -+ if (make_mode_list(&output->base.mode_list, info) < 0) -+ goto fail; -+ -+ output->base.current_mode = get_current_mode(&output->base.mode_list); -+ output->base.height = output->base.current_mode->height; -+ output->base.width = output->base.current_mode->width; -+ /* WL_OUTPUT_MODE_CURRENT already set */ -+ weston_output_init(&output->base, remote->transmitter->compositor); -+ -+ /* -+ * renderer_output_create skipped: -+ * no renderer awareness is needed for this output -+ */ -+ -+ /* -+ * weston_compositor_add_output() skipped: -+ * Most other code uses weston_compositor::output_list when traversing -+ * all outputs, we do not want any of that. -+ * Also weston_compositor::output_created_signal must not trigger -+ * for this output, since we must not involve input device management -+ * or color management or any kind of local management. -+ */ -+ output->base.enable = transmitter_output_enable; -+ output->base.start_repaint_loop = transmitter_start_repaint_loop; -+ output->base.repaint = transmitter_output_repaint; -+ output->base.destroy = transmitter_output_destroy_; -+ output->base.assign_planes = NULL; -+ output->base.set_dpms = NULL; -+ output->base.switch_mode = NULL; -+ output->base.gamma_size = 0; -+ output->base.set_gamma = NULL; -+ -+ output->base.native_mode = output->base.current_mode; -+ output->base.native_scale = output->base.current_scale; -+ output->base.scale = 1; -+ output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL; -+ -+ output->remote = remote; -+ wl_list_insert(&remote->output_list, &output->link); -+ -+ /* Loading a waltham renderer library */ -+ waltham_renderer = weston_load_module("waltham-renderer.so","waltham_renderer_interface"); -+ -+ if (waltham_renderer->display_create(output) < 0) { -+ weston_log("Failed to create waltham renderer display \n"); -+ return -1; -+ } -+ -+ weston_output_enable(&output->base); -+ -+ return 0; -+ -+fail: -+ free_mode_list(&output->base.mode_list); -+ free(output->base.serial_number); -+ free(output->base.model); -+ free(output->base.make); -+ free(output->base.name); -+ free(output); -+ -+ return -1; -+} -diff --git a/waltham-transmitter/transmitter-plugin/plugin.c b/waltham-transmitter/transmitter-plugin/plugin.c -new file mode 100644 -index 0000000..f643bd8 ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/plugin.c -@@ -0,0 +1,940 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture 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. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "compositor.h" -+ -+#include "weston.h" -+#include "plugin.h" -+#include "transmitter_api.h" -+#include "plugin-registry.h" -+#include "ivi-layout-export.h" -+ -+/* waltham */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_EPOLL_WATCHES 2 -+#define ESTABLISH_CONNECTION_PERIOD 2000 -+#define RETRY_CONNECTION_PERIOD 5000 -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+/** Send configure event through ivi-shell. -+ * -+ * \param txs The Transmitter surface. -+ * \param width Suggestion for surface width. -+ * \param height Suggestion for surface height. -+ * -+ * When the networking code receives a ivi_surface.configure event, it calls -+ * this function to relay it to the application. -+ * -+ * \c txs cannot be a zombie, because transmitter_surface_zombify() must -+ * tear down the network link, so a zombie cannot receive events. -+ */ -+void -+transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, -+ int32_t width, int32_t height) -+{ -+ assert(txs->resize_handler); -+ if (!txs->resize_handler) -+ return; -+ -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ -+ txs->resize_handler(txs->resize_handler_data, width, height); -+} -+ -+static void -+transmitter_surface_configure(struct weston_transmitter_surface *txs, -+ int32_t dx, int32_t dy) -+{ -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ -+ txs->attach_dx += dx; -+ txs->attach_dy += dy; -+} -+ -+static void -+buffer_send_complete(struct wthp_buffer *b, uint32_t serial) -+{ -+ if (b) -+ wthp_buffer_destroy(b); -+} -+ -+static const struct wthp_buffer_listener buffer_listener = { -+ buffer_send_complete -+}; -+ -+static void -+transmitter_surface_gather_state(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter_remote *remote = txs->remote; -+ struct waltham_display *dpy = remote->display; -+ int ret; -+ -+ if(!dpy->running) { -+ if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) { -+ remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED; -+ wth_connection_destroy(remote->display->connection); -+ wl_event_source_remove(remote->source); -+ wl_event_source_timer_update(remote->retry_timer, 1); -+ } -+ } -+ else { -+ /* TODO: transmit surface state to remote */ -+ /* The buffer must be transmitted to remote side */ -+ -+ /* waltham */ -+ struct weston_surface *surf = txs->surface; -+ struct weston_compositor *comp = surf->compositor; -+ int32_t stride, data_sz, width, height; -+ void *data; -+ -+ width = 1; -+ height = 1; -+ stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8); -+ -+ data = malloc(stride * height); -+ data_sz = stride * height; -+ -+ /* fake sending buffer */ -+ txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory, -+ data_sz, -+ data, -+ surf->width, -+ surf->height, -+ stride, -+ PIXMAN_FORMAT_BPP(comp->read_format)); -+ -+ wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs); -+ -+ wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy); -+ wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height); -+ wthp_surface_commit(txs->wthp_surf); -+ -+ wth_connection_flush(remote->display->connection); -+ txs->attach_dx = 0; -+ txs->attach_dy = 0; -+ } -+} -+ -+/** Mark the weston_transmitter_surface dead. -+ * -+ * Stop all remoting actions on this surface. -+ * -+ * Still keeps the pointer stored by a shell valid, so it can be freed later. -+ */ -+static void -+transmitter_surface_zombify(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter_remote *remote; -+ /* may be called multiple times */ -+ if (!txs->surface) -+ return; -+ -+ wl_signal_emit(&txs->destroy_signal, txs); -+ -+ wl_list_remove(&txs->surface_destroy_listener.link); -+ txs->surface = NULL; -+ -+ wl_list_remove(&txs->sync_output_destroy_listener.link); -+ -+ remote = txs->remote; -+ if (!remote->display->compositor) -+ weston_log("remote->compositor is NULL\n"); -+ if (txs->wthp_surf) -+ wthp_surface_destroy(txs->wthp_surf); -+ if (txs->wthp_ivi_surface) -+ wthp_ivi_surface_destroy(txs->wthp_ivi_surface); -+ -+ /* In case called from destroy_transmitter() */ -+ txs->remote = NULL; -+} -+ -+static void -+transmitter_surface_destroy(struct weston_transmitter_surface *txs) -+{ -+ transmitter_surface_zombify(txs); -+ -+ wl_list_remove(&txs->link); -+ free(txs); -+} -+ -+/** weston_surface destroy signal handler */ -+static void -+transmitter_surface_destroyed(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs = -+ wl_container_of(listener, txs, surface_destroy_listener); -+ -+ assert(data == txs->surface); -+ -+ transmitter_surface_zombify(txs); -+} -+ -+static void -+sync_output_destroy_handler(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_surface *txs; -+ -+ txs = wl_container_of(listener, txs, sync_output_destroy_listener); -+ -+ wl_list_remove(&txs->sync_output_destroy_listener.link); -+ wl_list_init(&txs->sync_output_destroy_listener.link); -+ -+ weston_surface_force_output(txs->surface, NULL); -+} -+ -+static void -+transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs) -+{ -+ struct weston_transmitter_remote *remote = txs->remote; -+ struct waltham_display *dpy = remote->display; -+ struct weston_surface *ws; -+ struct ivi_layout_surface **pp_surface = NULL; -+ struct ivi_layout_surface *ivi_surf = NULL; -+ int32_t surface_length = 0; -+ int32_t ret = 0; -+ int32_t i = 0; -+ -+ ret = txs->lyt->get_surfaces(&surface_length, &pp_surface); -+ if(!ret) -+ weston_log("No ivi_surface\n"); -+ -+ ws = txs->surface; -+ -+ for(i = 0; i < surface_length; i++) { -+ ivi_surf = pp_surface[i]; -+ if (ivi_surf->surface == ws) { -+ assert(txs->surface); -+ if (!txs->surface) -+ return; -+ if(!dpy) -+ weston_log("no content in waltham_display\n"); -+ if(!dpy->compositor) -+ weston_log("no content in compositor object\n"); -+ if(!dpy->seat) -+ weston_log("no content in seat object\n"); -+ if(!dpy->application) -+ weston_log("no content in ivi-application object\n"); -+ -+ txs->wthp_ivi_surface = wthp_ivi_application_surface_create -+ (dpy->application, ivi_surf->id_surface, txs->wthp_surf); -+ weston_log("surface ID %d\n", ivi_surf->id_surface); -+ if(!txs->wthp_ivi_surface){ -+ weston_log("Failed to create txs->ivi_surf\n"); -+ } -+ } -+ } -+ free(pp_surface); -+ pp_surface = NULL; -+} -+ -+static struct weston_transmitter_surface * -+transmitter_surface_push_to_remote(struct weston_surface *ws, -+ struct weston_transmitter_remote *remote, -+ struct wl_listener *stream_status) -+{ -+ struct weston_transmitter *txr = remote->transmitter; -+ struct weston_transmitter_surface *txs; -+ bool found = false; -+ -+ if (remote->status != WESTON_TRANSMITTER_CONNECTION_READY) -+ { -+ return NULL; -+ } -+ -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ if (txs->surface == ws) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ txs = NULL; -+ txs = zalloc(sizeof (*txs)); -+ if (!txs) -+ return NULL; -+ -+ txs->remote = remote; -+ wl_signal_init(&txs->destroy_signal); -+ wl_list_insert(&remote->surface_list, &txs->link); -+ -+ txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING; -+ wl_signal_init(&txs->stream_status_signal); -+ if (stream_status) -+ wl_signal_add(&txs->stream_status_signal, stream_status); -+ -+ txs->surface = ws; -+ txs->surface_destroy_listener.notify = transmitter_surface_destroyed; -+ wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener); -+ -+ wl_list_init(&txs->sync_output_destroy_listener.link); -+ -+ wl_list_init(&txs->frame_callback_list); -+ wl_list_init(&txs->feedback_list); -+ -+ txs->lyt = weston_plugin_api_get(txr->compositor, -+ IVI_LAYOUT_API_NAME, sizeof(txs->lyt)); -+ } -+ -+ /* TODO: create the content stream connection... */ -+ if (!remote->display->compositor) -+ weston_log("remote->compositor is NULL\n"); -+ if (!txs->wthp_surf) { -+ weston_log("txs->wthp_surf is NULL\n"); -+ txs->wthp_surf = wthp_compositor_create_surface(remote->display->compositor); -+ transmitter_surface_set_ivi_id(txs); -+ } -+ -+ return txs; -+} -+ -+static enum weston_transmitter_stream_status -+transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs) -+{ -+ return txs->status; -+} -+ -+/* waltham */ -+/* The server advertises a global interface. -+ * We can store the ad for later and/or bind to it immediately -+ * if we want to. -+ * We also need to keep track of the globals we bind to, so that -+ * global_remove can be handled properly (not implemented). -+ */ -+static void -+registry_handle_global(struct wthp_registry *registry, -+ uint32_t name, -+ const char *interface, -+ uint32_t version) -+{ -+ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry); -+ -+ if (strcmp(interface, "wthp_compositor") == 0) { -+ assert(!dpy->compositor); -+ dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1); -+ /* has no events to handle */ -+ } else if (strcmp(interface, "wthp_blob_factory") == 0) { -+ assert(!dpy->blob_factory); -+ dpy->blob_factory = (struct wthp_blob_factory *)wthp_registry_bind(registry, name, interface, 1); -+ /* has no events to handle */ -+ } else if (strcmp(interface, "wthp_seat") == 0) { -+ assert(!dpy->seat); -+ dpy->seat = (struct wthp_seat *)wthp_registry_bind(registry, name, interface, 1); -+ wthp_seat_set_listener(dpy->seat, &seat_listener, dpy); -+ } else if (strcmp(interface, "wthp_ivi_application") == 0) { -+ assert(!dpy->application); -+ dpy->application = (struct wthp_ivi_application *)wthp_registry_bind(registry, name, interface, 1); -+ } -+} -+ -+/* notify connection ready */ -+static void -+conn_ready_notify(struct wl_listener *l, void *data) -+{ -+ struct weston_transmitter_remote *remote = -+ wl_container_of(l, remote, establish_listener); -+ struct weston_transmitter_output_info info = { -+ WL_OUTPUT_SUBPIXEL_NONE, -+ WL_OUTPUT_TRANSFORM_NORMAL, -+ 1, -+ 0, 0, -+ 300, 200, -+ strdup(remote->model), -+ { -+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, -+ 800, 600, -+ 51519, -+ { NULL, NULL } -+ } -+ }; -+ if(remote->width != 0) { -+ if(remote->height != 0) { -+ info.mode.width = remote->width; -+ info.mode.height = remote->height; -+ } -+ } -+ /* Outputs and seats are dynamic, do not guarantee they are all -+ * present when signalling connection status. -+ */ -+ transmitter_remote_create_output(remote, &info); -+ transmitter_remote_create_seat(remote); -+} -+ -+/* waltham */ -+/* The server removed a global. -+ * We should destroy everything we created through that global, -+ * and destroy the objects we created by binding to it. -+ * The identification happens by global's name, so we need to keep -+ * track what names we bound. -+ * (not implemented) -+ */ -+static void -+registry_handle_global_remove(struct wthp_registry *wthp_registry, -+ uint32_t name) -+{ -+ if (wthp_registry) -+ wthp_registry_free(wthp_registry); -+} -+ -+static const struct wthp_registry_listener registry_listener = { -+ registry_handle_global, -+ registry_handle_global_remove -+}; -+ -+static void -+connection_handle_data(struct watch *w, uint32_t events) -+{ -+ struct waltham_display *dpy = wl_container_of(w, dpy, conn_watch); -+ struct weston_transmitter_remote *remote = dpy->remote; -+ int ret; -+ -+ -+ if (!dpy->running) { -+ weston_log("This server is not running yet. %s:%s\n", remote->addr, remote->port); -+ return; -+ } -+ -+ if (events & EPOLLERR) { -+ weston_log("Connection errored out.\n"); -+ dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ return; -+ } -+ -+ if (events & EPOLLOUT) { -+ /* Flush out again. If the flush completes, stop -+ * polling for writable as everything has been written. -+ */ -+ ret = wth_connection_flush(dpy->connection); -+ } -+ -+ if (events & EPOLLIN) { -+ /* Do not ignore EPROTO */ -+ ret = wth_connection_read(dpy->connection); -+ -+ if (ret < 0) { -+ weston_log("Connection read error %s:%s\n", remote->addr, remote->port); -+ perror("Connection read error\n"); -+ dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ perror("EPOLL_CTL_DEL\n"); -+ -+ return; -+ } -+ } -+ -+ if (events & EPOLLHUP) { -+ weston_log("Connection hung up.\n"); -+ dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ -+ return; -+ } -+} -+ -+static void -+waltham_mainloop(int fd, uint32_t mask, void *data) -+{ -+ struct weston_transmitter_remote *remote = data; -+ struct watch *w; -+ int ret; -+ int running_display; -+ running_display = 0; -+ -+ struct waltham_display *dpy = remote->display; -+ w = &dpy->conn_watch; -+ if (!dpy) -+ goto not_running; -+ -+ if (!dpy->connection) -+ dpy->running = false; -+ -+ if (!dpy->running) -+ goto not_running; -+ -+ running_display++; -+ /* Dispatch queued events. */ -+ ret = wth_connection_dispatch(dpy->connection); -+ if (ret < 0) { -+ dpy->running = false; -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ } -+ if (!dpy->running) -+ goto not_running; -+ -+ /* Run any application idle tasks at this point. */ -+ /* (nothing to run so far) */ -+ -+ /* Flush out buffered requests. If the Waltham socket is -+ * full, poll it for writable too, and continue flushing then. -+ */ -+ ret = wth_connection_flush(dpy->connection); -+ -+ if (0 < running_display) { -+ /* Waltham events only read in the callback, not dispatched, -+ * if the Waltham socket signalled readable. If it signalled -+ * writable, flush more. See connection_handle_data(). -+ */ -+ w->cb(w, mask); -+ } -+ -+not_running: -+ ; -+} -+ -+static int -+waltham_client_init(struct waltham_display *dpy) -+{ -+ if (!dpy) -+ return -1; -+ /* -+ * get server_address from controller (adrress is set to weston.ini) -+ */ -+ dpy->connection = wth_connect_to_server(dpy->remote->addr, dpy->remote->port); -+ if(!dpy->connection) { -+ return -2; -+ } -+ else { -+ dpy->remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -+ wl_signal_emit(&dpy->remote->connection_status_signal, dpy->remote); -+ } -+ -+ dpy->conn_watch.display = dpy; -+ dpy->conn_watch.cb = connection_handle_data; -+ dpy->conn_watch.fd = wth_connection_get_fd(dpy->connection); -+ dpy->remote->source = wl_event_loop_add_fd(dpy->remote->transmitter->loop, -+ dpy->conn_watch.fd, -+ WL_EVENT_READABLE, -+ waltham_mainloop, dpy->remote); -+ -+ dpy->display = wth_connection_get_display(dpy->connection); -+ /* wth_display_set_listener() is already done by waltham, as -+ * all the events are just control messaging. -+ */ -+ -+ /* Create a registry so that we will get advertisements of the -+ * interfaces implemented by the server. -+ */ -+ dpy->registry = wth_display_get_registry(dpy->display); -+ wthp_registry_set_listener(dpy->registry, ®istry_listener, dpy); -+ -+ /* Roundtrip ensures all globals' ads have been received. */ -+ if (wth_connection_roundtrip(dpy->connection) < 0) { -+ weston_log("Roundtrip failed.\n"); -+ return -1; -+ } -+ -+ if (!dpy->compositor) { -+ weston_log("Did not find wthp_compositor, quitting.\n"); -+ return -1; -+ } -+ -+ dpy->running = true; -+ -+ return 0; -+} -+ -+static int -+establish_timer_handler(void *data) -+{ -+ struct weston_transmitter_remote *remote = data; -+ int ret; -+ -+ ret = waltham_client_init(remote->display); -+ if(ret == -2) { -+ wl_event_source_timer_update(remote->establish_timer, -+ ESTABLISH_CONNECTION_PERIOD); -+ return 0; -+ } -+ remote->status = WESTON_TRANSMITTER_CONNECTION_READY; -+ wl_signal_emit(&remote->connection_status_signal, remote); -+ return 0; -+} -+ -+static void -+init_globals(struct waltham_display *dpy) -+{ -+ dpy->compositor = NULL; -+ dpy->blob_factory = NULL; -+ dpy->seat = NULL; -+ dpy->application = NULL; -+ dpy->pointer = NULL; -+ dpy->keyboard = NULL; -+ dpy->touch = NULL; -+} -+ -+static void -+disconnect_surface(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_surface *txs; -+ wl_list_for_each(txs, &remote->surface_list, link) -+ { -+ free(txs->wthp_ivi_surface); -+ txs->wthp_ivi_surface = NULL; -+ free(txs->wthp_surf); -+ txs->wthp_surf = NULL; -+ } -+} -+ -+static int -+retry_timer_handler(void *data) -+{ -+ struct weston_transmitter_remote *remote = data; -+ struct waltham_display *dpy = remote->display; -+ -+ if(!dpy->running) -+ { -+ registry_handle_global_remove(dpy->registry, 1); -+ init_globals(dpy); -+ disconnect_surface(remote); -+ wl_event_source_timer_update(remote->establish_timer, -+ ESTABLISH_CONNECTION_PERIOD); -+ -+ return 0; -+ } -+ else -+ wl_event_source_timer_update(remote->retry_timer, -+ RETRY_CONNECTION_PERIOD); -+ return 0; -+} -+ -+static struct weston_transmitter_remote * -+transmitter_connect_to_remote(struct weston_transmitter *txr) -+{ -+ struct weston_transmitter_remote *remote; -+ struct wl_event_loop *loop_est, *loop_retry; -+ int ret; -+ -+ wl_list_for_each_reverse(remote, &txr->remote_list, link) { -+ /* XXX: actually start connecting */ -+ /* waltham */ -+ remote->display = zalloc(sizeof *remote->display); -+ if (!remote->display) -+ return NULL; -+ remote->display->remote = remote; -+ /* set connection establish timer */ -+ loop_est = wl_display_get_event_loop(txr->compositor->wl_display); -+ remote->establish_timer = -+ wl_event_loop_add_timer(loop_est, establish_timer_handler, remote); -+ wl_event_source_timer_update(remote->establish_timer, 1); -+ /* set connection retry timer */ -+ loop_retry = wl_display_get_event_loop(txr->compositor->wl_display); -+ remote->retry_timer = -+ wl_event_loop_add_timer(loop_retry, retry_timer_handler, remote); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter waltham connecting failed.\n"); -+ return NULL; -+ } -+ wl_signal_emit(&remote->conn_establish_signal, NULL); -+ } -+ -+ return remote; -+} -+ -+static enum weston_transmitter_connection_status -+transmitter_remote_get_status(struct weston_transmitter_remote *remote) -+{ -+ return remote->status; -+} -+ -+static void -+transmitter_remote_destroy(struct weston_transmitter_remote *remote) -+{ -+ struct weston_transmitter_surface *txs; -+ struct weston_transmitter_output *output, *otmp; -+ struct weston_transmitter_seat *seat, *stmp; -+ -+ /* Do not emit connection_status_signal. */ -+ -+ /* -+ * Must not touch remote->transmitter as it may be stale: -+ * the desctruction order between the shell and Transmitter is -+ * undefined. -+ */ -+ -+ if (!wl_list_empty(&remote->surface_list)) -+ weston_log("Transmitter warning: surfaces remain in %s.\n", -+ __func__); -+ wl_list_for_each(txs, &remote->surface_list, link) -+ txs->remote = NULL; -+ wl_list_remove(&remote->surface_list); -+ -+ wl_list_for_each_safe(seat, stmp, &remote->seat_list, link) -+ transmitter_seat_destroy(seat); -+ -+ wl_list_for_each_safe(output, otmp, &remote->output_list, link) -+ transmitter_output_destroy(output); -+ -+ free(remote->addr); -+ wl_list_remove(&remote->link); -+ -+ wl_event_source_remove(remote->source); -+ -+ free(remote); -+} -+ -+/** Transmitter is destroyed on compositor shutdown. */ -+static void -+transmitter_compositor_destroyed(struct wl_listener *listener, void *data) -+{ -+ struct weston_transmitter_remote *remote; -+ struct weston_transmitter_surface *txs; -+ struct weston_transmitter *txr = -+ wl_container_of(listener, txr, compositor_destroy_listener); -+ -+ assert(data == txr->compositor); -+ -+ /* may be called before or after shell cleans up */ -+ wl_list_for_each(remote, &txr->remote_list, link) { -+ wl_list_for_each(txs, &remote->surface_list, link) { -+ transmitter_surface_zombify(txs); -+ } -+ } -+ -+ /* -+ * Remove the head in case the list is not empty, to avoid -+ * transmitter_remote_destroy() accessing freed memory if the shell -+ * cleans up after Transmitter. -+ */ -+ wl_list_remove(&txr->remote_list); -+ -+ free(txr); -+} -+ -+static struct weston_transmitter * -+transmitter_get(struct weston_compositor *compositor) -+{ -+ struct wl_listener *listener; -+ struct weston_transmitter *txr; -+ -+ listener = wl_signal_get(&compositor->destroy_signal, -+ transmitter_compositor_destroyed); -+ if (!listener) -+ return NULL; -+ -+ txr = wl_container_of(listener, txr, compositor_destroy_listener); -+ assert(compositor == txr->compositor); -+ -+ return txr; -+} -+ -+static void -+transmitter_register_connection_status(struct weston_transmitter *txr, -+ struct wl_listener *connected_listener) -+{ -+ wl_signal_add(&txr->connected_signal, connected_listener); -+} -+ -+static struct weston_surface * -+transmitter_get_weston_surface(struct weston_transmitter_surface *txs) -+{ -+ return txs->surface; -+} -+ -+static const struct weston_transmitter_api transmitter_api_impl = { -+ transmitter_get, -+ transmitter_connect_to_remote, -+ transmitter_remote_get_status, -+ transmitter_remote_destroy, -+ transmitter_surface_push_to_remote, -+ transmitter_surface_get_stream_status, -+ transmitter_surface_destroy, -+ transmitter_surface_configure, -+ transmitter_surface_gather_state, -+ transmitter_register_connection_status, -+ transmitter_get_weston_surface, -+}; -+ -+static void -+transmitter_surface_set_resize_callback( -+ struct weston_transmitter_surface *txs, -+ weston_transmitter_ivi_resize_handler_t cb, -+ void *data) -+{ -+ txs->resize_handler = cb; -+ txs->resize_handler_data = data; -+} -+ -+static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = { -+ transmitter_surface_set_resize_callback, -+}; -+ -+static int -+transmitter_create_remote(struct weston_transmitter *txr, -+ const char *model, -+ const char *addr, -+ const char *port, -+ const char *width, -+ const char *height) -+{ -+ struct weston_transmitter_remote *remote; -+ -+ remote = zalloc(sizeof (*remote)); -+ if (!remote) -+ return -1; -+ -+ remote->transmitter = txr; -+ wl_list_insert(&txr->remote_list, &remote->link); -+ remote->model = strdup(model); -+ remote->addr = strdup(addr); -+ remote->port = strdup(port); -+ remote->width = atoi(width); -+ remote->height = atoi(height); -+ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING; -+ wl_signal_init(&remote->connection_status_signal); -+ wl_list_init(&remote->output_list); -+ wl_list_init(&remote->surface_list); -+ wl_list_init(&remote->seat_list); -+ wl_signal_init(&remote->conn_establish_signal); -+ remote->establish_listener.notify = conn_ready_notify; -+ wl_signal_add(&remote->conn_establish_signal, &remote->establish_listener); -+ -+ return 0; -+} -+ -+struct wet_compositor { -+ struct weston_config *config; -+ struct wet_output_config *parsed_options; -+ struct wl_listener pending_output_listener; -+ bool drm_use_current_mode; -+}; -+ -+static void -+transmitter_get_server_config(struct weston_transmitter *txr) -+{ -+ struct wet_compositor *compositor = -+ (struct wet_compositor *)weston_compositor_get_user_data(txr->compositor); -+ struct weston_config *config = wet_get_config(txr->compositor); -+ struct weston_config_section *section; -+ const char *name = NULL; -+ char *model = NULL; -+ char *addr = NULL; -+ char *port = NULL; -+ char *width = '0'; -+ char *height = '0'; -+ int ret; -+ -+ section = weston_config_get_section(config, "remote", NULL, NULL); -+ -+ while (weston_config_next_section(config, §ion, &name)) { -+ if (0 == strcmp(name, "remote-output")) { -+ if (0 != weston_config_section_get_string(section, "output-name", -+ &model, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "server-address", -+ &addr, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "port", -+ &port, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "width", -+ &width, 0)) -+ continue; -+ -+ if (0 != weston_config_section_get_string(section, "height", -+ &height, 0)) -+ continue; -+ ret = transmitter_create_remote(txr, model, addr, -+ port, width, height); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter create_remote failed.\n"); -+ } -+ } -+ } -+} -+ -+WL_EXPORT int -+wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[]) -+{ -+ struct weston_transmitter *txr; -+ int ret; -+ -+ txr = zalloc(sizeof *txr); -+ if (!txr){ -+ weston_log("Transmitter disabled\n"); -+ return -1; -+ } -+ wl_list_init(&txr->remote_list); -+ -+ txr->compositor = compositor; -+ txr->compositor_destroy_listener.notify = -+ transmitter_compositor_destroyed; -+ wl_signal_add(&compositor->destroy_signal, -+ &txr->compositor_destroy_listener); -+ -+ ret = weston_plugin_api_register(compositor, -+ WESTON_TRANSMITTER_API_NAME, -+ &transmitter_api_impl, -+ sizeof(transmitter_api_impl)); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter API registration failed.\n"); -+ goto fail; -+ } -+ -+ ret = weston_plugin_api_register(compositor, -+ WESTON_TRANSMITTER_IVI_API_NAME, -+ &transmitter_ivi_api_impl, -+ sizeof(transmitter_ivi_api_impl)); -+ if (ret < 0) { -+ weston_log("Fatal: Transmitter IVI API registration failed.\n"); -+ goto fail; -+ } -+ -+ weston_log("Transmitter initialized.\n"); -+ -+ txr->loop = wl_display_get_event_loop(compositor->wl_display); -+ transmitter_get_server_config(txr); -+ transmitter_connect_to_remote(txr); -+ -+ return 0; -+ -+fail: -+ wl_list_remove(&txr->compositor_destroy_listener.link); -+ free(txr); -+ -+ return -1; -+} -diff --git a/waltham-transmitter/transmitter-plugin/plugin.h b/waltham-transmitter/transmitter-plugin/plugin.h -new file mode 100644 -index 0000000..a473dab ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/plugin.h -@@ -0,0 +1,330 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture 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. -+ */ -+ -+#ifndef WESTON_TRANSMITTER_PLUGIN_H -+#define WESTON_TRANSMITTER_PLUGIN_H -+ -+/* XXX: all functions and variables with a name, and things marked with a -+ * comment, containing the word "fake" are mockups that need to be -+ * removed from the final implementation. -+ */ -+ -+#include -+#include -+ -+#include "compositor.h" -+#include "transmitter_api.h" -+#include "ivi-layout-export.h" -+ -+#include -+ -+ -+struct waltham_display; -+ -+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 waltham_display *display; -+ int fd; -+ void (*cb)(struct watch *w, uint32_t events); -+}; -+ -+struct waltham_display { -+ struct wth_connection *connection; -+ struct watch conn_watch; -+ struct wth_display *display; -+ -+ bool running; -+ -+ struct wthp_registry *registry; -+ -+ struct wthp_callback *bling; -+ -+ struct wthp_compositor *compositor; -+ struct wthp_blob_factory *blob_factory; -+ struct wthp_seat *seat; -+ struct wthp_pointer *pointer; -+ struct wthp_keyboard *keyboard; -+ struct wthp_touch *touch; -+ struct wthp_ivi_application *application; -+ struct wtimer *fiddle_timer; -+ -+ struct weston_transmitter_remote *remote; -+ char *addr; -+ char *port; -+}; -+ -+/* a timerfd based timer */ -+struct wtimer { -+ struct watch watch; -+ void (*func)(struct wtimer *, void *); -+ void *data; -+}; -+ -+struct weston_transmitter { -+ struct weston_compositor *compositor; -+ struct wl_listener compositor_destroy_listener; -+ -+ struct wl_list remote_list; /* transmitter_remote::link */ -+ -+ struct wl_listener stream_listener; -+ struct wl_signal connected_signal; -+ struct wl_event_loop *loop; -+}; -+ -+struct weston_transmitter_remote { -+ struct weston_transmitter *transmitter; -+ struct wl_list link; -+ char *model; -+ char *addr; -+ char *port; -+ int32_t width; -+ int32_t height; -+ -+ enum weston_transmitter_connection_status status; -+ struct wl_signal connection_status_signal; -+ struct wl_signal conn_establish_signal; -+ -+ struct wl_list output_list; /* weston_transmitter_output::link */ -+ struct wl_list surface_list; /* weston_transmitter_surface::link */ -+ struct wl_list seat_list; /* weston_transmitter_seat::link */ -+ -+ struct wl_listener establish_listener; -+ -+ struct wl_event_source *establish_timer; /* for establish connection */ -+ struct wl_event_source *retry_timer; /* for retry connection */ -+ -+ struct waltham_display *display; /* waltham */ -+ struct wl_event_source *source; -+}; -+ -+ -+struct weston_transmitter_surface { -+ struct weston_transmitter_remote *remote; -+ struct wl_list link; /* weston_transmitter_remote::surface_list */ -+ struct wl_signal destroy_signal; /* data: weston_transmitter_surface */ -+ -+ enum weston_transmitter_stream_status status; -+ struct wl_signal stream_status_signal; -+ -+ struct weston_surface *surface; -+ struct wl_listener surface_destroy_listener; -+ const struct ivi_layout_interface *lyt; -+ -+ weston_transmitter_ivi_resize_handler_t resize_handler; -+ void *resize_handler_data; -+ -+ struct weston_output *sync_output; -+ struct wl_listener sync_output_destroy_listener; -+ -+ int32_t attach_dx; /**< wl_surface.attach(buffer, dx, dy) */ -+ int32_t attach_dy; /**< wl_surface.attach(buffer, dx, dy) */ -+ struct wl_list frame_callback_list; /* weston_frame_callback::link */ -+ struct wl_list feedback_list; /* weston_presentation_feedback::link */ -+ -+ /* waltham */ -+ struct wthp_surface *wthp_surf; -+ struct wthp_blob_factory *wthp_blob; -+ struct wthp_buffer *wthp_buf; -+ struct wthp_ivi_surface *wthp_ivi_surface; -+ struct wthp_ivi_application *wthp_ivi_application; -+}; -+ -+struct weston_transmitter_output_info { -+ uint32_t subpixel; /* enum wl_output_subpixel */ -+ uint32_t transform; /* enum wl_output_transform */ -+ int32_t scale; -+ int32_t x; -+ int32_t y; -+ int32_t width_mm; -+ int32_t height_mm; -+ /* char *make; is WESTON_TRANSMITTER_OUTPUT_MAKE */ -+ char *model; -+ -+ struct weston_mode mode; -+}; -+ -+struct weston_transmitter_output { -+ struct weston_output base; -+ -+ struct { -+ bool draw_initial_frame; -+ struct wl_surface *surface; -+ struct wl_output *output; -+ struct wl_display *display; -+ int configure_width, configure_height; -+ bool wait_for_configure; -+ } parent; -+ -+ struct weston_transmitter_remote *remote; -+ struct wl_list link; /* weston_transmitter_remote::output_list */ -+ -+ struct frame *frame; -+ -+ struct wl_callback *frame_cb; -+ struct renderer *renderer; -+}; -+ -+struct weston_transmitter_seat { -+ struct weston_seat *base; -+ struct wl_list link; -+ -+ /* pointer */ -+ wl_fixed_t pointer_surface_x; -+ wl_fixed_t pointer_surface_y; -+ -+ struct wl_listener get_pointer_listener; -+ struct weston_transmitter_surface *pointer_focus; -+ struct wl_listener pointer_focus_destroy_listener; -+ -+ struct wl_event_source *pointer_timer; /* fake */ -+ -+ double pointer_phase; /* fake */ -+ -+ /* keyboard */ -+ struct weston_transmitter_surface *keyboard_focus; -+ -+ /* touch */ -+ struct weston_transmitter_surface *touch_focus; -+}; -+ -+struct ivi_layout_surface { -+ struct wl_list link; /* ivi_layout::surface_list */ -+ struct wl_signal property_changed; -+ int32_t update_count; -+ uint32_t id_surface; -+ -+ struct ivi_layout *layout; -+ struct weston_surface *surface; -+ -+ struct ivi_layout_surface_properties prop; -+ -+ struct { -+ struct ivi_layout_surface_properties prop; -+ } pending; -+ -+ struct wl_list view_list; /* ivi_layout_view::surf_link */ -+}; -+ -+void -+transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs, -+ int32_t width, int32_t height); -+ -+int -+transmitter_remote_create_output(struct weston_transmitter_remote *remote, -+ const struct weston_transmitter_output_info *info); -+ -+void -+transmitter_output_destroy(struct weston_transmitter_output *output); -+ -+int -+transmitter_remote_create_seat(struct weston_transmitter_remote *remote); -+ -+void -+transmitter_seat_destroy(struct weston_transmitter_seat *seat); -+ -+/* The below are the functions to be called from the network protocol -+ * input event handlers. -+ */ -+ -+void -+transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y); -+ -+void -+transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ struct weston_transmitter_surface *txs); -+ -+void -+transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ wl_fixed_t surface_x, -+ wl_fixed_t surface_y); -+ -+void -+transmitter_seat_pointer_button(struct weston_transmitter_seat *seat, -+ uint32_t serial, -+ uint32_t time, -+ uint32_t button, -+ uint32_t state); -+ -+void -+transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis, -+ wl_fixed_t value); -+ -+void -+transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat); -+ -+void -+transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat, -+ uint32_t axis_source); -+ -+void -+transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat, -+ uint32_t time, -+ uint32_t axis); -+ -+void -+transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat, -+ uint32_t axis, -+ int32_t discrete); -+ -+/* Fake functions for mockup testing: */ -+ -+int -+transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat, -+ struct weston_transmitter_surface *txs); -+ -+void -+seat_capabilities(struct wthp_seat *wthp_seat, -+ enum wthp_seat_capability caps); -+ -+static const struct wthp_seat_listener seat_listener = { -+ seat_capabilities, -+ NULL -+}; -+ -+ -+#endif /* WESTON_TRANSMITTER_PLUGIN_H */ -diff --git a/waltham-transmitter/transmitter-plugin/transmitter_api.h b/waltham-transmitter/transmitter-plugin/transmitter_api.h -new file mode 100644 -index 0000000..9b3e5fe ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/transmitter_api.h -@@ -0,0 +1,278 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture 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. -+ */ -+ -+#ifndef WESTON_TRANSMITTER_API_H -+#define WESTON_TRANSMITTER_API_H -+ -+#include "plugin-registry.h" -+ -+#include -+ -+/** \file -+ * -+ * This is the Transmitter API published via weston_plugin_api_register(). -+ */ -+ -+struct weston_transmitter; -+struct weston_transmitter_remote; -+struct weston_transmitter_surface; -+ -+#define WESTON_TRANSMITTER_API_NAME "transmitter_v1" -+ -+/** See weston_transmitter_api::remote_get_status */ -+enum weston_transmitter_connection_status { -+ /** The connection hand-shake is not yet complete */ -+ WESTON_TRANSMITTER_CONNECTION_INITIALIZING, -+ -+ /** The connection is live and ready to be used. */ -+ WESTON_TRANSMITTER_CONNECTION_READY, -+ -+ /** The connection is dead. */ -+ WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, -+}; -+ -+/** See weston_transmitter_api::surface_get_stream_status */ -+enum weston_transmitter_stream_status { -+ /** The stream hand-shake is not yet complete. */ -+ WESTON_TRANSMITTER_STREAM_INITIALIZING, -+ -+ /** The stream is carrying surface content updates as needed. */ -+ WESTON_TRANSMITTER_STREAM_LIVE, -+ -+ /** The stream has failed and disconnected permanently. */ -+ WESTON_TRANSMITTER_STREAM_FAILED, -+}; -+ -+/** The Transmitter Base API -+ * -+ * Transmitter is a Weston plugin that provides remoting of weston_surfaces -+ * over the network. Shells use this API to create remote connections and -+ * push surfaces over the network. Shells are also responsible for relaying -+ * basic window state changes to Transmitter. -+ * -+ * In addition to the Transmitter Base API, shells also need to use a -+ * shell protocol specific Transmitter API to relay specific window state -+ * changes. -+ */ -+struct weston_transmitter_api { -+ /** Fetch the Transmitter plugin context -+ * -+ * \param compositor The compositor instance. -+ * \return The weston_transmitter context, which is always the same -+ * for the given compositor instance. -+ */ -+ struct weston_transmitter * -+ (*transmitter_get)(struct weston_compositor *compositor); -+ -+ /** -+ * Connect to a remote server via Transmitter. -+ * -+ * \param txr The Transmitter context. -+ * \param status Listener to inform of connection status changes. -+ * \return A handle to the remote connection, or NULL on failure. -+ * -+ * This call attempts to open a connection asynchronously. The -+ * connection is not usable until the listener signals it is ready. -+ * The listener may also signal that the connection failed instead. -+ * -+ * The listener callback argument is the weston_transmitter_remote -+ * returned by this function. Use remote_get_status() to fetch the -+ * current status. -+ * -+ */ -+ struct weston_transmitter_remote * -+ (*connect_to_remote)(struct weston_transmitter *txr); -+ -+ /** -+ * Retrieve the connection status. -+ * -+ * If the status is WESTON_TRANSMITTER_CONNECTION_DISCONNECTED, -+ * you have to shut the remote down completely. There is no automatic -+ * reconnect. -+ */ -+ enum weston_transmitter_connection_status -+ (*remote_get_status)(struct weston_transmitter_remote *remote); -+ -+ /** -+ * Destroy/disconnect a remote connection. -+ * -+ * Disconnects if connected, and destroys the connection. -+ * The connection status handler is not called. -+ * -+ * The caller is responsible for destroying all -+ * weston_transmitter_surfaces before calling this. -+ */ -+ void -+ (*remote_destroy)(struct weston_transmitter_remote *remote); -+ -+ /** Push a weston_surface to be transmitted to a remote. -+ * -+ * \param ws The surface to push. -+ * \param remote The remote connection to use. -+ * \param stream_status Listener for stream status changes. -+ * \return The Transmitter surface handle. -+ * -+ * The surface cannot be visible on the remote until the stream -+ * status listener signals WESTON_TRANSMITTER_STREAM_LIVE. After that, -+ * surface updates made by the application will be automatically -+ * streamed to the remote, and input events from the remote will be -+ * delivered to the application. -+ * -+ * The listener callback argument is the weston_transmitter_surface -+ * returned by this function. Use surface_get_stream_status() to -+ * fetch the current status. -+ */ -+ struct weston_transmitter_surface * -+ (*surface_push_to_remote)(struct weston_surface *ws, -+ struct weston_transmitter_remote *remote, -+ struct wl_listener *stream_status); -+ -+ /** -+ * Retrieve the surface content stream status. -+ * -+ * If the status is WESTON_TRANSMITTER_STREAM_FAILED, remoting the -+ * surface has stopped. There is no automatic retry. -+ */ -+ enum weston_transmitter_stream_status -+ (*surface_get_stream_status)(struct weston_transmitter_surface *txs); -+ -+ /** Stop remoting a weston_surface -+ * -+ * \param txs Transmitter surface handle to be stopped and freed. -+ * -+ * The surface stream status handler is not called. -+ */ -+ void -+ (*surface_destroy)(struct weston_transmitter_surface *txs); -+ -+ /** Notify of weston_surface being configured -+ * -+ * \param txs The Transmitter surface handle. -+ * \param dx The x delta given in wl_surface.attach request. -+ * \param dy The y delta given in wl_surface.attach request. -+ * -+ * Notifies Transmitter of new surface confguration. Transmitter will -+ * forward the arguments, window state, and reference the buffer for -+ * image transmission. -+ * -+ * Shells are meant to call this function for remoted surfaces in -+ * the weston_surface::configure handler. -+ * -+ * XXX: Is this necessary if we have weston_surface::apply_state_signal? -+ * -+ * Essentially this is just an elaborate way to forward dx,dy. -+ */ -+ void -+ (*surface_configure)(struct weston_transmitter_surface *txs, -+ int32_t dx, int32_t dy); -+ -+ void -+ (*surface_gather_state)(struct weston_transmitter_surface *txs); -+ -+ /** Notify that surface is connected to receiver -+ * -+ * \param txr The Transmitter context. -+ * \param connected_listener Listener for connected_signal. -+ */ -+ void -+ (*register_connection_status)(struct weston_transmitter *txr, -+ struct wl_listener *connected_listener); -+ -+ /** get weston_surface from weston_transmitter_surface -+ * -+ * \param txs The Transmitter surface. -+ */ -+ struct weston_surface * -+ (*get_weston_surface)(struct weston_transmitter_surface *txs); -+}; -+ -+static inline const struct weston_transmitter_api * -+weston_get_transmitter_api(struct weston_compositor *compositor) -+{ -+ return weston_plugin_api_get(compositor, WESTON_TRANSMITTER_API_NAME, -+ sizeof(struct weston_transmitter_api)); -+} -+ -+#define WESTON_TRANSMITTER_IVI_API_NAME "transmitter_ivi_v1" -+ -+/** For relaying configure events from Transmitter to shell. */ -+typedef void (*weston_transmitter_ivi_resize_handler_t)(void *data, -+ int32_t width, -+ int32_t height); -+ -+/** The Transmitter IVI-shell API -+ * -+ * Contains the IVI-shell specifics required to remote an ivi-surface. -+ */ -+struct weston_transmitter_ivi_api { -+ /** Set IVI-id for a transmitter surface -+ * -+ * \param txs The transmitted surface. -+ * \param ivi_id The IVI-surface id as specified by the -+ * ivi_application.surface_create request. -+ */ -+ void -+ (*set_ivi_id)(struct weston_transmitter_surface *txs, uint32_t ivi_id); -+ -+ /** Set callback to relay configure events. -+ * -+ * \param txs The transmitted surface. -+ * \param cb The callback function pointer. -+ * \param data User data to be passed to the callback. -+ * -+ * The arguments to the callback function are user data, and width and -+ * height from the configure event from the remote compositor. The -+ * shell must relay this event to the application. -+ */ -+ void -+ (*set_resize_callback)(struct weston_transmitter_surface *txs, -+ weston_transmitter_ivi_resize_handler_t cb, -+ void *data); -+}; -+ -+static inline const struct weston_transmitter_ivi_api * -+weston_get_transmitter_ivi_api(struct weston_compositor *compositor) -+{ -+ return weston_plugin_api_get(compositor, -+ WESTON_TRANSMITTER_IVI_API_NAME, -+ sizeof(struct weston_transmitter_ivi_api)); -+} -+ -+/** Identifies outputs created by the Transmitter by make */ -+#define WESTON_TRANSMITTER_OUTPUT_MAKE "Weston-Transmitter" -+ -+/* Remote compositor/output are identified by model */ -+ -+ -+struct renderer { -+ void (*repaint_output)(struct weston_output *base); -+ struct GstAppContext *ctx; -+ int32_t dmafd; /* dmafd received from compositor-drm */ -+ int surface_width; -+ int surface_height; -+ bool recorder_enabled; -+}; -+ -+#endif /* WESTON_TRANSMITTER_API_H */ -diff --git a/waltham-transmitter/transmitter-plugin/weston.ini.transmitter b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter -new file mode 100644 -index 0000000..1aff0b2 ---- /dev/null -+++ b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter -@@ -0,0 +1,21 @@ -+[core] -+shell=ivi-shell.so -+modules=transmitter.so -+ -+[ivi-shell] -+ivi-module=ivi-controller.so -+ivi-input-module=ivi-input-controller.so -+ -+[remote-output] -+output-name=transmitter_1 -+server-address=192.168.2.11 -+port=34400 -+width=1920 -+height=1080 -+ -+[remote-output] -+output-name=transmitter_2 -+server-address=192.168.2.12 -+port=34400 -+width=1920 -+height=1080 -diff --git a/waltham-transmitter/waltham-renderer/CMakeLists.txt b/waltham-transmitter/waltham-renderer/CMakeLists.txt -new file mode 100644 -index 0000000..abf1a4c ---- /dev/null -+++ b/waltham-transmitter/waltham-renderer/CMakeLists.txt -@@ -0,0 +1,59 @@ -+project (waltham-renderer) -+ -+find_package(PkgConfig REQUIRED) -+pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED) -+pkg_check_modules(WESTON weston>=2.0.0 REQUIRED) -+pkg_check_modules(PIXMAN pixman-1 REQUIRED) -+pkg_check_modules(WALTHAM waltham REQUIRED) -+pkg_search_module(GSTREAMER gstreamer-1.0 required) -+pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required) -+ -+include_directories( -+ ${CMAKE_SOURCE_DIR}/waltham-transmitter/transmitter-plugin -+ ${CMAKE_CURRENT_BINARY_DIR} -+ ${WAYLAND_CLIENT_INCLUDE_DIRS} -+ ${WAYLAND_SERVER_INCLUDE_DIRS} -+ ${WESTON_INCLUDE_DIRS} -+ ${PIXMAN_INCLUDE_DIRS} -+ ${WALTHAM_INCLUDE_DIRS} -+ ${GSTREAMER_INCLUDE_DIRS} -+ ${GSTREAMERAPP_INCLUDE_DIRS} -+) -+ -+link_directories( -+ ${WAYLAND_SERVER_LIBRARY_DIRS} -+ ${WESTON_LIBRARY_DIRS} -+ ${PIXMAN_LIBRARY_DIRS} -+ ${WALTHAM_LIBRARY_DIRS} -+ ${GSTREAMER_LIBRARY_DIRS} -+ ${GSTREAMERAPP_LIBRARY_DIRS} -+) -+ -+add_library(${PROJECT_NAME} MODULE -+ waltham-renderer.c -+ waltham-renderer.h -+) -+ -+set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") -+ -+set(LIBS -+ m -+ weston-2 -+ gstallocators-1.0 -+ gstvideo-1.0 -+ ${WAYLAND_SERVER_LIBRARIES} -+ ${WESTON_LIBRARIES} -+ ${PIXMAN_LIBRARIES} -+ ${WALTHAM_LIBRARIES} -+ ${GSTREAMER_LIBRARIES} -+ ${GSTREAMERAPP_LIBRARIES} -+) -+ -+add_dependencies(${PROJECT_NAME} ${LIBS}) -+ -+target_link_libraries(${PROJECT_NAME} ${LIBS}) -+ -+install ( -+ TARGETS ${PROJECT_NAME} -+ LIBRARY DESTINATION lib64/libweston-2 -+) -diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.c b/waltham-transmitter/waltham-renderer/waltham-renderer.c -new file mode 100644 -index 0000000..16ad3f8 ---- /dev/null -+++ b/waltham-transmitter/waltham-renderer/waltham-renderer.c -@@ -0,0 +1,270 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial -+ * portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -+ * SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "compositor.h" -+ -+#include "transmitter_api.h" -+#include "waltham-renderer.h" -+#include "plugin.h" -+ -+struct waltham_renderer { -+ struct renderer base; -+}; -+ -+struct GstAppContext -+{ -+ GMainLoop *loop; -+ GstBus *bus; -+ GstElement *pipeline; -+ GstElement *appsrc; -+ GstBuffer *gstbuffer; -+}; -+ -+gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) -+{ -+ struct GstAppContext *gstctx = p; -+ -+ 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); -+ switch (newstate){ -+ case GST_STATE_NULL: -+ fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); -+ } -+ break; -+ } -+ default: -+ fprintf(stderr, "Unhandled message\n"); -+ break; -+ } -+} -+ -+static int -+gst_pipe_init(struct weston_transmitter_output *output, struct gst_settings *settings) -+{ -+ struct GstAppContext *gstctx; -+ gstctx=zalloc(sizeof (*gstctx)); -+ if(!gstctx){ -+ weston_log("Enable to allocate memory\n"); -+ return -1; -+ } -+ GstCaps *caps; -+ int ret = 0; -+ GError *gerror = NULL; -+ FILE * pFile; -+ long lSize; -+ char * pipe = NULL; -+ size_t res; -+ -+ /* create gstreamer pipeline */ -+ gst_init(NULL, NULL); -+ gstctx->loop = g_main_loop_new(NULL, FALSE); -+ -+ /* read pipeline from file */ -+ pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); -+ if (pFile==NULL) -+ { -+ weston_log("File open error\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) -+ { -+ weston_log("Cannot allocate memory\n"); -+ return -1; -+ } -+ -+ /* copy the file into the buffer: */ -+ res = fread (pipe,1,lSize,pFile); -+ if (res != lSize) -+ { -+ weston_log("File read error\n"); -+ return -1; -+ } -+ -+ /* close file */ -+ fclose (pFile); -+ weston_log("Parsing GST pipeline:%s",pipe); -+ gstctx->pipeline = gst_parse_launch(pipe, &gerror); -+ free(pipe); -+ if(!gstctx->pipeline) -+ weston_log("Could not create gstreamer pipeline.\n"); -+ -+ gstctx->bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx->pipeline)); -+ gst_bus_add_watch(gstctx->bus, bus_message, &gstctx); -+ -+ gstctx->appsrc = (GstAppSrc*) -+ gst_bin_get_by_name(GST_BIN(gstctx->pipeline), "src"); -+ if (!gstctx->appsrc) -+ return -1; -+ -+ caps = gst_caps_new_simple("video/x-raw", -+ "format", G_TYPE_STRING, "BGRx", -+ "width", G_TYPE_INT, settings->width, -+ "height", G_TYPE_INT, settings->height, -+ NULL); -+ if (!caps) -+ return -1; -+ -+ g_object_set(G_OBJECT(gstctx->appsrc), -+ "caps", caps, -+ "stream-type", 0, -+ "format", GST_FORMAT_TIME, -+ "is-live", TRUE, -+ NULL); -+ gst_caps_unref(caps); -+ -+ gst_element_set_state((GstElement*)((void*)gstctx->pipeline), GST_STATE_PLAYING); -+ output->renderer->ctx = gstctx; -+ -+ return 0; -+} -+ -+static int -+recorder_enable(struct weston_transmitter_output *output) -+{ -+ struct gst_settings *settings; -+ -+ struct weston_output* base = &output->base; -+ struct weston_compositor *compositor = base->compositor; -+ struct weston_transmitter_remote* remote = output->remote; -+ -+ /* -+ * Limitation: -+ * Hard coding bitrate and crop params. -+ * In case of gst-recorder case these were taken from weston.ini -+ */ -+ int32_t bitrate = 3000000; -+ -+ settings = malloc(sizeof(* settings)); -+ settings->ip = remote->addr; -+ -+ settings->port = atoi(remote->port); -+ -+ settings->bitrate = bitrate; -+ settings->width = output->renderer->surface_width; -+ settings->height = output->renderer->surface_height; -+ -+ weston_log("gst-setting are :-->\n"); -+ weston_log("ip = %s \n",settings->ip); -+ weston_log("port = %d \n",settings->port); -+ weston_log("bitrate = %d \n",settings->bitrate); -+ weston_log("width = %d \n",settings->width); -+ weston_log("width = %d \n",settings->height); -+ -+ gst_pipe_init(output, settings); -+ -+ return 0; -+err: -+ weston_log("[gst recorder] %s:" -+ " invalid settings\n", -+ output->base.name); -+ free(settings); -+ return -1; -+} -+ -+static void waltham_renderer_repaint_output(struct weston_transmitter_output *output) -+{ -+ GstBuffer *gstbuffer; -+ GstMemory *mem; -+ GstAllocator *allocator; -+ int stride = output->renderer->surface_width * 4; -+ gsize offset = 0; -+ -+ if(!output->renderer->recorder_enabled) -+ { -+ recorder_enable(&output->base); -+ output->renderer->recorder_enabled = 1; -+ } -+ -+ gstbuffer = gst_buffer_new(); -+ allocator = gst_dmabuf_allocator_new(); -+ mem = gst_dmabuf_allocator_alloc(allocator, output->renderer->dmafd, -+ stride * output->renderer->surface_height); -+ gst_buffer_append_memory(gstbuffer, mem); -+ gst_buffer_add_video_meta_full(gstbuffer, -+ GST_VIDEO_FRAME_FLAG_NONE, -+ GST_VIDEO_FORMAT_BGRx, -+ output->renderer->surface_width, -+ output->renderer->surface_height, -+ 1, -+ &offset, -+ &stride); -+ -+ gst_app_src_push_buffer(output->renderer->ctx->appsrc, gstbuffer); -+ gst_object_unref(allocator); -+} -+ -+static int -+waltham_renderer_display_create(struct weston_transmitter_output *output) -+{ -+ struct waltham_renderer *wth_renderer; -+ -+ wth_renderer = zalloc(sizeof *wth_renderer); -+ if (wth_renderer == NULL) -+ return -1; -+ wth_renderer->base.repaint_output = waltham_renderer_repaint_output; -+ -+ output->renderer = &wth_renderer->base; -+ -+ return 0; -+} -+ -+WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = { -+ .display_create = waltham_renderer_display_create -+}; -diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.h b/waltham-transmitter/waltham-renderer/waltham-renderer.h -new file mode 100644 -index 0000000..a9ac513 ---- /dev/null -+++ b/waltham-transmitter/waltham-renderer/waltham-renderer.h -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation -+ * -+ * 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 TRANSMITTER_WALTHAM_RENDERER_H_ -+#define TRANSMITTER_WALTHAM_RENDERER_H_ -+ -+struct waltham_renderer_interface { -+ int (*display_create)(struct weston_transmitter_output *output); -+}; -+ -+struct gst_settings { -+ int width; -+ int height; -+ int bitrate; -+ char *ip; -+ int port; -+}; -+ -+#endif /* TRANSMITTER_WALTHAM_RENDERER_H_ */ --- -2.7.4 - diff --git a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb index 55d3aee73..f5a72dddc 100644 --- a/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb +++ b/meta-agl-profile-graphical/recipes-graphics/wayland/waltham-transmitter_git.bb @@ -5,14 +5,13 @@ LICENSE = "MIT" LIC_FILES_CHKSUM = "file://waltham-transmitter/COPYING;md5=d79ee9e66bb0f95d3386a7acae780b70" SRCREV = "${AUTOREV}" -SRC_URI = "https://gerrit.automotivelinux.org/gerrit/p/src/weston-ivi-plugins.git \ - file://0001-waltham-transmitter-initial-commit-of-waltham-transm.patch \ +SRC_URI = "ssh://wmizuno@gerrit.automotivelinux.org:29418/src/weston-ivi-plugins.git \ " S = "${WORKDIR}/git" -SRC_URI[md5sum] = "1819db75d41e607beb5520fafc3f542a" -SRC_URI[sha256sum] = "364f377f065d89ba44fd7efa10eec5cdb5108b892aaee5271c145ba10101b4c0" +SRC_URI[md5sum] = "f1e84f6901f355113fb9328433faef15" +SRC_URI[sha256sum] = "ba68233c4cf16cebbfa31399ee9dfcf183de36f5183677cfb26fa7e360634b33" inherit autotools pkgconfig inherit cmake