--- /dev/null
+DESCRIPTION = "Waltham is a network IPC library designed to resemble Wayland both protocol and protocol-API wise"
+HOMEPAGE = "https://github.com/waltham/waltham"
+
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = " \
+ file://LICENSE;md5=e8ad01a5182f2c1b3a2640e9ea268264 \
+"
+SRCREV = "${AUTOREV}"
+SRC_URI = "git://github.com/wmizuno/waltham.git \
+ "
+S = "${WORKDIR}/git"
+
+inherit autotools pkgconfig
+
+DEPENDS += "libdrm virtual/kernel wayland"
+RDEPENDS_${PN} += "libdrm"
\ No newline at end of file
--- /dev/null
+From aa3ea1af1dfa0e0ef5b452d8a5c53cd3eb508f52 Mon Sep 17 00:00:00 2001
+From: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
+Date: Wed, 2 Mar 2016 16:57:45 +0200
+Subject: [PATCH 1/3] transmitter: add an incomplete plugin (output and
+ pointer)
+
+Enabled with ./configure --enable-surface-remoting
+
+Draft the public API for binding and unbinding a surface for remoting,
+and another for ivi-shell specifics.
+
+Add the plumbing needed to relay a configure event from the network to
+the shell, to be forwarded to the application.
+
+Implement support for (fake) connection object tracking.
+
+Create a weston_output for a (fake) remote output. Force the
+sync-to-output on remoted surfaces. Use timers to fake wl_surface.enter
+and frame callback events. Also Presentation feedback is poorly faked.
+
+Hooking to weston_surface happens in two ways: surface_configure in
+Transmitter plugin API is used to relay the dx,dy from
+wl_surface.attach, and weston_surface::apply_state_signal relays state
+updates.
+
+Create a fake seat with pointer:
+
+- Add an internal pointer API that will be called by the networking code
+ for incoming input events. The API should match 1:1 to the events.
+ These functions will reimplement the parts of src/input.c to send out
+ the events to Wayland clients.
+
+- Implement pointer enter/leave of the internal pointer API. Code is
+ mimicked from weston_pointer_set_focus(), but without all the logic
+ needed to determine the right actions.
+
+- Implement pointer frame of the internal pointer API.
+
+- Add a fake pointer input generator. It only make the pointer enter the
+ surface remoted the most recently, and moves the pointer in a circle.
+
+All ways of getting pointer focus should be covered. Serial tracking is
+the same as in Weston core. Seat maintains the pointer focus surface.
+Focus_client is managed while Weston core never sees any focus.
+Transmitter surface gained a destroy signal.
+
+Surface destruction relies on forwarding the destroy to the remote,
+which will then reply with appropriate pointer.leave events. This is not
+implemented by the input faking code.
+
+Transmitter is expected to open all inputs available on the remote and
+multiplex those to local clients as clients subscribe.
+
+Notes about the design and guidelines for finishing the implementation
+are included, and all the mockup code is annotated as "fake" so it is
+easy to spot and replace with a proper network implementation.
+
+There are listener-based APIs for getting both remote connection status
+changes, and per-surface stream status changes.
+
+Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
+---
+ Makefile.am | 19 ++
+ configure.ac | 9 +
+ transmitter/README | 53 ++++
+ transmitter/input.c | 597 +++++++++++++++++++++++++++++++++++++++
+ transmitter/output.c | 234 ++++++++++++++++
+ transmitter/plugin.c | 638 ++++++++++++++++++++++++++++++++++++++++++
+ transmitter/plugin.h | 207 ++++++++++++++
+ transmitter/transmitter_api.h | 253 +++++++++++++++++
+ 8 files changed, 2010 insertions(+)
+ create mode 100644 transmitter/README
+ create mode 100644 transmitter/input.c
+ create mode 100644 transmitter/output.c
+ create mode 100644 transmitter/plugin.c
+ create mode 100644 transmitter/plugin.h
+ create mode 100644 transmitter/transmitter_api.h
+
+diff --git a/Makefile.am b/Makefile.am
+index cdf82ab..6cca875 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -502,6 +502,25 @@ cms_colord_la_SOURCES = \
+ endif
+ endif
+
++if ENABLE_SURFACE_REMOTING
++module_LTLIBRARIES += transmitter.la
++transmitter_la_LDFLAGS = -module -avoid-version
++transmitter_la_CFLAGS = \
++ $(COMPOSITOR_CFLAGS) \
++ $(AM_CFLAGS)
++transmitter_la_LIBADD = $(COMPOSITOR_LIBS)
++transmitter_la_SOURCES = \
++ transmitter/plugin.c \
++ transmitter/plugin.h \
++ transmitter/output.c \
++ transmitter/input.c \
++ transmitter/transmitter_api.h \
++ shared/helpers.h \
++ shared/timespec-util.h \
++ shared/zalloc.h \
++ src/compositor.h
++endif
++
+ noinst_PROGRAMS += spring-tool
+ spring_tool_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
+ spring_tool_LDADD = $(COMPOSITOR_LIBS) -lm
+diff --git a/configure.ac b/configure.ac
+index d0dee1b..06cda73 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -562,6 +562,14 @@ AS_IF([test "x$have_systemd_login_209" = "xyes"],
+ [AC_DEFINE([HAVE_SYSTEMD_LOGIN_209], [1], [Have systemd-login >= 209])])
+
+
++# surface remoting
++AC_ARG_ENABLE(surface-remoting,
++ AS_HELP_STRING([--enable-surface-remoting],
++ [support for surface remoting over network]),,
++ enable_surface_remoting=no)
++AM_CONDITIONAL(ENABLE_SURFACE_REMOTING, test "x$enable_surface_remoting" = "xyes")
++
++
+ # Note that other features might want libxml2, or this feature might use
+ # alternative xml libraries at some point. Therefore the feature and
+ # pre-requisite concepts are split.
+@@ -750,4 +758,5 @@ AC_MSG_RESULT([
+ libunwind Support ${have_libunwind}
+ VA H.264 encoding Support ${have_libva}
+ GStreamer H.264 enc. Support ${enable_gst_recorder}
++ Surface remoting support ${enable_surface_remoting}
+ ])
+diff --git a/transmitter/README b/transmitter/README
+new file mode 100644
+index 0000000..a7977ba
+--- /dev/null
++++ b/transmitter/README
+@@ -0,0 +1,53 @@
++Testing Transmitter with ivi-shell
++
++The current implementation of Transmitter is a stub which interfaces to
++other Weston parts appropriately, but all networking is just a mockup.
++
++
++Configure Weston with --enable-surface-remoting to build the Transmitter
++plugin.
++
++In weston.ini, add 'transmitter.so' to the 'modules' key under '[core]', and
++make sure the 'shell' is 'ivi-shell.so'. Follow the ivi-shell example
++weston.ini for everything else.
++
++When you start weston, the log should contain something like this:
++
++[13:13:54.799] Loading module '/home/pq/local/lib/weston/ivi-shell.so'
++[13:13:54.799] launching '/home/pq/local/libexec/weston-keyboard'
++[13:13:54.799] Loading module '/home/pq/local/lib/weston/hmi-controller.so'
++[13:13:54.799] Loading module '/home/pq/local/lib/weston/transmitter.so'
++[13:13:54.799] Registered plugin API 'transmitter_v1' of size 48
++[13:13:54.799] Registered plugin API 'transmitter_ivi_v1' of size 16
++[13:13:54.799] Transmitter initialized.
++[13:13:54.799] ivi-layout: Transmitter enabled.
++[13:13:54.799] launching '/home/pq/build/weston/weston-ivi-shell-user-interface'
++[13:13:54.799] hmi-controller: Transmitter enabled.
++[13:13:54.799] Transmitter connecting to 0.0.0.0:66...
++[13:13:55.800] Transmitter connected to 0.0.0.0:66.
++[13:13:55.800] hmi-controller: connection status 0
++[13:13:55.800] Transmitter created output 'transmitter-0.0.0.0:66-1': Weston-Transmitter, transmitter-0.0.0.0:66-1, 0
++[13:13:55.800] Transmitter created seat=0x1c37bd0 'transmitter-0.0.0.0:66-default'
++[13:13:55.800] Transmitter created pointer=0x1c38430 for seat 0x1c37bd0
++[13:13:55.800] transmitter_start_repaint_loop(transmitter-0.0.0.0:66-1)
++
++
++If you have edited a client to have ivi-id >= 0xfaa01000, when you start that
++client it should be "remoted" automatically and not appear on screen.
++
++You can also manually start remoting:
++- Start an IVI application.
++- Move pointer onto the application window.
++- Press Mod+Shift+space, and then 'k'.
++- The window should disappear.
++
++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
++
++Once remoting has started, the mockup code will generate fake pointer input for
++the window. This can be seen with e.g. weston-eventdemo, or running an
++application with WAYLAND_DEBUG=client.
+diff --git a/transmitter/input.c b/transmitter/input.c
+new file mode 100644
+index 0000000..0ba04d4
+--- /dev/null
++++ b/transmitter/input.c
+@@ -0,0 +1,597 @@
++/*
++ * Copyright (C) 2016 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 "config.h"
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++/* for fake stuff */
++#include <math.h>
++
++#include "compositor.h"
++#include "helpers.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,
++};
++
++/* 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);
++
++ seat->get_pointer_listener.notify = seat_get_pointer_handler;
++ wl_signal_add(&seat->base.get_pointer_signal,
++ &seat->get_pointer_listener);
++
++ 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_client = weston_pointer_get_pointer_client(pointer,
++ client);
++ 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)
++{
++ assert(!"TODO");
++}
++
++void
++transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat,
++ uint32_t time,
++ uint32_t axis,
++ wl_fixed_t value)
++{
++ assert(!"TODO");
++}
++
++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)
++{
++ assert(!"TODO");
++}
++
++void
++transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat,
++ uint32_t time,
++ uint32_t axis)
++{
++ assert(!"TODO");
++}
++
++void
++transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat,
++ uint32_t axis,
++ int32_t discrete)
++{
++ assert(!"TODO");
++}
++
++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);
++
++ weston_seat_release(&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);
++}
++
++int
++transmitter_remote_create_seat(struct weston_transmitter_remote *remote)
++{
++ struct weston_transmitter_seat *seat = NULL;
++ char *name = 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;
++
++ 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);
++
++ /* XXX: mirror remote capabilities */
++ transmitter_seat_create_pointer(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/transmitter/output.c b/transmitter/output.c
+new file mode 100644
+index 0000000..6a78721
+--- /dev/null
++++ b/transmitter/output.c
+@@ -0,0 +1,234 @@
++/*
++ * Copyright (C) 2016 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 "config.h"
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++#include "compositor.h"
++#include "helpers.h"
++
++#include "plugin.h"
++#include "transmitter_api.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 inline struct weston_transmitter_output *
++to_transmitter_output(struct weston_output *base)
++{
++ return container_of(base, struct weston_transmitter_output, base);
++}
++
++static char *
++make_model(struct weston_transmitter_remote *remote, int name)
++{
++ char *str;
++
++ if (asprintf(&str, "transmitter-%s-%d", remote->addr, 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 = container_of(mode_list->next, struct weston_mode, link);
++
++ wl_list_remove(&mode->link);
++ free(mode);
++ }
++}
++
++void
++transmitter_output_destroy(struct weston_transmitter_output *output)
++{
++ weston_log("Transmitter destroying output '%s'\n", output->base.name);
++
++ 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 = to_transmitter_output(base);
++
++ transmitter_output_destroy(output);
++}
++
++static void
++transmitter_start_repaint_loop(struct weston_output *base)
++{
++ weston_log("%s(%s)\n", __func__, base->name);
++}
++
++static int
++transmitter_output_repaint(struct weston_output *base,
++ pixman_region32_t *damage)
++{
++ weston_log("%s(%s)\n", __func__, base->name);
++
++ return -1;
++}
++
++int
++transmitter_remote_create_output(
++ struct weston_transmitter_remote *remote,
++ const struct weston_transmitter_output_info *info)
++{
++ struct weston_transmitter_output *output;
++
++ output = zalloc(sizeof *output);
++ if (!output)
++ return -1;
++
++ 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");
++
++ 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);
++ /* 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.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->remote = remote;
++ wl_list_insert(&remote->output_list, &output->link);
++
++ weston_log("Transmitter created output '%s': %s, %s, %s\n",
++ output->base.name, output->base.make, output->base.model,
++ output->base.serial_number);
++
++ 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/transmitter/plugin.c b/transmitter/plugin.c
+new file mode 100644
+index 0000000..c5e56d3
+--- /dev/null
++++ b/transmitter/plugin.c
+@@ -0,0 +1,638 @@
++/*
++ * Copyright (C) 2016 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 "config.h"
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++#include <linux/input.h>
++
++#include "compositor.h"
++#include "helpers.h"
++#include "timespec-util.h"
++
++#include "plugin.h"
++#include "transmitter_api.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.
++ */
++
++/** 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 int
++frame_callback_handler(void *data) /* fake */
++{
++ struct weston_transmitter_surface *txs = data;
++ struct weston_frame_callback *cb, *cnext;
++ struct weston_output *output;
++ struct weston_compositor *compositor;
++ uint32_t frame_time;
++ uint32_t presented_flags;
++ int32_t refresh_nsec;
++ struct timespec stamp;
++
++ compositor = txs->remote->transmitter->compositor;
++ output = txs->sync_output;
++
++ /* wl_surface.enter should arrive before any frame callbacks,
++ * but remote might send frame callbacks for non-visible too.
++ */
++ if (!output)
++ return 0;
++
++ /* XXX: eeeew */
++ frame_time = weston_compositor_get_time();
++
++ wl_list_for_each_safe(cb, cnext, &txs->frame_callback_list, link) {
++ wl_callback_send_done(cb->resource, frame_time);
++ wl_resource_destroy(cb->resource);
++ }
++
++ presented_flags = 0;
++ refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
++ /* XXX: waaahhhahaa */
++ weston_compositor_read_presentation_clock(compositor, &stamp);
++ weston_presentation_feedback_present_list(&txs->feedback_list,
++ output, refresh_nsec, &stamp,
++ output->msc,
++ presented_flags);
++
++ return 0;
++}
++
++static void
++fake_frame_callback(struct weston_transmitter_surface *txs)
++{
++ struct weston_transmitter *txr = txs->remote->transmitter;
++ struct wl_event_loop *loop;
++
++ if (!txs->frame_timer) {
++ loop = wl_display_get_event_loop(txr->compositor->wl_display);
++ txs->frame_timer =
++ wl_event_loop_add_timer(loop,
++ frame_callback_handler, txs);
++ }
++
++ wl_event_source_timer_update(txs->frame_timer, 85);
++}
++
++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
++transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
++{
++ weston_log("Transmitter: update surface %p (%d, %d), %d cb\n",
++ txs->surface, txs->attach_dx, txs->attach_dy,
++ wl_list_length(&txs->surface->frame_callback_list));
++
++ wl_list_insert_list(&txs->frame_callback_list,
++ &txs->surface->frame_callback_list);
++ wl_list_init(&txs->surface->frame_callback_list);
++
++ wl_list_insert_list(&txs->feedback_list, &txs->surface->feedback_list);
++ wl_list_init(&txs->surface->feedback_list);
++
++ /* TODO: transmit surface state to remote */
++
++ txs->attach_dx = 0;
++ txs->attach_dy = 0;
++}
++
++/** weston_surface apply state signal handler */
++static void
++transmitter_surface_apply_state(struct wl_listener *listener, void *data)
++{
++ struct weston_transmitter_surface *txs =
++ container_of(listener, struct weston_transmitter_surface,
++ apply_state_listener);
++
++ assert(data == NULL);
++
++ transmitter_surface_gather_state(txs);
++ fake_frame_callback(txs);
++}
++
++/** 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_frame_callback *framecb, *cnext;
++
++ /* may be called multiple times */
++ if (!txs->surface)
++ return;
++
++ wl_signal_emit(&txs->destroy_signal, txs);
++
++ wl_list_remove(&txs->surface_destroy_listener.link);
++ weston_log("Transmitter unbound surface %p.\n", txs->surface);
++ txs->surface = NULL;
++
++ wl_list_remove(&txs->sync_output_destroy_listener.link);
++ wl_list_remove(&txs->apply_state_listener.link);
++
++ if (txs->map_timer)
++ wl_event_source_remove(txs->map_timer);
++ if (txs->frame_timer)
++ wl_event_source_remove(txs->frame_timer);
++
++ weston_presentation_feedback_discard_list(&txs->feedback_list);
++ wl_list_for_each_safe(framecb, cnext, &txs->frame_callback_list, link)
++ wl_resource_destroy(framecb->resource);
++
++ /* 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 =
++ container_of(listener, struct weston_transmitter_surface,
++ surface_destroy_listener);
++
++ assert(data == txs->surface);
++
++ transmitter_surface_zombify(txs);
++}
++
++static struct weston_transmitter_surface *
++transmitter_surface_get(struct weston_surface *ws)
++{
++ struct wl_listener *listener;
++ struct weston_transmitter_surface *txs;
++
++ listener = wl_signal_get(&ws->destroy_signal,
++ transmitter_surface_destroyed);
++
++ if (!listener)
++ return NULL;
++
++ txs = container_of(listener, struct weston_transmitter_surface,
++ surface_destroy_listener);
++ assert(ws == txs->surface);
++
++ return txs;
++}
++
++static void
++sync_output_destroy_handler(struct wl_listener *listener, void *data)
++{
++ struct weston_transmitter_surface *txs;
++
++ txs = container_of(listener, struct weston_transmitter_surface,
++ 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
++fake_input(struct weston_transmitter_surface *txs)
++{
++ struct wl_list *seat_list = &txs->remote->seat_list;
++ struct weston_transmitter_seat *seat;
++
++ assert(wl_list_length(seat_list) == 1);
++ seat = container_of(seat_list->next,
++ struct weston_transmitter_seat, link);
++
++ transmitter_seat_fake_pointer_input(seat, txs);
++}
++
++/* fake receiving wl_surface.enter(output) */
++static int
++map_timer_handler(void *data)
++{
++ struct weston_transmitter_surface *txs = data;
++ struct weston_transmitter_output *output;
++
++ assert(!wl_list_empty(&txs->remote->output_list));
++
++ output = container_of(txs->remote->output_list.next,
++ struct weston_transmitter_output, link);
++
++ txs->sync_output = &output->base;
++ txs->sync_output_destroy_listener.notify = sync_output_destroy_handler;
++ wl_list_remove(&txs->sync_output_destroy_listener.link);
++ wl_signal_add(&txs->sync_output->destroy_signal,
++ &txs->sync_output_destroy_listener);
++
++ weston_surface_force_output(txs->surface, txs->sync_output);
++
++ weston_log("Transmitter: surface %p entered output %s\n",
++ txs->surface, txs->sync_output->name);
++
++ fake_frame_callback(txs);
++ fake_input(txs);
++
++ return 0;
++}
++
++/* Fake a delay for the remote end to map the surface to an output */
++static void
++fake_output_mapping(struct weston_transmitter_surface *txs)
++{
++ struct weston_transmitter *txr = txs->remote->transmitter;
++ struct wl_event_loop *loop;
++
++ loop = wl_display_get_event_loop(txr->compositor->wl_display);
++ txs->map_timer = wl_event_loop_add_timer(loop, map_timer_handler, txs);
++ wl_event_source_timer_update(txs->map_timer, 400);
++}
++
++/* Fake getting "connection established" from the content streamer. */
++static void
++fake_stream_opening_handler(void *data)
++{
++ struct weston_transmitter_surface *txs = data;
++
++ /* ...once the connection is up: */
++ txs->status = WESTON_TRANSMITTER_STREAM_LIVE;
++ wl_signal_emit(&txs->stream_status_signal, txs);
++
++ /* need to create the surface on the remote and set all state */
++ transmitter_surface_gather_state(txs);
++
++ fake_output_mapping(txs);
++}
++
++/* Fake a callback from content streamer. */
++static void
++fake_stream_opening(struct weston_transmitter_surface *txs)
++{
++ struct weston_transmitter *txr = txs->remote->transmitter;
++ struct wl_event_loop *loop;
++
++ loop = wl_display_get_event_loop(txr->compositor->wl_display);
++ wl_event_loop_add_idle(loop, fake_stream_opening_handler, txs);
++}
++
++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_surface *txs;
++
++ if (transmitter_surface_get(ws)) {
++ weston_log("Transmitter: surface %p already bound.\n", ws);
++ return 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);
++ 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);
++
++ txs->apply_state_listener.notify = transmitter_surface_apply_state;
++ wl_signal_add(&ws->apply_state_signal, &txs->apply_state_listener);
++
++ wl_list_init(&txs->sync_output_destroy_listener.link);
++
++ wl_list_init(&txs->frame_callback_list);
++ wl_list_init(&txs->feedback_list);
++
++ /* TODO: create the content stream connection... */
++ fake_stream_opening(txs);
++
++ return txs;
++}
++
++static enum weston_transmitter_stream_status
++transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs)
++{
++ return txs->status;
++}
++
++static int
++conn_timer_handler(void *data) /* fake */
++{
++ struct weston_transmitter_remote *remote = data;
++ struct weston_transmitter_output_info info = {
++ WL_OUTPUT_SUBPIXEL_NONE,
++ WL_OUTPUT_TRANSFORM_NORMAL,
++ 1,
++ 0, 0,
++ 300, 200,
++ "fake",
++ {
++ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
++ 800, 600,
++ 51519,
++ { NULL, NULL }
++ }
++ };
++
++ weston_log("Transmitter connected to %s.\n", remote->addr);
++ remote->status = WESTON_TRANSMITTER_CONNECTION_READY;
++ wl_signal_emit(&remote->connection_status_signal, remote);
++
++ wl_event_source_remove(remote->conn_timer);
++ remote->conn_timer = NULL;
++
++ /* 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);
++
++ return 0;
++}
++
++static struct weston_transmitter_remote *
++transmitter_connect_to_remote(struct weston_transmitter *txr,
++ const char *addr,
++ struct wl_listener *status)
++{
++ struct weston_transmitter_remote *remote;
++ struct wl_event_loop *loop;
++
++ remote = zalloc(sizeof (*remote));
++ if (!remote)
++ return NULL;
++
++ remote->transmitter = txr;
++ wl_list_insert(&txr->remote_list, &remote->link);
++ remote->addr = strdup(addr);
++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
++ wl_signal_init(&remote->connection_status_signal);
++ wl_signal_add(&remote->connection_status_signal, status);
++ wl_list_init(&remote->output_list);
++ wl_list_init(&remote->surface_list);
++ wl_list_init(&remote->seat_list);
++
++ /* XXX: actually start connecting */
++ weston_log("Transmitter connecting to %s...\n", addr);
++ /* fake it with a one second timer */
++ loop = wl_display_get_event_loop(txr->compositor->wl_display);
++ remote->conn_timer = wl_event_loop_add_timer(loop, conn_timer_handler,
++ remote);
++ wl_event_source_timer_update(remote->conn_timer, 1000);
++
++ 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.
++ */
++ weston_log("Transmitter disconnecting from %s.\n", remote->addr);
++
++ if (remote->conn_timer)
++ wl_event_source_remove(remote->conn_timer);
++
++ 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);
++
++ 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 =
++ container_of(listener, struct weston_transmitter,
++ 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);
++
++ weston_log("Transmitter terminating.\n");
++ 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 = container_of(listener, struct weston_transmitter,
++ compositor_destroy_listener);
++ assert(compositor == txr->compositor);
++
++ return txr;
++}
++
++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,
++};
++
++static void
++transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs,
++ uint32_t ivi_id)
++{
++ assert(txs->surface);
++ if (!txs->surface)
++ return;
++
++ weston_log("%s(%p, %#x)\n", __func__, txs->surface, ivi_id);
++}
++
++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_ivi_id,
++ transmitter_surface_set_resize_callback,
++};
++
++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)
++ 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");
++
++ return 0;
++
++fail:
++ wl_list_remove(&txr->compositor_destroy_listener.link);
++ free(txr);
++
++ return -1;
++}
+diff --git a/transmitter/plugin.h b/transmitter/plugin.h
+new file mode 100644
+index 0000000..710b543
+--- /dev/null
++++ b/transmitter/plugin.h
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (C) 2016 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 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 <stdint.h>
++
++#include "compositor.h"
++#include "transmitter_api.h"
++
++struct weston_transmitter {
++ struct weston_compositor *compositor;
++ struct wl_listener compositor_destroy_listener;
++
++ struct wl_list remote_list; /* transmitter_remote::link */
++};
++
++struct weston_transmitter_remote {
++ struct weston_transmitter *transmitter;
++ struct wl_list link;
++
++ char *addr;
++
++ enum weston_transmitter_connection_status status;
++ struct wl_signal connection_status_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_event_source *conn_timer; /* fake */
++};
++
++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;
++ struct wl_listener apply_state_listener;
++
++ weston_transmitter_ivi_resize_handler_t resize_handler;
++ void *resize_handler_data;
++
++ struct weston_output *sync_output;
++ struct wl_listener sync_output_destroy_listener;
++
++ struct wl_event_source *map_timer; /* fake */
++ struct wl_event_source *frame_timer; /* fake */
++
++ 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 */
++};
++
++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 weston_transmitter_remote *remote;
++ struct wl_list link; /* weston_transmitter_remote::output_list */
++};
++
++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 */
++
++ /* touch */
++};
++
++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);
++
++
++#endif /* WESTON_TRANSMITTER_PLUGIN_H */
+diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h
+new file mode 100644
+index 0000000..95d82ec
+--- /dev/null
++++ b/transmitter/transmitter_api.h
+@@ -0,0 +1,253 @@
++/*
++ * Copyright (C) 2016 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 WESTON_TRANSMITTER_API_H
++#define WESTON_TRANSMITTER_API_H
++
++#include "plugin-registry.h"
++
++#include <stdint.h>
++
++/** \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 addr Address of the remote server.
++ * \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.
++ *
++ * The address argument is a string in the form "host:port".
++ */
++ struct weston_transmitter_remote *
++ (*connect_to_remote)(struct weston_transmitter *txr,
++ const char *addr,
++ struct wl_listener *status);
++
++ /**
++ * 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);
++};
++
++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 */
++
++#endif /* WESTON_TRANSMITTER_API_H */
+--
+2.7.4
+
--- /dev/null
+From 8e586a78c7e74f0faaddd02abbdfcf6879d0f096 Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Wed, 27 Sep 2017 09:09:17 +0900
+Subject: [PATCH 2/3] ivi-layout :Register ivi-layout-interface It enables to
+ use ivi-layout-interface without load module
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ ivi-shell/ivi-layout-export.h | 2 ++
+ ivi-shell/ivi-layout.c | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/ivi-shell/ivi-layout-export.h b/ivi-shell/ivi-layout-export.h
+index 2317d6e..11ea874 100644
+--- a/ivi-shell/ivi-layout-export.h
++++ b/ivi-shell/ivi-layout-export.h
+@@ -63,6 +63,8 @@ extern "C" {
+ #define IVI_SUCCEEDED (0)
+ #define IVI_FAILED (-1)
+
++#define IVI_LAYOUT_API_NAME "ivi_layout_api_v1"
++
+ struct ivi_layout_layer;
+ struct ivi_layout_screen;
+ struct ivi_layout_surface;
+diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
+index 64e4ead..602a42f 100644
+--- a/ivi-shell/ivi-layout.c
++++ b/ivi-shell/ivi-layout.c
+@@ -67,6 +67,7 @@
+ #include "ivi-layout-export.h"
+ #include "ivi-layout-private.h"
+ #include "ivi-layout-shell.h"
++#include "plugin-registry.h"
+
+ #include "shared/helpers.h"
+ #include "shared/os-compatibility.h"
+@@ -2139,5 +2140,8 @@ load_controller_modules(struct weston_compositor *compositor, const char *module
+ p++;
+ }
+
++ weston_plugin_api_register(compositor, IVI_LAYOUT_API_NAME,
++ &ivi_layout_interface, sizeof(struct ivi_layout_interface));
++
+ return 0;
+ }
+--
+2.7.4
+
--- /dev/null
+From 0d114839f299b6a9e3f504e75c22d636222c3b20 Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Tue, 10 Apr 2018 15:23:02 +0900
+Subject: [PATCH 3/3] transmitter: transmitter plugin for waltham protocol
+
+The transmitter plugin enables weston to communicate with
+remote site compositor over the ethernet.
+Communication is done with waltham protocol which is the
+wayland like IPC protocol.
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ Makefile.am | 11 +-
+ configure.ac | 12 +
+ transmitter/README | 108 +++--
+ transmitter/input.c | 783 ++++++++++++++++++++++++++++++++-
+ transmitter/output.c | 139 +++++-
+ transmitter/plugin.c | 875 ++++++++++++++++++++++++++-----------
+ transmitter/plugin.h | 140 +++++-
+ transmitter/transmitter_api.h | 26 +-
+ transmitter/weston.ini.transmitter | 21 +
+ 9 files changed, 1763 insertions(+), 352 deletions(-)
+ create mode 100644 transmitter/weston.ini.transmitter
+
+diff --git a/Makefile.am b/Makefile.am
+index 6cca875..2cb1920 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -306,6 +306,11 @@ westoninclude_HEADERS += \
+ ivi-shell/ivi-layout-export.h
+ endif
+
++if ENABLE_SURFACE_REMOTING
++westoninclude_HEADERS += \
++ transmitter/transmitter_api.h
++endif
++
+ if ENABLE_EGL
+ libweston_module_LTLIBRARIES += gl-renderer.la
+ gl_renderer_la_LDFLAGS = -module -avoid-version
+@@ -507,8 +512,10 @@ module_LTLIBRARIES += transmitter.la
+ transmitter_la_LDFLAGS = -module -avoid-version
+ transmitter_la_CFLAGS = \
+ $(COMPOSITOR_CFLAGS) \
+- $(AM_CFLAGS)
+-transmitter_la_LIBADD = $(COMPOSITOR_LIBS)
++ $(AM_CFLAGS) \
++ $(WALTHAM_CFLAGS)
++transmitter_la_LIBADD = $(COMPOSITOR_LIBS) \
++ -lwaltham
+ transmitter_la_SOURCES = \
+ transmitter/plugin.c \
+ transmitter/plugin.h \
+diff --git a/configure.ac b/configure.ac
+index 6cf2883..4819e08 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -543,6 +543,18 @@ AC_ARG_ENABLE(surface-remoting,
+ AS_HELP_STRING([--enable-surface-remoting],
+ [support for surface remoting over network]),,
+ enable_surface_remoting=no)
++if test "x$enable_surface_remoting" != "xno"; then
++ PKG_CHECK_MODULES(WALTHAM,
++ waltham >= 0.1.0,
++ have_waltham=yes,
++ have_waltham=no)
++ if test "x$have_waltham" = "xno" -a "x$enable_surface_remoting" = "xyes"; then
++ AC_MSG_ERROR([surface_remoting support explicitly requested, but waltham couldn't be found])
++ fi
++ if test "x$have_waltham" = "xyes"; then
++ enable_surface_remoting=yes
++ fi
++fi
+ AM_CONDITIONAL(ENABLE_SURFACE_REMOTING, test "x$enable_surface_remoting" = "xyes")
+
+
+diff --git a/transmitter/README b/transmitter/README
+index a7977ba..af80574 100644
+--- a/transmitter/README
++++ b/transmitter/README
+@@ -1,45 +1,84 @@
+-Testing Transmitter with ivi-shell
++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.
+
+-In weston.ini, add 'transmitter.so' to the 'modules' key under '[core]', and
+-make sure the 'shell' is 'ivi-shell.so'. Follow the ivi-shell example
+-weston.ini for everything else.
+-
+-When you start weston, the log should contain something like this:
+-
+-[13:13:54.799] Loading module '/home/pq/local/lib/weston/ivi-shell.so'
+-[13:13:54.799] launching '/home/pq/local/libexec/weston-keyboard'
+-[13:13:54.799] Loading module '/home/pq/local/lib/weston/hmi-controller.so'
+-[13:13:54.799] Loading module '/home/pq/local/lib/weston/transmitter.so'
+-[13:13:54.799] Registered plugin API 'transmitter_v1' of size 48
+-[13:13:54.799] Registered plugin API 'transmitter_ivi_v1' of size 16
+-[13:13:54.799] Transmitter initialized.
+-[13:13:54.799] ivi-layout: Transmitter enabled.
+-[13:13:54.799] launching '/home/pq/build/weston/weston-ivi-shell-user-interface'
+-[13:13:54.799] hmi-controller: Transmitter enabled.
+-[13:13:54.799] Transmitter connecting to 0.0.0.0:66...
+-[13:13:55.800] Transmitter connected to 0.0.0.0:66.
+-[13:13:55.800] hmi-controller: connection status 0
+-[13:13:55.800] Transmitter created output 'transmitter-0.0.0.0:66-1': Weston-Transmitter, transmitter-0.0.0.0:66-1, 0
+-[13:13:55.800] Transmitter created seat=0x1c37bd0 'transmitter-0.0.0.0:66-default'
+-[13:13:55.800] Transmitter created pointer=0x1c38430 for seat 0x1c37bd0
+-[13:13:55.800] transmitter_start_repaint_loop(transmitter-0.0.0.0:66-1)
+-
+-
+-If you have edited a client to have ivi-id >= 0xfaa01000, when you start that
+-client it should be "remoted" automatically and not appear on screen.
+-
+-You can also manually start remoting:
++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 repository.
++
++If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can
++see the log like this:
++
++ [06:12:41.238] Loading module '/usr/lib64/weston/ivi-shell.so'
++ [06:12:41.245] launching '/usr/libexec/weston-keyboard'
++ [06:12:41.247] Loading module '/usr/lib64/weston/ivi-controller.so'
++ [06:12:41.252] Loading module '/usr/lib64/weston/ivi-input-controller.so'
++ [06:12:41.253] ivi-input-controller module loaded successfully!
++ [06:12:41.255] Loading module '/usr/lib64/weston/transmitter.so'
++ [06:12:41.260] Registered plugin API 'transmitter_v1' of size 88
++ [06:12:41.260] Registered plugin API 'transmitter_ivi_v1' of size 16
++ [06:12:41.260] Transmitter initialized.
++ [06:12:41.260] ivi-layout: Transmitter enabled.
++ [06:12:41.260] Transmitter weston_seat 0x14f8010
++ [06:12:41.260] Transmitter created pointer=0x139a440 for seat 0x14f8010
++ [06:12:41.261] Transmitter created keyboard=0x14f8160 for seat 0x14f8010
++ [06:12:41.261] Transmitter created touch=0x1508750 for seat 0x14f8010
++
++The connection is established, you can see following debug messages:
++
++ root@gr-mrb-64:~# debug: wth_connection_insert_new_object: new object id: 1
++ debug: wth_connection_insert_new_object: new object id: 2
++ 2017-07-19T06:14:31Z 00001000030000000100000002000000 wth_display_get_registry
++ debug: wth_connection_insert_new_object: new object id: 3
++ 2017-07-19T06:14:31Z 00001000020000000100000003000000 wth_display_sync
++ debug: Message received on conn 0x1560340: (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
++ 2017-07-19T06:14:31Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthp_registry_bind
++ debug: Message received on conn 0x1560340: (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: 5
++ 2017-07-19T06:14:31Z 000030000800000002000000010000000500000012000000777468705f626c6f625f666163746f72790001000000 wthp_registry_bind
++ debug: Message received on conn 0x1560340: (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: 6
++ 2017-07-19T06:14:31Z 000034000800000002000000010000000600000015000000777468705f6976695f6170706c69636174696f6e0001000000 wthp_registry_bind
++ debug: Message received on conn 0x1560340: (11) 16 bytes
++ debug: wthp_callback_send_done(3, 0) (opcode 11) called.
++ sending wth_display.sync...
++ debug: wth_connection_insert_new_object: new object id: 7
++ 2017-07-19T06:14:31Z 00001000020000000100000007000000 wth_display_sync
++ debug: Message received on conn 0x1560340: (11) 16 bytes
++ debug: wthp_callback_send_done(7, 0) (opcode 11) called.
++ ...sync done.
++
++Start remoting :
+ - Start an IVI application.
+-- Move pointer onto the application window.
+-- Press Mod+Shift+space, and then 'k'.
+-- The window should disappear.
++- Put surface on backend output
++- Put surface on transmitter output
+
+ Weston log will indicate remoting has started:
+
+@@ -48,6 +87,3 @@ Weston log will indicate remoting has started:
+ [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
+
+-Once remoting has started, the mockup code will generate fake pointer input for
+-the window. This can be seen with e.g. weston-eventdemo, or running an
+-application with WAYLAND_DEBUG=client.
+diff --git a/transmitter/input.c b/transmitter/input.c
+index 0ba04d4..eeb7452 100644
+--- a/transmitter/input.c
++++ b/transmitter/input.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2016 DENSO CORPORATION
++ * 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
+@@ -129,6 +130,79 @@ static const struct weston_pointer_grab_interface pointer_grab_impl = {
+ 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
+@@ -207,7 +281,7 @@ seat_get_pointer_handler(struct wl_listener *listener, void *data)
+ if (wl_resource_get_client(surface) != client)
+ return;
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+ assert(pointer); /* guaranteed by having pointer_focus */
+ pointer_client = weston_pointer_get_pointer_client(pointer, client);
+
+@@ -235,13 +309,9 @@ transmitter_seat_create_pointer(struct weston_transmitter_seat *seat)
+ seat->pointer_focus = NULL;
+ wl_list_init(&seat->pointer_focus_destroy_listener.link);
+
+- weston_seat_init_pointer(&seat->base);
+-
+- seat->get_pointer_listener.notify = seat_get_pointer_handler;
+- wl_signal_add(&seat->base.get_pointer_signal,
+- &seat->get_pointer_listener);
++ weston_seat_init_pointer(seat->base);
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+
+ /* not exported:
+ * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */
+@@ -252,7 +322,7 @@ transmitter_seat_create_pointer(struct weston_transmitter_seat *seat)
+ wl_list_init(&pointer->output_destroy_listener.link);
+
+ weston_log("Transmitter created pointer=%p for seat %p\n",
+- pointer, &seat->base);
++ pointer, seat->base);
+ }
+
+ static void
+@@ -279,7 +349,7 @@ transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat,
+ struct wl_list *focus_resource_list;
+ struct wl_resource *resource;
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+ assert(pointer);
+
+ assert(txs->surface);
+@@ -299,8 +369,6 @@ transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat,
+ seat->pointer_surface_x = surface_x;
+ seat->pointer_surface_y = surface_y;
+
+- pointer->focus_client = weston_pointer_get_pointer_client(pointer,
+- client);
+ pointer->focus_serial = serial;
+
+ /* pointer->focus is not used, because it is a weston_view, while
+@@ -347,7 +415,7 @@ transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat,
+ assert(txs->surface);
+ surface_resource = txs->surface->resource;
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+ assert(pointer);
+ if (!pointer->focus_client)
+ return;
+@@ -373,7 +441,7 @@ transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat,
+ struct wl_resource *resource;
+ struct weston_transmitter_surface *txs;
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+ assert(pointer);
+
+ seat->pointer_surface_x = surface_x;
+@@ -401,7 +469,27 @@ transmitter_seat_pointer_button(struct weston_transmitter_seat *seat,
+ uint32_t button,
+ uint32_t state)
+ {
+- assert(!"TODO");
++ 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
+@@ -410,7 +498,27 @@ transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat,
+ uint32_t axis,
+ wl_fixed_t value)
+ {
+- assert(!"TODO");
++ 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
+@@ -418,7 +526,7 @@ transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat)
+ {
+ struct weston_pointer *pointer;
+
+- pointer = weston_seat_get_pointer(&seat->base);
++ pointer = weston_seat_get_pointer(seat->base);
+ if (pointer)
+ weston_pointer_send_frame(pointer);
+ }
+@@ -427,7 +535,7 @@ void
+ transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat,
+ uint32_t axis_source)
+ {
+- assert(!"TODO");
++ /* ToDo : implement axis event handling */
+ }
+
+ void
+@@ -435,7 +543,7 @@ transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat,
+ uint32_t time,
+ uint32_t axis)
+ {
+- assert(!"TODO");
++ /* ToDo : implement axis event handling */
+ }
+
+ void
+@@ -443,7 +551,222 @@ transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat,
+ uint32_t axis,
+ int32_t discrete)
+ {
+- assert(!"TODO");
++ /* 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 *
+@@ -462,9 +785,7 @@ transmitter_seat_destroy(struct weston_transmitter_seat *seat)
+ {
+ wl_list_remove(&seat->link);
+
+- weston_log("Transmitter destroy seat=%p\n", &seat->base);
+-
+- weston_seat_release(&seat->base);
++ 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);
+@@ -475,11 +796,406 @@ transmitter_seat_destroy(struct weston_transmitter_seat *seat)
+ 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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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 = container_of(seat_list->next,
++ struct weston_transmitter_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)
+@@ -493,6 +1209,24 @@ transmitter_remote_create_seat(struct weston_transmitter_remote *remote)
+ 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);
+
+@@ -515,9 +1249,12 @@ transmitter_remote_create_seat(struct weston_transmitter_remote *remote)
+
+ 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);
+
+@@ -582,7 +1319,7 @@ transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat,
+
+ if (!seat->pointer_timer) {
+ /* schedule timer for motion */
+- loop = wl_display_get_event_loop(seat->base.compositor->wl_display);
++ 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);
+diff --git a/transmitter/output.c b/transmitter/output.c
+index 6a78721..a3f8ed1 100644
+--- a/transmitter/output.c
++++ b/transmitter/output.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2016 DENSO CORPORATION
++ * 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
+@@ -73,7 +74,7 @@ make_model(struct weston_transmitter_remote *remote, int name)
+ {
+ char *str;
+
+- if (asprintf(&str, "transmitter-%s-%d", remote->addr, name) < 0)
++ if (asprintf(&str, "transmitter-%s:%s-%d", remote->addr, remote->port, name) < 0)
+ return NULL;
+
+ return str;
+@@ -124,8 +125,6 @@ free_mode_list(struct wl_list *mode_list)
+ void
+ transmitter_output_destroy(struct weston_transmitter_output *output)
+ {
+- weston_log("Transmitter destroying output '%s'\n", output->base.name);
+-
+ wl_list_remove(&output->link);
+
+ free_mode_list(&output->base.mode_list);
+@@ -145,46 +144,150 @@ transmitter_output_destroy_(struct weston_output *base)
+ transmitter_output_destroy(output);
+ }
+
++
+ static void
+ transmitter_start_repaint_loop(struct weston_output *base)
+ {
+- weston_log("%s(%s)\n", __func__, base->name);
++ struct timespec ts;
++ struct weston_transmitter_output *output = to_transmitter_output(base);
++
++ weston_compositor_read_presentation_clock(output->base.compositor, &ts);
++ weston_output_finish_frame(&output->base, &ts, 0);
++}
++
++static int
++transmitter_check_output(struct weston_transmitter_surface *txs,
++ struct weston_compositor *compositor)
++{
++ struct weston_output *def_output = container_of(compositor->output_list.next,
++ struct weston_output, link);
++ struct weston_view *view;
++
++ wl_list_for_each_reverse(view, &compositor->view_list, link) {
++ if (view->output == def_output) {
++ if (view->surface == txs->surface)
++ return 1;
++ }
++ }
++
++ return 0;
+ }
+
+ static int
+ transmitter_output_repaint(struct weston_output *base,
+ pixman_region32_t *damage)
+ {
+- weston_log("%s(%s)\n", __func__, base->name);
++ struct weston_transmitter_output* output = to_transmitter_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;
++
++ if (!output->from_frame_signal)
++ return 0;
++
++ output->from_frame_signal = false;
++
++ /*
++ * 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;
++
++ 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 (!transmitter_check_output(txs, compositor))
++ break;
++
++ if (!txs->wthp_surf)
++ transmitter_api->surface_push_to_remote
++ (view->surface, remote, NULL);
++ transmitter_api->surface_gather_state(txs);
++ break;
++ }
++ }
++ if (!found_surface)
++ transmitter_api->surface_push_to_remote(view->surface,
++ remote, NULL);
++ }
++ }
++ if (!found_output)
++ goto out;
+
+- return -1;
++ return 0;
++
++out:
++ transmitter_start_repaint_loop(base);
++
++ return 0;
++}
++
++static void
++transmitter_output_enable(struct weston_output *base)
++{
++ struct weston_transmitter_output *output = to_transmitter_output(base);
++
++
++ output->base.assign_planes = NULL;
++ output->base.set_backlight = NULL;
++ output->base.set_dpms = NULL;
++ output->base.switch_mode = NULL;
++}
++
++static void
++transmitter_output_frame_handler(struct wl_listener *listener, void *data)
++{
++ struct weston_transmitter_output *output;
++ int ret;
++
++ output = container_of(listener, struct weston_transmitter_output,
++ frame_listener);
++ output->from_frame_signal = true;
++
++ ret = transmitter_output_repaint(&output->base, NULL);
+ }
+
+ int
+-transmitter_remote_create_output(
+- struct weston_transmitter_remote *remote,
+- const struct weston_transmitter_output_info *info)
++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);
+
+ /*
+@@ -200,7 +303,7 @@ transmitter_remote_create_output(
+ * 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_;
+@@ -212,13 +315,19 @@ transmitter_remote_create_output(
+
+ 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);
+
+- weston_log("Transmitter created output '%s': %s, %s, %s\n",
+- output->base.name, output->base.make, output->base.model,
+- output->base.serial_number);
++ weston_output_enable(&output->base);
++
++ output->frame_listener.notify = transmitter_output_frame_handler;
++ def_output = container_of(txr->compositor->output_list.next,
++ struct weston_output, link);
++ wl_signal_add(&def_output->frame_signal, &output->frame_listener);
++ output->from_frame_signal = false;
+
+ return 0;
+
+diff --git a/transmitter/plugin.c b/transmitter/plugin.c
+index c5e56d3..1ebd1ef 100644
+--- a/transmitter/plugin.c
++++ b/transmitter/plugin.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2016 DENSO CORPORATION
++ * 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
+@@ -34,8 +35,23 @@
+ #include "helpers.h"
+ #include "timespec-util.h"
+
++#include "compositor/weston.h"
+ #include "plugin.h"
+ #include "transmitter_api.h"
++#include "plugin-registry.h"
++#include "ivi-shell/ivi-layout-export.h"
++
++/* waltham */
++#include <errno.h>
++#include <sys/epoll.h>
++#include <sys/timerfd.h>
++#include <waltham-object.h>
++#include <waltham-client.h>
++#include <waltham-connection.h>
++
++#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
+@@ -69,63 +85,6 @@ transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs,
+ txs->resize_handler(txs->resize_handler_data, width, height);
+ }
+
+-static int
+-frame_callback_handler(void *data) /* fake */
+-{
+- struct weston_transmitter_surface *txs = data;
+- struct weston_frame_callback *cb, *cnext;
+- struct weston_output *output;
+- struct weston_compositor *compositor;
+- uint32_t frame_time;
+- uint32_t presented_flags;
+- int32_t refresh_nsec;
+- struct timespec stamp;
+-
+- compositor = txs->remote->transmitter->compositor;
+- output = txs->sync_output;
+-
+- /* wl_surface.enter should arrive before any frame callbacks,
+- * but remote might send frame callbacks for non-visible too.
+- */
+- if (!output)
+- return 0;
+-
+- /* XXX: eeeew */
+- frame_time = weston_compositor_get_time();
+-
+- wl_list_for_each_safe(cb, cnext, &txs->frame_callback_list, link) {
+- wl_callback_send_done(cb->resource, frame_time);
+- wl_resource_destroy(cb->resource);
+- }
+-
+- presented_flags = 0;
+- refresh_nsec = millihz_to_nsec(output->current_mode->refresh);
+- /* XXX: waaahhhahaa */
+- weston_compositor_read_presentation_clock(compositor, &stamp);
+- weston_presentation_feedback_present_list(&txs->feedback_list,
+- output, refresh_nsec, &stamp,
+- output->msc,
+- presented_flags);
+-
+- return 0;
+-}
+-
+-static void
+-fake_frame_callback(struct weston_transmitter_surface *txs)
+-{
+- struct weston_transmitter *txr = txs->remote->transmitter;
+- struct wl_event_loop *loop;
+-
+- if (!txs->frame_timer) {
+- loop = wl_display_get_event_loop(txr->compositor->wl_display);
+- txs->frame_timer =
+- wl_event_loop_add_timer(loop,
+- frame_callback_handler, txs);
+- }
+-
+- wl_event_source_timer_update(txs->frame_timer, 85);
+-}
+-
+ static void
+ transmitter_surface_configure(struct weston_transmitter_surface *txs,
+ int32_t dx, int32_t dy)
+@@ -139,37 +98,75 @@ transmitter_surface_configure(struct weston_transmitter_surface *txs,
+ }
+
+ static void
+-transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
++buffer_send_complete(struct wthp_buffer *b, uint32_t serial)
+ {
+- weston_log("Transmitter: update surface %p (%d, %d), %d cb\n",
+- txs->surface, txs->attach_dx, txs->attach_dy,
+- wl_list_length(&txs->surface->frame_callback_list));
+-
+- wl_list_insert_list(&txs->frame_callback_list,
+- &txs->surface->frame_callback_list);
+- wl_list_init(&txs->surface->frame_callback_list);
+-
+- wl_list_insert_list(&txs->feedback_list, &txs->surface->feedback_list);
+- wl_list_init(&txs->surface->feedback_list);
+-
+- /* TODO: transmit surface state to remote */
+-
+- txs->attach_dx = 0;
+- txs->attach_dy = 0;
++ if (b)
++ wthp_buffer_destroy(b);
+ }
+
+-/** weston_surface apply state signal handler */
++static const struct wthp_buffer_listener buffer_listener = {
++ buffer_send_complete
++};
++
+ static void
+-transmitter_surface_apply_state(struct wl_listener *listener, void *data)
++transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
+ {
+- struct weston_transmitter_surface *txs =
+- container_of(listener, struct weston_transmitter_surface,
+- apply_state_listener);
+-
+- assert(data == NULL);
++ struct weston_transmitter_remote *remote = txs->remote;
++ struct waltham_display *dpy = remote->display;
+
+- transmitter_surface_gather_state(txs);
+- fake_frame_callback(txs);
++ if(!dpy->running) {
++ if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) {
++ remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED;
++ 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 width = 100;
++ int32_t height = 100;
++ int32_t stride;
++ int ret = 0;
++ void *pixels;
++
++// stride = surf->width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8);
++ stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8);
++// weston_log("width %d\n", surf->width);
++// weston_log("height %d\n", surf->height);
++// weston_log("stride %d\n", stride);
++ pixels = malloc(stride * height);
++
++ ret = weston_surface_copy_content(surf, pixels,
++ (stride * height), 0, 0,
++ width, height);
++ if(ret < 0)
++ fprintf(stderr, "failed to get surface content\n");
++
++ /* fake sending buffer */
++ txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory,
++ (stride * height),
++ pixels,
++ width,
++ 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_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, width, 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.
+@@ -181,8 +178,7 @@ transmitter_surface_apply_state(struct wl_listener *listener, void *data)
+ static void
+ transmitter_surface_zombify(struct weston_transmitter_surface *txs)
+ {
+- struct weston_frame_callback *framecb, *cnext;
+-
++ struct weston_transmitter_remote *remote;
+ /* may be called multiple times */
+ if (!txs->surface)
+ return;
+@@ -190,20 +186,17 @@ transmitter_surface_zombify(struct weston_transmitter_surface *txs)
+ wl_signal_emit(&txs->destroy_signal, txs);
+
+ wl_list_remove(&txs->surface_destroy_listener.link);
+- weston_log("Transmitter unbound surface %p.\n", txs->surface);
+ txs->surface = NULL;
+
+ wl_list_remove(&txs->sync_output_destroy_listener.link);
+- wl_list_remove(&txs->apply_state_listener.link);
+-
+- if (txs->map_timer)
+- wl_event_source_remove(txs->map_timer);
+- if (txs->frame_timer)
+- wl_event_source_remove(txs->frame_timer);
+
+- weston_presentation_feedback_discard_list(&txs->feedback_list);
+- wl_list_for_each_safe(framecb, cnext, &txs->frame_callback_list, link)
+- wl_resource_destroy(framecb->resource);
++ 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;
+@@ -231,25 +224,6 @@ transmitter_surface_destroyed(struct wl_listener *listener, void *data)
+ transmitter_surface_zombify(txs);
+ }
+
+-static struct weston_transmitter_surface *
+-transmitter_surface_get(struct weston_surface *ws)
+-{
+- struct wl_listener *listener;
+- struct weston_transmitter_surface *txs;
+-
+- listener = wl_signal_get(&ws->destroy_signal,
+- transmitter_surface_destroyed);
+-
+- if (!listener)
+- return NULL;
+-
+- txs = container_of(listener, struct weston_transmitter_surface,
+- surface_destroy_listener);
+- assert(ws == txs->surface);
+-
+- return txs;
+-}
+-
+ static void
+ sync_output_destroy_handler(struct wl_listener *listener, void *data)
+ {
+@@ -265,84 +239,48 @@ sync_output_destroy_handler(struct wl_listener *listener, void *data)
+ }
+
+ static void
+-fake_input(struct weston_transmitter_surface *txs)
+-{
+- struct wl_list *seat_list = &txs->remote->seat_list;
+- struct weston_transmitter_seat *seat;
+-
+- assert(wl_list_length(seat_list) == 1);
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
+-
+- transmitter_seat_fake_pointer_input(seat, txs);
+-}
+-
+-/* fake receiving wl_surface.enter(output) */
+-static int
+-map_timer_handler(void *data)
+-{
+- struct weston_transmitter_surface *txs = data;
+- struct weston_transmitter_output *output;
+-
+- assert(!wl_list_empty(&txs->remote->output_list));
+-
+- output = container_of(txs->remote->output_list.next,
+- struct weston_transmitter_output, link);
+-
+- txs->sync_output = &output->base;
+- txs->sync_output_destroy_listener.notify = sync_output_destroy_handler;
+- wl_list_remove(&txs->sync_output_destroy_listener.link);
+- wl_signal_add(&txs->sync_output->destroy_signal,
+- &txs->sync_output_destroy_listener);
+-
+- weston_surface_force_output(txs->surface, txs->sync_output);
+-
+- weston_log("Transmitter: surface %p entered output %s\n",
+- txs->surface, txs->sync_output->name);
+-
+- fake_frame_callback(txs);
+- fake_input(txs);
+-
+- return 0;
+-}
+-
+-/* Fake a delay for the remote end to map the surface to an output */
+-static void
+-fake_output_mapping(struct weston_transmitter_surface *txs)
+-{
+- struct weston_transmitter *txr = txs->remote->transmitter;
+- struct wl_event_loop *loop;
+-
+- loop = wl_display_get_event_loop(txr->compositor->wl_display);
+- txs->map_timer = wl_event_loop_add_timer(loop, map_timer_handler, txs);
+- wl_event_source_timer_update(txs->map_timer, 400);
+-}
+-
+-/* Fake getting "connection established" from the content streamer. */
+-static void
+-fake_stream_opening_handler(void *data)
+-{
+- struct weston_transmitter_surface *txs = data;
+-
+- /* ...once the connection is up: */
+- txs->status = WESTON_TRANSMITTER_STREAM_LIVE;
+- wl_signal_emit(&txs->stream_status_signal, txs);
+-
+- /* need to create the surface on the remote and set all state */
+- transmitter_surface_gather_state(txs);
+-
+- fake_output_mapping(txs);
+-}
+-
+-/* Fake a callback from content streamer. */
+-static void
+-fake_stream_opening(struct weston_transmitter_surface *txs)
++transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs)
+ {
+- struct weston_transmitter *txr = txs->remote->transmitter;
+- struct wl_event_loop *loop;
+-
+- loop = wl_display_get_event_loop(txr->compositor->wl_display);
+- wl_event_loop_add_idle(loop, fake_stream_opening_handler, 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 *
+@@ -350,39 +288,58 @@ 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 (transmitter_surface_get(ws)) {
+- weston_log("Transmitter: surface %p already bound.\n", ws);
++ if (remote->status != WESTON_TRANSMITTER_CONNECTION_READY)
++ {
+ return NULL;
+ }
+
+- txs = zalloc(sizeof (*txs));
+- if (!txs)
+- return NULL;
++ wl_list_for_each(txs, &remote->surface_list, link) {
++ if (txs->surface == ws) {
++ found = true;
++ break;
++ }
++ }
+
+- txs->remote = remote;
+- wl_signal_init(&txs->destroy_signal);
+- wl_list_insert(&remote->surface_list, &txs->link);
++ if (!found) {
++ txs = NULL;
++ txs = zalloc(sizeof (*txs));
++ if (!txs)
++ return NULL;
+
+- txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING;
+- wl_signal_init(&txs->stream_status_signal);
+- wl_signal_add(&txs->stream_status_signal, stream_status);
++ txs->remote = remote;
++ wl_signal_init(&txs->destroy_signal);
++ wl_list_insert(&remote->surface_list, &txs->link);
+
+- txs->surface = ws;
+- txs->surface_destroy_listener.notify = transmitter_surface_destroyed;
+- wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener);
++ 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->apply_state_listener.notify = transmitter_surface_apply_state;
+- wl_signal_add(&ws->apply_state_signal, &txs->apply_state_listener);
++ 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->sync_output_destroy_listener.link);
+
+- wl_list_init(&txs->frame_callback_list);
+- wl_list_init(&txs->feedback_list);
++ 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... */
+- fake_stream_opening(txs);
++ 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;
+ }
+@@ -393,17 +350,53 @@ transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs)
+ return txs->status;
+ }
+
+-static int
+-conn_timer_handler(void *data) /* fake */
++/* 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 weston_transmitter_remote *remote = data;
++ 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 =
++ container_of(l, struct weston_transmitter_remote,
++ establish_listener);
+ struct weston_transmitter_output_info info = {
+ WL_OUTPUT_SUBPIXEL_NONE,
+ WL_OUTPUT_TRANSFORM_NORMAL,
+ 1,
+ 0, 0,
+ 300, 200,
+- "fake",
++ strdup(remote->model),
+ {
+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
+ 800, 600,
+@@ -411,52 +404,303 @@ conn_timer_handler(void *data) /* fake */
+ { NULL, NULL }
+ }
+ };
+-
+- weston_log("Transmitter connected to %s.\n", remote->addr);
+- remote->status = WESTON_TRANSMITTER_CONNECTION_READY;
+- wl_signal_emit(&remote->connection_status_signal, remote);
+-
+- wl_event_source_remove(remote->conn_timer);
+- remote->conn_timer = 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 = container_of(w, struct waltham_display, 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;
++
++ 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;
++ perror("EPOLL_CTL_DEL\n");
++
++ return;
++ }
++ }
++
++ if (events & EPOLLHUP) {
++ fprintf(stderr, "Connection hung up.\n");
++ dpy->running = false;
++
++ return;
++ }
++}
++
++static void
++waltham_mainloop(int fd, uint32_t mask, void *data)
++{
++ struct weston_transmitter_remote *remote = data;
++ struct watch *w;
++ int count;
++ int i;
++ 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)
++ goto not_running;
++
++ if (!dpy->running)
++ goto not_running;
++
++ running_display++;
++ /* Dispatch queued events. */
++
++ ret = wth_connection_dispatch(dpy->connection);
++ if (ret < 0)
++ dpy->running = false;
++ 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);
++ }
++ wl_event_source_remove(remote->source);
++ remote->source = wl_event_loop_add_fd(remote->transmitter->loop,
++ remote->display->conn_watch.fd,
++ WL_EVENT_READABLE,
++ waltham_mainloop, remote);
++
++not_running:
++ ;
++}
++
++/* A one-off asynchronous open-coded roundtrip handler. */
++static void
++bling_done(struct wthp_callback *cb, uint32_t arg)
++{
++ fprintf(stderr, "...sync done.\n");
++
++ wthp_callback_free(cb);
++}
++
++static const struct wthp_callback_listener bling_listener = {
++ bling_done
++};
++
++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->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) {
++ fprintf(stderr, "Roundtrip failed.\n");
++ return -1;
++ }
++
++ if (!dpy->compositor) {
++ fprintf(stderr, "Did not find wthp_compositor, quitting.\n");
++ return -1;
++ }
++
++ /* A one-off asynchronous roundtrip, just for fun. */
++ fprintf(stderr, "sending wth_display.sync...\n");
++ dpy->bling = wth_display_sync(dpy->display);
++ wthp_callback_set_listener(dpy->bling, &bling_listener, dpy);
++
++ dpy->running = true;
+
+ return 0;
+ }
+
+-static struct weston_transmitter_remote *
+-transmitter_connect_to_remote(struct weston_transmitter *txr,
+- const char *addr,
+- struct wl_listener *status)
++static int
++establish_timer_handler(void *data)
+ {
+- struct weston_transmitter_remote *remote;
+- struct wl_event_loop *loop;
++ struct weston_transmitter_remote *remote = data;
++ int ret;
+
+- remote = zalloc(sizeof (*remote));
+- if (!remote)
+- return NULL;
++ 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;
++}
+
+- remote->transmitter = txr;
+- wl_list_insert(&txr->remote_list, &remote->link);
+- remote->addr = strdup(addr);
+- remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
+- wl_signal_init(&remote->connection_status_signal);
+- wl_signal_add(&remote->connection_status_signal, status);
+- wl_list_init(&remote->output_list);
+- wl_list_init(&remote->surface_list);
+- wl_list_init(&remote->seat_list);
++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);
++ free(txs->wthp_surf);
++ txs->wthp_ivi_surface = NULL;
++ txs->wthp_surf = NULL;
++ }
++}
+
+- /* XXX: actually start connecting */
+- weston_log("Transmitter connecting to %s...\n", addr);
+- /* fake it with a one second timer */
+- loop = wl_display_get_event_loop(txr->compositor->wl_display);
+- remote->conn_timer = wl_event_loop_add_timer(loop, conn_timer_handler,
+- remote);
+- wl_event_source_timer_update(remote->conn_timer, 1000);
++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;
+ }
+@@ -481,10 +725,6 @@ transmitter_remote_destroy(struct weston_transmitter_remote *remote)
+ * the desctruction order between the shell and Transmitter is
+ * undefined.
+ */
+- weston_log("Transmitter disconnecting from %s.\n", remote->addr);
+-
+- if (remote->conn_timer)
+- wl_event_source_remove(remote->conn_timer);
+
+ if (!wl_list_empty(&remote->surface_list))
+ weston_log("Transmitter warning: surfaces remain in %s.\n",
+@@ -502,6 +742,8 @@ transmitter_remote_destroy(struct weston_transmitter_remote *remote)
+ free(remote->addr);
+ wl_list_remove(&remote->link);
+
++ wl_event_source_remove(remote->source);
++
+ free(remote);
+ }
+
+@@ -531,7 +773,6 @@ transmitter_compositor_destroyed(struct wl_listener *listener, void *data)
+ */
+ wl_list_remove(&txr->remote_list);
+
+- weston_log("Transmitter terminating.\n");
+ free(txr);
+ }
+
+@@ -553,6 +794,19 @@ transmitter_get(struct weston_compositor *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,
+@@ -562,20 +816,12 @@ static const struct weston_transmitter_api transmitter_api_impl = {
+ 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_ivi_id(struct weston_transmitter_surface *txs,
+- uint32_t ivi_id)
+-{
+- assert(txs->surface);
+- if (!txs->surface)
+- return;
+-
+- weston_log("%s(%p, %#x)\n", __func__, txs->surface, ivi_id);
+-}
+-
+-static void
+ transmitter_surface_set_resize_callback(
+ struct weston_transmitter_surface *txs,
+ weston_transmitter_ivi_resize_handler_t cb,
+@@ -586,10 +832,108 @@ transmitter_surface_set_resize_callback(
+ }
+
+ static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = {
+- transmitter_surface_set_ivi_id,
+ 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;
++}
++
++static void
++transmitter_get_server_config(struct weston_transmitter *txr)
++{
++ 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");
++ }
++ }
++ }
++}
++
++static void
++transmitter_post_init(void *data)
++{
++ struct weston_transmitter *txr = data;
++ struct weston_transmitter_remote *remote;
++
++ if (!txr) {
++ weston_log("Transmitter disabled\n");
++ } else {
++ transmitter_get_server_config(txr);
++ transmitter_connect_to_remote(txr);
++
++ wl_list_for_each(remote, &txr->remote_list, link) {
++ remote->source = wl_event_loop_add_fd(txr->loop,
++ remote->display->conn_watch.fd,
++ WL_EVENT_READABLE,
++ waltham_mainloop, remote);
++ }
++ }
++}
++
+ WL_EXPORT int
+ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
+ {
+@@ -628,6 +972,9 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
+
+ weston_log("Transmitter initialized.\n");
+
++ txr->loop = wl_display_get_event_loop(compositor->wl_display);
++ wl_event_loop_add_idle(txr->loop, transmitter_post_init, txr);
++
+ return 0;
+
+ fail:
+diff --git a/transmitter/plugin.h b/transmitter/plugin.h
+index 710b543..48f49b8 100644
+--- a/transmitter/plugin.h
++++ b/transmitter/plugin.h
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2016 DENSO CORPORATION
++ * 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
+@@ -32,33 +33,109 @@
+ */
+
+ #include <stdint.h>
++#include <wayland-client.h>
+
+ #include "compositor.h"
+ #include "transmitter_api.h"
++#include "ivi-shell/ivi-layout-export.h"
++
++#include <waltham-client.h>
++
++
++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_event_source *conn_timer; /* fake */
++ 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 */
+@@ -69,7 +146,7 @@ struct weston_transmitter_surface {
+
+ struct weston_surface *surface;
+ struct wl_listener surface_destroy_listener;
+- struct wl_listener apply_state_listener;
++ const struct ivi_layout_interface *lyt;
+
+ weston_transmitter_ivi_resize_handler_t resize_handler;
+ void *resize_handler_data;
+@@ -77,13 +154,17 @@ struct weston_transmitter_surface {
+ struct weston_output *sync_output;
+ struct wl_listener sync_output_destroy_listener;
+
+- struct wl_event_source *map_timer; /* fake */
+- struct wl_event_source *frame_timer; /* fake */
+-
+ 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 {
+@@ -103,12 +184,28 @@ struct weston_transmitter_output_info {
+ 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 wl_listener frame_listener;
++
++ bool from_frame_signal;
+ };
+
+ struct weston_transmitter_seat {
+- struct weston_seat base;
++ struct weston_seat *base;
+ struct wl_list link;
+
+ /* pointer */
+@@ -124,8 +221,28 @@ struct weston_transmitter_seat {
+ 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
+@@ -203,5 +320,14 @@ 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/transmitter/transmitter_api.h b/transmitter/transmitter_api.h
+index 95d82ec..b28f946 100644
+--- a/transmitter/transmitter_api.h
++++ b/transmitter/transmitter_api.h
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright (C) 2016 DENSO CORPORATION
++ * 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
+@@ -90,7 +91,6 @@ struct weston_transmitter_api {
+ * Connect to a remote server via Transmitter.
+ *
+ * \param txr The Transmitter context.
+- * \param addr Address of the remote server.
+ * \param status Listener to inform of connection status changes.
+ * \return A handle to the remote connection, or NULL on failure.
+ *
+@@ -102,12 +102,9 @@ struct weston_transmitter_api {
+ * returned by this function. Use remote_get_status() to fetch the
+ * current status.
+ *
+- * The address argument is a string in the form "host:port".
+ */
+ struct weston_transmitter_remote *
+- (*connect_to_remote)(struct weston_transmitter *txr,
+- const char *addr,
+- struct wl_listener *status);
++ (*connect_to_remote)(struct weston_transmitter *txr);
+
+ /**
+ * Retrieve the connection status.
+@@ -191,6 +188,25 @@ struct weston_transmitter_api {
+ 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 *
+diff --git a/transmitter/weston.ini.transmitter b/transmitter/weston.ini.transmitter
+new file mode 100644
+index 0000000..1aff0b2
+--- /dev/null
++++ b/transmitter/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
+--
+2.7.4
+
--- /dev/null
+From 99fb36e62d3d0e3bda3d2984f280f534a629f70c Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Thu, 12 Oct 2017 14:55:13 +0900
+Subject: [PATCH 1/5] compositor: add output type to weston_output
+
+This enables weston to use multiple types of backend
+Each backends have own output structure for each functions
+To avoid invalid member access, type identifier is needed
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ libweston/compositor-drm.c | 100 +++++++++++++++++++++++-----------------
+ libweston/compositor-fbdev.c | 1 +
+ libweston/compositor-headless.c | 1 +
+ libweston/compositor-rdp.c | 1 +
+ libweston/compositor-wayland.c | 1 +
+ libweston/compositor-x11.c | 1 +
+ libweston/compositor.h | 12 +++++
+ 7 files changed, 74 insertions(+), 43 deletions(-)
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 1d38f05..0b5b4c4 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -243,14 +243,16 @@ drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id)
+ struct drm_output *output;
+
+ wl_list_for_each(output, &b->compositor->output_list, base.link) {
+- if (output->crtc_id == crtc_id)
+- return output;
++ if(output->base.output_type == OUTPUT_DRM)
++ if (output->crtc_id == crtc_id)
++ return output;
+ }
+
+ wl_list_for_each(output, &b->compositor->pending_output_list,
+ base.link) {
+- if (output->crtc_id == crtc_id)
+- return output;
++ if(output->base.output_type == OUTPUT_DRM)
++ if (output->crtc_id == crtc_id)
++ return output;
+ }
+
+ return NULL;
+@@ -262,14 +264,16 @@ drm_output_find_by_connector(struct drm_backend *b, uint32_t connector_id)
+ struct drm_output *output;
+
+ wl_list_for_each(output, &b->compositor->output_list, base.link) {
+- if (output->connector_id == connector_id)
+- return output;
++ if(output->base.output_type == OUTPUT_DRM)
++ if (output->connector_id == connector_id)
++ return output;
+ }
+
+ wl_list_for_each(output, &b->compositor->pending_output_list,
+ base.link) {
+- if (output->connector_id == connector_id)
+- return output;
++ if(output->base.output_type == OUTPUT_DRM)
++ if (output->connector_id == connector_id)
++ return output;
+ }
+
+ return NULL;
+@@ -2433,6 +2437,7 @@ drm_output_enable(struct weston_output *base)
+ struct weston_mode *m;
+
+ output->dpms_prop = drm_get_prop(b->drm.fd, output->connector, "DPMS");
++ output->base.output_type = OUTPUT_DRM;
+
+ if (b->use_pixman) {
+ if (drm_output_init_pixman(output, b) < 0) {
+@@ -2797,38 +2802,42 @@ update_outputs(struct drm_backend *b, struct udev_device *drm_device)
+
+ wl_list_for_each_safe(output, next, &b->compositor->output_list,
+ base.link) {
+- bool disconnected = true;
+-
+- for (i = 0; i < resources->count_connectors; i++) {
+- if (connected[i] == output->connector_id) {
+- disconnected = false;
+- break;
++ if (output->base.output_type == OUTPUT_DRM) {
++ bool disconnected = true;
++
++ for (i = 0; i < resources->count_connectors; i++) {
++ if (connected[i] == output->connector_id) {
++ disconnected = false;
++ break;
++ }
+ }
+- }
+
+- if (!disconnected)
+- continue;
++ if (!disconnected)
++ continue;
+
+- weston_log("connector %d disconnected\n", output->connector_id);
+- drm_output_destroy(&output->base);
++ weston_log("connector %d disconnected\n", output->connector_id);
++ drm_output_destroy(&output->base);
++ }
+ }
+
+ wl_list_for_each_safe(output, next, &b->compositor->pending_output_list,
+ base.link) {
+- bool disconnected = true;
+-
+- for (i = 0; i < resources->count_connectors; i++) {
+- if (connected[i] == output->connector_id) {
+- disconnected = false;
+- break;
++ if (output->base.output_type == OUTPUT_DRM) {
++ bool disconnected = true;
++
++ for (i = 0; i < resources->count_connectors; i++) {
++ if (connected[i] == output->connector_id) {
++ disconnected = false;
++ break;
++ }
+ }
+- }
+
+- if (!disconnected)
+- continue;
++ if (!disconnected)
++ continue;
+
+- weston_log("connector %d disconnected\n", output->connector_id);
+- drm_output_destroy(&output->base);
++ weston_log("connector %d disconnected\n", output->connector_id);
++ drm_output_destroy(&output->base);
++ }
+ }
+
+ free(connected);
+@@ -2925,18 +2934,21 @@ session_notify(struct wl_listener *listener, void *data)
+ * pending frame callbacks. */
+
+ wl_list_for_each(output, &compositor->output_list, base.link) {
+- output->base.repaint_needed = 0;
+- drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
++ if(output->base.output_type == OUTPUT_DRM) {
++ output->base.repaint_needed = 0;
++ drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
++ }
++ }
++ if(output->base.output_type == OUTPUT_DRM) {
++ output = container_of(compositor->output_list.next,
++ struct drm_output, base.link);
++
++ wl_list_for_each(sprite, &b->sprite_list, link)
++ drmModeSetPlane(b->drm.fd,
++ sprite->plane_id,
++ output->crtc_id, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+-
+- output = container_of(compositor->output_list.next,
+- struct drm_output, base.link);
+-
+- wl_list_for_each(sprite, &b->sprite_list, link)
+- drmModeSetPlane(b->drm.fd,
+- sprite->plane_id,
+- output->crtc_id, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 0);
+ };
+ }
+
+@@ -3148,7 +3160,8 @@ switch_to_gl_renderer(struct drm_backend *b)
+ }
+
+ wl_list_for_each(output, &b->compositor->output_list, base.link)
+- pixman_renderer_output_destroy(&output->base);
++ if(output->base.output_type == OUTPUT_DRM)
++ pixman_renderer_output_destroy(&output->base);
+
+ b->compositor->renderer->destroy(b->compositor);
+
+@@ -3160,7 +3173,8 @@ switch_to_gl_renderer(struct drm_backend *b)
+ }
+
+ wl_list_for_each(output, &b->compositor->output_list, base.link)
+- drm_output_init_egl(output, b);
++ if(output->base.output_type == OUTPUT_DRM)
++ drm_output_init_egl(output, b);
+
+ b->use_pixman = 0;
+
+diff --git a/libweston/compositor-fbdev.c b/libweston/compositor-fbdev.c
+index 44f0cf5..9cb903e 100644
+--- a/libweston/compositor-fbdev.c
++++ b/libweston/compositor-fbdev.c
+@@ -433,6 +433,7 @@ fbdev_output_enable(struct weston_output *base)
+ int fb_fd;
+ struct wl_event_loop *loop;
+
++ output->base.output_type = OUTPUT_FBDEV;
+ /* Create the frame buffer. */
+ fb_fd = fbdev_frame_buffer_open(output, output->device, &output->fb_info);
+ if (fb_fd < 0) {
+diff --git a/libweston/compositor-headless.c b/libweston/compositor-headless.c
+index a1aec6d..b0d5afb 100644
+--- a/libweston/compositor-headless.c
++++ b/libweston/compositor-headless.c
+@@ -148,6 +148,7 @@ headless_output_enable(struct weston_output *base)
+ loop = wl_display_get_event_loop(b->compositor->wl_display);
+ output->finish_frame_timer =
+ wl_event_loop_add_timer(loop, finish_frame_handler, output);
++ output->base.output_type = OUTPUT_HEADLESS;
+
+ if (b->use_pixman) {
+ output->image_buf = malloc(output->base.current_mode->width *
+diff --git a/libweston/compositor-rdp.c b/libweston/compositor-rdp.c
+index d9668e8..d525982 100644
+--- a/libweston/compositor-rdp.c
++++ b/libweston/compositor-rdp.c
+@@ -519,6 +519,7 @@ rdp_output_enable(struct weston_output *base)
+ struct rdp_backend *b = to_rdp_backend(base->compositor);
+ struct wl_event_loop *loop;
+
++ output->base.output_type = OUTPUT_RDP;
+ output->shadow_surface = pixman_image_create_bits(PIXMAN_x8r8g8b8,
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+diff --git a/libweston/compositor-wayland.c b/libweston/compositor-wayland.c
+index 9d35ef7..66a0dbf 100644
+--- a/libweston/compositor-wayland.c
++++ b/libweston/compositor-wayland.c
+@@ -1164,6 +1164,7 @@ wayland_output_enable(struct weston_output *base)
+ struct wayland_backend *b = to_wayland_backend(base->compositor);
+ int ret = 0;
+
++ output->base.output_type = OUTPUT_WAYLAND;
+ weston_log("Creating %dx%d wayland output at (%d, %d)\n",
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+diff --git a/libweston/compositor-x11.c b/libweston/compositor-x11.c
+index f9cb461..fcf39e1 100644
+--- a/libweston/compositor-x11.c
++++ b/libweston/compositor-x11.c
+@@ -825,6 +825,7 @@ x11_output_enable(struct weston_output *base)
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY,
+ 0
+ };
++ output->base.output_type = OUTPUT_X11;
+
+ if (!b->no_input)
+ values[0] |=
+diff --git a/libweston/compositor.h b/libweston/compositor.h
+index 08e728a..51157d0 100644
+--- a/libweston/compositor.h
++++ b/libweston/compositor.h
+@@ -146,9 +146,21 @@ enum dpms_enum {
+ WESTON_DPMS_OFF
+ };
+
++/* bit compatible with drm definitions. */
++enum output_type {
++ OUTPUT_DRM,
++ OUTPUT_FBDEV,
++ OUTPUT_HEADLESS,
++ OUTPUT_RDP,
++ OUTPUT_WAYLAND,
++ OUTPUT_X11,
++ OUTPUT_WALTHAM
++};
++
+ struct weston_output {
+ uint32_t id;
+ char *name;
++ enum output_type output_type;
+
+ void *renderer_state;
+
+--
+2.7.4
+
--- /dev/null
+From 329b7a0a897af8142871e5c44e0f9bc4b55f2bc6 Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Thu, 12 Oct 2017 16:13:58 +0900
+Subject: [PATCH 2/5] transmitter: add output type for waltham output
+
+Transmitter creates waltham output
+This makes weston has several outputs
+Since each backends have each output several outputs
+makes invalid member access
+To avoid it output type should be identified
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ transmitter/output.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/transmitter/output.c b/transmitter/output.c
+index a3f8ed1..19a3273 100644
+--- a/transmitter/output.c
++++ b/transmitter/output.c
+@@ -239,7 +239,7 @@ transmitter_output_enable(struct weston_output *base)
+ {
+ struct weston_transmitter_output *output = to_transmitter_output(base);
+
+-
++ output->base.output_type = OUTPUT_WALTHAM;
+ output->base.assign_planes = NULL;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+--
+2.7.4
+
--- /dev/null
+From b93057e8f4f05b33c5eb2c6f06dae3228dbb409e Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Tue, 10 Apr 2018 19:36:02 +0900
+Subject: [PATCH 1/2] transmitter: did code clean -Remove unused variables and
+ functions -Replace container_of to wl_container_of
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ transmitter/input.c | 45 ++++--------
+ transmitter/output.c | 37 ++++------
+ transmitter/plugin.c | 156 +++++++++++++++---------------------------
+ transmitter/plugin.h | 3 +-
+ transmitter/transmitter_api.h | 3 +-
+ 5 files changed, 87 insertions(+), 157 deletions(-)
+
+diff --git a/transmitter/input.c b/transmitter/input.c
+index eeb7452..6797b6e 100644
+--- a/transmitter/input.c
++++ b/transmitter/input.c
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (C) 2016 DENSO CORPORATION
+- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
++ * 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
+@@ -24,8 +23,6 @@
+ * SOFTWARE.
+ */
+
+-#include "config.h"
+-
+ #include <stdlib.h>
+ #include <assert.h>
+ #include <string.h>
+@@ -34,7 +31,6 @@
+ #include <math.h>
+
+ #include "compositor.h"
+-#include "helpers.h"
+
+ #include "plugin.h"
+ #include "transmitter_api.h"
+@@ -810,8 +806,7 @@ pointer_handle_enter(struct wthp_pointer *wthp_pointer,
+ struct weston_transmitter_seat *seat;
+ struct weston_transmitter_surface *txs;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+@@ -836,8 +831,7 @@ pointer_handle_leave(struct wthp_pointer *wthp_pointer,
+ struct weston_transmitter_seat *seat;
+ struct weston_transmitter_surface *txs;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+@@ -859,8 +853,7 @@ pointer_handle_motion(struct wthp_pointer *wthp_pointer,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_pointer_motion(seat, time,
+ surface_x,
+@@ -880,8 +873,7 @@ pointer_handle_button(struct wthp_pointer *wthp_pointer,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_pointer_button(seat, serial,
+ time, button,
+@@ -899,8 +891,7 @@ pointer_handle_axis(struct wthp_pointer *wthp_pointer,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_pointer_axis(seat, time,
+ axis, value);
+@@ -974,8 +965,7 @@ keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard,
+ wl_key->alloc = keys->alloc;
+ wl_key->data = keys->data;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+@@ -999,8 +989,7 @@ keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard,
+ struct weston_transmitter_seat *seat;
+ struct weston_transmitter_surface *txs;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+@@ -1023,8 +1012,7 @@ keyboard_handle_key(struct wthp_keyboard *wthp_keyboard,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_keyboard_key(seat, serial, time, key, state);
+ }
+@@ -1073,8 +1061,7 @@ touch_handle_down (struct wthp_touch * wthp_touch,
+ struct weston_transmitter_seat *seat;
+ struct weston_transmitter_surface *txs;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+@@ -1097,8 +1084,7 @@ touch_handle_up (struct wthp_touch * wthp_touch,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_touch_up(seat, serial, time, id);
+ }
+@@ -1116,8 +1102,7 @@ touch_handle_motion (struct wthp_touch * wthp_touch,
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_touch_motion(seat, time, id, x, y);
+ }
+@@ -1132,8 +1117,7 @@ touch_handle_frame (struct wthp_touch * wthp_touch)
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_touch_frame(seat);
+ }
+@@ -1147,8 +1131,7 @@ touch_handle_cancel (struct wthp_touch * wthp_touch)
+ struct wl_list *seat_list = &remote->seat_list;
+ struct weston_transmitter_seat *seat;
+
+- seat = container_of(seat_list->next,
+- struct weston_transmitter_seat, link);
++ seat = wl_container_of(seat_list->next, seat, link);
+
+ transmitter_seat_touch_cancel(seat);
+ }
+diff --git a/transmitter/output.c b/transmitter/output.c
+index 19a3273..003056f 100644
+--- a/transmitter/output.c
++++ b/transmitter/output.c
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (C) 2016 DENSO CORPORATION
+- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
++ * 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
+@@ -24,14 +23,11 @@
+ * SOFTWARE.
+ */
+
+-#include "config.h"
+-
+ #include <stdlib.h>
+ #include <assert.h>
+ #include <string.h>
+
+ #include "compositor.h"
+-#include "helpers.h"
+
+ #include "plugin.h"
+ #include "transmitter_api.h"
+@@ -63,12 +59,6 @@
+ * exclusive with weston_compositor_add_output().
+ */
+
+-static inline struct weston_transmitter_output *
+-to_transmitter_output(struct weston_output *base)
+-{
+- return container_of(base, struct weston_transmitter_output, base);
+-}
+-
+ static char *
+ make_model(struct weston_transmitter_remote *remote, int name)
+ {
+@@ -115,7 +105,7 @@ free_mode_list(struct wl_list *mode_list)
+ struct weston_mode *mode;
+
+ while (!wl_list_empty(mode_list)) {
+- mode = container_of(mode_list->next, struct weston_mode, link);
++ mode = wl_container_of(mode_list->next, mode, link);
+
+ wl_list_remove(&mode->link);
+ free(mode);
+@@ -139,7 +129,7 @@ transmitter_output_destroy(struct weston_transmitter_output *output)
+ static void
+ transmitter_output_destroy_(struct weston_output *base)
+ {
+- struct weston_transmitter_output *output = to_transmitter_output(base);
++ struct weston_transmitter_output *output = wl_container_of(base, output, base);
+
+ transmitter_output_destroy(output);
+ }
+@@ -149,7 +139,7 @@ static void
+ transmitter_start_repaint_loop(struct weston_output *base)
+ {
+ struct timespec ts;
+- struct weston_transmitter_output *output = to_transmitter_output(base);
++ 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);
+@@ -159,8 +149,8 @@ static int
+ transmitter_check_output(struct weston_transmitter_surface *txs,
+ struct weston_compositor *compositor)
+ {
+- struct weston_output *def_output = container_of(compositor->output_list.next,
+- struct weston_output, link);
++ struct weston_output *def_output = wl_container_of(compositor->output_list.next,
++ def_output, link);
+ struct weston_view *view;
+
+ wl_list_for_each_reverse(view, &compositor->view_list, link) {
+@@ -177,7 +167,7 @@ static int
+ transmitter_output_repaint(struct weston_output *base,
+ pixman_region32_t *damage)
+ {
+- struct weston_transmitter_output* output = to_transmitter_output(base);
++ 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 =
+@@ -201,6 +191,9 @@ transmitter_output_repaint(struct weston_output *base,
+ 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) {
+@@ -237,9 +230,8 @@ out:
+ static void
+ transmitter_output_enable(struct weston_output *base)
+ {
+- struct weston_transmitter_output *output = to_transmitter_output(base);
++ struct weston_transmitter_output *output = wl_container_of(base, output, base);
+
+- output->base.output_type = OUTPUT_WALTHAM;
+ output->base.assign_planes = NULL;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+@@ -252,8 +244,7 @@ transmitter_output_frame_handler(struct wl_listener *listener, void *data)
+ struct weston_transmitter_output *output;
+ int ret;
+
+- output = container_of(listener, struct weston_transmitter_output,
+- frame_listener);
++ output = wl_container_of(listener, output, frame_listener);
+ output->from_frame_signal = true;
+
+ ret = transmitter_output_repaint(&output->base, NULL);
+@@ -324,8 +315,8 @@ transmitter_remote_create_output(struct weston_transmitter_remote *remote,
+ weston_output_enable(&output->base);
+
+ output->frame_listener.notify = transmitter_output_frame_handler;
+- def_output = container_of(txr->compositor->output_list.next,
+- struct weston_output, link);
++ def_output = wl_container_of(txr->compositor->output_list.next,
++ def_output, link);
+ wl_signal_add(&def_output->frame_signal, &output->frame_listener);
+ output->from_frame_signal = false;
+
+diff --git a/transmitter/plugin.c b/transmitter/plugin.c
+index 1ebd1ef..1f00f33 100644
+--- a/transmitter/plugin.c
++++ b/transmitter/plugin.c
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (C) 2016 DENSO CORPORATION
+- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
++ * 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
+@@ -24,16 +23,12 @@
+ * SOFTWARE.
+ */
+
+-#include "config.h"
+-
+ #include <stdlib.h>
+ #include <assert.h>
+ #include <string.h>
+ #include <linux/input.h>
+
+ #include "compositor.h"
+-#include "helpers.h"
+-#include "timespec-util.h"
+
+ #include "compositor/weston.h"
+ #include "plugin.h"
+@@ -113,10 +108,13 @@ 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);
+ }
+ }
+@@ -127,43 +125,32 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
+ /* waltham */
+ struct weston_surface *surf = txs->surface;
+ struct weston_compositor *comp = surf->compositor;
+- int32_t width = 100;
+- int32_t height = 100;
+- int32_t stride;
+- int ret = 0;
+- void *pixels;
+-
+-// stride = surf->width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8);
++ int32_t stride, data_sz, width, height;
++ void *data;
++
++ width = 1;
++ height = 1;
+ stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8);
+-// weston_log("width %d\n", surf->width);
+-// weston_log("height %d\n", surf->height);
+-// weston_log("stride %d\n", stride);
+- pixels = malloc(stride * height);
+
+- ret = weston_surface_copy_content(surf, pixels,
+- (stride * height), 0, 0,
+- width, height);
+- if(ret < 0)
+- fprintf(stderr, "failed to get surface content\n");
+-
++ data = malloc(stride * height);
++ data_sz = stride * height;
++
+ /* fake sending buffer */
+ txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory,
+- (stride * height),
+- pixels,
+- width,
+- height,
++ 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_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, width, height);
++ 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);
+
++ wth_connection_flush(remote->display->connection);
+ txs->attach_dx = 0;
+ txs->attach_dy = 0;
+ }
+@@ -216,8 +203,7 @@ static void
+ transmitter_surface_destroyed(struct wl_listener *listener, void *data)
+ {
+ struct weston_transmitter_surface *txs =
+- container_of(listener, struct weston_transmitter_surface,
+- surface_destroy_listener);
++ wl_container_of(listener, txs, surface_destroy_listener);
+
+ assert(data == txs->surface);
+
+@@ -229,8 +215,7 @@ sync_output_destroy_handler(struct wl_listener *listener, void *data)
+ {
+ struct weston_transmitter_surface *txs;
+
+- txs = container_of(listener, struct weston_transmitter_surface,
+- sync_output_destroy_listener);
++ 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);
+@@ -364,7 +349,7 @@ registry_handle_global(struct wthp_registry *registry,
+ 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);
+@@ -388,8 +373,7 @@ static void
+ conn_ready_notify(struct wl_listener *l, void *data)
+ {
+ struct weston_transmitter_remote *remote =
+- container_of(l, struct weston_transmitter_remote,
+- establish_listener);
++ wl_container_of(l, remote, establish_listener);
+ struct weston_transmitter_output_info info = {
+ WL_OUTPUT_SUBPIXEL_NONE,
+ WL_OUTPUT_TRANSFORM_NORMAL,
+@@ -441,7 +425,7 @@ static const struct wthp_registry_listener registry_listener = {
+ static void
+ connection_handle_data(struct watch *w, uint32_t events)
+ {
+- struct waltham_display *dpy = container_of(w, struct waltham_display, conn_watch);
++ struct waltham_display *dpy = wl_container_of(w, dpy, conn_watch);
+ struct weston_transmitter_remote *remote = dpy->remote;
+ int ret;
+
+@@ -454,7 +438,7 @@ connection_handle_data(struct watch *w, uint32_t events)
+ if (events & EPOLLERR) {
+ weston_log("Connection errored out.\n");
+ dpy->running = false;
+-
++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
+ return;
+ }
+
+@@ -468,10 +452,12 @@ connection_handle_data(struct watch *w, uint32_t events)
+ 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;
+@@ -479,8 +465,9 @@ connection_handle_data(struct watch *w, uint32_t events)
+ }
+
+ if (events & EPOLLHUP) {
+- fprintf(stderr, "Connection hung up.\n");
++ weston_log("Connection hung up.\n");
+ dpy->running = false;
++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
+
+ return;
+ }
+@@ -491,8 +478,6 @@ waltham_mainloop(int fd, uint32_t mask, void *data)
+ {
+ struct weston_transmitter_remote *remote = data;
+ struct watch *w;
+- int count;
+- int i;
+ int ret;
+ int running_display;
+ running_display = 0;
+@@ -503,17 +488,18 @@ waltham_mainloop(int fd, uint32_t mask, void *data)
+ goto not_running;
+
+ if (!dpy->connection)
+- goto not_running;
+-
++ dpy->running = false;
++
+ if (!dpy->running)
+ goto not_running;
+
+ running_display++;
+ /* Dispatch queued events. */
+-
+ ret = wth_connection_dispatch(dpy->connection);
+- if (ret < 0)
++ if (ret < 0) {
+ dpy->running = false;
++ remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
++ }
+ if (!dpy->running)
+ goto not_running;
+
+@@ -532,29 +518,11 @@ waltham_mainloop(int fd, uint32_t mask, void *data)
+ */
+ w->cb(w, mask);
+ }
+- wl_event_source_remove(remote->source);
+- remote->source = wl_event_loop_add_fd(remote->transmitter->loop,
+- remote->display->conn_watch.fd,
+- WL_EVENT_READABLE,
+- waltham_mainloop, remote);
+
+ not_running:
+ ;
+ }
+
+-/* A one-off asynchronous open-coded roundtrip handler. */
+-static void
+-bling_done(struct wthp_callback *cb, uint32_t arg)
+-{
+- fprintf(stderr, "...sync done.\n");
+-
+- wthp_callback_free(cb);
+-}
+-
+-static const struct wthp_callback_listener bling_listener = {
+- bling_done
+-};
+-
+ static int
+ waltham_client_init(struct waltham_display *dpy)
+ {
+@@ -575,6 +543,10 @@ waltham_client_init(struct waltham_display *dpy)
+ 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
+@@ -589,19 +561,17 @@ waltham_client_init(struct waltham_display *dpy)
+
+ /* Roundtrip ensures all globals' ads have been received. */
+ if (wth_connection_roundtrip(dpy->connection) < 0) {
+- fprintf(stderr, "Roundtrip failed.\n");
++ weston_log("Roundtrip failed.\n");
+ return -1;
+ }
+
+ if (!dpy->compositor) {
+- fprintf(stderr, "Did not find wthp_compositor, quitting.\n");
++ weston_log("Did not find wthp_compositor, quitting.\n");
+ return -1;
+ }
+
+ /* A one-off asynchronous roundtrip, just for fun. */
+- fprintf(stderr, "sending wth_display.sync...\n");
+- dpy->bling = wth_display_sync(dpy->display);
+- wthp_callback_set_listener(dpy->bling, &bling_listener, dpy);
++ weston_log("sending wth_display.sync...\n");
+
+ dpy->running = true;
+
+@@ -644,8 +614,8 @@ disconnect_surface(struct weston_transmitter_remote *remote)
+ wl_list_for_each(txs, &remote->surface_list, link)
+ {
+ free(txs->wthp_ivi_surface);
+- free(txs->wthp_surf);
+ txs->wthp_ivi_surface = NULL;
++ free(txs->wthp_surf);
+ txs->wthp_surf = NULL;
+ }
+ }
+@@ -754,8 +724,7 @@ transmitter_compositor_destroyed(struct wl_listener *listener, void *data)
+ struct weston_transmitter_remote *remote;
+ struct weston_transmitter_surface *txs;
+ struct weston_transmitter *txr =
+- container_of(listener, struct weston_transmitter,
+- compositor_destroy_listener);
++ wl_container_of(listener, txr, compositor_destroy_listener);
+
+ assert(data == txr->compositor);
+
+@@ -787,8 +756,7 @@ transmitter_get(struct weston_compositor *compositor)
+ if (!listener)
+ return NULL;
+
+- txr = container_of(listener, struct weston_transmitter,
+- compositor_destroy_listener);
++ txr = wl_container_of(listener, txr, compositor_destroy_listener);
+ assert(compositor == txr->compositor);
+
+ return txr;
+@@ -868,9 +836,18 @@ transmitter_create_remote(struct weston_transmitter *txr,
+ 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;
+@@ -913,27 +890,6 @@ transmitter_get_server_config(struct weston_transmitter *txr)
+ }
+ }
+
+-static void
+-transmitter_post_init(void *data)
+-{
+- struct weston_transmitter *txr = data;
+- struct weston_transmitter_remote *remote;
+-
+- if (!txr) {
+- weston_log("Transmitter disabled\n");
+- } else {
+- transmitter_get_server_config(txr);
+- transmitter_connect_to_remote(txr);
+-
+- wl_list_for_each(remote, &txr->remote_list, link) {
+- remote->source = wl_event_loop_add_fd(txr->loop,
+- remote->display->conn_watch.fd,
+- WL_EVENT_READABLE,
+- waltham_mainloop, remote);
+- }
+- }
+-}
+-
+ WL_EXPORT int
+ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
+ {
+@@ -941,9 +897,10 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
+ int ret;
+
+ txr = zalloc(sizeof *txr);
+- if (!txr)
++ if (!txr){
++ weston_log("Transmitter disabled\n");
+ return -1;
+-
++ }
+ wl_list_init(&txr->remote_list);
+
+ txr->compositor = compositor;
+@@ -973,7 +930,8 @@ wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
+ weston_log("Transmitter initialized.\n");
+
+ txr->loop = wl_display_get_event_loop(compositor->wl_display);
+- wl_event_loop_add_idle(txr->loop, transmitter_post_init, txr);
++ transmitter_get_server_config(txr);
++ transmitter_connect_to_remote(txr);
+
+ return 0;
+
+diff --git a/transmitter/plugin.h b/transmitter/plugin.h
+index 48f49b8..116c1f6 100644
+--- a/transmitter/plugin.h
++++ b/transmitter/plugin.h
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (C) 2016 DENSO CORPORATION
+- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
++ * 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
+diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h
+index b28f946..4a660a0 100644
+--- a/transmitter/transmitter_api.h
++++ b/transmitter/transmitter_api.h
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (C) 2016 DENSO CORPORATION
+- * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
++ * 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
+--
+2.7.4
+
--- /dev/null
+From 3dbffb783f44752ec221a2ee7a94a21934d681a2 Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Tue, 10 Apr 2018 12:22:07 +0900
+Subject: [PATCH 5/5] compositor-drm: introduce drm_get_dmafd_from_view
+
+This API enables to get dmafd from weston_view
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ libweston/compositor-drm.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++
+ libweston/compositor-drm.h | 7 ++++
+ 2 files changed, 87 insertions(+)
+
+diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
+index 0b5b4c4..77f2ece 100644
+--- a/libweston/compositor-drm.c
++++ b/libweston/compositor-drm.c
+@@ -2430,6 +2430,85 @@ drm_output_set_seat(struct weston_output *base,
+ }
+
+ static int
++drm_get_dma_fd_from_view(struct weston_output *base,
++ struct weston_view *ev)
++{
++ struct drm_backend *b = to_drm_backend(base->compositor);
++ struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
++ struct gbm_bo *bo;
++ struct drm_fb *current;
++ struct linux_dmabuf_buffer *dmabuf;
++ uint32_t format;
++ int fd, ret;
++
++ if(!buffer) {
++ weston_log("buffer is NULL\n");
++ return -1;
++ }
++
++ if(dmabuf = linux_dmabuf_buffer_get(buffer->resource)) {
++ struct gbm_import_fd_data gbm_dmabuf = {
++ .fd = dmabuf->attributes.fd[0],
++ .width = dmabuf->attributes.width,
++ .height = dmabuf->attributes.height,
++ .stride = dmabuf->attributes.stride[0],
++ .format = dmabuf->attributes.format
++ };
++
++ bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD,
++ &gbm_dmabuf, GBM_BO_USE_SCANOUT);
++ if (!bo) {
++ weston_log("failed to get gbm_bo\n");
++ return -1;
++ }
++
++ current = zalloc(sizeof *current);
++ current->handle = gbm_bo_get_handle(bo).s32;
++ if (!current->handle) {
++ fprintf(stderr, "failed to get drm_handle\n");
++ return -1;
++ }
++ }
++ else if(ev->surface->buffer_ref.buffer->legacy_buffer) {
++ bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
++ buffer->resource, GBM_BO_USE_SCANOUT);
++
++ if (!bo) {
++ weston_log("failed to get gbm_bo\n");
++ return -1;
++ }
++
++ format = gbm_bo_get_format(bo);
++ if (!format) {
++ weston_log("failed to get format\n");
++ gbm_bo_destroy(bo);
++ return -1;
++ }
++
++ current = drm_fb_get_from_bo(bo, b, format);
++ if (!current) {
++ weston_log("failed to get drm_fb\n");
++ gbm_bo_destroy(bo);
++ return -1;
++ }
++ }
++ else {
++ weston_log("Buffer is not supported\n");
++ return -1;
++ }
++
++ ret = drmPrimeHandleToFD(b->drm.fd, current->handle,
++ DRM_CLOEXEC, &fd);
++ free(current);
++ if (ret) {
++ weston_log("failed to create prime fd for front buffer\n");
++ return -1;
++ }
++
++ return fd;
++}
++
++static int
+ drm_output_enable(struct weston_output *base)
+ {
+ struct drm_output *output = to_drm_output(base);
+@@ -3199,6 +3278,7 @@ static const struct weston_drm_output_api api = {
+ drm_output_set_mode,
+ drm_output_set_gbm_format,
+ drm_output_set_seat,
++ drm_get_dma_fd_from_view,
+ };
+
+ static struct drm_backend *
+diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
+index 2e2995a..fe00bd5 100644
+--- a/libweston/compositor-drm.h
++++ b/libweston/compositor-drm.h
+@@ -78,6 +78,13 @@ struct weston_drm_output_api {
+ */
+ void (*set_seat)(struct weston_output *output,
+ const char *seat);
++
++ /** Get the dma fd from drm view.
++ *
++ * The dma fd is got from weston_view.
++ * Returns fd on success, -1 on failure.
++ */
++ int (*get_dma_fd_from_view)(struct weston_output *output, struct weston_view *view);
+ };
+
+ static inline const struct weston_drm_output_api *
+--
+2.7.4
+
--- /dev/null
+From 0db59bf629def81fe9925fa435ec845e2069dd4b Mon Sep 17 00:00:00 2001
+From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+Date: Wed, 11 Apr 2018 12:19:58 +0900
+Subject: [PATCH] transmitter: introduce waltham-renderer
+
+The waltham-renderer creates and sends buffer for remote site.
+This is using gst-recorder APIs.
+
+Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
+---
+ Makefile.am | 12 +++
+ transmitter/README | 86 +++++++++++----------
+ transmitter/input.c | 2 +-
+ transmitter/output.c | 104 ++++++++++++++------------
+ transmitter/plugin.c | 45 ++++++-----
+ transmitter/plugin.h | 6 +-
+ transmitter/transmitter_api.h | 9 +++
+ transmitter/waltham-renderer.c | 166 +++++++++++++++++++++++++++++++++++++++++
+ transmitter/waltham-renderer.h | 33 ++++++++
+ 9 files changed, 347 insertions(+), 116 deletions(-)
+ create mode 100644 transmitter/waltham-renderer.c
+ create mode 100644 transmitter/waltham-renderer.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 2cb1920..0af66d6 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -526,6 +526,18 @@ transmitter_la_SOURCES = \
+ shared/timespec-util.h \
+ shared/zalloc.h \
+ src/compositor.h
++
++module_LTLIBRARIES += waltham-renderer.la
++waltham_renderer_la_LDFLAGS = -module -avoid-version
++waltham_renderer_la_CFLAGS = \
++ $(COMPOSITOR_CFLAGS) \
++ $(AM_CFLAGS) \
++ $(WALTHAM_CFLAGS)
++waltham_renderer_la_LIBADD = $(COMPOSITOR_LIBS) \
++ -lwaltham
++waltham_renderer_la_SOURCES = \
++ transmitter/waltham-renderer.c \
++ transmitter/waltham-renderer.h
+ endif
+
+ noinst_PROGRAMS += spring-tool
+diff --git a/transmitter/README b/transmitter/README
+index af80574..345142d 100644
+--- a/transmitter/README
++++ b/transmitter/README
+@@ -1,4 +1,4 @@
+-Transmitter plugin
++Transmitter plugin
+
+ The current implementation of Transmitter is a stub which interfaces to
+ other Weston parts appropriately, but all networking is just a mockup.
+@@ -15,8 +15,8 @@ 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'.
++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
+@@ -27,57 +27,66 @@ In details, see 'weston.ini.transmitter'.
+
+ How to test
+ ===========
+-You can use server side test application in waltham repository.
++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:
+
+- [06:12:41.238] Loading module '/usr/lib64/weston/ivi-shell.so'
+- [06:12:41.245] launching '/usr/libexec/weston-keyboard'
+- [06:12:41.247] Loading module '/usr/lib64/weston/ivi-controller.so'
+- [06:12:41.252] Loading module '/usr/lib64/weston/ivi-input-controller.so'
+- [06:12:41.253] ivi-input-controller module loaded successfully!
+- [06:12:41.255] Loading module '/usr/lib64/weston/transmitter.so'
+- [06:12:41.260] Registered plugin API 'transmitter_v1' of size 88
+- [06:12:41.260] Registered plugin API 'transmitter_ivi_v1' of size 16
+- [06:12:41.260] Transmitter initialized.
+- [06:12:41.260] ivi-layout: Transmitter enabled.
+- [06:12:41.260] Transmitter weston_seat 0x14f8010
+- [06:12:41.260] Transmitter created pointer=0x139a440 for seat 0x14f8010
+- [06:12:41.261] Transmitter created keyboard=0x14f8160 for seat 0x14f8010
+- [06:12:41.261] Transmitter created touch=0x1508750 for seat 0x14f8010
++ [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:
+
+- root@gr-mrb-64:~# debug: wth_connection_insert_new_object: new object id: 1
++ debug: wth_connection_insert_new_object: new object id: 1
+ debug: wth_connection_insert_new_object: new object id: 2
+- 2017-07-19T06:14:31Z 00001000030000000100000002000000 wth_display_get_registry
++ 2018-01-09T13:24:22Z 00001000030000000100000002000000 wth_display_get_registry
+ debug: wth_connection_insert_new_object: new object id: 3
+- 2017-07-19T06:14:31Z 00001000020000000100000003000000 wth_display_sync
+- debug: Message received on conn 0x1560340: (9) 40 bytes
++ 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
+- 2017-07-19T06:14:31Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthp_registry_bind
+- debug: Message received on conn 0x1560340: (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: 5
+- 2017-07-19T06:14:31Z 000030000800000002000000010000000500000012000000777468705f626c6f625f666163746f72790001000000 wthp_registry_bind
+- debug: Message received on conn 0x1560340: (9) 48 bytes
++ 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
+- 2017-07-19T06:14:31Z 000034000800000002000000010000000600000015000000777468705f6976695f6170706c69636174696f6e0001000000 wthp_registry_bind
+- debug: Message received on conn 0x1560340: (11) 16 bytes
+- debug: wthp_callback_send_done(3, 0) (opcode 11) called.
+- sending wth_display.sync...
++ 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
+- 2017-07-19T06:14:31Z 00001000020000000100000007000000 wth_display_sync
+- debug: Message received on conn 0x1560340: (11) 16 bytes
+- debug: wthp_callback_send_done(7, 0) (opcode 11) called.
+- ...sync done.
++ 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 backend output
+ - Put surface on transmitter output
+
+ Weston log will indicate remoting has started:
+@@ -85,5 +94,4 @@ 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
+-
++[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/transmitter/input.c b/transmitter/input.c
+index 6797b6e..e00546b 100644
+--- a/transmitter/input.c
++++ b/transmitter/input.c
+@@ -964,7 +964,7 @@ keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard,
+ 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)
+diff --git a/transmitter/output.c b/transmitter/output.c
+index 003056f..2cca781 100644
+--- a/transmitter/output.c
++++ b/transmitter/output.c
+@@ -28,9 +28,12 @@
+ #include <string.h>
+
+ #include "compositor.h"
++#include "compositor-drm.h"
++#include "plugin-registry.h"
+
+ #include "plugin.h"
+ #include "transmitter_api.h"
++#include "waltham-renderer.h"
+
+ /** @file
+ *
+@@ -59,6 +62,8 @@
+ * exclusive with weston_compositor_add_output().
+ */
+
++static struct waltham_renderer_interface *waltham_renderer;
++
+ static char *
+ make_model(struct weston_transmitter_remote *remote, int name)
+ {
+@@ -146,45 +151,26 @@ transmitter_start_repaint_loop(struct weston_output *base)
+ }
+
+ static int
+-transmitter_check_output(struct weston_transmitter_surface *txs,
+- struct weston_compositor *compositor)
+-{
+- struct weston_output *def_output = wl_container_of(compositor->output_list.next,
+- def_output, link);
+- struct weston_view *view;
+-
+- wl_list_for_each_reverse(view, &compositor->view_list, link) {
+- if (view->output == def_output) {
+- if (view->surface == txs->surface)
+- return 1;
+- }
+- }
+-
+- return 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 =
++ 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;
+
+- if (!output->from_frame_signal)
+- return 0;
+-
+- output->from_frame_signal = false;
++ 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,
++ * 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.
+ */
+@@ -201,24 +187,34 @@ transmitter_output_repaint(struct weston_output *base,
+ wl_list_for_each(txs, &remote->surface_list, link) {
+ if (txs->surface == view->surface) {
+ found_surface = true;
+- if (!transmitter_check_output(txs, compositor))
+- break;
+-
+ 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;
++ }
++ 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,
++ 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:
+@@ -228,28 +224,38 @@ out:
+ }
+
+ 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 = NULL;
++ output->base.assign_planes = transmitter_assign_planes;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+ output->base.switch_mode = NULL;
+ }
+
+-static void
+-transmitter_output_frame_handler(struct wl_listener *listener, void *data)
+-{
+- struct weston_transmitter_output *output;
+- int ret;
+-
+- output = wl_container_of(listener, output, frame_listener);
+- output->from_frame_signal = true;
+-
+- ret = transmitter_output_repaint(&output->base, NULL);
+-}
+-
+ int
+ transmitter_remote_create_output(struct weston_transmitter_remote *remote,
+ const struct weston_transmitter_output_info *info)
+@@ -312,13 +318,15 @@ transmitter_remote_create_output(struct weston_transmitter_remote *remote,
+ output->remote = remote;
+ wl_list_insert(&remote->output_list, &output->link);
+
+- weston_output_enable(&output->base);
++ /* 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;
++ }
+
+- output->frame_listener.notify = transmitter_output_frame_handler;
+- def_output = wl_container_of(txr->compositor->output_list.next,
+- def_output, link);
+- wl_signal_add(&def_output->frame_signal, &output->frame_listener);
+- output->from_frame_signal = false;
++ weston_output_enable(&output->base);
+
+ return 0;
+
+diff --git a/transmitter/plugin.c b/transmitter/plugin.c
+index 1f00f33..faf28b5 100644
+--- a/transmitter/plugin.c
++++ b/transmitter/plugin.c
+@@ -121,20 +121,20 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
+ 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,
+@@ -143,13 +143,13 @@ transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
+ 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;
+@@ -255,7 +255,7 @@ transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs)
+ 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);
+@@ -313,7 +313,7 @@ transmitter_surface_push_to_remote(struct weston_surface *ws,
+ wl_list_init(&txs->frame_callback_list);
+ wl_list_init(&txs->feedback_list);
+
+- txs->lyt = weston_plugin_api_get(txr->compositor,
++ txs->lyt = weston_plugin_api_get(txr->compositor,
+ IVI_LAYOUT_API_NAME, sizeof(txs->lyt));
+ }
+
+@@ -351,15 +351,15 @@ registry_handle_global(struct wthp_registry *registry,
+ struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry);
+
+ if (strcmp(interface, "wthp_compositor") == 0) {
+- assert(!dpy->compositor);
++ 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);
++ 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);
++ 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) {
+@@ -486,13 +486,13 @@ waltham_mainloop(int fd, uint32_t mask, void *data)
+ 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);
+@@ -505,7 +505,7 @@ waltham_mainloop(int fd, uint32_t mask, void *data)
+
+ /* 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.
+ */
+@@ -570,9 +570,6 @@ waltham_client_init(struct waltham_display *dpy)
+ return -1;
+ }
+
+- /* A one-off asynchronous roundtrip, just for fun. */
+- weston_log("sending wth_display.sync...\n");
+-
+ dpy->running = true;
+
+ return 0;
+@@ -586,7 +583,7 @@ establish_timer_handler(void *data)
+
+ ret = waltham_client_init(remote->display);
+ if(ret == -2) {
+- wl_event_source_timer_update(remote->establish_timer,
++ wl_event_source_timer_update(remote->establish_timer,
+ ESTABLISH_CONNECTION_PERIOD);
+ return 0;
+ }
+@@ -631,13 +628,13 @@ retry_timer_handler(void *data)
+ registry_handle_global_remove(dpy->registry, 1);
+ init_globals(dpy);
+ disconnect_surface(remote);
+- wl_event_source_timer_update(remote->establish_timer,
++ wl_event_source_timer_update(remote->establish_timer,
+ ESTABLISH_CONNECTION_PERIOD);
+
+ return 0;
+ }
+ else
+- wl_event_source_timer_update(remote->retry_timer,
++ wl_event_source_timer_update(remote->retry_timer,
+ RETRY_CONNECTION_PERIOD);
+ return 0;
+ }
+@@ -648,7 +645,7 @@ 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 */
+@@ -658,12 +655,12 @@ transmitter_connect_to_remote(struct weston_transmitter *txr)
+ remote->display->remote = remote;
+ /* set connection establish timer */
+ loop_est = wl_display_get_event_loop(txr->compositor->wl_display);
+- remote->establish_timer =
++ 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 =
++ 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");
+diff --git a/transmitter/plugin.h b/transmitter/plugin.h
+index 116c1f6..ec776fa 100644
+--- a/transmitter/plugin.h
++++ b/transmitter/plugin.h
+@@ -59,7 +59,7 @@ enum wthp_seat_capability {
+ };
+
+ /* epoll structure */
+-struct watch {
++struct watch {
+ struct waltham_display *display;
+ int fd;
+ void (*cb)(struct watch *w, uint32_t events);
+@@ -198,9 +198,7 @@ struct weston_transmitter_output {
+ struct frame *frame;
+
+ struct wl_callback *frame_cb;
+- struct wl_listener frame_listener;
+-
+- bool from_frame_signal;
++ struct renderer *renderer;
+ };
+
+ struct weston_transmitter_seat {
+diff --git a/transmitter/transmitter_api.h b/transmitter/transmitter_api.h
+index 4a660a0..c473256 100644
+--- a/transmitter/transmitter_api.h
++++ b/transmitter/transmitter_api.h
+@@ -265,4 +265,13 @@ weston_get_transmitter_ivi_api(struct weston_compositor *compositor)
+
+ /* Remote compositor/output are identified by model */
+
++
++struct renderer {
++ void (*repaint_output)(struct weston_output *base);
++ struct gst_recorder *recorder; /* gst-recorder instance */
++ int32_t dmafd; /* dmafd received from compositor-drm */
++ int surface_width;
++ int surface_height;
++};
++
+ #endif /* WESTON_TRANSMITTER_API_H */
+diff --git a/transmitter/waltham-renderer.c b/transmitter/waltham-renderer.c
+new file mode 100644
+index 0000000..f9e4e21
+--- /dev/null
++++ b/transmitter/waltham-renderer.c
+@@ -0,0 +1,166 @@
++/*
++ * 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 <stdlib.h>
++#include <assert.h>
++#include <string.h>
++
++#include "compositor.h"
++#include "libweston/gst-recorder.h"
++
++#include "transmitter_api.h"
++#include "waltham-renderer.h"
++#include "plugin.h"
++
++struct waltham_renderer {
++ struct renderer base;
++};
++
++static void
++recorder_frame_notify(struct weston_transmitter_output* output)
++{
++ gst_recorder_frame_dmafd(output->renderer->recorder, output->renderer->dmafd,
++ output->renderer->surface_width*4);
++}
++
++static int parse_crop_rect(const char *s, struct v4l2_rect* crop)
++{
++ crop->left = 0;
++ crop->top = 0;
++ crop->width = 0;
++ crop->height = 0;
++
++ if (sscanf(s, "%dx%d@%dx%d",
++ &crop->width,
++ &crop->height,
++ &crop->top,
++ &crop->left) != 4)
++ return -1;
++
++ return 0;
++}
++
++static int
++recorder_enable(struct weston_transmitter_output *output)
++{
++ int enable_recorder = 0;
++ struct gst_recorder_settings *settings;
++ struct weston_config_section *section;
++
++ 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;
++ char *crop_params = "384x368@0x0";
++
++ struct v4l2_rect crop = { .width = output->base.current_mode->width,
++ .height = output->base.current_mode->height,
++ .top = 0,
++ .left = 0 };
++
++ if (output->renderer->recorder)
++ return -1;
++
++ settings = malloc(sizeof(* settings));
++ settings->ip = remote->addr;
++
++ settings->port = atoi(remote->port);
++
++ settings->bitrate = bitrate;
++ settings->width = output->base.current_mode->width;
++ settings->height = output->base.current_mode->height;
++
++ settings->crop = crop;
++
++ if (parse_crop_rect(crop_params, &settings->crop)) {
++ weston_log("[gst recorder] %s:"
++ " failed to parse crop parameter\n",
++ output->base.name);
++ goto err;
++ }
++
++ 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("crop = %d x %d \n",settings->crop.width,settings->crop.height);
++ weston_log("width = %d \n",settings->width);
++ weston_log("width = %d \n",settings->height);
++
++
++ gst_recorder_init();
++
++ output->renderer->recorder =
++ gst_recorder_create(settings);
++ if (!output->renderer->recorder) {
++ weston_log("[gst recorder] %s:"
++ " failed to create gst recorder\n",
++ output->base.name);
++ goto err;
++ }
++
++ weston_log("[gst recorder] %s:"
++ " recorder initialized\n",
++ output->base.name);
++
++ 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)
++{
++ recorder_frame_notify(output);
++}
++
++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;
++
++ recorder_enable(&output->base);
++ return 0;
++}
++
++WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = {
++ .display_create = waltham_renderer_display_create
++};
+diff --git a/transmitter/waltham-renderer.h b/transmitter/waltham-renderer.h
+new file mode 100644
+index 0000000..458794e
+--- /dev/null
++++ b/transmitter/waltham-renderer.h
+@@ -0,0 +1,33 @@
++/*
++ * 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);
++};
++
++#endif /* TRANSMITTER_WALTHAM_RENDERER_H_ */
+--
+2.7.4
+
file://0014-simple-shm-remove-ivi-application-support.patch \
file://0015-window-client-remove-ivi-application-support.patch \
file://0016-ivi-shell_add_screen_remove_layer_api.patch \
+ file://0017-transmitter-add-an-incomplete-plugin-output-and-poin.patch \
+ file://0018-ivi-layout-Register-ivi-layout-interface-It-enables-.patch \
+ file://0019-transmitter-transmitter-plugin-for-waltham-protocol.patch \
+ file://0020-compositor-add-output-type-to-weston_output.patch \
+ file://0021-transmitter-add-output-type-for-waltham-output.patch \
+ file://0022-transmitter-did-code-cleaning.patch \
+ file://0023-compositor-drm-introduce-drm_get_dmafd_from_view.patch \
+ file://0024-transmitter-introduce-waltham-renderer.patch \
"
-EXTRA_OECONF_append = " --enable-sys-uid"
+DEPENDS += "waltham"
+
+EXTRA_OECONF_append = " --enable-sys-uid \
+ --enable-surface-remoting \
+ "
+