1 From 2bcc81912b92d6ba7a6d24e972e0bcce2e746cab Mon Sep 17 00:00:00 2001
2 From: Wataru Mizuno <wmizuno@jp.adit-jv.com>
3 Date: Wed, 4 Jul 2018 09:09:33 +0900
4 Subject: [PATCH] transmitter: initial commit for waltham-transmitter
6 The waltham-transmitter is the plugin of weston to enable client
7 applications to share its surface between multiple domains.
9 Signed-off-by: Wataru Mizuno <wmizuno@jp.adit-jv.com>
12 waltham-transmitter/CMakeLists.txt | 4 +
13 waltham-transmitter/COPYING | 30 +
14 .../transmitter-plugin/CMakeLists.txt | 62 +
15 waltham-transmitter/transmitter-plugin/README | 97 ++
16 waltham-transmitter/transmitter-plugin/input.c | 1317 ++++++++++++++++++++
17 waltham-transmitter/transmitter-plugin/output.c | 352 ++++++
18 waltham-transmitter/transmitter-plugin/plugin.c | 940 ++++++++++++++
19 waltham-transmitter/transmitter-plugin/plugin.h | 330 +++++
20 .../transmitter-plugin/transmitter_api.h | 278 +++++
21 .../transmitter-plugin/weston.ini.transmitter | 21 +
22 .../waltham-renderer/CMakeLists.txt | 59 +
23 .../waltham-renderer/waltham-renderer.c | 270 ++++
24 .../waltham-renderer/waltham-renderer.h | 41 +
25 14 files changed, 3804 insertions(+)
26 create mode 100644 CMakeLists.txt
27 create mode 100644 waltham-transmitter/CMakeLists.txt
28 create mode 100644 waltham-transmitter/COPYING
29 create mode 100644 waltham-transmitter/transmitter-plugin/CMakeLists.txt
30 create mode 100644 waltham-transmitter/transmitter-plugin/README
31 create mode 100644 waltham-transmitter/transmitter-plugin/input.c
32 create mode 100644 waltham-transmitter/transmitter-plugin/output.c
33 create mode 100644 waltham-transmitter/transmitter-plugin/plugin.c
34 create mode 100644 waltham-transmitter/transmitter-plugin/plugin.h
35 create mode 100644 waltham-transmitter/transmitter-plugin/transmitter_api.h
36 create mode 100644 waltham-transmitter/transmitter-plugin/weston.ini.transmitter
37 create mode 100644 waltham-transmitter/waltham-renderer/CMakeLists.txt
38 create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.c
39 create mode 100644 waltham-transmitter/waltham-renderer/waltham-renderer.h
41 diff --git a/CMakeLists.txt b/CMakeLists.txt
43 index 0000000..00fd14e
47 +project (weston-ivi-plugins)
49 +add_subdirectory(waltham-transmitter)
50 diff --git a/waltham-transmitter/CMakeLists.txt b/waltham-transmitter/CMakeLists.txt
52 index 0000000..b4d1243
54 +++ b/waltham-transmitter/CMakeLists.txt
56 +project (transmitter)
58 +add_subdirectory(transmitter-plugin)
59 +add_subdirectory(waltham-renderer)
60 diff --git a/waltham-transmitter/COPYING b/waltham-transmitter/COPYING
62 index 0000000..faefd8f
64 +++ b/waltham-transmitter/COPYING
66 +Copyright © 2008-2012 Kristian Høgsberg
67 +Copyright © 2010-2012 Intel Corporation
68 +Copyright © 2010-2011 Benjamin Franzke
69 +Copyright © 2011-2012 Collabora, Ltd.
70 +Copyright © 2010 Red Hat <mjg@redhat.com>
72 +Permission is hereby granted, free of charge, to any person obtaining a
73 +copy of this software and associated documentation files (the "Software"),
74 +to deal in the Software without restriction, including without limitation
75 +the rights to use, copy, modify, merge, publish, distribute, sublicense,
76 +and/or sell copies of the Software, and to permit persons to whom the
77 +Software is furnished to do so, subject to the following conditions:
79 +The above copyright notice and this permission notice (including the next
80 +paragraph) shall be included in all copies or substantial portions of the
83 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
86 +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
88 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
89 +DEALINGS IN THE SOFTWARE.
93 +The above is the version of the MIT "Expat" License used by X.org:
95 + http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
96 diff --git a/waltham-transmitter/transmitter-plugin/CMakeLists.txt b/waltham-transmitter/transmitter-plugin/CMakeLists.txt
98 index 0000000..a900d3b
100 +++ b/waltham-transmitter/transmitter-plugin/CMakeLists.txt
102 +project (transmitter)
104 +find_package(PkgConfig REQUIRED)
105 +pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED)
106 +pkg_check_modules(WESTON weston>=2.0.0 REQUIRED)
107 +pkg_check_modules(PIXMAN pixman-1 REQUIRED)
108 +pkg_check_modules(WALTHAM waltham REQUIRED)
110 +include_directories(
112 + ${CMAKE_SOURCE_DIR}/waltham-transmitter/waltham-renderer
113 + ${CMAKE_CURRENT_BINARY_DIR}
114 + ${WAYLAND_CLIENT_INCLUDE_DIRS}
115 + ${WAYLAND_SERVER_INCLUDE_DIRS}
116 + ${WESTON_INCLUDE_DIRS}
117 + ${PIXMAN_INCLUDE_DIRS}
118 + ${WALTHAM_INCLUDE_DIRS}
122 + ${WAYLAND_SERVER_LIBRARY_DIRS}
123 + ${WESTON_LIBRARY_DIRS}
124 + ${PIXMAN_LIBRARY_DIRS}
125 + ${WALTHAM_LIBRARY_DIRS}
128 +add_library(${PROJECT_NAME} MODULE
136 +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
140 + ${WAYLAND_SERVER_LIBRARIES}
141 + ${WESTON_LIBRARIES}
142 + ${PIXMAN_LIBRARIES}
143 + ${WALTHAM_LIBRARIES}
156 +add_dependencies(${PROJECT_NAME} ${LIBS})
158 +target_link_libraries(${PROJECT_NAME} ${LIBS})
161 + TARGETS ${PROJECT_NAME}
162 + LIBRARY DESTINATION lib64/weston
164 diff --git a/waltham-transmitter/transmitter-plugin/README b/waltham-transmitter/transmitter-plugin/README
166 index 0000000..345142d
168 +++ b/waltham-transmitter/transmitter-plugin/README
172 +The current implementation of Transmitter is a stub which interfaces to
173 +other Weston parts appropriately, but all networking is just a mockup.
175 +Sections in this file describe:
177 +- How to write weston.ini
182 +Configure Weston with --enable-surface-remoting to build the Transmitter
185 +How to write weston.ini
186 +=======================
187 +To load transmitter plugin to weston, add 'transmitter.so' to the 'modules'
188 +key under '[core]', and make sure the 'shell' is 'ivi-shell.so'.
190 +The destination of remoting is configured in weston.ini.
191 +Add output name, server address, port number, output's width and height key
192 +under '[remote-output]'.
193 +You can speficy multiple [remote-output].
195 +In details, see 'weston.ini.transmitter'.
199 +You can use server side test application in waltham-server directory.
201 +If you set 'WALTHAM_DEBUG=1' to your environment valuable, you can
202 +see the log like this:
204 + [13:24:08.345] Loading module '/usr/lib64/weston/transmitter.so'
205 + [13:24:08.345] Registered plugin API 'transmitter_v1' of size 88
206 + [13:24:08.345] Registered plugin API 'transmitter_ivi_v1' of size 16
207 + [13:24:08.345] Transmitter initialized.
208 + [13:24:08.345] Loading module '/usr/lib64/libweston-2/waltham-renderer.so'
209 + [13:24:08.352] gst-setting are :-->
210 + [13:24:08.352] ip = 192.168.2.52
211 + [13:24:08.352] port = 34400
212 + [13:24:08.352] bitrate = 3000000
213 + [13:24:08.352] crop = 384 x 368
214 + [13:24:08.352] width = 1920
215 + [13:24:08.352] width = 1080
216 + [13:24:08.531] open media device: platform:fe960000.vsp (fe960000.vsp)
217 + [13:24:08.532] input pad setup ('fe960000.vsp rpf.0 input':'/dev/video0')
218 + [13:24:08.533] output pad setup (fe960000.vsp wpf.0 output:/dev/video5)
219 + [13:24:08.533] vsp-device '/dev/media0' created
220 + [13:24:08.533] gst_recorder_create (1920x1080) crop 384x368 at 0,0
221 + [13:24:08.533] gst_pipeline: starting: appsrc name=src ! omxh264enc target-bitrate=3000000 control-rate=2 no-copy=k
222 + [13:24:08.582] goot 1 pools
223 + [13:24:08.583] pool settings size 211968, min 5, max 5
224 + [13:24:08.583] gst_recorder_create done
225 + [13:24:08.583] [gst recorder] transmitter-192.168.2.52:34400-1: recorder initialized
226 + [13:24:08.583] Transmitter weston_seat 0x15424630
227 + [13:24:08.583] Transmitter created pointer=0x15625df0 for seat 0x15424630
228 + [13:24:08.583] Transmitter created keyboard=0x154247c0 for seat 0x15424630
229 + [13:24:08.583] Transmitter created touch=0x15625f10 for seat 0x15424630
231 +The connection is established, you can see following debug messages:
233 + debug: wth_connection_insert_new_object: new object id: 1
234 + debug: wth_connection_insert_new_object: new object id: 2
235 + 2018-01-09T13:24:22Z 00001000030000000100000002000000 wth_display_get_registry
236 + debug: wth_connection_insert_new_object: new object id: 3
237 + 2018-01-09T13:24:22Z 00001000020000000100000003000000 wth_display_sync
238 + debug: Message received on conn 0x15572730: (9) 40 bytes
239 + debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called.
240 + debug: wth_connection_insert_new_object: new object id: 4
241 + 2018-01-09T13:24:22Z 00002c000800000002000000010000000400000010000000777468705f636f6d706f7369746f720001000000 wthpd
242 + debug: Message received on conn 0x15572730: (9) 48 bytes
243 + debug: wthp_registry_send_global(2, 1, [variable type const char *], 1) (opcode 9) called.
244 + debug: wth_connection_insert_new_object: new object id: 5
245 + 2018-01-09T13:24:22Z 000034000800000002000000010000000500000015000000777468705f6976695f6170706c69636174696f6e00010d
246 + debug: Message received on conn 0x15572730: (9) 44 bytes
247 + debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called.
248 + debug: wth_connection_insert_new_object: new object id: 6
249 + 2018-01-09T13:24:22Z 000030000800000002000000010000000600000012000000777468705f626c6f625f666163746f72790001000000 d
250 + debug: Message received on conn 0x15572730: (9) 36 bytes
251 + debug: wthp_registry_send_global(2, 1, [variable type const char *], 4) (opcode 9) called.
252 + debug: wth_connection_insert_new_object: new object id: 7
253 + 2018-01-09T13:24:22Z 00002800080000000200000001000000070000000a000000777468705f736561740001000000 wthp_registry_bid
254 + debug: Message received on conn 0x15572730: (11) 16 bytes
255 + debug: wthp_callback_send_done(3, 0) (opcode 11) called.
258 +- Start an IVI application.
259 +- Put surface on transmitter output
261 +Weston log will indicate remoting has started:
263 +[13:18:24.572] HMI transmitting surface 0x1c3dad0, ivi-id 0x9ff6
264 +[13:18:24.572] Transmitter: update surface 0x1c3dad0 (0, 0), 0 cb
265 +[13:18:24.572] transmitter_surface_set_ivi_id(0x1c3dad0, 0x9ff6)
266 +[13:18:24.972] Transmitter: surface 0x1c3dad0 entered output transmitter-0.0.0.0:66-1
267 \ No newline at end of file
268 diff --git a/waltham-transmitter/transmitter-plugin/input.c b/waltham-transmitter/transmitter-plugin/input.c
270 index 0000000..e00546b
272 +++ b/waltham-transmitter/transmitter-plugin/input.c
275 + * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
277 + * Permission is hereby granted, free of charge, to any person obtaining
278 + * a copy of this software and associated documentation files (the
279 + * "Software"), to deal in the Software without restriction, including
280 + * without limitation the rights to use, copy, modify, merge, publish,
281 + * distribute, sublicense, and/or sell copies of the Software, and to
282 + * permit persons to whom the Software is furnished to do so, subject to
283 + * the following conditions:
285 + * The above copyright notice and this permission notice (including the
286 + * next paragraph) shall be included in all copies or substantial
287 + * portions of the Software.
289 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
290 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
291 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
292 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
293 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
294 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
295 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
303 +/* for fake stuff */
306 +#include "compositor.h"
309 +#include "transmitter_api.h"
313 + * This is an implementation of a remote input.
315 + * Request wl_data_device_manager.get_data_device would need to be blocked,
316 + * except maybe it's not necessary, we just "forget" to forward data to/from
317 + * the remote wl_seat. It might still work inside the local compositor.
319 + * weston_compositor_set_default_pointer_grab() will break our pointer
320 + * implementation, but no in-tree code is calling it.
323 +/* XXX: all functions and variables with a name, and things marked with a
324 + * comment, containing the word "fake" are mockups that need to be
325 + * removed from the final implementation.
329 +pointer_focus_grab_handler(struct weston_pointer_grab *grab)
333 + * Weston internal events do not change the focus.
338 +pointer_motion_grab_handler(struct weston_pointer_grab *grab,
340 + struct weston_pointer_motion_event *event)
342 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
343 + __func__, grab->pointer);
347 +pointer_button_grab_handler(struct weston_pointer_grab *grab,
352 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
353 + __func__, grab->pointer);
357 +pointer_axis_grab_handler(struct weston_pointer_grab *grab,
359 + struct weston_pointer_axis_event *event)
361 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
362 + __func__, grab->pointer);
366 +pointer_axis_source_grab_handler(struct weston_pointer_grab *grab,
369 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
370 + __func__, grab->pointer);
374 +pointer_frame_grab_handler(struct weston_pointer_grab *grab)
376 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
377 + __func__, grab->pointer);
381 +pointer_cancel_grab_handler(struct weston_pointer_grab *grab)
383 + weston_log("Unexpected! %s(pointer=%p, ...)\n",
384 + __func__, grab->pointer);
387 +/* These handlers would be called from the notify_*() functions in src/input.c.
388 + * However, as we do not use the low level input notify_*() functions that
389 + * backends drive, these are mostly uncalled, except the focus handler which
390 + * weston core generates internally.
392 +static const struct weston_pointer_grab_interface pointer_grab_impl = {
393 + pointer_focus_grab_handler,
394 + pointer_motion_grab_handler,
395 + pointer_button_grab_handler,
396 + pointer_axis_grab_handler,
397 + pointer_axis_source_grab_handler,
398 + pointer_frame_grab_handler,
399 + pointer_cancel_grab_handler,
403 +keyboard_grab_key(struct weston_keyboard_grab *grab,
411 +keyboard_grab_modifiers(struct weston_keyboard_grab *grab,
413 + uint32_t mods_depressed,
414 + uint32_t mods_latched,
415 + uint32_t mods_locked,
421 +keyboard_grab_cancel(struct weston_keyboard_grab *grab)
425 +static const struct weston_keyboard_grab_interface keyborad_grab_impl = {
427 + keyboard_grab_modifiers,
428 + keyboard_grab_cancel
432 +touch_grab_down_handler(struct weston_touch_grab *grab,
441 +touch_grab_up_handler(struct weston_touch_grab *grab,
448 +touch_grab_motion_handler(struct weston_touch_grab *grab,
457 +touch_grab_frame_handler(struct weston_touch_grab *grab)
462 +touch_grab_cancel_handler(struct weston_touch_grab *grab)
466 +static const struct weston_touch_grab_interface touch_grab_impl = {
467 + touch_grab_down_handler,
468 + touch_grab_up_handler,
469 + touch_grab_motion_handler,
470 + touch_grab_frame_handler,
471 + touch_grab_cancel_handler,
475 +/* The different ways to get pointer focus on a remoted surface:
477 + * 1. Transmitter seat has pointer. The client has wl_pointer. Transmitter
478 + * receives pointer.enter. (transmitter_seat_pointer_enter())
480 + * 2. Transmitter seat has pointer. Transmitter has received pointer.enter.
481 + * The client calls wl_seat.get_pointer. => send enter only on the new
482 + * wl_pointer. (seat_get_pointer_handler())
484 + * 3. Client has wl_pointer. Transmitter seat adds pointer capability.
485 + * Transmitter receives pointer.enter. wl_pointer MUST NOT enter,
486 + * specified by wl_seat.capabilities.
488 + * By definition, Transmitter cannot receive pointer.enter without having
489 + * pointer capability in the seat, so no other combinations are possible.
491 + * The same applies to wl_keyboard and wl_touch.
494 +/* Implementor notes:
496 + * The handling of all of wl_pointer, wl_keyboard and wl_touch should be
497 + * similar. To make it work, we need to add a signal to each of the
498 + * wl_seat.get_pointer, wl_seat.get_keyboard, and wl_seat.get_touch request
499 + * handlers in Weston core. Otherwise we cannot implement the case 2 of gaining
500 + * input device focus.
502 + * However, weston_keyboard::focus is a weston_surface, not a weston_view, so
503 + * we may be able to leverage more of the core implementation and maybe do
504 + * without the wl_seat.get_keyboard signal. Weston_touch uses a weston_view, so
505 + * that is similar to weston_pointer.
507 + * It might be useful to convert weston_keyboard and weston_touch to use a
508 + * similar thing as weston_pointer_client, in case it makes things more
509 + * consistent. It might also fix issues when a client has multiple copies of a
510 + * wl_keyboard or a wl_touch, but that is getting off-topic.
512 + * This file shows which part of the Weston input path we skip and where we
513 + * hook in. We skip everything starting from the notify_*() API used by
514 + * backends, and stub out the grab handlers. Instead of actual grab handlers,
515 + * we have our own network protocol events handlers. They do much of the same
516 + * as normal grab handlers would do, except focus is pre-given, and we do not
517 + * have weston_view for the focus surfaces, so we need to bypass core code
518 + * dealing with those.
520 + * Our remote seat implementation will leave many struct members unused and
521 + * replicate some from weston_pointer, weston_keyboard, and weston_touch.
522 + * Weston core must be kept out from the focus handling business, because we
523 + * will send enter/leave events ourselves, and focus assignments are given
524 + * to us from the remote, they cannot be changed at will by the local Weston.
527 +/** Callback from the protocol request handler for wl_seat.get_pointer
529 + * The Weston core handler never sees focus set on the weston_pointer,
530 + * so it won't send wl_pointer.enter nor set focus_client. It does call
531 + * weston_pointer_ensure_pointer_client() though.
534 +seat_get_pointer_handler(struct wl_listener *listener, void *data)
536 + struct wl_resource *new_pointer = data;
537 + struct weston_transmitter_seat *seat;
538 + struct wl_resource *surface;
539 + struct weston_pointer_client *pointer_client;
540 + struct wl_client *client;
541 + struct weston_pointer *pointer;
543 + seat = wl_container_of(listener, seat, get_pointer_listener);
544 + if (!seat->pointer_focus)
547 + client = wl_resource_get_client(new_pointer);
548 + surface = seat->pointer_focus->surface->resource;
550 + if (wl_resource_get_client(surface) != client)
553 + pointer = weston_seat_get_pointer(seat->base);
554 + assert(pointer); /* guaranteed by having pointer_focus */
555 + pointer_client = weston_pointer_get_pointer_client(pointer, client);
557 + if (!pointer->focus_client)
558 + pointer->focus_client = pointer_client;
560 + assert(pointer->focus_client == pointer_client);
562 + wl_pointer_send_enter(new_pointer, pointer->focus_serial, surface,
563 + seat->pointer_surface_x, seat->pointer_surface_y);
565 + if (wl_resource_get_version(new_pointer) >=
566 + WL_POINTER_FRAME_SINCE_VERSION)
567 + wl_pointer_send_frame(new_pointer);
571 +transmitter_seat_create_pointer(struct weston_transmitter_seat *seat)
573 + struct weston_pointer *pointer;
575 + seat->pointer_phase = 0.0;
576 + seat->pointer_surface_x = wl_fixed_from_int(-1000000);
577 + seat->pointer_surface_y = wl_fixed_from_int(-1000000);
578 + seat->pointer_focus = NULL;
579 + wl_list_init(&seat->pointer_focus_destroy_listener.link);
581 + weston_seat_init_pointer(seat->base);
583 + pointer = weston_seat_get_pointer(seat->base);
586 + * weston_pointer_set_default_grab(pointer, &pointer_grab_impl); */
587 + pointer->default_grab.interface = &pointer_grab_impl;
589 + /* Changes to local outputs are irrelevant. */
590 + wl_list_remove(&pointer->output_destroy_listener.link);
591 + wl_list_init(&pointer->output_destroy_listener.link);
593 + weston_log("Transmitter created pointer=%p for seat %p\n",
594 + pointer, seat->base);
598 +seat_pointer_focus_destroy_handler(struct wl_listener *listener, void *data)
600 + struct weston_transmitter_surface *txs = data;
601 + struct weston_transmitter_seat *seat;
603 + seat = wl_container_of(listener, seat, pointer_focus_destroy_listener);
604 + assert(seat->pointer_focus == txs);
606 + seat->pointer_focus = NULL;
610 +transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat,
612 + struct weston_transmitter_surface *txs,
613 + wl_fixed_t surface_x,
614 + wl_fixed_t surface_y)
616 + struct wl_client *client;
617 + struct weston_pointer *pointer;
618 + struct wl_list *focus_resource_list;
619 + struct wl_resource *resource;
621 + pointer = weston_seat_get_pointer(seat->base);
624 + assert(txs->surface);
625 + client = wl_resource_get_client(txs->surface->resource);
627 + seat->pointer_focus = txs;
628 + seat->pointer_focus_destroy_listener.notify =
629 + seat_pointer_focus_destroy_handler;
630 + wl_signal_add(&txs->destroy_signal,
631 + &seat->pointer_focus_destroy_listener);
633 + /* If pointer-focus gets destroyed, txs will get destroyed, the
634 + * remote surface object is destroyed, and the remote will send a
635 + * leave and a frame.
638 + seat->pointer_surface_x = surface_x;
639 + seat->pointer_surface_y = surface_y;
641 + pointer->focus_serial = serial;
643 + /* pointer->focus is not used, because it is a weston_view, while
644 + * remoted surfaces have no views.
646 + * pointer->x,y are not used because they are in global coordinates.
647 + * Remoted surfaces are not in the global space at all, so there are
648 + * no such coordinates.
651 + if (!pointer->focus_client)
654 + focus_resource_list = &pointer->focus_client->pointer_resources;
655 + wl_resource_for_each(resource, focus_resource_list) {
656 + wl_pointer_send_enter(resource,
658 + txs->surface->resource,
659 + surface_x, surface_y);
664 +transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat,
666 + struct weston_transmitter_surface *txs)
668 + struct weston_pointer *pointer;
669 + struct wl_list *focus_resource_list;
670 + struct wl_resource *surface_resource;
671 + struct wl_resource *resource;
673 + if (txs != seat->pointer_focus) {
674 + weston_log("Transmitter Warning: pointer leave for %p, expected %p\n",
675 + txs, seat->pointer_focus);
678 + seat->pointer_focus = NULL;
679 + wl_list_remove(&seat->pointer_focus_destroy_listener.link);
680 + wl_list_init(&seat->pointer_focus_destroy_listener.link);
684 + assert(txs->surface);
685 + surface_resource = txs->surface->resource;
687 + pointer = weston_seat_get_pointer(seat->base);
689 + if (!pointer->focus_client)
692 + focus_resource_list = &pointer->focus_client->pointer_resources;
693 + wl_resource_for_each(resource, focus_resource_list)
694 + wl_pointer_send_leave(resource, serial, surface_resource);
696 + /* Do not reset pointer->focus_client, because we need to be able
697 + * to send a following 'frame' event in
698 + * transmitter_seat_pointer_frame().
703 +transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat,
705 + wl_fixed_t surface_x,
706 + wl_fixed_t surface_y)
708 + struct weston_pointer *pointer;
709 + struct wl_list *focus_resource_list;
710 + struct wl_resource *resource;
711 + struct weston_transmitter_surface *txs;
713 + pointer = weston_seat_get_pointer(seat->base);
716 + seat->pointer_surface_x = surface_x;
717 + seat->pointer_surface_y = surface_y;
719 + if (!pointer->focus_client)
722 + txs = seat->pointer_focus;
724 + assert(wl_resource_get_client(txs->surface->resource) ==
725 + pointer->focus_client->client);
727 + focus_resource_list = &pointer->focus_client->pointer_resources;
728 + wl_resource_for_each(resource, focus_resource_list) {
729 + wl_pointer_send_motion(resource, time,
730 + surface_x, surface_y);
735 +transmitter_seat_pointer_button(struct weston_transmitter_seat *seat,
741 + struct weston_pointer *pointer;
742 + struct wl_list *focus_resource_list;
743 + struct wl_resource *resource;
744 + struct weston_transmitter_surface *txs;
746 + pointer = weston_seat_get_pointer(seat->base);
749 + if (!pointer->focus_client)
752 + txs = seat->pointer_focus;
754 + assert(wl_resource_get_client(txs->surface->resource) ==
755 + pointer->focus_client->client);
757 + focus_resource_list = &pointer->focus_client->pointer_resources;
758 + wl_resource_for_each(resource, focus_resource_list) {
759 + wl_pointer_send_button(resource, serial, time,
765 +transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat,
770 + struct weston_pointer *pointer;
771 + struct wl_list *focus_resource_list;
772 + struct wl_resource *resource;
773 + struct weston_transmitter_surface *txs;
775 + pointer = weston_seat_get_pointer(seat->base);
778 + if (!pointer->focus_client)
781 + txs = seat->pointer_focus;
783 + assert(wl_resource_get_client(txs->surface->resource) ==
784 + pointer->focus_client->client);
786 + focus_resource_list = &pointer->focus_client->pointer_resources;
787 + wl_resource_for_each(resource, focus_resource_list) {
788 + wl_pointer_send_axis(resource, time,
794 +transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat)
796 + struct weston_pointer *pointer;
798 + pointer = weston_seat_get_pointer(seat->base);
800 + weston_pointer_send_frame(pointer);
804 +transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat,
805 + uint32_t axis_source)
807 + /* ToDo : implement axis event handling */
811 +transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat,
815 + /* ToDo : implement axis event handling */
819 +transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat,
823 + /* ToDo : implement axis event handling */
827 +transmitter_seat_create_keyboard(struct weston_transmitter_seat *seat)
829 + struct weston_keyboard *keyboard;
831 + seat->keyboard_focus = NULL;
832 + weston_seat_init_keyboard(seat->base, NULL);
834 + keyboard = weston_seat_get_keyboard(seat->base);
836 + keyboard->default_grab.interface = &keyborad_grab_impl;
838 + weston_log("Transmitter created keyboard=%p for seat %p\n",
839 + keyboard, seat->base);
843 +transmitter_seat_keyboard_enter(struct weston_transmitter_seat *seat,
845 + struct weston_transmitter_surface *txs,
846 + struct wl_array *keys)
848 + struct weston_keyboard *keyboard;
849 + struct wl_resource *resource = NULL;
850 + struct wl_resource *surface_resource;
852 + keyboard = weston_seat_get_keyboard(seat->base);
855 + assert(txs->surface);
856 + surface_resource = txs->surface->resource;
858 + seat->keyboard_focus = txs;
859 + wl_array_copy(&keyboard->keys, keys);
861 + wl_resource_for_each(resource, &keyboard->resource_list) {
862 + if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) {
863 + wl_keyboard_send_enter(resource,
872 +transmitter_seat_keyboard_leave(struct weston_transmitter_seat *seat,
874 + struct weston_transmitter_surface *txs)
876 + struct weston_keyboard *keyboard;
877 + struct wl_resource *resource = NULL;
878 + struct wl_resource *surface_resource;
880 + keyboard = weston_seat_get_keyboard(seat->base);
883 + assert(txs->surface);
884 + surface_resource = txs->surface->resource;
886 + wl_resource_for_each(resource, &keyboard->resource_list) {
887 + if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) {
888 + wl_keyboard_send_leave(resource,
896 +transmitter_seat_keyboard_key(struct weston_transmitter_seat *seat,
902 + struct weston_keyboard *keyboard;
903 + struct wl_resource *resource = NULL;
905 + keyboard = weston_seat_get_keyboard(seat->base);
908 + wl_resource_for_each(resource, &keyboard->resource_list) {
909 + if (wl_resource_get_client(resource) ==
910 + wl_resource_get_client(seat->keyboard_focus->surface->resource)) {
911 + wl_keyboard_send_key(resource,
921 +transmitter_seat_create_touch(struct weston_transmitter_seat *seat)
923 + struct weston_touch *touch;
925 + seat->touch_focus = NULL;
926 + weston_seat_init_touch(seat->base);
928 + touch = weston_seat_get_touch(seat->base);
930 + touch->default_grab.interface = &touch_grab_impl;
932 + weston_log("Transmitter created touch=%p for seat %p\n",
933 + touch, seat->base);
937 +transmitter_seat_touch_down (struct weston_transmitter_seat *seat,
940 + struct weston_transmitter_surface *txs,
945 + struct weston_touch *touch;
946 + struct wl_resource *resource = NULL;
947 + struct wl_resource *surface_resource;
949 + touch = weston_seat_get_touch(seat->base);
952 + assert(txs->surface);
953 + surface_resource = txs->surface->resource;
955 + seat->touch_focus = txs;
957 + wl_resource_for_each(resource, &touch->resource_list) {
958 + if (wl_resource_get_client(resource) == wl_resource_get_client(surface_resource)) {
959 + wl_touch_send_down(resource, serial, time,
967 +transmitter_seat_touch_up (struct weston_transmitter_seat *seat,
972 + struct weston_touch *touch;
973 + struct wl_resource *resource = NULL;
975 + touch = weston_seat_get_touch(seat->base);
978 + wl_resource_for_each(resource, &touch->resource_list) {
979 + if (wl_resource_get_client(resource) ==
980 + wl_resource_get_client(seat->touch_focus->surface->resource)) {
981 + wl_touch_send_up(resource, serial, time, touch_id);
987 +transmitter_seat_touch_motion (struct weston_transmitter_seat *seat,
993 + struct weston_touch *touch;
994 + struct wl_resource *resource = NULL;
996 + touch = weston_seat_get_touch(seat->base);
999 + wl_resource_for_each(resource, &touch->resource_list) {
1000 + if (wl_resource_get_client(resource) ==
1001 + wl_resource_get_client(seat->touch_focus->surface->resource)) {
1002 + wl_touch_send_motion(resource, time, touch_id, x, y);
1008 +transmitter_seat_touch_frame (struct weston_transmitter_seat *seat)
1010 + struct weston_touch *touch;
1011 + struct wl_resource *resource = NULL;
1013 + touch = weston_seat_get_touch(seat->base);
1016 + wl_resource_for_each(resource, &touch->resource_list) {
1017 + if (wl_resource_get_client(resource) ==
1018 + wl_resource_get_client(seat->touch_focus->surface->resource)) {
1019 + wl_touch_send_frame(resource);
1025 +transmitter_seat_touch_cancel (struct weston_transmitter_seat *seat)
1027 + struct weston_touch *touch;
1028 + struct wl_resource *resource = NULL;
1030 + touch = weston_seat_get_touch(seat->base);
1033 + wl_resource_for_each(resource, &touch->resource_list) {
1034 + if (wl_resource_get_client(resource) ==
1035 + wl_resource_get_client(seat->touch_focus->surface->resource)) {
1036 + wl_touch_send_cancel(resource);
1042 +make_seat_name(struct weston_transmitter_remote *remote, const char *name)
1046 + if (asprintf(&str, "transmitter-%s-%s", remote->addr, name) < 0)
1053 +transmitter_seat_destroy(struct weston_transmitter_seat *seat)
1055 + wl_list_remove(&seat->link);
1057 + weston_log("Transmitter destroy seat=%p\n", seat->base);
1059 + wl_list_remove(&seat->get_pointer_listener.link);
1060 + wl_list_remove(&seat->pointer_focus_destroy_listener.link);
1062 + if (seat->pointer_timer)
1063 + wl_event_source_remove(seat->pointer_timer);
1069 +pointer_handle_enter(struct wthp_pointer *wthp_pointer,
1071 + struct wthp_surface *surface,
1072 + wth_fixed_t surface_x,
1073 + wth_fixed_t surface_y)
1075 + struct waltham_display *dpy =
1076 + wth_object_get_user_data((struct wth_object *)wthp_pointer);
1077 + struct weston_transmitter_remote *remote = dpy->remote;
1078 + struct wl_list *seat_list = &remote->seat_list;
1079 + struct weston_transmitter_seat *seat;
1080 + struct weston_transmitter_surface *txs;
1082 + seat = wl_container_of(seat_list->next, seat, link);
1084 + wl_list_for_each(txs, &remote->surface_list, link)
1086 + if (txs->wthp_surf == surface) {
1087 + if (txs != seat->pointer_focus)
1088 + transmitter_seat_pointer_leave(seat, serial, seat->pointer_focus);
1089 + transmitter_seat_pointer_enter(seat, serial, txs,
1090 + surface_x, surface_y);
1096 +pointer_handle_leave(struct wthp_pointer *wthp_pointer,
1098 + struct wthp_surface *surface)
1100 + struct waltham_display *dpy =
1101 + wth_object_get_user_data((struct wth_object *)wthp_pointer);
1102 + struct weston_transmitter_remote *remote = dpy->remote;
1103 + struct wl_list *seat_list = &remote->seat_list;
1104 + struct weston_transmitter_seat *seat;
1105 + struct weston_transmitter_surface *txs;
1107 + seat = wl_container_of(seat_list->next, seat, link);
1109 + wl_list_for_each(txs, &remote->surface_list, link)
1111 + if (txs->wthp_surf == surface) {
1112 + transmitter_seat_pointer_leave(seat, serial, txs);
1118 +pointer_handle_motion(struct wthp_pointer *wthp_pointer,
1120 + wth_fixed_t surface_x,
1121 + wth_fixed_t surface_y)
1123 + struct waltham_display *dpy =
1124 + wth_object_get_user_data((struct wth_object *)wthp_pointer);
1125 + struct weston_transmitter_remote *remote = dpy->remote;
1126 + struct wl_list *seat_list = &remote->seat_list;
1127 + struct weston_transmitter_seat *seat;
1129 + seat = wl_container_of(seat_list->next, seat, link);
1131 + transmitter_seat_pointer_motion(seat, time,
1137 +pointer_handle_button(struct wthp_pointer *wthp_pointer,
1143 + struct waltham_display *dpy =
1144 + wth_object_get_user_data((struct wth_object *)wthp_pointer);
1145 + struct weston_transmitter_remote *remote = dpy->remote;
1146 + struct wl_list *seat_list = &remote->seat_list;
1147 + struct weston_transmitter_seat *seat;
1149 + seat = wl_container_of(seat_list->next, seat, link);
1151 + transmitter_seat_pointer_button(seat, serial,
1157 +pointer_handle_axis(struct wthp_pointer *wthp_pointer,
1159 + uint32_t axis, wth_fixed_t value)
1161 + struct waltham_display *dpy =
1162 + wth_object_get_user_data((struct wth_object *)wthp_pointer);
1163 + struct weston_transmitter_remote *remote = dpy->remote;
1164 + struct wl_list *seat_list = &remote->seat_list;
1165 + struct weston_transmitter_seat *seat;
1167 + seat = wl_container_of(seat_list->next, seat, link);
1169 + transmitter_seat_pointer_axis(seat, time,
1174 +pointer_handle_frame(struct wthp_pointer *wthp_pointer)
1176 + /* ToDo : implement pointer handle frame */
1180 +pointer_handle_axis_source(struct wthp_pointer *wthp_pointer,
1181 + uint32_t axis_source)
1183 + /* ToDo : implement pointer handle axis source */
1187 +pointer_handle_axis_stop(struct wthp_pointer *wthp_pointer,
1191 + /* ToDo : implement pointer handle axis stop */
1195 +pointer_handle_axis_discrete(struct wthp_pointer *wthp_pointer,
1199 + /* ToDo : implement pointer handle axis discrete */
1202 +static const struct wthp_pointer_listener pointer_listener = {
1203 + pointer_handle_enter,
1204 + pointer_handle_leave,
1205 + pointer_handle_motion,
1206 + pointer_handle_button,
1207 + pointer_handle_axis,
1208 + pointer_handle_frame,
1209 + pointer_handle_axis_source,
1210 + pointer_handle_axis_stop,
1211 + pointer_handle_axis_discrete
1215 +keyboard_handle_keymap(struct wthp_keyboard * wthp_keyboard,
1217 + uint32_t keymap_sz,
1220 + /* ToDo : implement keyboard handle keymap */
1224 +keyboard_handle_enter(struct wthp_keyboard *wthp_keyboard,
1226 + struct wthp_surface *surface,
1227 + struct wth_array *keys)
1229 + struct waltham_display *dpy =
1230 + wth_object_get_user_data((struct wth_object *)wthp_keyboard);
1231 + struct weston_transmitter_remote *remote = dpy->remote;
1232 + struct wl_list *seat_list = &remote->seat_list;
1233 + struct weston_transmitter_seat *seat;
1234 + struct weston_transmitter_surface *txs;
1235 + struct wl_array *wl_key = (struct wl_array *)malloc(sizeof(struct wl_array));
1237 + wl_key->size = keys->size;
1238 + wl_key->alloc = keys->alloc;
1239 + wl_key->data = keys->data;
1241 + seat = wl_container_of(seat_list->next, seat, link);
1243 + wl_list_for_each(txs, &remote->surface_list, link)
1245 + if (txs->wthp_surf == surface) {
1246 + //transmitter_seat_keyboard_enter(seat, serial, txs, keys);
1247 + transmitter_seat_keyboard_enter(seat, serial, txs, wl_key);
1254 +keyboard_handle_leave(struct wthp_keyboard *wthp_keyboard,
1256 + struct wthp_surface *surface)
1258 + struct waltham_display *dpy =
1259 + wth_object_get_user_data((struct wth_object *)wthp_keyboard);
1260 + struct weston_transmitter_remote *remote = dpy->remote;
1261 + struct wl_list *seat_list = &remote->seat_list;
1262 + struct weston_transmitter_seat *seat;
1263 + struct weston_transmitter_surface *txs;
1265 + seat = wl_container_of(seat_list->next, seat, link);
1267 + wl_list_for_each(txs, &remote->surface_list, link)
1269 + if (txs->wthp_surf == surface) {
1270 + transmitter_seat_keyboard_leave(seat, serial, txs);
1276 +keyboard_handle_key(struct wthp_keyboard *wthp_keyboard,
1282 + struct waltham_display *dpy =
1283 + wth_object_get_user_data((struct wth_object *)wthp_keyboard);
1284 + struct weston_transmitter_remote *remote = dpy->remote;
1285 + struct wl_list *seat_list = &remote->seat_list;
1286 + struct weston_transmitter_seat *seat;
1288 + seat = wl_container_of(seat_list->next, seat, link);
1290 + transmitter_seat_keyboard_key(seat, serial, time, key, state);
1294 +keyboard_handle_modifiers(struct wthp_keyboard *wthp_keyboard,
1296 + uint32_t mods_depressed,
1297 + uint32_t mods_latched,
1298 + uint32_t mods_locked,
1301 + weston_log("keyboard_handle_modifiers\n");
1305 +keyboard_handle_repeat_info(struct wthp_keyboard *wthp_keyboard,
1309 + weston_log("keyboard_handle_repeat_info\n");
1312 +static const struct wthp_keyboard_listener keyboard_listener = {
1313 + keyboard_handle_keymap,
1314 + keyboard_handle_enter,
1315 + keyboard_handle_leave,
1316 + keyboard_handle_key,
1317 + keyboard_handle_modifiers,
1318 + keyboard_handle_repeat_info
1322 +touch_handle_down (struct wthp_touch * wthp_touch,
1325 + struct wthp_surface * surface,
1330 + struct waltham_display *dpy =
1331 + wth_object_get_user_data((struct wth_object *)wthp_touch);
1332 + struct weston_transmitter_remote *remote = dpy->remote;
1333 + struct wl_list *seat_list = &remote->seat_list;
1334 + struct weston_transmitter_seat *seat;
1335 + struct weston_transmitter_surface *txs;
1337 + seat = wl_container_of(seat_list->next, seat, link);
1339 + wl_list_for_each(txs, &remote->surface_list, link)
1341 + if (txs->wthp_surf == surface) {
1342 + transmitter_seat_touch_down(seat, serial, time,
1349 +touch_handle_up (struct wthp_touch * wthp_touch,
1354 + struct waltham_display *dpy =
1355 + wth_object_get_user_data((struct wth_object *)wthp_touch);
1356 + struct weston_transmitter_remote *remote = dpy->remote;
1357 + struct wl_list *seat_list = &remote->seat_list;
1358 + struct weston_transmitter_seat *seat;
1360 + seat = wl_container_of(seat_list->next, seat, link);
1362 + transmitter_seat_touch_up(seat, serial, time, id);
1366 +touch_handle_motion (struct wthp_touch * wthp_touch,
1372 + struct waltham_display *dpy =
1373 + wth_object_get_user_data((struct wth_object *)wthp_touch);
1374 + struct weston_transmitter_remote *remote = dpy->remote;
1375 + struct wl_list *seat_list = &remote->seat_list;
1376 + struct weston_transmitter_seat *seat;
1378 + seat = wl_container_of(seat_list->next, seat, link);
1380 + transmitter_seat_touch_motion(seat, time, id, x, y);
1385 +touch_handle_frame (struct wthp_touch * wthp_touch)
1387 + struct waltham_display *dpy =
1388 + wth_object_get_user_data((struct wth_object *)wthp_touch);
1389 + struct weston_transmitter_remote *remote = dpy->remote;
1390 + struct wl_list *seat_list = &remote->seat_list;
1391 + struct weston_transmitter_seat *seat;
1393 + seat = wl_container_of(seat_list->next, seat, link);
1395 + transmitter_seat_touch_frame(seat);
1399 +touch_handle_cancel (struct wthp_touch * wthp_touch)
1401 + struct waltham_display *dpy =
1402 + wth_object_get_user_data((struct wth_object *)wthp_touch);
1403 + struct weston_transmitter_remote *remote = dpy->remote;
1404 + struct wl_list *seat_list = &remote->seat_list;
1405 + struct weston_transmitter_seat *seat;
1407 + seat = wl_container_of(seat_list->next, seat, link);
1409 + transmitter_seat_touch_cancel(seat);
1413 +static const struct wthp_touch_listener touch_listener = {
1414 + touch_handle_down,
1416 + touch_handle_motion,
1417 + touch_handle_frame,
1418 + touch_handle_cancel
1422 +seat_capabilities(struct wthp_seat *wthp_seat,
1423 + enum wthp_seat_capability caps)
1425 + struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)wthp_seat);
1427 + weston_log("seat_capabilities\n");
1429 + if ((caps & WTHP_SEAT_CAPABILITY_POINTER) && !dpy->pointer)
1431 + weston_log("WTHP_SEAT_CAPABILITY_POINTER\n");
1432 + dpy->pointer = wthp_seat_get_pointer(dpy->seat);
1433 + wthp_pointer_set_listener(dpy->pointer, &pointer_listener, dpy);
1435 + if ((caps & WTHP_SEAT_CAPABILITY_KEYBOARD) && !dpy->keyboard)
1437 + weston_log("WTHP_SEAT_CAPABILITY_KEYBOARD\n");
1438 + dpy->keyboard = wthp_seat_get_keyboard(dpy->seat);
1439 + wthp_keyboard_set_listener(dpy->keyboard, &keyboard_listener, dpy);
1441 + if ((caps & WTHP_SEAT_CAPABILITY_TOUCH) && !dpy->touch)
1443 + weston_log("WTHP_SEAT_CAPABILITY_TOUCH\n");
1444 + dpy->touch = wthp_seat_get_touch(dpy->seat);
1445 + wthp_touch_set_listener(dpy->touch, &touch_listener, dpy);
1450 +transmitter_remote_create_seat(struct weston_transmitter_remote *remote)
1452 + struct weston_transmitter_seat *seat = NULL;
1453 + char *name = NULL;
1454 + struct weston_seat *weston_seat = NULL;
1456 + seat = zalloc(sizeof *seat);
1460 + wl_list_init(&seat->get_pointer_listener.link);
1461 + wl_list_init(&seat->pointer_focus_destroy_listener.link);
1463 + /* XXX: get the name from remote */
1464 + name = make_seat_name(remote, "default");
1469 + if (wl_list_empty(&remote->transmitter->compositor->seat_list)) {
1470 + weston_seat = zalloc(sizeof *weston_seat);
1474 + weston_seat_init(weston_seat, remote->transmitter->compositor, name);
1475 + seat->base = weston_seat;
1476 + weston_log("Transmitter created seat=%p \n", &seat->base);
1478 + wl_list_for_each(weston_seat, &remote->transmitter->compositor->seat_list, link) {
1479 + weston_log("Transmitter weston_seat %p\n", weston_seat);
1480 + seat->base = weston_seat;
1486 + weston_seat_init(&seat->base, remote->transmitter->compositor, name);
1489 + /* Hide the weston_seat from the rest of Weston, there are too many
1490 + * things making assumptions:
1491 + * - backends assume they control all seats
1492 + * - shells assume they control all input foci
1493 + * We do not want either to mess with our seat.
1495 + wl_list_remove(&seat->base.link);
1496 + wl_list_init(&seat->base.link);
1498 + /* The weston_compositor::seat_created_signal has already been
1499 + * emitted. Shells use it to subscribe to focus changes, but we should
1500 + * never handle focus with weston core... except maybe with keyboard.
1501 + * text-backend.c will also act on the new seat.
1502 + * It is possible weston_seat_init() needs to be split to fix this
1506 + weston_log("Transmitter created seat=%p '%s'\n",
1507 + &seat->base, seat->base.seat_name);
1510 + /* XXX: mirror remote capabilities */
1511 + transmitter_seat_create_pointer(seat);
1512 + transmitter_seat_create_keyboard(seat);
1513 + transmitter_seat_create_touch(seat);
1515 + wl_list_insert(&remote->seat_list, &seat->link);
1527 +fake_pointer_get_position(struct weston_transmitter_seat *seat, double step,
1528 + wl_fixed_t *x, wl_fixed_t *y)
1532 + seat->pointer_phase += step;
1533 + while (seat->pointer_phase > 2.0 * M_PI)
1534 + seat->pointer_phase -= 2.0 * M_PI;
1536 + sincos(seat->pointer_phase, &s, &c);
1537 + *x = wl_fixed_from_double(100.0 + 50.0 * c);
1538 + *y = wl_fixed_from_double(100.0 + 50.0 * s);
1542 +fake_pointer_timer_handler(void *data)
1544 + struct weston_transmitter_seat *seat = data;
1548 + time = weston_compositor_get_time();
1550 + fake_pointer_get_position(seat, 18.0 / 180.0 * M_PI, &x, &y);
1551 + transmitter_seat_pointer_motion(seat, time, x, y);
1552 + transmitter_seat_pointer_frame(seat);
1554 + wl_event_source_timer_update(seat->pointer_timer, 100);
1560 +transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat,
1561 + struct weston_transmitter_surface *txs)
1563 + struct wl_event_loop *loop;
1565 + uint32_t serial = 5;
1567 + /* remove focus from earlier surface */
1568 + transmitter_seat_pointer_leave(seat, serial++, seat->pointer_focus);
1569 + transmitter_seat_pointer_frame(seat);
1571 + /* set pointer focus to surface */
1572 + fake_pointer_get_position(seat, 0.0, &x, &y);
1573 + transmitter_seat_pointer_enter(seat, serial++, txs, x, y);
1574 + transmitter_seat_pointer_frame(seat);
1576 + if (!seat->pointer_timer) {
1577 + /* schedule timer for motion */
1578 + loop = wl_display_get_event_loop(seat->base->compositor->wl_display);
1579 + seat->pointer_timer = wl_event_loop_add_timer(loop,
1580 + fake_pointer_timer_handler, seat);
1581 + wl_event_source_timer_update(seat->pointer_timer, 100);
1584 + /* XXX: if the now focused surface disappears, we should call
1585 + * transmitter_seat_pointer_leave() as part of the mockup. Otherwise
1586 + * you get a "Transmitter Warning: no pointer->focus_client?".
1591 diff --git a/waltham-transmitter/transmitter-plugin/output.c b/waltham-transmitter/transmitter-plugin/output.c
1592 new file mode 100644
1593 index 0000000..c379ce5
1595 +++ b/waltham-transmitter/transmitter-plugin/output.c
1598 + * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
1600 + * Permission is hereby granted, free of charge, to any person obtaining
1601 + * a copy of this software and associated documentation files (the
1602 + * "Software"), to deal in the Software without restriction, including
1603 + * without limitation the rights to use, copy, modify, merge, publish,
1604 + * distribute, sublicense, and/or sell copies of the Software, and to
1605 + * permit persons to whom the Software is furnished to do so, subject to
1606 + * the following conditions:
1608 + * The above copyright notice and this permission notice (including the
1609 + * next paragraph) shall be included in all copies or substantial
1610 + * portions of the Software.
1612 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1613 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1614 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1615 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1616 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1617 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1618 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1622 +#include <stdlib.h>
1623 +#include <assert.h>
1624 +#include <string.h>
1626 +#include "compositor.h"
1627 +#include "compositor-drm.h"
1628 +#include "plugin-registry.h"
1630 +#include "plugin.h"
1631 +#include "transmitter_api.h"
1632 +#include "waltham-renderer.h"
1636 + * This is an implementation of a remote output.
1638 + * A remote output must not be accepted as an argument to:
1639 + * - wl_shell_surface.set_fullscreen
1640 + * - wl_shell_surface.set_maximized
1641 + * - zwp_fullscreen_shell_v1.present_surface
1642 + * - zwp_fullscreen_shell_v1.present_surface_for_mode
1643 + * - zwp_input_panel_surface_v1.set_toplevel
1644 + * - xdg_surface.set_fullscreen
1646 + * If a remote output is an argument to the above or similar requests,
1647 + * it should have the same effect as NULL if possible.
1649 + * @todo Should we instead accept the argument and have it start remoting
1650 + * automatically? That would be shell-specific.
1652 + * In ivi-shell's case, only zwp_input_panel_surface_v1.set_toplevel is
1653 + * reachable from keyboard.c. That just blindly uses whatever the first
1654 + * output happens to be, so there is no need to check for now.
1656 + * @todo Add weston_output_set_remote() which sets weston_output::is_remote
1657 + * to true and inits weston_output::link. This should be made mutually
1658 + * exclusive with weston_compositor_add_output().
1661 +static struct waltham_renderer_interface *waltham_renderer;
1664 +make_model(struct weston_transmitter_remote *remote, int name)
1668 + if (asprintf(&str, "transmitter-%s:%s-%d", remote->addr, remote->port, name) < 0)
1675 +make_mode_list(struct wl_list *list,
1676 + const struct weston_transmitter_output_info *info)
1678 + struct weston_mode *mode;
1680 + mode = zalloc(sizeof *mode);
1684 + *mode = info->mode;
1685 + wl_list_insert(list->prev, &mode->link);
1690 +static struct weston_mode *
1691 +get_current_mode(struct wl_list *mode_list)
1693 + struct weston_mode *mode;
1695 + wl_list_for_each(mode, mode_list, link)
1696 + if (mode->flags & WL_OUTPUT_MODE_CURRENT)
1704 +free_mode_list(struct wl_list *mode_list)
1706 + struct weston_mode *mode;
1708 + while (!wl_list_empty(mode_list)) {
1709 + mode = wl_container_of(mode_list->next, mode, link);
1711 + wl_list_remove(&mode->link);
1717 +transmitter_output_destroy(struct weston_transmitter_output *output)
1719 + wl_list_remove(&output->link);
1721 + free_mode_list(&output->base.mode_list);
1722 + free(output->base.serial_number);
1723 + free(output->base.model);
1724 + free(output->base.make);
1726 + weston_output_destroy(&output->base);
1731 +transmitter_output_destroy_(struct weston_output *base)
1733 + struct weston_transmitter_output *output = wl_container_of(base, output, base);
1735 + transmitter_output_destroy(output);
1740 +transmitter_start_repaint_loop(struct weston_output *base)
1742 + struct timespec ts;
1743 + struct weston_transmitter_output *output = wl_container_of(base, output, base);
1745 + weston_compositor_read_presentation_clock(output->base.compositor, &ts);
1746 + weston_output_finish_frame(&output->base, &ts, 0);
1750 +transmitter_output_repaint(struct weston_output *base,
1751 + pixman_region32_t *damage)
1753 + struct weston_transmitter_output* output = wl_container_of(base, output, base);
1754 + struct weston_transmitter_remote* remote = output->remote;
1755 + struct weston_transmitter* txr = remote->transmitter;
1756 + struct weston_transmitter_api* transmitter_api =
1757 + weston_get_transmitter_api(txr->compositor);
1758 + struct weston_transmitter_surface* txs;
1759 + struct weston_compositor *compositor = base->compositor;
1760 + struct weston_view *view;
1761 + bool found_output = false;
1762 + struct timespec ts;
1764 + struct weston_drm_output_api *api =
1765 + weston_plugin_api_get(txr->compositor, WESTON_DRM_OUTPUT_API_NAME, sizeof(api));
1768 + * Pick up weston_view in transmitter_output and check weston_view's surface
1769 + * If the surface hasn't been conbined to weston_transmitter_surface,
1770 + * then call push_to_remote.
1771 + * If the surface has already been combined, call gather_state.
1773 + if (wl_list_empty(&compositor->view_list))
1776 + if (remote->status == WESTON_TRANSMITTER_CONNECTION_DISCONNECTED)
1779 + wl_list_for_each_reverse(view, &compositor->view_list, link) {
1780 + bool found_surface = false;
1781 + if (view->output == &output->base) {
1782 + found_output = true;
1783 + wl_list_for_each(txs, &remote->surface_list, link) {
1784 + if (txs->surface == view->surface) {
1785 + found_surface = true;
1786 + if (!txs->wthp_surf)
1787 + transmitter_api->surface_push_to_remote
1788 + (view->surface, remote, NULL);
1790 + output->renderer->dmafd =
1791 + api->get_dma_fd_from_view(&output->base, view);
1792 + if(!output->renderer->dmafd) {
1793 + weston_log("Failed to get dmafd\n");
1798 + * Updating the width x height
1799 + * from surface to gst-recorder
1801 + output->renderer->surface_width
1802 + = view->surface->width;
1803 + output->renderer->surface_height
1804 + = view->surface->height;
1806 + output->renderer->repaint_output(output);
1807 + output->renderer->dmafd = NULL;
1808 + transmitter_api->surface_gather_state(txs);
1809 + weston_buffer_reference(&view->surface->buffer_ref, NULL);
1813 + if (!found_surface)
1814 + transmitter_api->surface_push_to_remote(view->surface,
1818 + if (!found_output)
1821 + weston_compositor_read_presentation_clock(output->base.compositor, &ts);
1822 + weston_output_finish_frame(&output->base, &ts, 0);
1827 + transmitter_start_repaint_loop(base);
1833 +transmitter_assign_planes(struct weston_output *base) {
1835 + * This function prevents compositor releasing buffer early.
1837 + struct weston_transmitter_output* output = wl_container_of(base, output, base);
1838 + struct weston_transmitter_remote* remote = output->remote;
1839 + struct weston_transmitter_surface* txs;
1840 + struct weston_compositor *compositor = base->compositor;
1841 + struct weston_view *view;
1843 + wl_list_for_each_reverse(view, &compositor->view_list, link) {
1844 + if (view->output == &output->base) {
1845 + wl_list_for_each(txs, &remote->surface_list, link) {
1846 + if (txs->surface == view->surface)
1847 + view->surface->keep_buffer = true;
1855 +transmitter_output_enable(struct weston_output *base)
1857 + struct weston_transmitter_output *output = wl_container_of(base, output, base);
1859 + output->base.assign_planes = transmitter_assign_planes;
1860 + output->base.set_backlight = NULL;
1861 + output->base.set_dpms = NULL;
1862 + output->base.switch_mode = NULL;
1866 +transmitter_remote_create_output(struct weston_transmitter_remote *remote,
1867 + const struct weston_transmitter_output_info *info)
1869 + struct weston_transmitter_output *output;
1870 + struct weston_transmitter *txr = remote->transmitter;
1871 + struct weston_output *def_output;
1873 + output = zalloc(sizeof *output);
1877 + output->parent.draw_initial_frame = true;
1879 + output->base.subpixel = info->subpixel;
1881 + output->base.name = make_model(remote, 1);
1882 + output->base.make = strdup(WESTON_TRANSMITTER_OUTPUT_MAKE);
1883 + output->base.model = make_model(remote, 1);
1884 + output->base.serial_number = strdup("0");
1885 + /* x and y is fake value */
1886 + wl_list_init(&output->base.mode_list);
1887 + if (make_mode_list(&output->base.mode_list, info) < 0)
1890 + output->base.current_mode = get_current_mode(&output->base.mode_list);
1891 + output->base.height = output->base.current_mode->height;
1892 + output->base.width = output->base.current_mode->width;
1893 + /* WL_OUTPUT_MODE_CURRENT already set */
1894 + weston_output_init(&output->base, remote->transmitter->compositor);
1897 + * renderer_output_create skipped:
1898 + * no renderer awareness is needed for this output
1902 + * weston_compositor_add_output() skipped:
1903 + * Most other code uses weston_compositor::output_list when traversing
1904 + * all outputs, we do not want any of that.
1905 + * Also weston_compositor::output_created_signal must not trigger
1906 + * for this output, since we must not involve input device management
1907 + * or color management or any kind of local management.
1909 + output->base.enable = transmitter_output_enable;
1910 + output->base.start_repaint_loop = transmitter_start_repaint_loop;
1911 + output->base.repaint = transmitter_output_repaint;
1912 + output->base.destroy = transmitter_output_destroy_;
1913 + output->base.assign_planes = NULL;
1914 + output->base.set_dpms = NULL;
1915 + output->base.switch_mode = NULL;
1916 + output->base.gamma_size = 0;
1917 + output->base.set_gamma = NULL;
1919 + output->base.native_mode = output->base.current_mode;
1920 + output->base.native_scale = output->base.current_scale;
1921 + output->base.scale = 1;
1922 + output->base.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1924 + output->remote = remote;
1925 + wl_list_insert(&remote->output_list, &output->link);
1927 + /* Loading a waltham renderer library */
1928 + waltham_renderer = weston_load_module("waltham-renderer.so","waltham_renderer_interface");
1930 + if (waltham_renderer->display_create(output) < 0) {
1931 + weston_log("Failed to create waltham renderer display \n");
1935 + weston_output_enable(&output->base);
1940 + free_mode_list(&output->base.mode_list);
1941 + free(output->base.serial_number);
1942 + free(output->base.model);
1943 + free(output->base.make);
1944 + free(output->base.name);
1949 diff --git a/waltham-transmitter/transmitter-plugin/plugin.c b/waltham-transmitter/transmitter-plugin/plugin.c
1950 new file mode 100644
1951 index 0000000..f643bd8
1953 +++ b/waltham-transmitter/transmitter-plugin/plugin.c
1956 + * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
1958 + * Permission is hereby granted, free of charge, to any person obtaining
1959 + * a copy of this software and associated documentation files (the
1960 + * "Software"), to deal in the Software without restriction, including
1961 + * without limitation the rights to use, copy, modify, merge, publish,
1962 + * distribute, sublicense, and/or sell copies of the Software, and to
1963 + * permit persons to whom the Software is furnished to do so, subject to
1964 + * the following conditions:
1966 + * The above copyright notice and this permission notice (including the
1967 + * next paragraph) shall be included in all copies or substantial
1968 + * portions of the Software.
1970 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1971 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1972 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1973 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1974 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1975 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1976 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1980 +#include <stdlib.h>
1981 +#include <assert.h>
1982 +#include <string.h>
1983 +#include <linux/input.h>
1985 +#include "compositor.h"
1987 +#include "weston.h"
1988 +#include "plugin.h"
1989 +#include "transmitter_api.h"
1990 +#include "plugin-registry.h"
1991 +#include "ivi-layout-export.h"
1995 +#include <sys/epoll.h>
1996 +#include <sys/timerfd.h>
1997 +#include <waltham-object.h>
1998 +#include <waltham-client.h>
1999 +#include <waltham-connection.h>
2001 +#define MAX_EPOLL_WATCHES 2
2002 +#define ESTABLISH_CONNECTION_PERIOD 2000
2003 +#define RETRY_CONNECTION_PERIOD 5000
2005 +/* XXX: all functions and variables with a name, and things marked with a
2006 + * comment, containing the word "fake" are mockups that need to be
2007 + * removed from the final implementation.
2010 +/** Send configure event through ivi-shell.
2012 + * \param txs The Transmitter surface.
2013 + * \param width Suggestion for surface width.
2014 + * \param height Suggestion for surface height.
2016 + * When the networking code receives a ivi_surface.configure event, it calls
2017 + * this function to relay it to the application.
2019 + * \c txs cannot be a zombie, because transmitter_surface_zombify() must
2020 + * tear down the network link, so a zombie cannot receive events.
2023 +transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs,
2024 + int32_t width, int32_t height)
2026 + assert(txs->resize_handler);
2027 + if (!txs->resize_handler)
2030 + assert(txs->surface);
2031 + if (!txs->surface)
2034 + txs->resize_handler(txs->resize_handler_data, width, height);
2038 +transmitter_surface_configure(struct weston_transmitter_surface *txs,
2039 + int32_t dx, int32_t dy)
2041 + assert(txs->surface);
2042 + if (!txs->surface)
2045 + txs->attach_dx += dx;
2046 + txs->attach_dy += dy;
2050 +buffer_send_complete(struct wthp_buffer *b, uint32_t serial)
2053 + wthp_buffer_destroy(b);
2056 +static const struct wthp_buffer_listener buffer_listener = {
2057 + buffer_send_complete
2061 +transmitter_surface_gather_state(struct weston_transmitter_surface *txs)
2063 + struct weston_transmitter_remote *remote = txs->remote;
2064 + struct waltham_display *dpy = remote->display;
2067 + if(!dpy->running) {
2068 + if(remote->status != WESTON_TRANSMITTER_CONNECTION_DISCONNECTED) {
2069 + remote->status = WESTON_TRANSMITTER_CONNECTION_DISCONNECTED;
2070 + wth_connection_destroy(remote->display->connection);
2071 + wl_event_source_remove(remote->source);
2072 + wl_event_source_timer_update(remote->retry_timer, 1);
2076 + /* TODO: transmit surface state to remote */
2077 + /* The buffer must be transmitted to remote side */
2080 + struct weston_surface *surf = txs->surface;
2081 + struct weston_compositor *comp = surf->compositor;
2082 + int32_t stride, data_sz, width, height;
2087 + stride = width * (PIXMAN_FORMAT_BPP(comp->read_format) / 8);
2089 + data = malloc(stride * height);
2090 + data_sz = stride * height;
2092 + /* fake sending buffer */
2093 + txs->wthp_buf = wthp_blob_factory_create_buffer(remote->display->blob_factory,
2099 + PIXMAN_FORMAT_BPP(comp->read_format));
2101 + wthp_buffer_set_listener(txs->wthp_buf, &buffer_listener, txs);
2103 + wthp_surface_attach(txs->wthp_surf, txs->wthp_buf, txs->attach_dx, txs->attach_dy);
2104 + wthp_surface_damage(txs->wthp_surf, txs->attach_dx, txs->attach_dy, surf->width, surf->height);
2105 + wthp_surface_commit(txs->wthp_surf);
2107 + wth_connection_flush(remote->display->connection);
2108 + txs->attach_dx = 0;
2109 + txs->attach_dy = 0;
2113 +/** Mark the weston_transmitter_surface dead.
2115 + * Stop all remoting actions on this surface.
2117 + * Still keeps the pointer stored by a shell valid, so it can be freed later.
2120 +transmitter_surface_zombify(struct weston_transmitter_surface *txs)
2122 + struct weston_transmitter_remote *remote;
2123 + /* may be called multiple times */
2124 + if (!txs->surface)
2127 + wl_signal_emit(&txs->destroy_signal, txs);
2129 + wl_list_remove(&txs->surface_destroy_listener.link);
2130 + txs->surface = NULL;
2132 + wl_list_remove(&txs->sync_output_destroy_listener.link);
2134 + remote = txs->remote;
2135 + if (!remote->display->compositor)
2136 + weston_log("remote->compositor is NULL\n");
2137 + if (txs->wthp_surf)
2138 + wthp_surface_destroy(txs->wthp_surf);
2139 + if (txs->wthp_ivi_surface)
2140 + wthp_ivi_surface_destroy(txs->wthp_ivi_surface);
2142 + /* In case called from destroy_transmitter() */
2143 + txs->remote = NULL;
2147 +transmitter_surface_destroy(struct weston_transmitter_surface *txs)
2149 + transmitter_surface_zombify(txs);
2151 + wl_list_remove(&txs->link);
2155 +/** weston_surface destroy signal handler */
2157 +transmitter_surface_destroyed(struct wl_listener *listener, void *data)
2159 + struct weston_transmitter_surface *txs =
2160 + wl_container_of(listener, txs, surface_destroy_listener);
2162 + assert(data == txs->surface);
2164 + transmitter_surface_zombify(txs);
2168 +sync_output_destroy_handler(struct wl_listener *listener, void *data)
2170 + struct weston_transmitter_surface *txs;
2172 + txs = wl_container_of(listener, txs, sync_output_destroy_listener);
2174 + wl_list_remove(&txs->sync_output_destroy_listener.link);
2175 + wl_list_init(&txs->sync_output_destroy_listener.link);
2177 + weston_surface_force_output(txs->surface, NULL);
2181 +transmitter_surface_set_ivi_id(struct weston_transmitter_surface *txs)
2183 + struct weston_transmitter_remote *remote = txs->remote;
2184 + struct waltham_display *dpy = remote->display;
2185 + struct weston_surface *ws;
2186 + struct ivi_layout_surface **pp_surface = NULL;
2187 + struct ivi_layout_surface *ivi_surf = NULL;
2188 + int32_t surface_length = 0;
2192 + ret = txs->lyt->get_surfaces(&surface_length, &pp_surface);
2194 + weston_log("No ivi_surface\n");
2196 + ws = txs->surface;
2198 + for(i = 0; i < surface_length; i++) {
2199 + ivi_surf = pp_surface[i];
2200 + if (ivi_surf->surface == ws) {
2201 + assert(txs->surface);
2202 + if (!txs->surface)
2205 + weston_log("no content in waltham_display\n");
2206 + if(!dpy->compositor)
2207 + weston_log("no content in compositor object\n");
2209 + weston_log("no content in seat object\n");
2210 + if(!dpy->application)
2211 + weston_log("no content in ivi-application object\n");
2213 + txs->wthp_ivi_surface = wthp_ivi_application_surface_create
2214 + (dpy->application, ivi_surf->id_surface, txs->wthp_surf);
2215 + weston_log("surface ID %d\n", ivi_surf->id_surface);
2216 + if(!txs->wthp_ivi_surface){
2217 + weston_log("Failed to create txs->ivi_surf\n");
2222 + pp_surface = NULL;
2225 +static struct weston_transmitter_surface *
2226 +transmitter_surface_push_to_remote(struct weston_surface *ws,
2227 + struct weston_transmitter_remote *remote,
2228 + struct wl_listener *stream_status)
2230 + struct weston_transmitter *txr = remote->transmitter;
2231 + struct weston_transmitter_surface *txs;
2232 + bool found = false;
2234 + if (remote->status != WESTON_TRANSMITTER_CONNECTION_READY)
2239 + wl_list_for_each(txs, &remote->surface_list, link) {
2240 + if (txs->surface == ws) {
2248 + txs = zalloc(sizeof (*txs));
2252 + txs->remote = remote;
2253 + wl_signal_init(&txs->destroy_signal);
2254 + wl_list_insert(&remote->surface_list, &txs->link);
2256 + txs->status = WESTON_TRANSMITTER_STREAM_INITIALIZING;
2257 + wl_signal_init(&txs->stream_status_signal);
2258 + if (stream_status)
2259 + wl_signal_add(&txs->stream_status_signal, stream_status);
2261 + txs->surface = ws;
2262 + txs->surface_destroy_listener.notify = transmitter_surface_destroyed;
2263 + wl_signal_add(&ws->destroy_signal, &txs->surface_destroy_listener);
2265 + wl_list_init(&txs->sync_output_destroy_listener.link);
2267 + wl_list_init(&txs->frame_callback_list);
2268 + wl_list_init(&txs->feedback_list);
2270 + txs->lyt = weston_plugin_api_get(txr->compositor,
2271 + IVI_LAYOUT_API_NAME, sizeof(txs->lyt));
2274 + /* TODO: create the content stream connection... */
2275 + if (!remote->display->compositor)
2276 + weston_log("remote->compositor is NULL\n");
2277 + if (!txs->wthp_surf) {
2278 + weston_log("txs->wthp_surf is NULL\n");
2279 + txs->wthp_surf = wthp_compositor_create_surface(remote->display->compositor);
2280 + transmitter_surface_set_ivi_id(txs);
2286 +static enum weston_transmitter_stream_status
2287 +transmitter_surface_get_stream_status(struct weston_transmitter_surface *txs)
2289 + return txs->status;
2293 +/* The server advertises a global interface.
2294 + * We can store the ad for later and/or bind to it immediately
2296 + * We also need to keep track of the globals we bind to, so that
2297 + * global_remove can be handled properly (not implemented).
2300 +registry_handle_global(struct wthp_registry *registry,
2302 + const char *interface,
2305 + struct waltham_display *dpy = wth_object_get_user_data((struct wth_object *)registry);
2307 + if (strcmp(interface, "wthp_compositor") == 0) {
2308 + assert(!dpy->compositor);
2309 + dpy->compositor = (struct wthp_compositor *)wthp_registry_bind(registry, name, interface, 1);
2310 + /* has no events to handle */
2311 + } else if (strcmp(interface, "wthp_blob_factory") == 0) {
2312 + assert(!dpy->blob_factory);
2313 + dpy->blob_factory = (struct wthp_blob_factory *)wthp_registry_bind(registry, name, interface, 1);
2314 + /* has no events to handle */
2315 + } else if (strcmp(interface, "wthp_seat") == 0) {
2316 + assert(!dpy->seat);
2317 + dpy->seat = (struct wthp_seat *)wthp_registry_bind(registry, name, interface, 1);
2318 + wthp_seat_set_listener(dpy->seat, &seat_listener, dpy);
2319 + } else if (strcmp(interface, "wthp_ivi_application") == 0) {
2320 + assert(!dpy->application);
2321 + dpy->application = (struct wthp_ivi_application *)wthp_registry_bind(registry, name, interface, 1);
2325 +/* notify connection ready */
2327 +conn_ready_notify(struct wl_listener *l, void *data)
2329 + struct weston_transmitter_remote *remote =
2330 + wl_container_of(l, remote, establish_listener);
2331 + struct weston_transmitter_output_info info = {
2332 + WL_OUTPUT_SUBPIXEL_NONE,
2333 + WL_OUTPUT_TRANSFORM_NORMAL,
2337 + strdup(remote->model),
2339 + WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
2345 + if(remote->width != 0) {
2346 + if(remote->height != 0) {
2347 + info.mode.width = remote->width;
2348 + info.mode.height = remote->height;
2351 + /* Outputs and seats are dynamic, do not guarantee they are all
2352 + * present when signalling connection status.
2354 + transmitter_remote_create_output(remote, &info);
2355 + transmitter_remote_create_seat(remote);
2359 +/* The server removed a global.
2360 + * We should destroy everything we created through that global,
2361 + * and destroy the objects we created by binding to it.
2362 + * The identification happens by global's name, so we need to keep
2363 + * track what names we bound.
2364 + * (not implemented)
2367 +registry_handle_global_remove(struct wthp_registry *wthp_registry,
2370 + if (wthp_registry)
2371 + wthp_registry_free(wthp_registry);
2374 +static const struct wthp_registry_listener registry_listener = {
2375 + registry_handle_global,
2376 + registry_handle_global_remove
2380 +connection_handle_data(struct watch *w, uint32_t events)
2382 + struct waltham_display *dpy = wl_container_of(w, dpy, conn_watch);
2383 + struct weston_transmitter_remote *remote = dpy->remote;
2387 + if (!dpy->running) {
2388 + weston_log("This server is not running yet. %s:%s\n", remote->addr, remote->port);
2392 + if (events & EPOLLERR) {
2393 + weston_log("Connection errored out.\n");
2394 + dpy->running = false;
2395 + remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
2399 + if (events & EPOLLOUT) {
2400 + /* Flush out again. If the flush completes, stop
2401 + * polling for writable as everything has been written.
2403 + ret = wth_connection_flush(dpy->connection);
2406 + if (events & EPOLLIN) {
2407 + /* Do not ignore EPROTO */
2408 + ret = wth_connection_read(dpy->connection);
2411 + weston_log("Connection read error %s:%s\n", remote->addr, remote->port);
2412 + perror("Connection read error\n");
2413 + dpy->running = false;
2414 + remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
2415 + perror("EPOLL_CTL_DEL\n");
2421 + if (events & EPOLLHUP) {
2422 + weston_log("Connection hung up.\n");
2423 + dpy->running = false;
2424 + remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
2431 +waltham_mainloop(int fd, uint32_t mask, void *data)
2433 + struct weston_transmitter_remote *remote = data;
2436 + int running_display;
2437 + running_display = 0;
2439 + struct waltham_display *dpy = remote->display;
2440 + w = &dpy->conn_watch;
2444 + if (!dpy->connection)
2445 + dpy->running = false;
2447 + if (!dpy->running)
2450 + running_display++;
2451 + /* Dispatch queued events. */
2452 + ret = wth_connection_dispatch(dpy->connection);
2454 + dpy->running = false;
2455 + remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
2457 + if (!dpy->running)
2460 + /* Run any application idle tasks at this point. */
2461 + /* (nothing to run so far) */
2463 + /* Flush out buffered requests. If the Waltham socket is
2464 + * full, poll it for writable too, and continue flushing then.
2466 + ret = wth_connection_flush(dpy->connection);
2468 + if (0 < running_display) {
2469 + /* Waltham events only read in the callback, not dispatched,
2470 + * if the Waltham socket signalled readable. If it signalled
2471 + * writable, flush more. See connection_handle_data().
2481 +waltham_client_init(struct waltham_display *dpy)
2486 + * get server_address from controller (adrress is set to weston.ini)
2488 + dpy->connection = wth_connect_to_server(dpy->remote->addr, dpy->remote->port);
2489 + if(!dpy->connection) {
2493 + dpy->remote->status = WESTON_TRANSMITTER_CONNECTION_READY;
2494 + wl_signal_emit(&dpy->remote->connection_status_signal, dpy->remote);
2497 + dpy->conn_watch.display = dpy;
2498 + dpy->conn_watch.cb = connection_handle_data;
2499 + dpy->conn_watch.fd = wth_connection_get_fd(dpy->connection);
2500 + dpy->remote->source = wl_event_loop_add_fd(dpy->remote->transmitter->loop,
2501 + dpy->conn_watch.fd,
2502 + WL_EVENT_READABLE,
2503 + waltham_mainloop, dpy->remote);
2505 + dpy->display = wth_connection_get_display(dpy->connection);
2506 + /* wth_display_set_listener() is already done by waltham, as
2507 + * all the events are just control messaging.
2510 + /* Create a registry so that we will get advertisements of the
2511 + * interfaces implemented by the server.
2513 + dpy->registry = wth_display_get_registry(dpy->display);
2514 + wthp_registry_set_listener(dpy->registry, ®istry_listener, dpy);
2516 + /* Roundtrip ensures all globals' ads have been received. */
2517 + if (wth_connection_roundtrip(dpy->connection) < 0) {
2518 + weston_log("Roundtrip failed.\n");
2522 + if (!dpy->compositor) {
2523 + weston_log("Did not find wthp_compositor, quitting.\n");
2527 + dpy->running = true;
2533 +establish_timer_handler(void *data)
2535 + struct weston_transmitter_remote *remote = data;
2538 + ret = waltham_client_init(remote->display);
2540 + wl_event_source_timer_update(remote->establish_timer,
2541 + ESTABLISH_CONNECTION_PERIOD);
2544 + remote->status = WESTON_TRANSMITTER_CONNECTION_READY;
2545 + wl_signal_emit(&remote->connection_status_signal, remote);
2550 +init_globals(struct waltham_display *dpy)
2552 + dpy->compositor = NULL;
2553 + dpy->blob_factory = NULL;
2555 + dpy->application = NULL;
2556 + dpy->pointer = NULL;
2557 + dpy->keyboard = NULL;
2558 + dpy->touch = NULL;
2562 +disconnect_surface(struct weston_transmitter_remote *remote)
2564 + struct weston_transmitter_surface *txs;
2565 + wl_list_for_each(txs, &remote->surface_list, link)
2567 + free(txs->wthp_ivi_surface);
2568 + txs->wthp_ivi_surface = NULL;
2569 + free(txs->wthp_surf);
2570 + txs->wthp_surf = NULL;
2575 +retry_timer_handler(void *data)
2577 + struct weston_transmitter_remote *remote = data;
2578 + struct waltham_display *dpy = remote->display;
2582 + registry_handle_global_remove(dpy->registry, 1);
2583 + init_globals(dpy);
2584 + disconnect_surface(remote);
2585 + wl_event_source_timer_update(remote->establish_timer,
2586 + ESTABLISH_CONNECTION_PERIOD);
2591 + wl_event_source_timer_update(remote->retry_timer,
2592 + RETRY_CONNECTION_PERIOD);
2596 +static struct weston_transmitter_remote *
2597 +transmitter_connect_to_remote(struct weston_transmitter *txr)
2599 + struct weston_transmitter_remote *remote;
2600 + struct wl_event_loop *loop_est, *loop_retry;
2603 + wl_list_for_each_reverse(remote, &txr->remote_list, link) {
2604 + /* XXX: actually start connecting */
2606 + remote->display = zalloc(sizeof *remote->display);
2607 + if (!remote->display)
2609 + remote->display->remote = remote;
2610 + /* set connection establish timer */
2611 + loop_est = wl_display_get_event_loop(txr->compositor->wl_display);
2612 + remote->establish_timer =
2613 + wl_event_loop_add_timer(loop_est, establish_timer_handler, remote);
2614 + wl_event_source_timer_update(remote->establish_timer, 1);
2615 + /* set connection retry timer */
2616 + loop_retry = wl_display_get_event_loop(txr->compositor->wl_display);
2617 + remote->retry_timer =
2618 + wl_event_loop_add_timer(loop_retry, retry_timer_handler, remote);
2620 + weston_log("Fatal: Transmitter waltham connecting failed.\n");
2623 + wl_signal_emit(&remote->conn_establish_signal, NULL);
2629 +static enum weston_transmitter_connection_status
2630 +transmitter_remote_get_status(struct weston_transmitter_remote *remote)
2632 + return remote->status;
2636 +transmitter_remote_destroy(struct weston_transmitter_remote *remote)
2638 + struct weston_transmitter_surface *txs;
2639 + struct weston_transmitter_output *output, *otmp;
2640 + struct weston_transmitter_seat *seat, *stmp;
2642 + /* Do not emit connection_status_signal. */
2645 + * Must not touch remote->transmitter as it may be stale:
2646 + * the desctruction order between the shell and Transmitter is
2650 + if (!wl_list_empty(&remote->surface_list))
2651 + weston_log("Transmitter warning: surfaces remain in %s.\n",
2653 + wl_list_for_each(txs, &remote->surface_list, link)
2654 + txs->remote = NULL;
2655 + wl_list_remove(&remote->surface_list);
2657 + wl_list_for_each_safe(seat, stmp, &remote->seat_list, link)
2658 + transmitter_seat_destroy(seat);
2660 + wl_list_for_each_safe(output, otmp, &remote->output_list, link)
2661 + transmitter_output_destroy(output);
2663 + free(remote->addr);
2664 + wl_list_remove(&remote->link);
2666 + wl_event_source_remove(remote->source);
2671 +/** Transmitter is destroyed on compositor shutdown. */
2673 +transmitter_compositor_destroyed(struct wl_listener *listener, void *data)
2675 + struct weston_transmitter_remote *remote;
2676 + struct weston_transmitter_surface *txs;
2677 + struct weston_transmitter *txr =
2678 + wl_container_of(listener, txr, compositor_destroy_listener);
2680 + assert(data == txr->compositor);
2682 + /* may be called before or after shell cleans up */
2683 + wl_list_for_each(remote, &txr->remote_list, link) {
2684 + wl_list_for_each(txs, &remote->surface_list, link) {
2685 + transmitter_surface_zombify(txs);
2690 + * Remove the head in case the list is not empty, to avoid
2691 + * transmitter_remote_destroy() accessing freed memory if the shell
2692 + * cleans up after Transmitter.
2694 + wl_list_remove(&txr->remote_list);
2699 +static struct weston_transmitter *
2700 +transmitter_get(struct weston_compositor *compositor)
2702 + struct wl_listener *listener;
2703 + struct weston_transmitter *txr;
2705 + listener = wl_signal_get(&compositor->destroy_signal,
2706 + transmitter_compositor_destroyed);
2710 + txr = wl_container_of(listener, txr, compositor_destroy_listener);
2711 + assert(compositor == txr->compositor);
2717 +transmitter_register_connection_status(struct weston_transmitter *txr,
2718 + struct wl_listener *connected_listener)
2720 + wl_signal_add(&txr->connected_signal, connected_listener);
2723 +static struct weston_surface *
2724 +transmitter_get_weston_surface(struct weston_transmitter_surface *txs)
2726 + return txs->surface;
2729 +static const struct weston_transmitter_api transmitter_api_impl = {
2731 + transmitter_connect_to_remote,
2732 + transmitter_remote_get_status,
2733 + transmitter_remote_destroy,
2734 + transmitter_surface_push_to_remote,
2735 + transmitter_surface_get_stream_status,
2736 + transmitter_surface_destroy,
2737 + transmitter_surface_configure,
2738 + transmitter_surface_gather_state,
2739 + transmitter_register_connection_status,
2740 + transmitter_get_weston_surface,
2744 +transmitter_surface_set_resize_callback(
2745 + struct weston_transmitter_surface *txs,
2746 + weston_transmitter_ivi_resize_handler_t cb,
2749 + txs->resize_handler = cb;
2750 + txs->resize_handler_data = data;
2753 +static const struct weston_transmitter_ivi_api transmitter_ivi_api_impl = {
2754 + transmitter_surface_set_resize_callback,
2758 +transmitter_create_remote(struct weston_transmitter *txr,
2759 + const char *model,
2762 + const char *width,
2763 + const char *height)
2765 + struct weston_transmitter_remote *remote;
2767 + remote = zalloc(sizeof (*remote));
2771 + remote->transmitter = txr;
2772 + wl_list_insert(&txr->remote_list, &remote->link);
2773 + remote->model = strdup(model);
2774 + remote->addr = strdup(addr);
2775 + remote->port = strdup(port);
2776 + remote->width = atoi(width);
2777 + remote->height = atoi(height);
2778 + remote->status = WESTON_TRANSMITTER_CONNECTION_INITIALIZING;
2779 + wl_signal_init(&remote->connection_status_signal);
2780 + wl_list_init(&remote->output_list);
2781 + wl_list_init(&remote->surface_list);
2782 + wl_list_init(&remote->seat_list);
2783 + wl_signal_init(&remote->conn_establish_signal);
2784 + remote->establish_listener.notify = conn_ready_notify;
2785 + wl_signal_add(&remote->conn_establish_signal, &remote->establish_listener);
2790 +struct wet_compositor {
2791 + struct weston_config *config;
2792 + struct wet_output_config *parsed_options;
2793 + struct wl_listener pending_output_listener;
2794 + bool drm_use_current_mode;
2798 +transmitter_get_server_config(struct weston_transmitter *txr)
2800 + struct wet_compositor *compositor =
2801 + (struct wet_compositor *)weston_compositor_get_user_data(txr->compositor);
2802 + struct weston_config *config = wet_get_config(txr->compositor);
2803 + struct weston_config_section *section;
2804 + const char *name = NULL;
2805 + char *model = NULL;
2806 + char *addr = NULL;
2807 + char *port = NULL;
2808 + char *width = '0';
2809 + char *height = '0';
2812 + section = weston_config_get_section(config, "remote", NULL, NULL);
2814 + while (weston_config_next_section(config, §ion, &name)) {
2815 + if (0 == strcmp(name, "remote-output")) {
2816 + if (0 != weston_config_section_get_string(section, "output-name",
2820 + if (0 != weston_config_section_get_string(section, "server-address",
2824 + if (0 != weston_config_section_get_string(section, "port",
2828 + if (0 != weston_config_section_get_string(section, "width",
2832 + if (0 != weston_config_section_get_string(section, "height",
2835 + ret = transmitter_create_remote(txr, model, addr,
2836 + port, width, height);
2838 + weston_log("Fatal: Transmitter create_remote failed.\n");
2845 +wet_module_init(struct weston_compositor *compositor, int *argc, char *argv[])
2847 + struct weston_transmitter *txr;
2850 + txr = zalloc(sizeof *txr);
2852 + weston_log("Transmitter disabled\n");
2855 + wl_list_init(&txr->remote_list);
2857 + txr->compositor = compositor;
2858 + txr->compositor_destroy_listener.notify =
2859 + transmitter_compositor_destroyed;
2860 + wl_signal_add(&compositor->destroy_signal,
2861 + &txr->compositor_destroy_listener);
2863 + ret = weston_plugin_api_register(compositor,
2864 + WESTON_TRANSMITTER_API_NAME,
2865 + &transmitter_api_impl,
2866 + sizeof(transmitter_api_impl));
2868 + weston_log("Fatal: Transmitter API registration failed.\n");
2872 + ret = weston_plugin_api_register(compositor,
2873 + WESTON_TRANSMITTER_IVI_API_NAME,
2874 + &transmitter_ivi_api_impl,
2875 + sizeof(transmitter_ivi_api_impl));
2877 + weston_log("Fatal: Transmitter IVI API registration failed.\n");
2881 + weston_log("Transmitter initialized.\n");
2883 + txr->loop = wl_display_get_event_loop(compositor->wl_display);
2884 + transmitter_get_server_config(txr);
2885 + transmitter_connect_to_remote(txr);
2890 + wl_list_remove(&txr->compositor_destroy_listener.link);
2895 diff --git a/waltham-transmitter/transmitter-plugin/plugin.h b/waltham-transmitter/transmitter-plugin/plugin.h
2896 new file mode 100644
2897 index 0000000..a473dab
2899 +++ b/waltham-transmitter/transmitter-plugin/plugin.h
2902 + * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
2904 + * Permission is hereby granted, free of charge, to any person obtaining
2905 + * a copy of this software and associated documentation files (the
2906 + * "Software"), to deal in the Software without restriction, including
2907 + * without limitation the rights to use, copy, modify, merge, publish,
2908 + * distribute, sublicense, and/or sell copies of the Software, and to
2909 + * permit persons to whom the Software is furnished to do so, subject to
2910 + * the following conditions:
2912 + * The above copyright notice and this permission notice (including the
2913 + * next paragraph) shall be included in all copies or substantial
2914 + * portions of the Software.
2916 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2917 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2918 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2919 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2920 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2921 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2922 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2926 +#ifndef WESTON_TRANSMITTER_PLUGIN_H
2927 +#define WESTON_TRANSMITTER_PLUGIN_H
2929 +/* XXX: all functions and variables with a name, and things marked with a
2930 + * comment, containing the word "fake" are mockups that need to be
2931 + * removed from the final implementation.
2934 +#include <stdint.h>
2935 +#include <wayland-client.h>
2937 +#include "compositor.h"
2938 +#include "transmitter_api.h"
2939 +#include "ivi-layout-export.h"
2941 +#include <waltham-client.h>
2944 +struct waltham_display;
2946 +enum wthp_seat_capability {
2948 + * the seat has pointer devices
2950 + WTHP_SEAT_CAPABILITY_POINTER = 1,
2952 + * the seat has one or more keyboards
2954 + WTHP_SEAT_CAPABILITY_KEYBOARD = 2,
2956 + * the seat has touch devices
2958 + WTHP_SEAT_CAPABILITY_TOUCH = 4,
2961 +/* epoll structure */
2963 + struct waltham_display *display;
2965 + void (*cb)(struct watch *w, uint32_t events);
2968 +struct waltham_display {
2969 + struct wth_connection *connection;
2970 + struct watch conn_watch;
2971 + struct wth_display *display;
2975 + struct wthp_registry *registry;
2977 + struct wthp_callback *bling;
2979 + struct wthp_compositor *compositor;
2980 + struct wthp_blob_factory *blob_factory;
2981 + struct wthp_seat *seat;
2982 + struct wthp_pointer *pointer;
2983 + struct wthp_keyboard *keyboard;
2984 + struct wthp_touch *touch;
2985 + struct wthp_ivi_application *application;
2986 + struct wtimer *fiddle_timer;
2988 + struct weston_transmitter_remote *remote;
2993 +/* a timerfd based timer */
2995 + struct watch watch;
2996 + void (*func)(struct wtimer *, void *);
3000 +struct weston_transmitter {
3001 + struct weston_compositor *compositor;
3002 + struct wl_listener compositor_destroy_listener;
3004 + struct wl_list remote_list; /* transmitter_remote::link */
3006 + struct wl_listener stream_listener;
3007 + struct wl_signal connected_signal;
3008 + struct wl_event_loop *loop;
3011 +struct weston_transmitter_remote {
3012 + struct weston_transmitter *transmitter;
3013 + struct wl_list link;
3020 + enum weston_transmitter_connection_status status;
3021 + struct wl_signal connection_status_signal;
3022 + struct wl_signal conn_establish_signal;
3024 + struct wl_list output_list; /* weston_transmitter_output::link */
3025 + struct wl_list surface_list; /* weston_transmitter_surface::link */
3026 + struct wl_list seat_list; /* weston_transmitter_seat::link */
3028 + struct wl_listener establish_listener;
3030 + struct wl_event_source *establish_timer; /* for establish connection */
3031 + struct wl_event_source *retry_timer; /* for retry connection */
3033 + struct waltham_display *display; /* waltham */
3034 + struct wl_event_source *source;
3038 +struct weston_transmitter_surface {
3039 + struct weston_transmitter_remote *remote;
3040 + struct wl_list link; /* weston_transmitter_remote::surface_list */
3041 + struct wl_signal destroy_signal; /* data: weston_transmitter_surface */
3043 + enum weston_transmitter_stream_status status;
3044 + struct wl_signal stream_status_signal;
3046 + struct weston_surface *surface;
3047 + struct wl_listener surface_destroy_listener;
3048 + const struct ivi_layout_interface *lyt;
3050 + weston_transmitter_ivi_resize_handler_t resize_handler;
3051 + void *resize_handler_data;
3053 + struct weston_output *sync_output;
3054 + struct wl_listener sync_output_destroy_listener;
3056 + int32_t attach_dx; /**< wl_surface.attach(buffer, dx, dy) */
3057 + int32_t attach_dy; /**< wl_surface.attach(buffer, dx, dy) */
3058 + struct wl_list frame_callback_list; /* weston_frame_callback::link */
3059 + struct wl_list feedback_list; /* weston_presentation_feedback::link */
3062 + struct wthp_surface *wthp_surf;
3063 + struct wthp_blob_factory *wthp_blob;
3064 + struct wthp_buffer *wthp_buf;
3065 + struct wthp_ivi_surface *wthp_ivi_surface;
3066 + struct wthp_ivi_application *wthp_ivi_application;
3069 +struct weston_transmitter_output_info {
3070 + uint32_t subpixel; /* enum wl_output_subpixel */
3071 + uint32_t transform; /* enum wl_output_transform */
3076 + int32_t height_mm;
3077 + /* char *make; is WESTON_TRANSMITTER_OUTPUT_MAKE */
3080 + struct weston_mode mode;
3083 +struct weston_transmitter_output {
3084 + struct weston_output base;
3087 + bool draw_initial_frame;
3088 + struct wl_surface *surface;
3089 + struct wl_output *output;
3090 + struct wl_display *display;
3091 + int configure_width, configure_height;
3092 + bool wait_for_configure;
3095 + struct weston_transmitter_remote *remote;
3096 + struct wl_list link; /* weston_transmitter_remote::output_list */
3098 + struct frame *frame;
3100 + struct wl_callback *frame_cb;
3101 + struct renderer *renderer;
3104 +struct weston_transmitter_seat {
3105 + struct weston_seat *base;
3106 + struct wl_list link;
3109 + wl_fixed_t pointer_surface_x;
3110 + wl_fixed_t pointer_surface_y;
3112 + struct wl_listener get_pointer_listener;
3113 + struct weston_transmitter_surface *pointer_focus;
3114 + struct wl_listener pointer_focus_destroy_listener;
3116 + struct wl_event_source *pointer_timer; /* fake */
3118 + double pointer_phase; /* fake */
3121 + struct weston_transmitter_surface *keyboard_focus;
3124 + struct weston_transmitter_surface *touch_focus;
3127 +struct ivi_layout_surface {
3128 + struct wl_list link; /* ivi_layout::surface_list */
3129 + struct wl_signal property_changed;
3130 + int32_t update_count;
3131 + uint32_t id_surface;
3133 + struct ivi_layout *layout;
3134 + struct weston_surface *surface;
3136 + struct ivi_layout_surface_properties prop;
3139 + struct ivi_layout_surface_properties prop;
3142 + struct wl_list view_list; /* ivi_layout_view::surf_link */
3146 +transmitter_surface_ivi_resize(struct weston_transmitter_surface *txs,
3147 + int32_t width, int32_t height);
3150 +transmitter_remote_create_output(struct weston_transmitter_remote *remote,
3151 + const struct weston_transmitter_output_info *info);
3154 +transmitter_output_destroy(struct weston_transmitter_output *output);
3157 +transmitter_remote_create_seat(struct weston_transmitter_remote *remote);
3160 +transmitter_seat_destroy(struct weston_transmitter_seat *seat);
3162 +/* The below are the functions to be called from the network protocol
3163 + * input event handlers.
3167 +transmitter_seat_pointer_enter(struct weston_transmitter_seat *seat,
3169 + struct weston_transmitter_surface *txs,
3170 + wl_fixed_t surface_x,
3171 + wl_fixed_t surface_y);
3174 +transmitter_seat_pointer_leave(struct weston_transmitter_seat *seat,
3176 + struct weston_transmitter_surface *txs);
3179 +transmitter_seat_pointer_motion(struct weston_transmitter_seat *seat,
3181 + wl_fixed_t surface_x,
3182 + wl_fixed_t surface_y);
3185 +transmitter_seat_pointer_button(struct weston_transmitter_seat *seat,
3192 +transmitter_seat_pointer_axis(struct weston_transmitter_seat *seat,
3195 + wl_fixed_t value);
3198 +transmitter_seat_pointer_frame(struct weston_transmitter_seat *seat);
3201 +transmitter_seat_pointer_axis_source(struct weston_transmitter_seat *seat,
3202 + uint32_t axis_source);
3205 +transmitter_seat_pointer_axis_stop(struct weston_transmitter_seat *seat,
3210 +transmitter_seat_pointer_axis_discrete(struct weston_transmitter_seat *seat,
3212 + int32_t discrete);
3214 +/* Fake functions for mockup testing: */
3217 +transmitter_seat_fake_pointer_input(struct weston_transmitter_seat *seat,
3218 + struct weston_transmitter_surface *txs);
3221 +seat_capabilities(struct wthp_seat *wthp_seat,
3222 + enum wthp_seat_capability caps);
3224 +static const struct wthp_seat_listener seat_listener = {
3225 + seat_capabilities,
3230 +#endif /* WESTON_TRANSMITTER_PLUGIN_H */
3231 diff --git a/waltham-transmitter/transmitter-plugin/transmitter_api.h b/waltham-transmitter/transmitter-plugin/transmitter_api.h
3232 new file mode 100644
3233 index 0000000..9b3e5fe
3235 +++ b/waltham-transmitter/transmitter-plugin/transmitter_api.h
3238 + * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
3240 + * Permission is hereby granted, free of charge, to any person obtaining
3241 + * a copy of this software and associated documentation files (the
3242 + * "Software"), to deal in the Software without restriction, including
3243 + * without limitation the rights to use, copy, modify, merge, publish,
3244 + * distribute, sublicense, and/or sell copies of the Software, and to
3245 + * permit persons to whom the Software is furnished to do so, subject to
3246 + * the following conditions:
3248 + * The above copyright notice and this permission notice (including the
3249 + * next paragraph) shall be included in all copies or substantial
3250 + * portions of the Software.
3252 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3253 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3254 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3255 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3256 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3257 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3258 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3262 +#ifndef WESTON_TRANSMITTER_API_H
3263 +#define WESTON_TRANSMITTER_API_H
3265 +#include "plugin-registry.h"
3267 +#include <stdint.h>
3271 + * This is the Transmitter API published via weston_plugin_api_register().
3274 +struct weston_transmitter;
3275 +struct weston_transmitter_remote;
3276 +struct weston_transmitter_surface;
3278 +#define WESTON_TRANSMITTER_API_NAME "transmitter_v1"
3280 +/** See weston_transmitter_api::remote_get_status */
3281 +enum weston_transmitter_connection_status {
3282 + /** The connection hand-shake is not yet complete */
3283 + WESTON_TRANSMITTER_CONNECTION_INITIALIZING,
3285 + /** The connection is live and ready to be used. */
3286 + WESTON_TRANSMITTER_CONNECTION_READY,
3288 + /** The connection is dead. */
3289 + WESTON_TRANSMITTER_CONNECTION_DISCONNECTED,
3292 +/** See weston_transmitter_api::surface_get_stream_status */
3293 +enum weston_transmitter_stream_status {
3294 + /** The stream hand-shake is not yet complete. */
3295 + WESTON_TRANSMITTER_STREAM_INITIALIZING,
3297 + /** The stream is carrying surface content updates as needed. */
3298 + WESTON_TRANSMITTER_STREAM_LIVE,
3300 + /** The stream has failed and disconnected permanently. */
3301 + WESTON_TRANSMITTER_STREAM_FAILED,
3304 +/** The Transmitter Base API
3306 + * Transmitter is a Weston plugin that provides remoting of weston_surfaces
3307 + * over the network. Shells use this API to create remote connections and
3308 + * push surfaces over the network. Shells are also responsible for relaying
3309 + * basic window state changes to Transmitter.
3311 + * In addition to the Transmitter Base API, shells also need to use a
3312 + * shell protocol specific Transmitter API to relay specific window state
3315 +struct weston_transmitter_api {
3316 + /** Fetch the Transmitter plugin context
3318 + * \param compositor The compositor instance.
3319 + * \return The weston_transmitter context, which is always the same
3320 + * for the given compositor instance.
3322 + struct weston_transmitter *
3323 + (*transmitter_get)(struct weston_compositor *compositor);
3326 + * Connect to a remote server via Transmitter.
3328 + * \param txr The Transmitter context.
3329 + * \param status Listener to inform of connection status changes.
3330 + * \return A handle to the remote connection, or NULL on failure.
3332 + * This call attempts to open a connection asynchronously. The
3333 + * connection is not usable until the listener signals it is ready.
3334 + * The listener may also signal that the connection failed instead.
3336 + * The listener callback argument is the weston_transmitter_remote
3337 + * returned by this function. Use remote_get_status() to fetch the
3341 + struct weston_transmitter_remote *
3342 + (*connect_to_remote)(struct weston_transmitter *txr);
3345 + * Retrieve the connection status.
3347 + * If the status is WESTON_TRANSMITTER_CONNECTION_DISCONNECTED,
3348 + * you have to shut the remote down completely. There is no automatic
3351 + enum weston_transmitter_connection_status
3352 + (*remote_get_status)(struct weston_transmitter_remote *remote);
3355 + * Destroy/disconnect a remote connection.
3357 + * Disconnects if connected, and destroys the connection.
3358 + * The connection status handler is not called.
3360 + * The caller is responsible for destroying all
3361 + * weston_transmitter_surfaces before calling this.
3364 + (*remote_destroy)(struct weston_transmitter_remote *remote);
3366 + /** Push a weston_surface to be transmitted to a remote.
3368 + * \param ws The surface to push.
3369 + * \param remote The remote connection to use.
3370 + * \param stream_status Listener for stream status changes.
3371 + * \return The Transmitter surface handle.
3373 + * The surface cannot be visible on the remote until the stream
3374 + * status listener signals WESTON_TRANSMITTER_STREAM_LIVE. After that,
3375 + * surface updates made by the application will be automatically
3376 + * streamed to the remote, and input events from the remote will be
3377 + * delivered to the application.
3379 + * The listener callback argument is the weston_transmitter_surface
3380 + * returned by this function. Use surface_get_stream_status() to
3381 + * fetch the current status.
3383 + struct weston_transmitter_surface *
3384 + (*surface_push_to_remote)(struct weston_surface *ws,
3385 + struct weston_transmitter_remote *remote,
3386 + struct wl_listener *stream_status);
3389 + * Retrieve the surface content stream status.
3391 + * If the status is WESTON_TRANSMITTER_STREAM_FAILED, remoting the
3392 + * surface has stopped. There is no automatic retry.
3394 + enum weston_transmitter_stream_status
3395 + (*surface_get_stream_status)(struct weston_transmitter_surface *txs);
3397 + /** Stop remoting a weston_surface
3399 + * \param txs Transmitter surface handle to be stopped and freed.
3401 + * The surface stream status handler is not called.
3404 + (*surface_destroy)(struct weston_transmitter_surface *txs);
3406 + /** Notify of weston_surface being configured
3408 + * \param txs The Transmitter surface handle.
3409 + * \param dx The x delta given in wl_surface.attach request.
3410 + * \param dy The y delta given in wl_surface.attach request.
3412 + * Notifies Transmitter of new surface confguration. Transmitter will
3413 + * forward the arguments, window state, and reference the buffer for
3414 + * image transmission.
3416 + * Shells are meant to call this function for remoted surfaces in
3417 + * the weston_surface::configure handler.
3419 + * XXX: Is this necessary if we have weston_surface::apply_state_signal?
3421 + * Essentially this is just an elaborate way to forward dx,dy.
3424 + (*surface_configure)(struct weston_transmitter_surface *txs,
3425 + int32_t dx, int32_t dy);
3428 + (*surface_gather_state)(struct weston_transmitter_surface *txs);
3430 + /** Notify that surface is connected to receiver
3432 + * \param txr The Transmitter context.
3433 + * \param connected_listener Listener for connected_signal.
3436 + (*register_connection_status)(struct weston_transmitter *txr,
3437 + struct wl_listener *connected_listener);
3439 + /** get weston_surface from weston_transmitter_surface
3441 + * \param txs The Transmitter surface.
3443 + struct weston_surface *
3444 + (*get_weston_surface)(struct weston_transmitter_surface *txs);
3447 +static inline const struct weston_transmitter_api *
3448 +weston_get_transmitter_api(struct weston_compositor *compositor)
3450 + return weston_plugin_api_get(compositor, WESTON_TRANSMITTER_API_NAME,
3451 + sizeof(struct weston_transmitter_api));
3454 +#define WESTON_TRANSMITTER_IVI_API_NAME "transmitter_ivi_v1"
3456 +/** For relaying configure events from Transmitter to shell. */
3457 +typedef void (*weston_transmitter_ivi_resize_handler_t)(void *data,
3461 +/** The Transmitter IVI-shell API
3463 + * Contains the IVI-shell specifics required to remote an ivi-surface.
3465 +struct weston_transmitter_ivi_api {
3466 + /** Set IVI-id for a transmitter surface
3468 + * \param txs The transmitted surface.
3469 + * \param ivi_id The IVI-surface id as specified by the
3470 + * ivi_application.surface_create request.
3473 + (*set_ivi_id)(struct weston_transmitter_surface *txs, uint32_t ivi_id);
3475 + /** Set callback to relay configure events.
3477 + * \param txs The transmitted surface.
3478 + * \param cb The callback function pointer.
3479 + * \param data User data to be passed to the callback.
3481 + * The arguments to the callback function are user data, and width and
3482 + * height from the configure event from the remote compositor. The
3483 + * shell must relay this event to the application.
3486 + (*set_resize_callback)(struct weston_transmitter_surface *txs,
3487 + weston_transmitter_ivi_resize_handler_t cb,
3491 +static inline const struct weston_transmitter_ivi_api *
3492 +weston_get_transmitter_ivi_api(struct weston_compositor *compositor)
3494 + return weston_plugin_api_get(compositor,
3495 + WESTON_TRANSMITTER_IVI_API_NAME,
3496 + sizeof(struct weston_transmitter_ivi_api));
3499 +/** Identifies outputs created by the Transmitter by make */
3500 +#define WESTON_TRANSMITTER_OUTPUT_MAKE "Weston-Transmitter"
3502 +/* Remote compositor/output are identified by model */
3506 + void (*repaint_output)(struct weston_output *base);
3507 + struct GstAppContext *ctx;
3508 + int32_t dmafd; /* dmafd received from compositor-drm */
3509 + int surface_width;
3510 + int surface_height;
3511 + bool recorder_enabled;
3514 +#endif /* WESTON_TRANSMITTER_API_H */
3515 diff --git a/waltham-transmitter/transmitter-plugin/weston.ini.transmitter b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter
3516 new file mode 100644
3517 index 0000000..1aff0b2
3519 +++ b/waltham-transmitter/transmitter-plugin/weston.ini.transmitter
3523 +modules=transmitter.so
3526 +ivi-module=ivi-controller.so
3527 +ivi-input-module=ivi-input-controller.so
3530 +output-name=transmitter_1
3531 +server-address=192.168.2.11
3537 +output-name=transmitter_2
3538 +server-address=192.168.2.12
3542 diff --git a/waltham-transmitter/waltham-renderer/CMakeLists.txt b/waltham-transmitter/waltham-renderer/CMakeLists.txt
3543 new file mode 100644
3544 index 0000000..abf1a4c
3546 +++ b/waltham-transmitter/waltham-renderer/CMakeLists.txt
3548 +project (waltham-renderer)
3550 +find_package(PkgConfig REQUIRED)
3551 +pkg_check_modules(WAYLAND_SERVER wayland-server>=1.13.0 REQUIRED)
3552 +pkg_check_modules(WESTON weston>=2.0.0 REQUIRED)
3553 +pkg_check_modules(PIXMAN pixman-1 REQUIRED)
3554 +pkg_check_modules(WALTHAM waltham REQUIRED)
3555 +pkg_search_module(GSTREAMER gstreamer-1.0 required)
3556 +pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required)
3558 +include_directories(
3559 + ${CMAKE_SOURCE_DIR}/waltham-transmitter/transmitter-plugin
3560 + ${CMAKE_CURRENT_BINARY_DIR}
3561 + ${WAYLAND_CLIENT_INCLUDE_DIRS}
3562 + ${WAYLAND_SERVER_INCLUDE_DIRS}
3563 + ${WESTON_INCLUDE_DIRS}
3564 + ${PIXMAN_INCLUDE_DIRS}
3565 + ${WALTHAM_INCLUDE_DIRS}
3566 + ${GSTREAMER_INCLUDE_DIRS}
3567 + ${GSTREAMERAPP_INCLUDE_DIRS}
3571 + ${WAYLAND_SERVER_LIBRARY_DIRS}
3572 + ${WESTON_LIBRARY_DIRS}
3573 + ${PIXMAN_LIBRARY_DIRS}
3574 + ${WALTHAM_LIBRARY_DIRS}
3575 + ${GSTREAMER_LIBRARY_DIRS}
3576 + ${GSTREAMERAPP_LIBRARY_DIRS}
3579 +add_library(${PROJECT_NAME} MODULE
3580 + waltham-renderer.c
3581 + waltham-renderer.h
3584 +set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
3591 + ${WAYLAND_SERVER_LIBRARIES}
3592 + ${WESTON_LIBRARIES}
3593 + ${PIXMAN_LIBRARIES}
3594 + ${WALTHAM_LIBRARIES}
3595 + ${GSTREAMER_LIBRARIES}
3596 + ${GSTREAMERAPP_LIBRARIES}
3599 +add_dependencies(${PROJECT_NAME} ${LIBS})
3601 +target_link_libraries(${PROJECT_NAME} ${LIBS})
3604 + TARGETS ${PROJECT_NAME}
3605 + LIBRARY DESTINATION lib64/libweston-2
3607 diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.c b/waltham-transmitter/waltham-renderer/waltham-renderer.c
3608 new file mode 100644
3609 index 0000000..16ad3f8
3611 +++ b/waltham-transmitter/waltham-renderer/waltham-renderer.c
3614 + * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
3616 + * Permission is hereby granted, free of charge, to any person obtaining
3617 + * a copy of this software and associated documentation files (the
3618 + * "Software"), to deal in the Software without restriction, including
3619 + * without limitation the rights to use, copy, modify, merge, publish,
3620 + * distribute, sublicense, and/or sell copies of the Software, and to
3621 + * permit persons to whom the Software is furnished to do so, subject to
3622 + * the following conditions:
3624 + * The above copyright notice and this permission notice (including the
3625 + * next paragraph) shall be included in all copies or substantial
3626 + * portions of the Software.
3628 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3629 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3630 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3631 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3632 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3633 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3634 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3638 +#include <stdlib.h>
3639 +#include <assert.h>
3640 +#include <string.h>
3642 +#include <gst/gst.h>
3643 +#include <gst/video/gstvideometa.h>
3644 +#include <gst/allocators/gstdmabuf.h>
3645 +#include <gst/app/gstappsrc.h>
3647 +#include "compositor.h"
3649 +#include "transmitter_api.h"
3650 +#include "waltham-renderer.h"
3651 +#include "plugin.h"
3653 +struct waltham_renderer {
3654 + struct renderer base;
3657 +struct GstAppContext
3661 + GstElement *pipeline;
3662 + GstElement *appsrc;
3663 + GstBuffer *gstbuffer;
3666 +gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p)
3668 + struct GstAppContext *gstctx = p;
3670 + switch( GST_MESSAGE_TYPE(message)) {
3671 + case GST_MESSAGE_ERROR:
3676 + gst_message_parse_error(message, &err, &debug);
3677 + g_print("ERROR: %s\n", err->message);
3679 + g_error_free(err);
3681 + g_main_loop_quit(gstctx->loop);
3685 + case GST_MESSAGE_STATE_CHANGED:
3687 + GstState oldstate, newstate;
3689 + gst_message_parse_state_changed(message, &oldstate, &newstate, NULL);
3690 + switch (newstate){
3691 + case GST_STATE_NULL:
3692 + fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message));
3697 + fprintf(stderr, "Unhandled message\n");
3703 +gst_pipe_init(struct weston_transmitter_output *output, struct gst_settings *settings)
3705 + struct GstAppContext *gstctx;
3706 + gstctx=zalloc(sizeof (*gstctx));
3708 + weston_log("Enable to allocate memory\n");
3713 + GError *gerror = NULL;
3716 + char * pipe = NULL;
3719 + /* create gstreamer pipeline */
3720 + gst_init(NULL, NULL);
3721 + gstctx->loop = g_main_loop_new(NULL, FALSE);
3723 + /* read pipeline from file */
3724 + pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" );
3727 + weston_log("File open error\n");
3731 + /* obtain file size */
3732 + fseek (pFile , 0 , SEEK_END);
3733 + lSize = ftell (pFile);
3736 + /* allocate memory to contain the whole file: */
3737 + pipe = (char*) zalloc (sizeof(char)*lSize);
3740 + weston_log("Cannot allocate memory\n");
3744 + /* copy the file into the buffer: */
3745 + res = fread (pipe,1,lSize,pFile);
3748 + weston_log("File read error\n");
3754 + weston_log("Parsing GST pipeline:%s",pipe);
3755 + gstctx->pipeline = gst_parse_launch(pipe, &gerror);
3757 + if(!gstctx->pipeline)
3758 + weston_log("Could not create gstreamer pipeline.\n");
3760 + gstctx->bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx->pipeline));
3761 + gst_bus_add_watch(gstctx->bus, bus_message, &gstctx);
3763 + gstctx->appsrc = (GstAppSrc*)
3764 + gst_bin_get_by_name(GST_BIN(gstctx->pipeline), "src");
3765 + if (!gstctx->appsrc)
3768 + caps = gst_caps_new_simple("video/x-raw",
3769 + "format", G_TYPE_STRING, "BGRx",
3770 + "width", G_TYPE_INT, settings->width,
3771 + "height", G_TYPE_INT, settings->height,
3776 + g_object_set(G_OBJECT(gstctx->appsrc),
3779 + "format", GST_FORMAT_TIME,
3782 + gst_caps_unref(caps);
3784 + gst_element_set_state((GstElement*)((void*)gstctx->pipeline), GST_STATE_PLAYING);
3785 + output->renderer->ctx = gstctx;
3791 +recorder_enable(struct weston_transmitter_output *output)
3793 + struct gst_settings *settings;
3795 + struct weston_output* base = &output->base;
3796 + struct weston_compositor *compositor = base->compositor;
3797 + struct weston_transmitter_remote* remote = output->remote;
3801 + * Hard coding bitrate and crop params.
3802 + * In case of gst-recorder case these were taken from weston.ini
3804 + int32_t bitrate = 3000000;
3806 + settings = malloc(sizeof(* settings));
3807 + settings->ip = remote->addr;
3809 + settings->port = atoi(remote->port);
3811 + settings->bitrate = bitrate;
3812 + settings->width = output->renderer->surface_width;
3813 + settings->height = output->renderer->surface_height;
3815 + weston_log("gst-setting are :-->\n");
3816 + weston_log("ip = %s \n",settings->ip);
3817 + weston_log("port = %d \n",settings->port);
3818 + weston_log("bitrate = %d \n",settings->bitrate);
3819 + weston_log("width = %d \n",settings->width);
3820 + weston_log("width = %d \n",settings->height);
3822 + gst_pipe_init(output, settings);
3826 + weston_log("[gst recorder] %s:"
3827 + " invalid settings\n",
3828 + output->base.name);
3833 +static void waltham_renderer_repaint_output(struct weston_transmitter_output *output)
3835 + GstBuffer *gstbuffer;
3837 + GstAllocator *allocator;
3838 + int stride = output->renderer->surface_width * 4;
3841 + if(!output->renderer->recorder_enabled)
3843 + recorder_enable(&output->base);
3844 + output->renderer->recorder_enabled = 1;
3847 + gstbuffer = gst_buffer_new();
3848 + allocator = gst_dmabuf_allocator_new();
3849 + mem = gst_dmabuf_allocator_alloc(allocator, output->renderer->dmafd,
3850 + stride * output->renderer->surface_height);
3851 + gst_buffer_append_memory(gstbuffer, mem);
3852 + gst_buffer_add_video_meta_full(gstbuffer,
3853 + GST_VIDEO_FRAME_FLAG_NONE,
3854 + GST_VIDEO_FORMAT_BGRx,
3855 + output->renderer->surface_width,
3856 + output->renderer->surface_height,
3861 + gst_app_src_push_buffer(output->renderer->ctx->appsrc, gstbuffer);
3862 + gst_object_unref(allocator);
3866 +waltham_renderer_display_create(struct weston_transmitter_output *output)
3868 + struct waltham_renderer *wth_renderer;
3870 + wth_renderer = zalloc(sizeof *wth_renderer);
3871 + if (wth_renderer == NULL)
3873 + wth_renderer->base.repaint_output = waltham_renderer_repaint_output;
3875 + output->renderer = &wth_renderer->base;
3880 +WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = {
3881 + .display_create = waltham_renderer_display_create
3883 diff --git a/waltham-transmitter/waltham-renderer/waltham-renderer.h b/waltham-transmitter/waltham-renderer/waltham-renderer.h
3884 new file mode 100644
3885 index 0000000..a9ac513
3887 +++ b/waltham-transmitter/waltham-renderer/waltham-renderer.h
3890 + * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation
3892 + * Permission is hereby granted, free of charge, to any person obtaining
3893 + * a copy of this software and associated documentation files (the
3894 + * "Software"), to deal in the Software without restriction, including
3895 + * without limitation the rights to use, copy, modify, merge, publish,
3896 + * distribute, sublicense, and/or sell copies of the Software, and to
3897 + * permit persons to whom the Software is furnished to do so, subject to
3898 + * the following conditions:
3900 + * The above copyright notice and this permission notice (including the
3901 + * next paragraph) shall be included in all copies or substantial
3902 + * portions of the Software.
3904 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3905 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3906 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3907 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3908 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3909 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3910 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3914 +#ifndef TRANSMITTER_WALTHAM_RENDERER_H_
3915 +#define TRANSMITTER_WALTHAM_RENDERER_H_
3917 +struct waltham_renderer_interface {
3918 + int (*display_create)(struct weston_transmitter_output *output);
3921 +struct gst_settings {
3929 +#endif /* TRANSMITTER_WALTHAM_RENDERER_H_ */