From bf31f297dbbeb91c3420b691f4deffdbe6865b23 Mon Sep 17 00:00:00 2001 From: zheng_wenlong Date: Fri, 2 Nov 2018 14:01:12 +0900 Subject: add source for waltham receiver --- CMakeLists.txt | 111 ++ LICENSE | 54 - README.md | 102 +- als-meter-demo.pro | 3 - app/Als-meter-demo.qml | 290 ----- app/CameraControl.qml | 136 --- app/Mid.qml | 34 - app/MidOther.qml | 36 - app/Shift.qml | 51 - app/Speed.qml | 92 -- app/Tacho.qml | 101 -- app/als-meter-demo.qrc | 11 - app/app.pri | 5 - app/app.pro | 25 - app/camera.cpp | 139 --- app/camera.h | 70 -- app/config.tests/libhomescreen/libhomescreen.cpp | 8 - app/config.tests/libhomescreen/libhomescreen.pro | 5 - app/images/camera/camera_bg.svg | 484 -------- app/images/camera/camerainfo_bg.svg | 93 -- app/images/homescreen/homebg_bottom.svg | 1397 ---------------------- app/images/images.qrc | 39 - app/images/meters/speed_0.svg | 102 -- app/images/meters/speed_1.svg | 62 - app/images/meters/speed_2.svg | 94 -- app/images/meters/speed_3.svg | 138 --- app/images/meters/speed_4.svg | 78 -- app/images/meters/speed_5.svg | 104 -- app/images/meters/speed_6.svg | 119 -- app/images/meters/speed_7.svg | 102 -- app/images/meters/speed_8.svg | 164 --- app/images/meters/speed_9.svg | 143 --- app/images/meters/speed_center.svg | 391 ------ app/images/meters/speed_kmh.svg | 101 -- app/images/meters/speed_limit_none.svg | 156 --- app/images/meters/tacho_center.svg | 246 ---- app/images/meters/tacho_frame.svg | 213 ---- app/images/meters/tacho_hand.svg | 189 --- app/images/meters/tacho_scale.svg | 876 -------------- app/images/meters/tacho_shift_1.svg | 46 - app/images/meters/tacho_shift_2.svg | 63 - app/images/meters/tacho_shift_3.svg | 69 -- app/images/meters/tacho_shift_4.svg | 56 - app/images/meters/tacho_shift_5.svg | 67 -- app/images/meters/tacho_shift_6.svg | 72 -- app/images/meters/tacho_shift_B.svg | 82 -- app/images/meters/tacho_shift_D.svg | 67 -- app/images/meters/tacho_shift_N.svg | 66 - app/images/meters/tacho_shift_P.svg | 88 -- app/images/meters/tacho_shift_R.svg | 70 -- app/images/mid/mid_S_normal.svg | 1171 ------------------ app/images/mid/mid_other.svg | 123 -- app/images/mid/recirc_inter.svg | 339 ------ app/images/mid/recirc_outer.svg | 339 ------ app/main.cpp | 176 --- config/pipeline.cfg | 1 + include/bitmap.h | 35 + include/hmi-debug.h | 70 ++ include/os-compatibility.h | 58 + include/wth-server-waltham-comm.h | 524 ++++++++ include/wth-server-weston.h | 99 ++ package/config.xml | 19 - package/icon.svg | 892 -------------- package/package.pro | 19 - package/receiver/config.xml | 17 + package/receiver/icon.svg | 279 +++++ package/root/config.xml | 17 + package/root/icon.svg | 279 +++++ protocol/ivi-application.xml | 100 ++ sample/als-meter-demo_git.bb | 21 - src/utils/bitmap.c | 107 ++ src/utils/os-compatibility.c | 204 ++++ src/wth-server-gst.cpp | 1326 ++++++++++++++++++++ src/wth-server-main.cpp | 372 ++++++ src/wth-server-waltham-comm.cpp | 1202 +++++++++++++++++++ src/wth-server-weston.c | 811 +++++++++++++ 76 files changed, 5683 insertions(+), 10227 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 LICENSE delete mode 100644 als-meter-demo.pro delete mode 100644 app/Als-meter-demo.qml delete mode 100644 app/CameraControl.qml delete mode 100644 app/Mid.qml delete mode 100644 app/MidOther.qml delete mode 100644 app/Shift.qml delete mode 100644 app/Speed.qml delete mode 100644 app/Tacho.qml delete mode 100644 app/als-meter-demo.qrc delete mode 100644 app/app.pri delete mode 100644 app/app.pro delete mode 100644 app/camera.cpp delete mode 100644 app/camera.h delete mode 100644 app/config.tests/libhomescreen/libhomescreen.cpp delete mode 100644 app/config.tests/libhomescreen/libhomescreen.pro delete mode 100644 app/images/camera/camera_bg.svg delete mode 100644 app/images/camera/camerainfo_bg.svg delete mode 100644 app/images/homescreen/homebg_bottom.svg delete mode 100644 app/images/images.qrc delete mode 100644 app/images/meters/speed_0.svg delete mode 100644 app/images/meters/speed_1.svg delete mode 100644 app/images/meters/speed_2.svg delete mode 100644 app/images/meters/speed_3.svg delete mode 100644 app/images/meters/speed_4.svg delete mode 100644 app/images/meters/speed_5.svg delete mode 100644 app/images/meters/speed_6.svg delete mode 100644 app/images/meters/speed_7.svg delete mode 100644 app/images/meters/speed_8.svg delete mode 100644 app/images/meters/speed_9.svg delete mode 100644 app/images/meters/speed_center.svg delete mode 100644 app/images/meters/speed_kmh.svg delete mode 100644 app/images/meters/speed_limit_none.svg delete mode 100644 app/images/meters/tacho_center.svg delete mode 100644 app/images/meters/tacho_frame.svg delete mode 100644 app/images/meters/tacho_hand.svg delete mode 100644 app/images/meters/tacho_scale.svg delete mode 100644 app/images/meters/tacho_shift_1.svg delete mode 100644 app/images/meters/tacho_shift_2.svg delete mode 100644 app/images/meters/tacho_shift_3.svg delete mode 100644 app/images/meters/tacho_shift_4.svg delete mode 100644 app/images/meters/tacho_shift_5.svg delete mode 100644 app/images/meters/tacho_shift_6.svg delete mode 100644 app/images/meters/tacho_shift_B.svg delete mode 100644 app/images/meters/tacho_shift_D.svg delete mode 100644 app/images/meters/tacho_shift_N.svg delete mode 100644 app/images/meters/tacho_shift_P.svg delete mode 100644 app/images/meters/tacho_shift_R.svg delete mode 100644 app/images/mid/mid_S_normal.svg delete mode 100644 app/images/mid/mid_other.svg delete mode 100644 app/images/mid/recirc_inter.svg delete mode 100644 app/images/mid/recirc_outer.svg delete mode 100644 app/main.cpp create mode 100644 config/pipeline.cfg create mode 100644 include/bitmap.h create mode 100644 include/hmi-debug.h create mode 100644 include/os-compatibility.h create mode 100644 include/wth-server-waltham-comm.h create mode 100644 include/wth-server-weston.h delete mode 100644 package/config.xml delete mode 100644 package/icon.svg delete mode 100644 package/package.pro create mode 100644 package/receiver/config.xml create mode 100644 package/receiver/icon.svg create mode 100644 package/root/config.xml create mode 100644 package/root/icon.svg create mode 100644 protocol/ivi-application.xml delete mode 100644 sample/als-meter-demo_git.bb create mode 100644 src/utils/bitmap.c create mode 100644 src/utils/os-compatibility.c create mode 100644 src/wth-server-gst.cpp create mode 100644 src/wth-server-main.cpp create mode 100644 src/wth-server-waltham-comm.cpp create mode 100644 src/wth-server-weston.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2f8d74e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required( VERSION 2.8.5 ) + +project (waltham-server) + +set(CMAKE_CXX_FLAGS "-Wall -fpermissive") + +find_package(PkgConfig) +find_package (Threads) +pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED) +pkg_check_modules(WAYLAND_CURSOR wayland-cursor REQUIRED) +pkg_check_modules(WALTHAM waltham REQUIRED) +pkg_check_modules(GLESv2 glesv2 REQUIRED) +pkg_check_modules(WAYLAND_EGL wayland-egl REQUIRED) +pkg_search_module(EGL egl required) +pkg_search_module(GSTREAMER gstreamer-1.0 required) +pkg_search_module(GSTREAMERAPP gstreamer-app-1.0 required) +pkg_search_module(DRM libdrm required) + +find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) +find_library(GST_ALLOCATOR NAMES gstallocators-1.0 PATHs /usr/lib64) +find_library(GST_VIDEO NAMES gstvideo-1.0 PATHs /usr/lib64) +add_custom_command( + OUTPUT ivi-application-client-protocol.h + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header + < ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-client-protocol.h + DEPENDS ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml +) + +add_custom_command( + OUTPUT ivi-application-protocol.c + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code + < ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml + > ${CMAKE_CURRENT_BINARY_DIR}/ivi-application-protocol.c + DEPENDS ${CMAKE_SOURCE_DIR}/protocol/ivi-application.xml +) + +include_directories( + ${WAYLAND_CLIENT_INCLUDE_DIR} + ${WAYLAND_CURSOR_INCLUDE_DIR} + ${WALTHAM_INCLUDE_DIRS} + ${DRM_INCLUDE_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMER_INCLUDE_DIRS} + ${GSTREAMERAPP_INCLUDE_DIRS} + ${EGL_INCLUDE_DIRS} + ${WAYLAND_EGL_INCLUDE_DIR} + ${GLESv2_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/include/ + ${CMAKE_SOURCE_DIR}/waltham-renderer +) + +link_directories( + ${WAYLAND_CLIENT_LIBRARY_DIRS} + ${WAYLAND_CURSOR_LIBRARY_DIRS} + ${WALTHAM_LIBRARY_DIRS} + ${EGL_LIBRARY_DIRS} + ${WAYLAND_EGL_LIBRAY_DIRS} + ${GLESv2_LIBRARY_DIRS} + ${GSTREAMER_LIBRARY_DIRS} + ${GSTREAMERAPP_LIBRARY_DIRS} +) + +SET(LIBS + ${CMAKE_THREAD_LIBS_INIT} + ${WAYLAND_CLIENT_LIBRARIES} + ${WAYLAND_CURSOR_LIBRARIES} + ${WALTHAM_LIBRARIES} + ${EGL_LIBRARIES} + ${WAYLAND_EGL_LIBRARIES} + ${GLESv2_LIBRARIES} + ${GSTREAMER_LIBRARIES} + ${GSTREAMERAPP_LIBRARIES} + ${GST_ALLOCATOR} + ${GST_VIDEO} + libwindowmanager.so + libjson-c.so + libhomescreen.so +) + +SET(SRC_FILES + src/wth-server-main.cpp + src/wth-server-waltham-comm.cpp + src/wth-server-gst.cpp + src/utils/bitmap.c + src/utils/os-compatibility.c + ivi-application-protocol.c + ivi-application-client-protocol.h +) + +add_executable(${PROJECT_NAME} ${SRC_FILES}) + +add_definitions(${EGL_CFLAGS}) + +target_link_libraries(${PROJECT_NAME} ${LIBS}) + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/package ${PROJECT_BINARY_DIR} + COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/bin + COMMAND cp -rf ${PROJECT_BINARY_DIR}/${PROJECT_NAME} ${PROJECT_BINARY_DIR}/package/root/bin) + +add_custom_target(widget DEPENDS ${PROJECT_BINARY_DIR}/package/root + COMMAND wgtpkg-pack -f -o ${PROJECT_BINARY_DIR}/package/${PROJECT_NAME}.wgt ${PROJECT_BINARY_DIR}/package/root) + +add_custom_target(receiver DEPENDS ${PROJECT_BINARY_DIR}/package/root + COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/receiver/bin + COMMAND cp -rf ${PROJECT_BINARY_DIR}/${PROJECT_NAME} ${PROJECT_BINARY_DIR}/package/receiver/bin/receiver + COMMAND wgtpkg-pack -f -o ${PROJECT_BINARY_DIR}/package/receiver.wgt ${PROJECT_BINARY_DIR}/package/receiver) + +install (TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 31c692a..0000000 --- a/LICENSE +++ /dev/null @@ -1,54 +0,0 @@ -Apache License - -Version 2.0, January 2004 - -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - - You must give any other recipients of the Work or Derivative Works a copy of this License; and - You must cause any modified files to carry prominent notices stating that You changed the files; and - You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. - - You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index e54129a..0b48aa4 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,71 @@ -Information -==== -
This is sample application for af-steering-wheel-binding. -
At above of the screen will display usb-camera(UVC camera) video. -
At bottom of this screen will display the can information. -
Right now it can get VehicleSpeed,EngineSpeed,TransmissionMode information from af-steering-wheel-binding. -
Or you can change to use low-level-can-servcie. - -* Hardware: Renesas m3ulcb -* Software: Daring Dab 4.0.0 -* Application name: als-meter-demo -* Test Camera Device: Logitech c920r - -How to compile and install -==== -
These is a sample recipe for als-meter-demo, you can just add that recipes into your project and bitbake. -
Sample Recipes: als-meter-demo_git.bb - -How to use -==== -
1, If the camera has been connected, you can select the camera corresponding to the device ID, and set FPS , -
pixel parameters, open ON/OFF switch on the right, you can see the camera display content. -
2, operation steering-wheel device corresponding function, you can see vehicle speed, engine speed, transmission mode changes. - -Kernel configure -==== -
You need to enable some kernel configure to enable usb camera. -* CONFIG_VIDEOBUF2_VMALLOC=y -* CONFIG_MEDIA_USB_SUPPORT=y -* CONFIG_USB_VIDEO_CLASS=y -* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y \ No newline at end of file +**Overview** + +This application receives transmitted data by waltham-transmitter. +This application is implemented based on waltham-server. +The original source code of waltham-server is in `./orig`. + +**Download** + +Download souce code and SDK from gitlab. + +``` +$ git clone http://oss-project.tmc-tokai.jp/gitlab/WindowManager/waltham-server.git +``` + +*NOTE* + +This application uses waltham protocol, therefore waltham librarys is necessary. +The downloaded SDK includes the libraries. +If build this application, please use this SDK. + +**Install SDK** + +1. Install SDK which is in `./sdk`. +``` +$ cd ./sdk +$ ./poky-agl-glibc-x86_64-agl-demo-platform-crosssdk-aarch64-toolchain-6.0.0.sh +``` + +1. Copy gstglconfig.h +This SDK has gstglconfig.h +but it exists in `/sysroots/aarch64-agl-linux/usr/lib` +and it occures build error. +Therefore copy it to `/sysroots/aarch64-agl-linux/usr/include`. +``` +$ cd /sysroots/aarch64-agl-linux/ +$ cp usr/lib/gstreamer-1.0/include/gst/gl/gstglconfig.h usr/include/gstreamer-1.0/gst/gl/ +``` + +**Build application** + +Source SDK envirment and make. +``` +$ source /environment-setup-aarch64-agl-linux +$ cd waltham-server +$ mkdir build +$ cd build +$ cmake .. +$ make +$ make receiver +``` + +**Install wgt and config file** + +``` +[On host] +$ scp build/package/receiver.wgt root@ +$ scp config/pipeline.cfg root@:/etc/xdg/weston +$ ssh root@ + +[On target] +# afm-util install receiver.wgt +# sync +``` + +**NOTE** + +This application uses port 34400 by default. +If change it, please modify the followings: + +- In `config/pipeline.cfg`, value of `port` at line 1. +- In `src/wth-server-main.cpp`, value of `tcp_port` at line 49. diff --git a/als-meter-demo.pro b/als-meter-demo.pro deleted file mode 100644 index 579a952..0000000 --- a/als-meter-demo.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = app package -package.depends += app diff --git a/app/Als-meter-demo.qml b/app/Als-meter-demo.qml deleted file mode 100644 index 4549704..0000000 --- a/app/Als-meter-demo.qml +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 2.0 -import QtQuick.Window 2.2 -import Camera 1.0 -import QtWebSockets 1.0 - -ApplicationWindow { - id: root - width: 1080 - height: 1487 - - property string als_meter_demo_request_str: "" - property string api_str: "steering-wheel" - property var msgid_enu: { "call":2, "retok":3, "reterr":4, "event":5 } - property int recirc:0 - property int vehiclespeed: 0 - property real enginespeed: 0 - property int wshift: 0 - - WebSocket { - id: websocket - url: bindingAddressWS - - onStatusChanged: { - if (websocket.status === WebSocket.Error){ - console.log ("Error: " + websocket.errorString) - websocket.active = false - countdown.start() - }else if (websocket.status === WebSocket.Open){ - console.log ("Socket Open") - do_subscribe() - }else if (websocket.status === WebSocket.Closed){ - console.log ("Socket closed") - } - } - - onTextMessageReceived: { - var message_json = JSON.parse(message); - console.log("Raw response: " + message) - - if (message_json[0] === msgid_enu.event){ - var propertyName = message_json[2].event.split("/")[1] - if (propertyName === "TransmissionMode"){ - wshift = message_json[2].data.value - }else if (propertyName === "VehicleSpeed"){ - vehiclespeed = message_json[2].data.value - }else if (propertyName === "EngineSpeed"){ - enginespeed = message_json[2].data.value - } - }else if (message_json[0] === msgid_enu.retok){ - for (var item in message_json[2].response){ - if (item === "TransmissionMode"){ - wshift = message_json[2].response["TransmissionMode"]["value"] - }else if (item === "VehicleSpeed"){ - vehiclespeed = message_json[2].response["VehicleSpeed"]["value"] - }else if (item === "EngineSpeed"){ - enginespeed = message_json[2].response["EngineSpeed"]["value"] - } - } - }else{ - console.log ("Event type error:", message_json[0]) - } - } - - active: false - } - - Timer { - id: countdown - repeat: false - interval: 3000 - triggeredOnStart: false - onTriggered: { - websocket.active = true - } - } - - Item { - id: topscreen_up - width: root.width - height: (root.height - bottomscreen.height)/2 - - CameraControl { - id:cameracontrol_up - listWH: true - device: camera_up - width: root.width - height:80 - } - Camera { - id: camera_up - width: root.width - height: topscreen_up.height - cameracontrol_up.height - anchors.top: cameracontrol_up.bottom - onIsrunningChanged: { - camerabg_up.visible = !isrunning - - if (isrunning){ - if (cameracontrol_dn.device.cameraCnt() === 1) - cameracontrol_dn.switchstatus = false; - }else{ - cameracontrol_dn.switchstatus = true; - } - } - onCamraCntChanged: { - if (!camera_dn.isrunning) - cameracontrol_dn.number = camera_dn.camranum(); - - if (!camera_up.isrunning) - cameracontrol_up.number = camera_up.camranum(); - } - - Image { - id: camerabg_up - anchors.centerIn: parent - width: 200 - height: 200 - source: "images/camera/camera_bg.svg" - } - } - } - - Item { - id: topscreen_dn - width: root.width - height: (root.height - bottomscreen.height)/2 - anchors.top: topscreen_up.bottom - CameraControl { - id:cameracontrol_dn - listWH: false - device: camera_dn - width: root.width - height:80 - back:0 - } - Camera { - id: camera_dn - width: root.width - height: topscreen_dn.height - cameracontrol_dn.height - anchors.top: cameracontrol_dn.bottom - onIsrunningChanged: { - camerabg_dn.visible = !isrunning - - if (isrunning){ - if (cameracontrol_up.device.cameraCnt() === 1) - cameracontrol_up.switchstatus = false; - }else{ - cameracontrol_up.switchstatus = true; - } - } - - onCamraCntChanged: { - if (!camera_up.isrunning) - cameracontrol_up.number = camera_up.camranum(); - - if (!camera_dn.isrunning) - cameracontrol_dn.number = camera_dn.camranum(); - } - - Image { - id: camerabg_dn - anchors.centerIn: parent - width: 200 - height: 200 - source: "images/camera/camera_bg.svg" - } - } - } - - Item { - id: bottomscreen - width: root.width - height: 600 - anchors.bottom: parent.bottom - Image { - width: parent.width - height: parent.height - asynchronous: true - fillMode: Image.TileHorizontally - smooth: true - source: "images/homescreen/homebg_bottom.svg" - } - RowLayout { - id: smtparts - anchors.left: parent.left - anchors.right: parent.right - Speed { - id: speedparts - anchors.left: parent.left - anchors.leftMargin: 30 - anchors.bottom: parent.bottom - anchors.bottomMargin: 120 - width: imgwidth - height: imgheight - } - ColumnLayout { - id: tachoparts - anchors.horizontalCenter: parent.horizontalCenter - Tacho { - anchors.top: parent.top - anchors.topMargin: -60 - anchors.horizontalCenter: parent.horizontalCenter - width: imgwidth - height: imgheight - } - MidOther { - anchors.bottom: parent.bottom - anchors.bottomMargin: 110 - anchors.horizontalCenter: parent.horizontalCenter - width: imgwidth - height: imgheight - } - } - Mid { - id: midparts - anchors.right: parent.right - anchors.rightMargin: 25 - anchors.bottom: parent.bottom - anchors.bottomMargin: 90 - width: imgwidth - height: imgheight - } - } - } - - onVisibleChanged: { - if (visible){ - if (!websocket.active){ - websocket.active = true - }else{ - do_subscribe() - } - } - else { - countdown.stop() - if (websocket.active) - do_unsubscribe() - } - } - - Connections { - target: appVisible - onVisibleChanged: { - if (!visible){ - if (websocket.active) - do_unsubscribe() - }else{ - if (websocket.active){ - do_subscribe() - }else{ - websocket.active = true - } - } - } - } - - function do_call(binding, verb, event_name) { - als_meter_demo_request_str = '[' + msgid_enu.call + ',"99999","' + binding+'/'+verb + '", {"event":"' + event_name + '"} ]' - websocket.sendTextMessage (als_meter_demo_request_str) - } - - function do_subscribe() { - do_call(api_str, "subscribe", "VehicleSpeed") - do_call(api_str, "subscribe", "TransmissionMode") - do_call(api_str, "subscribe", "EngineSpeed") - } - - function do_unsubscribe() { - do_call(api_str, "unsubscribe", "VehicleSpeed") - do_call(api_str, "unsubscribe", "TransmissionMode") - do_call(api_str, "unsubscribe", "EngineSpeed") - } -} diff --git a/app/CameraControl.qml b/app/CameraControl.qml deleted file mode 100644 index f3407d5..0000000 --- a/app/CameraControl.qml +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Layouts 1.3 -import QtQuick.Controls 2.0 - -RowLayout { - property var device - property var listWH - property var number: [] - property var fps: ["10", "20", "30", "40", "50", "60"] - property var resolution: listWH ? ["320*240", "640*480", "1280*720", "1920*1080"] : ["320*240"] - property var models: [number, fps, resolution] - property real back: 1 - property bool switchstatus: true - - Repeater { - id: info - model: ["No.:", "FPS:", "W*H:"] - delegate: RowLayout{ - Label { - id: label - text: model.modelData - color: "#59FF7F" - } - ComboBox { - id: camerainfo - implicitWidth: index != 2 ? 100 : 245 - font: label.font - model: models[index] - contentItem: Text { - text: camerainfo.displayText - font: camerainfo.font - color: camerainfo.pressed ? "#17a81a" : "white" - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight - } - indicator: Canvas { - id: canvas - x: camerainfo.width - width - camerainfo.rightPadding - y: camerainfo.topPadding + (camerainfo.availableHeight - height) / 2 - width: 20 - height: 12 - contextType: "2d" - - Connections { - target: camerainfo - onPressedChanged: canvas.requestPaint() - } - - onPaint: { - context.reset(); - context.moveTo(0, 0); - context.lineTo(width, 0); - context.lineTo(width / 2, height); - context.closePath(); - context.fillStyle = camerainfo.pressed ? "#17a81a" : "white"; - context.fill(); - } - } - popup: Popup { - id: popup - y: camerainfo.height - 1 - implicitWidth: camerainfo.width - implicitHeight: listview.count > 6 ? (listview.contentHeight/3.3) : listview.contentHeight - padding: 0 - - contentItem: ListView { - id: listview - clip: true - model: camerainfo.visible ? camerainfo.delegateModel : null - currentIndex: camerainfo.highlightedIndex - ScrollIndicator.vertical: ScrollIndicator { } - } - background: Image { source: "images/camera/camerainfo_bg.svg" } - } - delegate: ItemDelegate { - id: popupdelegate - width: camerainfo.width - contentItem: Item { - implicitHeight: 30 - Text { - text: modelData - color: popupdelegate.pressed || highlighted ? "#21be2b" : "white" - font: camerainfo.font - elide: Text.ElideRight - verticalAlignment: Text.AlignVCenter - } - } - highlighted: camerainfo.highlightedIndex == index - } - - background: Image { source: "images/camera/camerainfo_bg.svg" } - } - } - } - Switch { - id: cameraswitch - enabled: switchstatus - onCheckedChanged: { - if (checked && device){ - device.start(info.itemAt(0).children[1].currentText, info.itemAt(1).children[1].currentText, info.itemAt(2).children[1].currentText) - }else if (!checked && device){ - device.stop() - } - } - } - - onVisibleChanged: { - if (!visible) - cameraswitch.checked = false - } - - Component.onCompleted: { - device.enumerateCameras(); - number = device.camranum(); - - if (device.cameraCnt() === 0) - switchstatus = false; - } -} diff --git a/app/Mid.qml b/app/Mid.qml deleted file mode 100644 index e658138..0000000 --- a/app/Mid.qml +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.0 - -Item { - property real imgwidth: 320 - property real imgheight: 320 - - Image { - id: midimg - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - source: "images/mid/mid_S_normal.svg" - } -} diff --git a/app/MidOther.qml b/app/MidOther.qml deleted file mode 100644 index 579d5f1..0000000 --- a/app/MidOther.qml +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.0 -import QtWebSockets 1.0 - -Item { - property real imgwidth: 430*120/150 - property real imgheight: 120 - - property var recirc_mid: ["images/mid/recirc_outer.svg", "images/mid/recirc_inter.svg"] - - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - source: recirc_mid[recirc] - } -} diff --git a/app/Shift.qml b/app/Shift.qml deleted file mode 100644 index 60a0f0f..0000000 --- a/app/Shift.qml +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Layouts 1.0 -import QtWebSockets 1.0 - -Row { - property real percent: 1 - property var carshift: [ - "images/meters/tacho_shift_N.svg", "images/meters/tacho_shift_D.svg" - ] - - property var wheelshift: [ - "images/meters/tacho_shift_1.svg", "images/meters/tacho_shift_2.svg", - "images/meters/tacho_shift_3.svg", "images/meters/tacho_shift_4.svg", - "images/meters/tacho_shift_5.svg", "images/meters/tacho_shift_6.svg" - ] - - Image { - width: percent*sourceSize.width - height: percent*sourceSize.height - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: wshift === 0 ? carshift[0] : carshift[1] - } - - Image { - visible: wshift > 0 - width: percent*sourceSize.width - height: percent*sourceSize.height - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: (wshift > 0 && wshift <= wheelshift.length) ? wheelshift[wshift-1] : wheelshift[0] - } -} diff --git a/app/Speed.qml b/app/Speed.qml deleted file mode 100644 index 46ec01f..0000000 --- a/app/Speed.qml +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtQuick.Layouts 1.3 -import QtWebSockets 1.0 - -Item { - property real imgwidth: 300 - property real imgheight: 300 - property var spdlist: [ - "images/meters/speed_0.svg", "images/meters/speed_1.svg", - "images/meters/speed_2.svg", "images/meters/speed_3.svg", - "images/meters/speed_4.svg", "images/meters/speed_5.svg", - "images/meters/speed_6.svg", "images/meters/speed_7.svg", - "images/meters/speed_8.svg", "images/meters/speed_9.svg" - ] - property var spdlimit: [ "images/meters/speed_limit_none.svg" ] - - Image { - width: 280 - height: 280 - anchors.top: parent.top - anchors.topMargin: 17 - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - source: "images/meters/speed_center.svg" - } - - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: spdlimit[0] - } - - Row { - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - Image { - width: imgwidth*sourceSize.width/480 - height: imgheight*sourceSize.height/480 - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - visible: vehiclespeed > 99 - source: ((vehiclespeed - vehiclespeed%100)/100%10 < spdlist.length) ? spdlist[(vehiclespeed - vehiclespeed%100)/100%10] : spdlist[0] - } - Image { - width: imgwidth*sourceSize.width/480 - height: imgheight*sourceSize.height/480 - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - visible: vehiclespeed > 9 - source: ((vehiclespeed - vehiclespeed%10)/10%10 < spdlist.length) ? spdlist[(vehiclespeed - vehiclespeed%10)/10%10] : spdlist[0] - } - Image { - width: imgwidth*sourceSize.width/480 - height: imgheight*sourceSize.height/480 - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - source: (vehiclespeed%10 < spdlist.length) ? spdlist[vehiclespeed%10] : spdlist[0] - } - } - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - asynchronous: true - smooth: true - source: "images/meters/speed_kmh.svg" - } -} diff --git a/app/Tacho.qml b/app/Tacho.qml deleted file mode 100644 index 9c4fbee..0000000 --- a/app/Tacho.qml +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import QtQuick 2.6 -import QtWebSockets 1.0 - -Item { - property real imgwidth: 600 - property real imgheight: 600 - - property real tacho: enginespeed === undefined ? 0 : (enginespeed > 9000 ? 9 : enginespeed*9/9000) - - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: "images/meters/tacho_center.svg" - } - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: "images/meters/tacho_frame.svg" - } - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - source: "images/meters/tacho_scale.svg" - } - Shift { - percent: imgwidth/480 - anchors.right: parent.right - anchors.rightMargin: wshift > 0 ? (imgwidth-width)/2+25 : (imgwidth-width)/2-5 - anchors.bottom: parent.bottom - anchors.bottomMargin: 100 - spacing: -10 - } - Canvas { - id: canvas - property real engleoffset: Math.PI*3/2.04 - property int linewidth: 90 - anchors.centerIn: parent - width: 420 - height: 420 - visible: tacho >= 0.05 - rotation: 135 - opacity: 0.5 - onPaint: { - var ctx = getContext("2d") - var gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height) - gradient.addColorStop(0.0, Qt.rgba(1.0, 1.0, 1.0, 1.0)) - gradient.addColorStop(1.0, Qt.rgba(1.0, 1.0, 1.0, 0.0)) - - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.beginPath(); - ctx.lineWidth = linewidth; - ctx.strokeStyle = gradient - ctx.arc(canvas.width/2, - canvas.height/2, - (canvas.width-ctx.lineWidth)/2, - 0.1, - engleoffset*(tacho/9) + (tacho < 3 ? 0.1 : (tacho < 7 ? 0.05 : 0.0)), - false) - ctx.stroke() - ctx.closePath() - } - } - Image { - width: imgwidth - height: imgheight - fillMode: Image.PreserveAspectFit - smooth: true - asynchronous: true - rotation: 28.8*tacho - source: "images/meters/tacho_hand.svg" - } - - onTachoChanged: { - canvas.requestPaint() - } -} diff --git a/app/als-meter-demo.qrc b/app/als-meter-demo.qrc deleted file mode 100644 index 4843da7..0000000 --- a/app/als-meter-demo.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - Als-meter-demo.qml - Speed.qml - Mid.qml - Tacho.qml - CameraControl.qml - Shift.qml - MidOther.qml - - diff --git a/app/app.pri b/app/app.pri deleted file mode 100644 index e535cbc..0000000 --- a/app/app.pri +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE = app - -load(configure) - -DESTDIR = $${OUT_PWD}/../package/root/bin diff --git a/app/app.pro b/app/app.pro deleted file mode 100644 index 035807c..0000000 --- a/app/app.pro +++ /dev/null @@ -1,25 +0,0 @@ -TARGET = als-meter-demo -QT = quickcontrols2 dbus - -LIBS += -lopencv_core -lopencv_videoio - -equals(QT_ARCH, "arm") { - QMAKE_CXXFLAGS += -mfp16-format=ieee -} - - -HEADERS += \ - camera.h - -SOURCES += \ - main.cpp \ - camera.cpp - -CONFIG += link_pkgconfig -PKGCONFIG += libhomescreen qlibwindowmanager - -RESOURCES += \ - als-meter-demo.qrc \ - images/images.qrc - -include(app.pri) diff --git a/app/camera.cpp b/app/camera.cpp deleted file mode 100644 index 107880c..0000000 --- a/app/camera.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "camera.h" -#include -#include - -#include -#include -#include -#include - -using namespace cv; - -Camera::Camera() { - running = false; - timer = new QTimer(this); - capture = new VideoCapture(); - - connect(timer, SIGNAL(timeout()), this, SLOT(grab())); -} - -Camera::~Camera() { - if (timer->isActive()) - timer->stop(); - if (capture && capture->isOpened()) - capture->release(); - delete timer; - delete capture; -} - -void Camera::paint(QPainter *painter) { - painter->drawImage(0, 0, image); -} - -void Camera::enumerateCameras() { - int maxID = 10; - for (int idx = 0; idx " << (char*)(cap.card) << ">" << (char*)(cap.bus_info);// << (cap.version>>16)&0xFF << (cap.version>>8)&0XFF << cap.version&0xFF; - cam_arr.push_back(idx); // vector of all available cameras - } - } - close(fd); - } - } - - camcnt = cam_arr.length(); - cam_arr_bak = cam_arr; -} - -void Camera::start(int no, int fps, QString res) { - try{ - for (QVariantList::iterator iter = cam_arr_bak.begin(); iter != cam_arr_bak.end(); ++iter){ - if (*iter == no){ - cam_arr_bak.erase(iter); - break; - } - } - - if (capture && capture->open(no)){ - capture->set(CAP_PROP_FRAME_WIDTH, res.section("*", 0, 0).toInt()); - capture->set(CAP_PROP_FRAME_HEIGHT, res.section("*", 1, 1).toInt()); - - if (fps > 0){ - timer->start(1000/fps); - running = true; - emit isrunningChanged(running); - - emit camraCntChanged(cam_arr_bak); - } - camnumbackup = no; - } - } - catch(cv::Exception & e) { - qDebug() << "als-meter-demo open device error: " << e.msg.c_str(); - } -} - -void Camera::stop() { - cam_arr_bak.push_back(camnumbackup); - - if (timer->isActive()) - timer->stop(); - if (capture && capture->isOpened()) - capture->release(); - image = QImage(); - update(); - running = false; - emit isrunningChanged(running); - - emit camraCntChanged(cam_arr_bak); -} - -QVariantList Camera::camranum() const{ - return cam_arr_bak; -} - -int Camera::cameraCnt() { - return camcnt; -} - -bool Camera::isrunning() const{ - return running; -} - -void Camera::grab() { - if (capture && capture->isOpened()){ - Mat frame; - capture->read(frame); - - if (!frame.empty()){ - image = QImage((const uchar*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888).rgbSwapped(); - image = image.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - update(); - } - } -} diff --git a/app/camera.h b/app/camera.h deleted file mode 100644 index 1b85d27..0000000 --- a/app/camera.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CAMERA_H -#define CAMERA_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -static QVariantList cam_arr_bak; - -class Camera : public QQuickPaintedItem -{ - Q_OBJECT - Q_PROPERTY(bool isrunning READ isrunning NOTIFY isrunningChanged) -public: - Camera(); - ~Camera(); - void paint(QPainter *painter); - bool isrunning() const; - Q_INVOKABLE QVariantList camranum() const; - - Q_INVOKABLE void start(int no, int fps, QString res); - Q_INVOKABLE void stop(); - - Q_INVOKABLE void enumerateCameras(); - Q_INVOKABLE int cameraCnt(); - -signals: - void isrunningChanged(const bool& isrunning); - void camraCntChanged(const QVariantList& camcnt); - -public slots: - void grab(); - -private: - bool running; - QImage image; - QTimer* timer; - cv::VideoCapture* capture; - - QVariantList cam_arr; - - int camnumbackup; - int camcnt; -}; - -#endif // CAMERA_H diff --git a/app/config.tests/libhomescreen/libhomescreen.cpp b/app/config.tests/libhomescreen/libhomescreen.cpp deleted file mode 100644 index d698b05..0000000 --- a/app/config.tests/libhomescreen/libhomescreen.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main(int argc,char **argv) -{ - LibHomeScreen libHomeScreen; - return 0; -} - diff --git a/app/config.tests/libhomescreen/libhomescreen.pro b/app/config.tests/libhomescreen/libhomescreen.pro deleted file mode 100644 index eb4e8f3..0000000 --- a/app/config.tests/libhomescreen/libhomescreen.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = libhomescreen.cpp - -CONFIG -= qt -CONFIG += link_pkgconfig -PKGCONFIG += homescreen diff --git a/app/images/camera/camera_bg.svg b/app/images/camera/camera_bg.svg deleted file mode 100644 index 458f81c..0000000 --- a/app/images/camera/camera_bg.svg +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/camera/camerainfo_bg.svg b/app/images/camera/camerainfo_bg.svg deleted file mode 100644 index 4251412..0000000 --- a/app/images/camera/camerainfo_bg.svg +++ /dev/null @@ -1,93 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/app/images/homescreen/homebg_bottom.svg b/app/images/homescreen/homebg_bottom.svg deleted file mode 100644 index 78bf678..0000000 --- a/app/images/homescreen/homebg_bottom.svg +++ /dev/null @@ -1,1397 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/images.qrc b/app/images/images.qrc deleted file mode 100644 index b1bee21..0000000 --- a/app/images/images.qrc +++ /dev/null @@ -1,39 +0,0 @@ - - - meters/speed_3.svg - meters/speed_7.svg - meters/speed_8.svg - meters/speed_9.svg - meters/tacho_hand.svg - meters/tacho_shift_P.svg - meters/tacho_shift_R.svg - meters/speed_center.svg - meters/tacho_shift_N.svg - meters/tacho_center.svg - meters/tacho_scale.svg - meters/speed_5.svg - meters/speed_4.svg - meters/speed_6.svg - meters/speed_2.svg - meters/tacho_shift_D.svg - meters/speed_0.svg - meters/speed_limit_none.svg - meters/tacho_frame.svg - meters/speed_1.svg - meters/speed_kmh.svg - homescreen/homebg_bottom.svg - camera/camera_bg.svg - camera/camerainfo_bg.svg - mid/mid_S_normal.svg - mid/recirc_inter.svg - mid/recirc_outer.svg - meters/tacho_shift_B.svg - meters/tacho_shift_1.svg - meters/tacho_shift_2.svg - meters/tacho_shift_3.svg - meters/tacho_shift_4.svg - meters/tacho_shift_5.svg - meters/tacho_shift_6.svg - mid/mid_other.svg - - diff --git a/app/images/meters/speed_0.svg b/app/images/meters/speed_0.svg deleted file mode 100644 index f3fb4ad..0000000 --- a/app/images/meters/speed_0.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_1.svg b/app/images/meters/speed_1.svg deleted file mode 100644 index 05d48b4..0000000 --- a/app/images/meters/speed_1.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_2.svg b/app/images/meters/speed_2.svg deleted file mode 100644 index dd97941..0000000 --- a/app/images/meters/speed_2.svg +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_3.svg b/app/images/meters/speed_3.svg deleted file mode 100644 index 67a987c..0000000 --- a/app/images/meters/speed_3.svg +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/meters/speed_4.svg b/app/images/meters/speed_4.svg deleted file mode 100644 index c9b2364..0000000 --- a/app/images/meters/speed_4.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_5.svg b/app/images/meters/speed_5.svg deleted file mode 100644 index 2768361..0000000 --- a/app/images/meters/speed_5.svg +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_6.svg b/app/images/meters/speed_6.svg deleted file mode 100644 index ba4dcd0..0000000 --- a/app/images/meters/speed_6.svg +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_7.svg b/app/images/meters/speed_7.svg deleted file mode 100644 index 2537843..0000000 --- a/app/images/meters/speed_7.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/meters/speed_8.svg b/app/images/meters/speed_8.svg deleted file mode 100644 index 656205f..0000000 --- a/app/images/meters/speed_8.svg +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_9.svg b/app/images/meters/speed_9.svg deleted file mode 100644 index 96a6e87..0000000 --- a/app/images/meters/speed_9.svg +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/meters/speed_center.svg b/app/images/meters/speed_center.svg deleted file mode 100644 index b9f9f60..0000000 --- a/app/images/meters/speed_center.svg +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_kmh.svg b/app/images/meters/speed_kmh.svg deleted file mode 100644 index daa2916..0000000 --- a/app/images/meters/speed_kmh.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/speed_limit_none.svg b/app/images/meters/speed_limit_none.svg deleted file mode 100644 index dde91bf..0000000 --- a/app/images/meters/speed_limit_none.svg +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_center.svg b/app/images/meters/tacho_center.svg deleted file mode 100644 index 46086d9..0000000 --- a/app/images/meters/tacho_center.svg +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_frame.svg b/app/images/meters/tacho_frame.svg deleted file mode 100644 index 84a854f..0000000 --- a/app/images/meters/tacho_frame.svg +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_hand.svg b/app/images/meters/tacho_hand.svg deleted file mode 100644 index 90ec605..0000000 --- a/app/images/meters/tacho_hand.svg +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/meters/tacho_scale.svg b/app/images/meters/tacho_scale.svg deleted file mode 100644 index 035b603..0000000 --- a/app/images/meters/tacho_scale.svg +++ /dev/null @@ -1,876 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_1.svg b/app/images/meters/tacho_shift_1.svg deleted file mode 100644 index 8e3ce67..0000000 --- a/app/images/meters/tacho_shift_1.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_2.svg b/app/images/meters/tacho_shift_2.svg deleted file mode 100644 index 8342580..0000000 --- a/app/images/meters/tacho_shift_2.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_3.svg b/app/images/meters/tacho_shift_3.svg deleted file mode 100644 index 9c8e804..0000000 --- a/app/images/meters/tacho_shift_3.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_4.svg b/app/images/meters/tacho_shift_4.svg deleted file mode 100644 index 5fb9296..0000000 --- a/app/images/meters/tacho_shift_4.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_5.svg b/app/images/meters/tacho_shift_5.svg deleted file mode 100644 index f4e9838..0000000 --- a/app/images/meters/tacho_shift_5.svg +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_6.svg b/app/images/meters/tacho_shift_6.svg deleted file mode 100644 index da2f200..0000000 --- a/app/images/meters/tacho_shift_6.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_B.svg b/app/images/meters/tacho_shift_B.svg deleted file mode 100644 index 3dcbe56..0000000 --- a/app/images/meters/tacho_shift_B.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_D.svg b/app/images/meters/tacho_shift_D.svg deleted file mode 100644 index 3c824c4..0000000 --- a/app/images/meters/tacho_shift_D.svg +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_N.svg b/app/images/meters/tacho_shift_N.svg deleted file mode 100644 index 3b41db7..0000000 --- a/app/images/meters/tacho_shift_N.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/meters/tacho_shift_P.svg b/app/images/meters/tacho_shift_P.svg deleted file mode 100644 index 3847b14..0000000 --- a/app/images/meters/tacho_shift_P.svg +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/meters/tacho_shift_R.svg b/app/images/meters/tacho_shift_R.svg deleted file mode 100644 index 9007e01..0000000 --- a/app/images/meters/tacho_shift_R.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - diff --git a/app/images/mid/mid_S_normal.svg b/app/images/mid/mid_S_normal.svg deleted file mode 100644 index 5aaa6ab..0000000 --- a/app/images/mid/mid_S_normal.svg +++ /dev/null @@ -1,1171 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/mid/mid_other.svg b/app/images/mid/mid_other.svg deleted file mode 100644 index 7c5b0ad..0000000 --- a/app/images/mid/mid_other.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/mid/recirc_inter.svg b/app/images/mid/recirc_inter.svg deleted file mode 100644 index 64e0ec8..0000000 --- a/app/images/mid/recirc_inter.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/mid/recirc_outer.svg b/app/images/mid/recirc_outer.svg deleted file mode 100644 index bd72e5c..0000000 --- a/app/images/mid/recirc_outer.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/main.cpp b/app/main.cpp deleted file mode 100644 index 88a4978..0000000 --- a/app/main.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * Copyright (C) 2016 The Qt Company Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "camera.h" - -#include -#include -#include - -class AppVisible : public QObject -{ - Q_OBJECT -public: - AppVisible(QObject *parent = nullptr) : QObject(parent){ - m_ppid = getppid(); - m_visible = true; - QDBusConnection::sessionBus().connect("org.agl.windowmanager", - "/windowmanager", - "org.agl.windowmanager", - "appLayerVisibleChanged", - this, - SLOT(appLayerVisibleChanged(int,bool))); - } - -public slots: - void appLayerVisibleChanged(int pid, bool visible){ - bool tempvis = visible; - - if(tempvis && (m_ppid != pid)) - tempvis = false; - - if(m_visible != tempvis){ - m_visible = tempvis; - emit visibleChanged(m_visible); - } - } - -signals: - void visibleChanged(const bool& visible); - -private: - int m_ppid; - bool m_visible; -}; - -class DBus : public QObject -{ - Q_OBJECT -public: - DBus(QObject *parent = nullptr) - : QObject(parent) - , interface("org.agl.homescreen", "/StatusBar", "org.agl.statusbar", QDBusConnection::sessionBus()) - {} - - Q_INVOKABLE void setStatusIcon(int index, const QString &url) { - interface.call("setStatusIcon", index, url); - } - -private: - QDBusInterface interface; -}; - -int main(int argc, char *argv[]) -{ - QString myname = QString("Als-meter-demo"); - - QGuiApplication app(argc, argv); - app.setApplicationName(myname); - app.setApplicationVersion(QStringLiteral("0.1.0")); - app.setOrganizationDomain(QStringLiteral("automotivelinux.org")); - app.setOrganizationName(QStringLiteral("AutomotiveGradeLinux")); - - QQuickStyle::setStyle("AGL"); - - QCommandLineParser parser; - parser.addPositionalArgument("port", app.translate("main", "port for binding")); - parser.addPositionalArgument("secret", app.translate("main", "secret for binding")); - parser.addHelpOption(); - parser.addVersionOption(); - parser.process(app); - QStringList positionalArguments = parser.positionalArguments(); - - qmlRegisterType("Camera", 1, 0, "Camera"); - - QQmlApplicationEngine engine; - int port = 0; - if (positionalArguments.length() == 2) { - port = positionalArguments.takeFirst().toInt(); - } - QString secret = positionalArguments.takeFirst(); - QUrl bindingAddressWS; - bindingAddressWS.setScheme(QStringLiteral("ws")); - bindingAddressWS.setHost(QStringLiteral("localhost")); - bindingAddressWS.setPort(port); - bindingAddressWS.setPath(QStringLiteral("/api")); - QUrlQuery query; - query.addQueryItem(QStringLiteral("token"), secret); - bindingAddressWS.setQuery(query); - QQmlContext *context = engine.rootContext(); - AppVisible appVisible; - context->setContextProperty(QStringLiteral("appVisible"), &appVisible); - context->setContextProperty(QStringLiteral("bindingAddressWS"), bindingAddressWS); - - std::string token = secret.toStdString(); - LibHomeScreen* hs = new LibHomeScreen(); - QLibWindowmanager* qwm = new QLibWindowmanager(); - - // WindowManager - if(qwm->init(port,secret) != 0){ - exit(EXIT_FAILURE); - } - // Request a surface as described in layers.json windowmanager’s file - if (qwm->requestSurface(myname) != 0) { - exit(EXIT_FAILURE); - } - // Create an event callback against an event type. Here a lambda is called when SyncDraw event occurs - qwm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [qwm, myname](json_object *object) { - fprintf(stderr, "Surface got syncDraw!\n"); - qwm->endDraw(myname); - }); - - // HomeScreen - hs->init(port, token.c_str()); - // Set the event handler for Event_TapShortcut which will activate the surface for windowmanager - hs->set_event_handler(LibHomeScreen::Event_TapShortcut, [qwm, myname](json_object *object){ - json_object *appnameJ = nullptr; - if(json_object_object_get_ex(object, "application_name", &appnameJ)) - { - const char *appname = json_object_get_string(appnameJ); - if(myname == appname) - { - qDebug("Surface %s got tapShortcut\n", appname); - qwm->activateSurface(myname); - } - } - }); - - DBus dbus; - engine.rootContext()->setContextProperty("dbus", &dbus); - engine.load(QUrl(QStringLiteral("qrc:/Als-meter-demo.qml"))); - - QObject *root = engine.rootObjects().first(); - QQuickWindow *window = qobject_cast(root); - QObject::connect(window, SIGNAL(frameSwapped()), qwm, SLOT(slotActivateSurface() - )); - - return app.exec(); -} - -#include "main.moc" diff --git a/config/pipeline.cfg b/config/pipeline.cfg new file mode 100644 index 0000000..536540b --- /dev/null +++ b/config/pipeline.cfg @@ -0,0 +1 @@ +udpsrc port=34400 caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)JPEG,payload=(int)26" ! rtpjpegdepay ! jpegdec ! videoconvert ! video/x-raw,format=RGBA ! appsink name=sink sync=true diff --git a/include/bitmap.h b/include/bitmap.h new file mode 100644 index 0000000..3cef52d --- /dev/null +++ b/include/bitmap.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef IVICONTROLLER_BITMAP_H_ +#define IVICONTROLLER_BITMAP_H_ + +#include + +int save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp + ); + +#endif /* IVICONTROLLER_BITMAP_H_*/ diff --git a/include/hmi-debug.h b/include/hmi-debug.h new file mode 100644 index 0000000..2a744ba --- /dev/null +++ b/include/hmi-debug.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HMI_DEBUG_H__ +#define __HMI_DEBUG_H__ + +#include +#include +#include +#include +#include + +enum LOG_LEVEL{ + LOG_LEVEL_NONE = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARNING, + LOG_LEVEL_NOTICE, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG, + LOG_LEVEL_MAX = LOG_LEVEL_DEBUG +}; + +#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) + +#define HMI_ERROR(prefix, args,...) _HMI_LOG(LOG_LEVEL_ERROR, __FILENAME__, __FUNCTION__, __LINE__, prefix, args, ##__VA_ARGS__) +#define HMI_WARNING(prefix, args,...) _HMI_LOG(LOG_LEVEL_WARNING, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_NOTICE(prefix, args,...) _HMI_LOG(LOG_LEVEL_NOTICE, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_INFO(prefix, args,...) _HMI_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) +#define HMI_DEBUG(prefix, args,...) _HMI_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__) + +static char ERROR_FLAG[6][20] = {"NONE", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"}; + +static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, const char* prefix, const char* log, ...) +{ + const int log_level = (getenv("USE_HMI_DEBUG") == NULL)?LOG_LEVEL_ERROR:atoi(getenv("USE_HMI_DEBUG")); + if(log_level < level) + { + return; + } + + char *message; + struct timespec tp; + unsigned int time; + + clock_gettime(CLOCK_REALTIME, &tp); + time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); + + va_list args; + va_start(args, log); + if (log == NULL || vasprintf(&message, log, args) < 0) + message = NULL; + fprintf(stderr, "[%10.3f] [%s %s] [%s, %s(), Line:%d] >>> %s \n", time / 1000.0, prefix, ERROR_FLAG[level], file, func, line, message); + va_end(args); + free(message); +} + +#endif //__HMI_DEBUG_H__ \ No newline at end of file diff --git a/include/os-compatibility.h b/include/os-compatibility.h new file mode 100644 index 0000000..690f229 --- /dev/null +++ b/include/os-compatibility.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef OS_COMPATIBILITY_H +#define OS_COMPATIBILITY_H + +#include + +#ifdef HAVE_EXECINFO_H +#include +#else +static inline int +backtrace(void **buffer, int size) +{ + return 0; +} +#endif + +int +os_fd_set_cloexec(int fd); + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv); + +int +os_epoll_create_cloexec(void); + +int +os_create_anonymous_file(off_t size); + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c); +#endif + +#endif /* OS_COMPATIBILITY_H */ diff --git a/include/wth-server-waltham-comm.h b/include/wth-server-waltham-comm.h new file mode 100644 index 0000000..1d58dde --- /dev/null +++ b/include/wth-server-waltham-comm.h @@ -0,0 +1,524 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc, ** +** required to interface with waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WTH_SERVER_WALTHAM_COMM_H_ +#define WTH_SERVER_WALTHAM_COMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct server; +struct client; +struct window; +struct pointer; +struct touch; +/* +pthread_mutex_t g_mutex; +pthread_cond_t g_cond; +int go_to_wait; +*/ +extern const struct wth_display_interface display_implementation; + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_accept_client(struct server *srv); + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void server_flush_clients(struct server *srv); + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void client_destroy(struct client *c); + +/** +* waltham_pointer_enter +* +* Send pointer enter event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* serial - serial number of the enter event +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_leave +* +* Send pointer leave event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* @param value window - window information +* serial - serial number of the leave event +* @return none +*/ +void waltham_pointer_leave(struct window *window, uint32_t serial); + +/** +* waltham_pointer_motion +* +* Send pointer motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* wl_fixed_t sx +* wl_fixed_t sy +* @param value window - window information +* time - timestamp with millisecond granularity +* sx - surface-local x coordinate +* sy - surface-local y coordinate +* @return none +*/ +void waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy); + +/** +* waltham_pointer_button +* +* Send pointer button event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* uint32_t button +* uint32_t state +* @param value window - window information +* serial - serial number of the button event +* time - timestamp with millisecond granularity +* button - button that produced the event +* state - physical state of the button +* @return none +*/ +void waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state); + +/** +* waltham_pointer_axis +* +* Send pointer axis event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* uint32_t axis +* wl_fixed_t value +* @param value window - window information +* time - timestamp with millisecond granularity +* axis - axis type +* value - length of vector in surface-local coordinate space +* @return none +*/ +void waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value); + +/** +* waltham_touch_down +* +* Send touch down event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* serial - serial number of the touch down event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_up +* +* Send touch up event received from weston to waltham client +* +* @param names struct window *window +* uint32_t serial +* uint32_t time +* int32_t id +* @param value window - window information +* serial - serial number of the touch up event +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* @return none +*/ +void waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id); + +/** +* waltham_touch_motion +* +* Send touch motion event received from weston to waltham client +* +* @param names struct window *window +* uint32_t time +* int32_t id +* wl_fixed_t x_w +* wl_fixed_t y_w +* @param value window - window information +* time - timestamp with millisecond granularity +* id - the unique ID of this touch point +* x_w - surface-local x coordinate +* y_w - surface-local y coordinate +* @return none +*/ +void waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w); + +/** +* waltham_touch_frame +* +* Send touch frame event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_frame(struct window *window); + +/** +* waltham_touch_cancel +* +* Send touch cancel event received from weston to waltham client +* +* @param names struct window *window +* @param value window - window information +* @return none +*/ +void waltham_touch_cancel(struct window *window); + + +/***** macros *******/ +#define MAX_EPOLL_WATCHES 2 + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define wl_list_last_until_empty(pos, head, member) \ + while (!wl_list_empty(head) && \ + (pos = wl_container_of((head)->prev, pos, member), 1)) + +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#endif + +#ifndef pr_fmt +# define pr_fmt(fmt) fmt +#endif + +#ifndef USE_STDOUT +# define PRINT_OUT stderr +#else +# define PRINT_OUT stdout +#endif + +#define wth_error(fmt, ...) \ + ({ fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); }) +#define wth_verbose(fmt, ...) \ + ({ if (get_verbosity()) { fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); } }) + +/****** incline functions *****/ +static inline void * +zalloc(size_t size) +{ + return calloc(1, size); +} + + +/***** Data types *****/ +/* wthp_region protocol object */ +struct region { + struct wthp_region *obj; + /* pixman_region32_t region; */ + struct wl_list link; /* struct client::region_list */ +}; + +/* wthp_compositor protocol object */ +struct compositor { + struct wthp_compositor *obj; + struct client *client; + struct wl_list link; /* struct client::compositor_list */ +}; + +/* wthp_blob_factory protocol object */ +struct blob_factory { + struct wthp_blob_factory *obj; + struct client *client; + struct wl_list link; /* struct client::blob_factory_list */ +}; + +/* wthp_buffer protocol object */ +struct buffer { + struct wthp_buffer *obj; + uint32_t data_sz; + void *data; + int32_t width; + int32_t height; + int32_t stride; + uint32_t format; + struct wl_list link; /* struct client::buffer_list */ +}; + +/* wthp_seat protocol object */ +struct seat { + struct wthp_seat *obj; + struct client *client; + struct pointer *pointer; + struct keyboard *keyboard; + struct touch *touch; + struct wl_list link; /* struct client::seat_list */ +}; + +/* wthp_pointer protocol object */ +struct pointer { + struct wthp_pointer *obj; + struct seat *seat; + struct wl_list link; /* struct client::pointer_list */ +}; + +/* wthp_keyboard protocol object */ +struct keyboard { + struct wthp_keyboard *obj; + struct seat *seat; + struct wl_list link; /* struct client::keyboard_list */ +}; + +/* wthp_touch protocol object */ +struct touch { + struct wthp_touch *obj; + struct seat *seat; + struct wl_list link; /* struct client::touch_list */ +}; + +/* wthp_surface protocol object */ +struct surface { + struct wthp_surface *obj; + uint32_t ivi_id; + struct ivisurface3 *ivisurf; + struct wthp_callback *cb; + struct window *shm_window; + struct wl_list link; /* struct client::surface_list */ +}; +/* wthp_ivi_surface protocol object */ +struct ivisurface { + struct wthp_ivi_surface *obj; + struct wthp_callback *cb; + struct wl_list link; /* struct client::surface_list */ + struct surface *surf; +}; + +/* wthp_ivi_application protocol object */ +struct application { + struct wthp_ivi_application *obj; + struct client *client; + struct wl_list link; /* struct client::surface_list */ +}; + +/* wthp_registry protocol object */ +struct registry { + struct wthp_registry *obj; + struct client *client; + struct wl_list link; /* struct client::registry_list */ +}; + +enum wthp_seat_capability { + /** + * the seat has pointer devices + */ + WTHP_SEAT_CAPABILITY_POINTER = 1, + /** + * the seat has one or more keyboards + */ + WTHP_SEAT_CAPABILITY_KEYBOARD = 2, + /** + * the seat has touch devices + */ + WTHP_SEAT_CAPABILITY_TOUCH = 4, +}; + +/* epoll structure */ +struct watch { + struct server *server; + int fd; + void (*cb)(struct watch *w, uint32_t events); +}; + +struct client { + struct wl_list link; /* struct server::client_list */ + struct server *server; + + struct wth_connection *connection; + struct watch conn_watch; + + /* client object lists for clean-up on disconnection */ + struct wl_list registry_list; /* struct registry::link */ + struct wl_list compositor_list; /* struct compositor::link */ + struct wl_list region_list; /* struct region::link */ + struct wl_list surface_list; /* struct surface::link */ + struct wl_list buffer_list; /* struct buffer::link */ + struct wl_list seat_list; /* struct seat::link */ + struct wl_list pointer_list; /* struct pointer::link */ + struct wl_list touch_list; /* struct touch::link */ +}; + +/* server structure */ +struct server { + int listen_fd; + struct watch listen_watch; + + bool running; + int epoll_fd; + + struct wl_list client_list; /* struct client::link */ +}; + +struct shm_buffer { + struct wl_buffer *buffer; + void *shm_data; + int busy; +}; + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shm *shm; + bool has_xrgb; + struct ivi_application *ivi_application; + + struct wl_seat *seat; + struct wl_pointer *wl_pointer; + struct wl_keyboard *wl_keyboard; + struct wl_touch *wl_touch; + struct window *window; + struct { + EGLDisplay dpy; + EGLContext ctx; + EGLConfig conf; + + PFNEGLCREATEIMAGEKHRPROC create_image; + PFNEGLDESTROYIMAGEKHRPROC destroy_image; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_texture_2d; + } egl; + struct { + GLuint vertex_shader; + GLuint fragment_shader; + GLuint program_object; + GLuint texture; + } gl; +}; + +struct window { + struct display *display; + struct { + GLuint rotation_uniform; + GLuint pos; + GLuint col; + } gl; + int width, height; + struct wl_surface *surface; + struct ivi_surface *ivi_surface; + struct shm_buffer buffers[2]; + struct shm_buffer *prev_buffer; + struct wl_callback *callback; + uint32_t window_frames; + uint32_t window_benchmark_time; + int wait; + struct surface *server_surf; + struct wl_egl_window *native; + EGLSurface egl_surface; + EGLImageKHR egl_img; + struct seat *server_seat; + struct pointer *server_pointer; + bool ready; + uint32_t id_ivisurf; +}; + + +#endif diff --git a/include/wth-server-weston.h b/include/wth-server-weston.h new file mode 100644 index 0000000..50e1b2c --- /dev/null +++ b/include/wth-server-weston.h @@ -0,0 +1,99 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : Header file declare macros, extern functions, data types etc ** +** required to interface with weston compositor at server side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#ifndef WALTHAM_SHM_H_ +#define WALTHAM_SHM_H_ + +#include "wth-server-waltham-comm.h" +/** +* wth_server_weston_shm_attach +* +* attach waltham surface data to weston surface +* +* @param names struct window *window +* uint32_t data_sz +* void * data +* int32_t width +* int32_t height +* int32_t stride +* uint32_t format +* @param value struct window *window - window info pointer +* uint32_t data_sz - buffer data size +* void * data - buffer pointer +* int32_t width - width +* int32_t height -height +* int32_t stride -stride information +* uint32_t format - buffer data format +* @return none +*/ +void wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); + +/** +* wth_server_weston_shm_damage +* +* Send weston surface damage +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_damage(struct window *window); + +/** +* wth_server_weston_shm_commit +* +* Commit weston surface data +* +* @param names struct window *window +* +* @param value struct window *window - window info pointer +* +* @return none +*/ +void wth_server_weston_shm_commit(struct window *window); + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int wth_server_weston_main(void *data); + + +#endif diff --git a/package/config.xml b/package/config.xml deleted file mode 100644 index a8047f7..0000000 --- a/package/config.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Als-meter-demo - - - This is a steering-wheel binding's demo application - TOYOTA - APL 2.0 - - - - - - - - - - - diff --git a/package/icon.svg b/package/icon.svg deleted file mode 100644 index 0004e6b..0000000 --- a/package/icon.svg +++ /dev/null @@ -1,892 +0,0 @@ - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/package/package.pro b/package/package.pro deleted file mode 100644 index a69111f..0000000 --- a/package/package.pro +++ /dev/null @@ -1,19 +0,0 @@ - -DISTFILES = icon.svg config.xml - -copy_icon.target = $$OUT_PWD/root/icon.svg -copy_icon.depends = $$_PRO_FILE_PWD_/icon.svg -copy_icon.commands = $(COPY_FILE) \"$$replace(copy_icon.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_icon.target, /, $$QMAKE_DIR_SEP)\" -QMAKE_EXTRA_TARGETS += copy_icon -PRE_TARGETDEPS += $$copy_icon.target - -copy_config.target = $$OUT_PWD/root/config.xml -copy_config.depends = $$_PRO_FILE_PWD_/config.xml -copy_config.commands = $(COPY_FILE) \"$$replace(copy_config.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_config.target, /, $$QMAKE_DIR_SEP)\" -QMAKE_EXTRA_TARGETS += copy_config -PRE_TARGETDEPS += $$copy_config.target - -wgt.target = package -wgt.commands = wgtpkg-pack -f -o als-meter-demo.wgt root - -QMAKE_EXTRA_TARGETS += wgt diff --git a/package/receiver/config.xml b/package/receiver/config.xml new file mode 100644 index 0000000..640108a --- /dev/null +++ b/package/receiver/config.xml @@ -0,0 +1,17 @@ + + + receiver + + + This is a demo application for waltham-server + TOYOA + APL 2.0 + MIT + + + + + + + + + diff --git a/package/receiver/icon.svg b/package/receiver/icon.svg new file mode 100644 index 0000000..91661a7 --- /dev/null +++ b/package/receiver/icon.svg @@ -0,0 +1,279 @@ + + + +image/svg+xmlMULTIMEDIA + \ No newline at end of file diff --git a/package/root/config.xml b/package/root/config.xml new file mode 100644 index 0000000..41f49ca --- /dev/null +++ b/package/root/config.xml @@ -0,0 +1,17 @@ + + + WALTHAM-SERVER + + + This is a demo application for waltham-server + TOYOA + APL 2.0 + MIT + + + + + + + + + diff --git a/package/root/icon.svg b/package/root/icon.svg new file mode 100644 index 0000000..91661a7 --- /dev/null +++ b/package/root/icon.svg @@ -0,0 +1,279 @@ + + + +image/svg+xmlMULTIMEDIA + \ No newline at end of file diff --git a/protocol/ivi-application.xml b/protocol/ivi-application.xml new file mode 100644 index 0000000..78e2569 --- /dev/null +++ b/protocol/ivi-application.xml @@ -0,0 +1,100 @@ + + + + + Copyright (C) 2013 DENSO CORPORATION + Copyright (c) 2013 BMW Car IT GmbH + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + + + This removes link from ivi_id to wl_surface and destroys ivi_surface. + The ID, ivi_id, is free and can be used for surface_create again. + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface-local coordinates. + + + + + + + + + This interface is exposed as a global singleton. + This interface is implemented by servers that provide IVI-style user interfaces. + It allows clients to associate a ivi_surface with wl_surface. + + + + + + + + + + This request gives the wl_surface the role of an IVI Surface. Creating more than + one ivi_surface for a wl_surface is not allowed. Note, that this still allows the + following example: + + 1. create a wl_surface + 2. create ivi_surface for the wl_surface + 3. destroy the ivi_surface + 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) + + surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + ivi compositor. These ivi_ids are defined as unique in the system to identify + it inside of ivi compositor. The ivi compositor implements business logic how to + set properties of the surface with ivi_id according to status of the system. + E.g. a unique ID for Car Navigation application is used for implementing special + logic of the application about where it shall be located. + The server regards following cases as protocol errors and disconnects the client. + - wl_surface already has an nother role. + - ivi_id is already assigned to an another wl_surface. + + If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, + ivi_id which is assigned to the ivi_surface is free for reuse. + + + + + + + + + diff --git a/sample/als-meter-demo_git.bb b/sample/als-meter-demo_git.bb deleted file mode 100644 index 6dffeab..0000000 --- a/sample/als-meter-demo_git.bb +++ /dev/null @@ -1,21 +0,0 @@ -SUMMARY = "Demo app for streeting-wheel" -DESCRIPTION = "AGL demo app for streeting-wheel" -HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/#/admin/projects/apps/als-meter-demo" -SECTION = "apps" - -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984" - -SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/als-meter-demo;protocol=https;branch=master" -SRCREV = "9457d3ebf0fd63f63f5d8abdd570868c0298a92f" - -PV = "1.0+git${SRCPV}" -S = "${WORKDIR}/git" - -# build-time dependencies -DEPENDS += "qtquickcontrols2 opencv" - -# runtime dependencies -RDEPENDS_${PN} += "agl-service-steering-wheel" - -inherit qmake5 aglwgt diff --git a/src/utils/bitmap.c b/src/utils/bitmap.c new file mode 100644 index 0000000..2c7fdb5 --- /dev/null +++ b/src/utils/bitmap.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 DENSO CORPORATION + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "bitmap.h" +#include + +struct __attribute__ ((__packed__)) BITMAPFILEHEADER { + char bfType[2]; + uint32_t bfSize; + uint16_t bfReserved1; + uint16_t bfReserved2; + uint32_t bfOffBits; +}; + +struct __attribute__ ((__packed__)) BITMAPINFOHEADER { + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + uint16_t biPlanes; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPixPerMeter; + uint32_t biYPixPerMeter; + uint32_t biClrUsed; + uint32_t biClrImporant; +}; + +static void +create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size) +{ + file_header->bfType[0] = 'B'; + file_header->bfType[1] = 'M'; + file_header->bfSize = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER) + + image_size; + file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER) + + sizeof(struct BITMAPINFOHEADER); +} + +static void +create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp) +{ + info_header->biSize = sizeof(struct BITMAPINFOHEADER); + info_header->biWidth = width; + info_header->biHeight = height; + info_header->biPlanes = 1; + info_header->biBitCount = bpp; + info_header->biSizeImage = image_size; +} + +static int +write_bitmap(const char *filename, + const struct BITMAPFILEHEADER *file_header, + const struct BITMAPINFOHEADER *info_header, + const char *buffer) +{ + FILE *fp = fopen(filename, "w"); + if (fp == NULL) { + return -1; + } + + fwrite(file_header, sizeof(struct BITMAPFILEHEADER), 1, fp); + fwrite(info_header, sizeof(struct BITMAPINFOHEADER), 1, fp); + fwrite(buffer, info_header->biSizeImage, 1, fp); + + fclose(fp); + return 0; +} + +int +save_as_bitmap(const char *filename, + const char *buffer, + int32_t image_size, + int32_t width, + int32_t height, + int16_t bpp) +{ + if ((filename == NULL) || (buffer == NULL)) { + return -1; + } + + struct BITMAPFILEHEADER file_header = {}; + struct BITMAPINFOHEADER info_header = {}; + + create_file_header(&file_header, image_size); + create_info_header(&info_header, image_size, width, height, bpp); + return write_bitmap(filename, &file_header, &info_header, buffer); +} diff --git a/src/utils/os-compatibility.c b/src/utils/os-compatibility.c new file mode 100644 index 0000000..d9502e5 --- /dev/null +++ b/src/utils/os-compatibility.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os-compatibility.h" + +int +os_fd_set_cloexec(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + return -1; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + return -1; + + return 0; +} + +static int +set_cloexec_or_close(int fd) +{ + if (os_fd_set_cloexec(fd) != 0) { + close(fd); + return -1; + } + return fd; +} + +int +os_socketpair_cloexec(int domain, int type, int protocol, int *sv) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (ret == 0 || errno != EINVAL) + return ret; +#endif + + ret = socketpair(domain, type, protocol, sv); + if (ret < 0) + return ret; + + sv[0] = set_cloexec_or_close(sv[0]); + sv[1] = set_cloexec_or_close(sv[1]); + + if (sv[0] != -1 && sv[1] != -1) + return 0; + + close(sv[0]); + close(sv[1]); + return -1; +} + +int +os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int +os_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} + +#ifndef HAVE_STRCHRNUL +char * +strchrnul(const char *s, int c) +{ + while (*s && *s != c) + s++; + return (char *)s; +} +#endif diff --git a/src/wth-server-gst.cpp b/src/wth-server-gst.cpp new file mode 100644 index 0000000..c282773 --- /dev/null +++ b/src/wth-server-gst.cpp @@ -0,0 +1,1326 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* + ** ** + ** SRC-MODULE: ** + ** ** + ** TARGET : linux ** + ** ** + ** PROJECT : waltham-server ** + ** ** + ** AUTHOR : ** + ** ** + ** ** + ** ** + ** PURPOSE : This file is acts as interface to weston compositor at server ** + ** side ** + ** ** + ** REMARKS : ** + ** ** + ** PLATFORM DEPENDANT [yes/no]: yes ** + ** ** + ** TO BE CHANGED BY USER [yes/no]: no ** + ** ** + *******************************************************************************/ + +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +// Error avoidance for dual declaration of strchrnul() +#define HAVE_STRCHRNUL 1 + +extern "C" { +#include "wth-server-waltham-comm.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" +} + +// Applied to Windowmanager, HomeScreen +#include "libwindowmanager.h" +#include +#include "hmi-debug.h" + + +LibHomeScreen* hs; +LibWindowmanager *wm; +extern bool gIsDraw; +extern uint32_t g_id_ivisurf; + +long port = 1700; +std::string token = "wm"; +std::string app_name = "receiver"; + +static int running = 1; + +extern bool get_verbosity(void); +extern int verbose; + +typedef struct _GstAppContext +{ + GMainLoop *loop; + GstBus *bus; + GstElement *pipeline; + GstElement *sink; + GstSample *sample; + GstBuffer *gstbuffer; + GstVideoMeta *vmeta; + + int dma_fd[2]; + + struct display *display; + struct window *window; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int wait; + + GstVideoInfo info; + uint32_t format; + bool no_dma_buf; +}GstAppContext; + +static const gchar *vertex_shader_str = +"attribute vec4 a_position; \n" +"attribute vec2 a_texCoord; \n" +"varying vec2 v_texCoord; \n" +"void main() \n" +"{ \n" +" gl_Position = a_position; \n" +" v_texCoord = a_texCoord; \n" +"} \n"; + +static const gchar *fragment_shader_str = +"#ifdef GL_ES \n" +"precision mediump float; \n" +"#endif \n" +"varying vec2 v_texCoord; \n" +"uniform sampler2D tex; \n" +"void main() \n" +"{ \n" +"vec2 uv; \n" +"uv = v_texCoord.xy; \n" +"vec4 c = texture2D(tex, uv); \n" +"gl_FragColor = c; \n" +"} \n"; + +/* + * pointer callbcak functions + */ + static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +static int +drm_fourcc_from_gst_format(GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + return DRM_FORMAT_RGB565; + + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + return DRM_FORMAT_BGR888; + + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_AYUV: + return DRM_FORMAT_ARGB8888; + + case GST_VIDEO_FORMAT_GRAY8: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + return DRM_FORMAT_GR88; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + return DRM_FORMAT_R8; + + case GST_VIDEO_FORMAT_NV12: + return DRM_FORMAT_NV12; + + default: + return -1; + } +} + +gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) +{ + GstAppContext *gstctx = p; + + fprintf(stderr, "mesage: %s\n", GST_MESSAGE_TYPE_NAME(message)); + + switch( GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: + { + GError *err; + gchar *debug; + + gst_message_parse_error(message, &err, &debug); + g_print("ERROR: %s\n", err->message); + + g_error_free(err); + g_free(debug); + g_main_loop_quit(gstctx->loop); + break; + } + + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate, newstate; + + gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); + fprintf(stderr, "#%s state changed\n", GST_MESSAGE_SRC_NAME(message)); + switch (newstate){ + case GST_STATE_NULL: + fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_READY: + fprintf(stderr, "%s: state is READY\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PAUSED: + fprintf(stderr, "%s: state is PAUSED\n", GST_MESSAGE_SRC_NAME(message)); + break; + case GST_STATE_PLAYING: + fprintf(stderr, "%s: state is PLAYING\n", GST_MESSAGE_SRC_NAME(message)); + break; + } + break; + } + default: + fprintf(stderr, "Unhandled message\n"); + break; + } + fprintf(stderr, "-----------------\n"); +} + +EGLImageKHR create_eglImage(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + + uint32_t n_planes = vmeta->n_planes; + EGLint attribs[30]; + int fourcc; + int atti = 0; + + fourcc = drm_fourcc_from_gst_format(vmeta->format); + + n_planes = GST_VIDEO_INFO_N_PLANES(&(gstctx->info)); + + int width = GST_VIDEO_INFO_WIDTH(&(gstctx->info)); + int height = GST_VIDEO_INFO_HEIGHT(&(gstctx->info)); + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = vmeta->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = vmeta->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = fourcc; + + /* + * Offset value for both the planes i.e Y and UV is "0" + * The omxdec gives the output is 2 different memory blocks, + * One for Y -> dmafd[0] and other for UV -> dmafd[1] + */ + + if (n_planes > 0) { + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = gstctx->dma_fd[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = vmeta->stride[0]; + } + + if (n_planes > 1) { + attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; + attribs[atti++] = gstctx->dma_fd[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; + attribs[atti++] = 0; + attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; + attribs[atti++] = vmeta->stride[1]; + } + + attribs[atti++] = EGL_NONE; + + return display->egl.create_image(display->egl.dpy, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, + attribs); +} + +static int +redraw(GstAppContext* gstctx) +{ + struct display *display = gstctx->display; + GstVideoMeta *vmeta = gstctx->vmeta; + struct window *window = display->window; + GLfloat vVertices[] = { -1.0f, 1.0f, 1.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -1.0f, -1.0f, 1.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 1.0f, -1.0f, 1.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 1.0f, 1.0f, 1.0f, // Position 3, skewed a bit + 1.0f, 0.0f // TexCoord 3 + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + glViewport(0,0,vmeta->width,vmeta->height); + wl_egl_window_resize(window->native,vmeta->width,vmeta->height,0,0); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(display->gl.program_object); + + /* Load the vertex position */ + GLint positionLoc = glGetAttribLocation(display->gl.program_object, "a_position"); + glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + /* Load the texture coordinate */ + GLint texCoordLoc = glGetAttribLocation(display->gl.program_object, "a_texCoord"); + glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + glEnableVertexAttribArray(positionLoc); + glEnableVertexAttribArray(texCoordLoc); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, display->gl.texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + if(gstctx->no_dma_buf == false && window->egl_img != NULL ) + { + display->egl.image_texture_2d(GL_TEXTURE_2D, window->egl_img); + } + else + { + GstMapInfo map; + gst_buffer_map(gstctx->gstbuffer, &map, GST_MAP_READ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, vmeta->width, vmeta->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)map.data); + gst_buffer_unmap(gstctx->gstbuffer, &map); + } + + /* Set the texture sampler to texture unit 0 */ + GLint tex = glGetUniformLocation(display->gl.program_object, "tex"); + glUniform1i(tex, 0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); +} + +static GstFlowReturn +appsink_callback(GstElement *object, gpointer *data) +{ + wth_verbose("%s >>> \n",__func__); + int ret; + //GstAppContext *gstctx = (struct gstApplContext *)data; + GstAppContext *gstctx = (GstAppContext *)data; + GstSample *sample; + GstBuffer *gstbuffer; + GstMemory *mem; + int i; + int n_mem; + + sample = gst_app_sink_pull_sample((GstAppSink*)((void*)object)); + if(sample == NULL) { + wth_error("No frame received\n"); + return -1; + } + else { + wth_verbose("Frame received\n"); + } + + /* get dmabuf fd from gstbuffer */ + gstbuffer = gst_sample_get_buffer(sample); + if(!gstbuffer){ + wth_error("Cannot get buffer from sample\n"); + } + gstctx->vmeta = gst_buffer_get_video_meta(gstbuffer); + if(gstctx->vmeta==NULL){ + wth_error("no metadata on buffer\n"); + } + + n_mem = gst_buffer_n_memory(gstbuffer); + if (n_mem < 1) { + wth_error("Buffer with no mem!\n"); + } + + for (i = 0; i < n_mem; i++) { + /* get dmabuf fd from gstbuffer */ + mem = gst_buffer_peek_memory (gstbuffer, i); + if (!gst_is_dmabuf_memory(mem)) { + wth_verbose("Memory is not of dmabuf type \n"); + gstctx->no_dma_buf = true; + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; + } + gstctx->dma_fd[i] = gst_dmabuf_memory_get_fd(mem); + } + + if (gstctx->dma_fd[0] < 0 || gstctx->dma_fd[1] < 0 ) { + wth_error("dma fd is null \n"); + return GST_FLOW_ERROR; + } + + gst_buffer_ref(gstbuffer); + gstctx->gstbuffer = gstbuffer; + gstctx->sample = sample; + + /* wake render thread up */ + gstctx->wait = 0; + pthread_cond_signal(&gstctx->cond); + wth_verbose(" <<< %s \n",__func__); + return GST_FLOW_OK; +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + /* stub */ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + /* stub */ +} +void +wth_server_weston_shm_damage(struct window *window) +{ + /* stub */ +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + /* stub */ +} + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +init_egl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint major, minor, count; + EGLBoolean ret; + + display->egl.dpy = eglGetDisplay(display->display); + assert(display->egl.dpy); + + ret = eglInitialize(display->egl.dpy, &major, &minor); + assert(ret == EGL_TRUE); + ret = eglBindAPI(EGL_OPENGL_ES_API); + assert(ret == EGL_TRUE); + + ret = eglChooseConfig(display->egl.dpy, config_attribs, + &display->egl.conf, 1, &count); + assert(ret && count >= 1); + + display->egl.ctx = eglCreateContext(display->egl.dpy, + display->egl.conf, + EGL_NO_CONTEXT, context_attribs); + assert(display->egl.ctx); + + eglSwapInterval(display->egl.dpy, 1); + + display->egl.create_image = + (void *) eglGetProcAddress("eglCreateImageKHR"); + assert(display->egl.create_image); + + display->egl.image_texture_2d = + (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES"); + assert(display->egl.image_texture_2d); + + display->egl.destroy_image = + (void *) eglGetProcAddress("eglDestroyImageKHR"); + assert(display->egl.destroy_image); +} + +GLuint load_shader(GLenum type, const char *shaderSrc) +{ + wth_verbose("%s >>> \n",__func__); + GLuint shader; + GLint compiled; + + /* Create the shader object */ + shader = glCreateShader(type); + if (shader == 0) + { + printf("\n Failed to create shader \n"); + return 0; + } + /* Load the shader source */ + glShaderSource(shader, 1, &shaderSrc, NULL); + /* Compile the shader */ + glCompileShader(shader); + /* Check the compile status */ + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc (sizeof(char) * infoLen ); + glGetShaderInfoLog(shader, infoLen, NULL, infoLog); + fprintf(stderr, "Error compiling shader:%s\n",infoLog); + free(infoLog); + } + glDeleteShader(shader); + return 0; + } + return shader; +} + +void init_gl(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + GLint linked; + + /* load vertext/fragment shader */ + display->gl.vertex_shader = load_shader(GL_VERTEX_SHADER, vertex_shader_str); + display->gl.fragment_shader = load_shader(GL_FRAGMENT_SHADER, fragment_shader_str); + + /* Create the program object */ + display->gl.program_object = glCreateProgram(); + if (display->gl.program_object == 0) + { + fprintf(stderr, "error program object\n"); + return; + } + + glAttachShader(display->gl.program_object, display->gl.vertex_shader); + glAttachShader(display->gl.program_object, display->gl.fragment_shader); + /* Bind vPosition to attribute 0 */ + glBindAttribLocation(display->gl.program_object, 0, "a_position"); + /* Link the program */ + glLinkProgram(display->gl.program_object); + /* Check the link status */ + glGetProgramiv(display->gl.program_object, GL_LINK_STATUS, &linked); + if (!linked) + { + GLint infoLen = 0; + glGetProgramiv(display->gl.program_object, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char*)malloc(sizeof(char) * infoLen); + glGetProgramInfoLog(display->gl.program_object, infoLen, NULL, infoLog); + fprintf(stderr, "Error linking program:%s\n", infoLog); + free(infoLog); + } + glDeleteProgram(display->gl.program_object); + } + + glGenTextures(1, &display->gl.texture); + + return; +} + +static void +create_surface(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct display *display = window->display; + int ret; + + window->surface = wl_compositor_create_surface(display->compositor); + assert(window->surface); + + window->native = wl_egl_window_create(window->surface, + window->width, window->height); + assert(window->native); + + window->egl_surface = eglCreateWindowSurface(display->egl.dpy, + display->egl.conf, + (NativeWindowType)window->native, NULL); + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = g_id_ivisurf; //window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + } else { + assert(0); + } + ret = eglMakeCurrent(display->egl.dpy, window->egl_surface, + window->egl_surface, display->egl.ctx); + assert(ret == EGL_TRUE); + + glClearColor(0.5, 0.5, 0.5, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + eglSwapBuffers(display->egl.dpy, window->egl_surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + + window->display = display; + window->width = width; + window->height = height; + window->window_frames = 0; + window->window_benchmark_time = 0; + + create_surface(window); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +void *stream_thread(void *data) +{ + wth_verbose("%s >>> \n",__func__); + GMainLoop *loop = data; + g_main_loop_run(loop); + wth_verbose(" <<< %s \n",__func__); +} + + + +static GstPadProbeReturn +pad_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + wth_verbose("%s >>> \n",__func__); + GstAppContext *dec = user_data; + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); + GstCaps *caps; + + (void)pad; + + if (GST_EVENT_TYPE(event) != GST_EVENT_CAPS) + return GST_PAD_PROBE_OK; + + gst_event_parse_caps(event, &caps); + + if (!caps) { + GST_ERROR("caps event without caps"); + return GST_PAD_PROBE_OK; + } + + if (!gst_video_info_from_caps(&dec->info, caps)) { + GST_ERROR("caps event with invalid video caps"); + return GST_PAD_PROBE_OK; + } + + switch (GST_VIDEO_INFO_FORMAT(&(dec->info))) { + case GST_VIDEO_FORMAT_I420: + dec->format = DRM_FORMAT_YUV420; + break; + case GST_VIDEO_FORMAT_NV12: + dec->format = DRM_FORMAT_NV12; + break; + case GST_VIDEO_FORMAT_YUY2: + dec->format = DRM_FORMAT_YUYV; + break; + default: + GST_ERROR("unknown format\n"); + return GST_PAD_PROBE_OK; + } + wth_verbose(" <<< %s \n",__func__); + return GST_PAD_PROBE_OK; +} + +// Applied to WM, HS +int +init_wm(LibWindowmanager *wm, struct window *window) +{ + HMI_DEBUG("waltham-server","called"); + char* surfaceIdStr; + + wth_verbose("app:%s port:%d token:%s \n", app_name.c_str(), port, token.c_str()); + + if (wm->init(port, token.c_str()) != 0) { + HMI_ERROR("waltham-server","wm init failed. "); + return -1; + } + + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + g_id_ivisurf = wm->requestSurface(obj); + if(g_id_ivisurf < 0) + { + HMI_ERROR("waltham-server","requestSurface failed: %d ", g_id_ivisurf); + return -1; + } + HMI_DEBUG("waltham-server","IVI_SURFACE_ID: %d ", g_id_ivisurf); + + wm->set_event_handler(LibWindowmanager::Event_Active, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got activated! ", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Inactive, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got inactivated!", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Visible, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got visibled!", label); + }); + + wm->set_event_handler(LibWindowmanager::Event_Invisible, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got invisibled!", label); + gIsDraw = false; + }); + + wm->set_event_handler(LibWindowmanager::Event_SyncDraw, [wm, window](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + const char *area = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingArea)); + + HMI_DEBUG("waltham-server","Layout:%s x:%d y:%d w:%d h:%d ", area, 0, 0, 640, 720); + wl_egl_window_resize(window->native, 640, 720, 0, 0); + window->width = 640; + window->height = 720; + //if (!window->fullscreen) + // window->window_size = window->geometry; + gIsDraw = true; + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + wm->endDraw(obj); + }); + + wm->set_event_handler(LibWindowmanager::Event_FlushDraw, [wm](json_object *object) { + const char *label = json_object_get_string( + json_object_object_get(object, wm->kKeyDrawingName)); + HMI_DEBUG("waltham-server","Surface %s got flushdraw! ", label); + }); + + return 0; +} + +int +init_hs(LibHomeScreen* hs) +{ + if(hs->init(port, token)!=0) + { + HMI_ERROR("waltham-server","homescreen init failed. "); + return -1; + } + + hs->set_event_handler(LibHomeScreen::Event_TapShortcut, [](json_object *object){ + const char *application_name = json_object_get_string( + json_object_object_get(object, "application_name")); + HMI_DEBUG("waltham-server","Event_TapShortcut application_name = %s ", application_name); + if(strcmp(application_name, app_name.c_str()) == 0) + { + HMI_DEBUG("waltham-server","try to activesurface %s ", app_name.c_str()); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("split.sub")); + gIsDraw = false; + fprintf(stderr, "@@@@@ called activate in tapshortcut handler\n"); + wm->activateWindow(obj); + } + }); + + hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, [](json_object *object){ + const char *display_message = json_object_get_string( + json_object_object_get(object, "display_message")); + HMI_DEBUG("waltham-server","Event_OnScreenMessage display_message = %s ", display_message); + }); + + return 0; +} + +GstAppContext gstctx; // @@@@@ +void init_receiver(struct window *window) +{ + struct sigaction sigint; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + memset(&gstctx, 0, sizeof(gstctx)); + /* Initialization for window creation */ + gstctx.display = create_display(); + init_egl(gstctx.display); + + /* windowmanager, homescreen */ + wm = new LibWindowmanager(); + hs = new LibHomeScreen(); + + if(init_wm(wm, window)!=0){ + // error process + wth_verbose("Error in init_wm.\n"); + return -1; + } + + if(init_hs(hs)!=0){ + // error process + wth_verbose("Error in init_hs.\n"); + return -1; + } + + /* ToDo: fix the hardcoded value of width, height */ +// create_window(window, gstctx.display,1920,1080); + create_window(window, gstctx.display,640,720); + init_gl(gstctx.display); + gstctx.window = window; + + gstctx.display->window = window; + + wth_verbose("display %p\n", gstctx.display); + wth_verbose("display->window %p\n", gstctx.display->window); + wth_verbose("window %p\n", window); + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* create gstreamer pipeline */ + gst_init(NULL, NULL); + gstctx.loop = g_main_loop_new(NULL, FALSE); + + /* Read pipeline from file */ + pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); + if (pFile==NULL){ + fprintf(stderr, "failed to open file\n"); + return -1; + } + + /* obtain file size */ + fseek (pFile , 0 , SEEK_END); + lSize = ftell (pFile); + rewind (pFile); + + /* allocate memory to contain the whole file */ + pipe = (char*) zalloc (sizeof(char)*lSize); + if (pipe == NULL){ + fprintf(stderr,"Cannot allocate memory\n"); + return -1; + } + + /* copy the file into the buffer */ + res = fread (pipe,1,lSize,pFile); + if (res != lSize){ + fprintf(stderr,"File read error\n"); + return -1; + } + + wth_verbose("Gst Pipeline=%s",pipe); + /* close file */ + fclose (pFile); + + /* parse the pipeline */ + gstctx.pipeline = gst_parse_launch(pipe, &gerror); + + if(!gstctx.pipeline) + fprintf(stderr,"Could not create gstreamer pipeline.\n"); + free(pipe); + + gstctx.bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx.pipeline)); + gst_bus_add_watch(gstctx.bus, bus_message, &gstctx); + fprintf(stderr, "registered bus signal\n"); + + gstctx.sink = gst_bin_get_by_name(GST_BIN(gstctx.pipeline), "sink"); + g_object_set(G_OBJECT(gstctx.sink), "emit-signals", TRUE, NULL); + g_signal_connect(gstctx.sink, "new-sample", G_CALLBACK(appsink_callback), &gstctx); + g_object_set(G_OBJECT(gstctx.sink), "drop", TRUE, "max-buffers",-1, NULL); + gst_pad_add_probe(gst_element_get_static_pad(gstctx.sink, "sink"), + GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + pad_probe, &gstctx, NULL); + + fprintf(stderr, "set state as playing\n"); + gst_element_set_state((GstElement*)((void*)gstctx.pipeline), GST_STATE_PLAYING); + + wth_verbose("wl_display_dispatch_pending >>>\n"); + wl_display_dispatch_pending(gstctx.display->display); + wth_verbose("<<< wl_display_dispatch_pending; redraw >>>\n"); + //redraw(&gstctx); + wth_verbose("<<< redraw\n"); + json_object *obj = json_object_new_object(); + json_object_object_add(obj, wm->kKeyDrawingName, json_object_new_string(app_name.c_str())); + json_object_object_add(obj, wm->kKeyDrawingArea, json_object_new_string("normal.full")); + wth_verbose("activateWindow >>>\n"); + fprintf(stderr, "@@@@@ called activate in init_receiver\n"); + wm->activateWindow(obj); +} + +/** + * wth_server_weston_main + * + * This is the main function which will handle connection to the compositor at server side + * + * @param names void *data + * @param value struct window data + * @return 0 on success, -1 on error + */ +int +wth_server_weston_main(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct sigaction sigint; + pthread_t pthread; +// GstAppContext gstctx; + int ret = 0; + GError *gerror = NULL; + char * pipe = NULL; + FILE *pFile; + long lSize; + size_t res; + + pthread_mutex_init(&gstctx.mutex, NULL); + pthread_cond_init(&gstctx.cond, NULL); + + pthread_create(&pthread, NULL, &stream_thread, gstctx.loop); + + fprintf(stderr, "rendering part\n"); + + gstctx.wait = 1; + pthread_mutex_lock(&gstctx.mutex); + + while (running && ret != -1) { + wth_verbose("in render loop\n"); + ret = wl_display_dispatch(gstctx.display->display); + if(gstctx.wait == 1) { + wth_verbose("cond wait\n"); + pthread_cond_wait(&gstctx.cond, &gstctx.mutex); + } + + if(gstctx.no_dma_buf == false) + { + wth_verbose("create egl image\n"); + window->egl_img = create_eglImage(&gstctx); + } + + wth_verbose("redraw\n"); + redraw(&gstctx); + wth_verbose("fin redraw\n"); + gstctx.display->egl.destroy_image(gstctx.display->egl.dpy, window->egl_img); + gst_buffer_unref(gstctx.gstbuffer); + gst_sample_unref(gstctx.sample); + gstctx.wait = 1; + } + pthread_mutex_unlock(&gstctx.mutex); + + wth_verbose("wth_server_gst_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(gstctx.display); + + wth_verbose(" <<< %s \n",__func__); + + return 0; +} diff --git a/src/wth-server-main.cpp b/src/wth-server-main.cpp new file mode 100644 index 0000000..ab86304 --- /dev/null +++ b/src/wth-server-main.cpp @@ -0,0 +1,372 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file handles connection with remote-client ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +extern "C" { +#include "wth-server-waltham-comm.h" +} +#include + +// Applied to Windowmanager, HomeScreen +#include "libwindowmanager.h" +#include + +#define MAX_EPOLL_WATCHES 2 + +extern long port; +extern std::string token; +extern std::string app_name; + +int verbose = 0; +uint16_t tcp_port = 34400; + +bool gIsDraw = false; + +uint32_t g_id_ivisurf = 9009; + +/** get verbosity + */ +bool +get_verbosity() +{ + if (verbose == 1) + { + return true; + } + else + { + return false; + } +} + +/** Print out the application help + */ +static void usage(void) +{ + printf("Usage: waltham server [options]\n"); + printf("Options:\n"); + printf(" -p --port number TCP port number\n"); + printf(" -h --help Usage\n"); + printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity()); +} + +static struct option long_options[] = { + {"port", required_argument, 0, 'p'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} +}; + +/** + * parse_args + * + * Parses the application arguments + * The arguments are parsed and saved in static structure for future use. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +static int parse_args(int argc, char *argv[]) +{ + int c = -1; + int long_index = 0; + + while ((c = getopt_long(argc, + argv, + "p:vh", + long_options, + &long_index)) != -1) + { + switch (c) + { + case 'p': + tcp_port = atoi(optarg); + break; + case 'v': + verbose=1; + break; + case 'h': + usage(); + return -1; + default: + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + if (tcp_port == 0) + { + wth_error("TCP port not set \n"); + wth_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + + return 0; +} + +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +/** +* listen_socket_handle_data +* +* Handles all incoming events on socket +* +* @param names struct watch *w ,uint32_t events +* @param value pointer to watch connection it holds server information, Incoming events information +* @return none +*/ +static void +listen_socket_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct server *srv = container_of(w, struct server, listen_watch); + + if (events & EPOLLERR) { + wth_error("Listening socket errored out.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLHUP) { + wth_error("Listening socket hung up.\n"); + srv->running = false; + + return; + } + + if (events & EPOLLIN) + { + wth_verbose("EPOLLIN evnet received. \n"); + server_accept_client(srv); + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_mainloop +* +* This is the main loop, which will flush all pending clients requests and +* listen to input events from socket +* +* @param names void *data +* @param value pointer to server struct - +* struct holds the client connection information +* @return none +*/ +static void +server_mainloop(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + + struct epoll_event ee[MAX_EPOLL_WATCHES]; + struct watch *w; + int count; + int i; + + srv->running = true; + + while (srv->running) { + /* Run any idle tasks at this point. */ + + server_flush_clients(srv); + + /* Wait for events or signals */ + count = epoll_wait(srv->epoll_fd, + ee, ARRAY_LENGTH(ee), -1); + if (count < 0 && errno != EINTR) { + perror("Error with epoll_wait"); + break; + } + + /* Handle all fds, both the listening socket + * (see listen_socket_handle_data()) and clients + * (see connection_handle_data()). + */ + for (i = 0; i < count; i++) { + w = ee[i].data.ptr; + w->cb(w, ee[i].events); + } + } + wth_verbose(" <<< %s \n",__func__); +} + +static int +server_listen(uint16_t tcp_port) +{ + wth_verbose("%s >>> \n",__func__); + int fd; + int reuse = 1; + struct sockaddr_in addr; + + fd = socket(AF_INET, SOCK_STREAM, 0); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(tcp_port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse); + + if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) { + wth_error("Failed to bind to port %d", tcp_port); + close(fd); + return -1; + } + + if (listen(fd, 1024) < 0) { + wth_error("Failed to listen to port %d", tcp_port); + close (fd); + return -1; + } + + wth_verbose(" <<< %s \n",__func__); + return fd; +} + +static bool *signal_int_handler_run_flag; + +static void +signal_int_handler(int signum) +{ + wth_verbose("%s >>> \n",__func__); + if (!*signal_int_handler_run_flag) + abort(); + + *signal_int_handler_run_flag = false; + wth_verbose(" <<< %s \n",__func__); +} + +static void +set_sigint_handler(bool *running) +{ + wth_verbose("%s >>> \n",__func__); + struct sigaction sigint; + + signal_int_handler_run_flag = running; + sigint.sa_handler = signal_int_handler; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + wth_verbose(" <<< %s \n",__func__); +} + + +struct window g_window; // @@@@@ +extern void init_receiver(struct window *window);// @@@@@ +/** +* main +* +* waltham server main function, it accepts tcp port number as argument. +* Establishes connection on the port and listen to port for incoming connection +* request from waltham clients +* +* @param names argv - argument list and argc -argument count +* @param value tcp port number as argument +* @return 0 on success, -1 on error +*/ +int +main(int argc, char *argv[]) +{ + struct server srv = { 0 }; + struct client *c; + + wth_verbose("%s >>> \n",__func__); + + if(argc > 2) + { + if(std::string(argv[0]).find("receiver") != std::string::npos) + app_name = std::string("receiver"); + port = strtol(argv[1], NULL, 10); + token = argv[2]; + } + + wth_verbose("app:%s port:%d token:%s \n", app_name.c_str(), port, token.c_str()); +#if 0 + /* Get command line arguments */ + if (parse_args(argc, argv) != 0) + { + return -1; + } +#endif + + set_sigint_handler(&srv.running); + + wl_list_init(&srv.client_list); + + srv.epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (srv.epoll_fd == -1) { + perror("Error on epoll_create1"); + exit(1); + } + + srv.listen_fd = server_listen(tcp_port); + if (srv.listen_fd < 0) { + perror("Error setting up listening socket"); + exit(1); + } + + srv.listen_watch.server = &srv; + srv.listen_watch.cb = listen_socket_handle_data; + srv.listen_watch.fd = srv.listen_fd; + if (watch_ctl(&srv.listen_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + perror("Error setting up listen polling"); + exit(1); + } + + init_receiver(&g_window); + + wth_verbose("Waltham server listening on TCP port %u...\n",tcp_port); + + server_mainloop(&srv); + + /* destroy all things */ + wl_list_last_until_empty(c, &srv.client_list, link) + client_destroy(c); + + close(srv.listen_fd); + close(srv.epoll_fd); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} diff --git a/src/wth-server-waltham-comm.cpp b/src/wth-server-waltham-comm.cpp new file mode 100644 index 0000000..6e3b08c --- /dev/null +++ b/src/wth-server-waltham-comm.cpp @@ -0,0 +1,1202 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file acts as interface to waltham IPC library ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ +extern "C" { +#include "wth-server-waltham-comm.h" +} +extern int wth_server_weston_main(struct window *); + +extern void wth_server_weston_shm_attach(struct window *, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format); +extern void wth_server_weston_shm_damage(struct window *); +extern void wth_server_weston_shm_commit(struct window *); + +extern bool get_verbosity(void); +extern int verbose; + +// container_of modified for C->C++ +/* +#undef container_of +#undef offsetof + +template +size_t offsetof(const M P::*member) +{ + return (size_t) &( reinterpret_cast(0)->*member); +} +template +P* container_of(M* ptr, const M P::*member) +{ + return (P*)( (char*)ptr - offsetof(member)); +} +*/ +typedef struct buffer Buffer; + +/* + * utility functions + */ +static int +watch_ctl(struct watch *w, int op, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct epoll_event ee; + + ee.events = events; + ee.data.ptr = w; + wth_verbose(" <<< %s \n",__func__); + return epoll_ctl(w->server->epoll_fd, op, w->fd, &ee); +} + +static void +client_post_out_of_memory(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct wth_display *disp; + + disp = wth_connection_get_display(c->connection); + wth_object_post_error((struct wth_object *)disp, 1, + "out of memory"); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham surface implementation + */ +static void +surface_destroy(struct surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("surface %p destroy\n", surface->obj); + + wthp_surface_free(surface->obj); + wl_list_remove(&surface->link); + free(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_destroy(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + + assert(wthp_surface == surface->obj); + + surface_destroy(surface); + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_attach(struct wthp_surface *wthp_surface, + struct wthp_buffer *wthp_buf, int32_t x, int32_t y) +{ + wth_verbose("%s >>> \n",__func__); + struct buffer *buffr = wth_object_get_user_data((struct wth_object *)wthp_buf); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + struct buffer *buf = NULL; + + //buf = container_of(wthp_buf, struct buffer, obj); + //buf = container_of(wthp_buf, &buffer::obj); + uint32_t *tmp_data_sz = (uint32_t *)wthp_buf + sizeof(struct wthp_buffer *); + buf = container_of(tmp_data_sz, struct buffer, data_sz); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_attach(surf->shm_window, + buf->data_sz, + buf->data, + buf->width, + buf->height, + buf->stride, + buf->format); + + wthp_buffer_send_complete(wthp_buf, 0); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_damage(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("surface %p damage(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_damage(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_frame(struct wthp_surface *wthp_surface, + struct wthp_callback *callback) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("surface %p callback(%p)\n",wthp_surface, callback); + + surf->cb = callback; + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_opaque_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_opaque_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_set_input_region(struct wthp_surface *wthp_surface, + struct wthp_region *region) +{ + wth_verbose("surface %p set_input_region(%p)\n", + wthp_surface, region); +} + +static void +surface_handle_commit(struct wthp_surface *wthp_surface) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surf = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("commit %p\n",wthp_surface); + + if (surf->ivi_id != 0) { + wth_server_weston_shm_commit(surf->shm_window); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +surface_handle_set_buffer_transform(struct wthp_surface *wthp_surface, + int32_t transform) +{ + wth_verbose("surface %p et_buffer_transform(%d)\n", + wthp_surface, transform); +} + +static void +surface_handle_set_buffer_scale(struct wthp_surface *wthp_surface, + int32_t scale) +{ + wth_verbose("surface %p set_buffer_scale(%d)\n", + wthp_surface, scale); +} + +static void +surface_handle_damage_buffer(struct wthp_surface *wthp_surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("surface %p damage_buffer(%d, %d, %d, %d)\n", + wthp_surface, x, y, width, height); +} + +static const struct wthp_surface_interface surface_implementation = { + surface_handle_destroy, + surface_handle_attach, + surface_handle_damage, + surface_handle_frame, + surface_handle_set_opaque_region, + surface_handle_set_input_region, + surface_handle_commit, + surface_handle_set_buffer_transform, + surface_handle_set_buffer_scale, + surface_handle_damage_buffer +}; + + +/* BEGIN wthp_region implementation */ + +static void +buffer_handle_destroy(struct wthp_buffer *wthp_buffer) +{ + struct buffer *buf = wth_object_get_user_data((struct wth_object *)wthp_buffer); + + wthp_buffer_free(wthp_buffer); + wl_list_remove(&buf->link); + free(buf); +} + +static const struct wthp_buffer_interface buffer_implementation = { + buffer_handle_destroy +}; + +/* END wthp_region implementation */ + +/* BEGIN wthp_blob_factory implementation */ + +static void +blob_factory_create_buffer(struct wthp_blob_factory *blob_factory, + struct wthp_buffer *wthp_buffer, uint32_t data_sz, void *data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + struct blob_factory *blob = wth_object_get_user_data((struct wth_object *)blob_factory); + struct buffer *buffer; + + + wth_verbose("wthp_blob_factory %p create_buffer(%p, %d, %p, %d, %d, %d, %d)\n", + blob_factory, wthp_buffer, data_sz, data, width, height, stride, format); + + buffer = zalloc(sizeof *buffer); + if (!buffer) { + client_post_out_of_memory(blob->client); + return; + } + + wl_list_insert(&blob->client->buffer_list, &buffer->link); + + buffer->data_sz = data_sz; + buffer->data = data; + buffer->width = width; + buffer->height = height; + buffer->stride = stride; + buffer->format = format; + buffer->obj = wthp_buffer; + + wthp_buffer_set_interface(wthp_buffer, &buffer_implementation, buffer); +} + +static const struct wthp_blob_factory_interface blob_factory_implementation = { + blob_factory_create_buffer +}; + +static void +client_bind_blob_factory(struct client *c, struct wthp_blob_factory *obj) +{ + struct blob_factory *blob; + + blob = zalloc(sizeof *blob); + if (!blob) { + client_post_out_of_memory(c); + return; + } + + blob->obj = obj; + blob->client = c; + wl_list_insert(&c->compositor_list, &blob->link); + + wthp_blob_factory_set_interface(obj, &blob_factory_implementation, + blob); + fprintf(stderr, "client %p bound wthp_blob_factory\n", c); +} + +/* + * waltam ivi surface implementation + */ +static void +wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) +{ + wth_verbose("%s >>> \n",__func__); + struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); + free(ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_surface_interface wthp_ivi_surface_implementation = { + wthp_ivi_surface_destroy, +}; + + +/* + * waltham ivi application implementation + */ +static void +wthp_ivi_application_surface_create(struct wthp_ivi_application * ivi_application, uint32_t ivi_id, + struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("ivi_application %p surface_create(%d, %p, %p)\n", + ivi_application, ivi_id, wthp_surface, obj); + struct application *app = wth_object_get_user_data((struct wth_object *)ivi_application); + struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); + wth_verbose("----------------------------------\n\n\n"); + wth_verbose("surface [%p]\n", surface); + wth_verbose("shm_window [%p]\n\n\n", surface->shm_window); + wth_verbose("----------------------------------\n"); + + surface->ivi_id = ivi_id + 100; + surface->shm_window->id_ivisurf = surface->ivi_id; + struct ivisurface *ivisurf; + + ivisurf = zalloc(sizeof *ivisurf); + if (!ivisurf) { + return; + } + + ivisurf->obj = obj; + ivisurf->surf = surface; + + wth_server_weston_main(surface->shm_window); + + while (!surface->shm_window->ready) + usleep(1); + + wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, + ivisurf); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_ivi_application_interface wthp_ivi_application_implementation = { + wthp_ivi_application_surface_create, +}; + +static void +client_bind_wthp_ivi_application(struct client *c, struct wthp_ivi_application *obj) +{ + wth_verbose("%s >>> \n",__func__); + + struct application *app; + + app = zalloc(sizeof *app); + if (!app) { + client_post_out_of_memory(c); + return; + } + + app->obj = obj; + app->client = c; + wl_list_insert(&c->compositor_list, &app->link); + + wthp_ivi_application_set_interface(obj, &wthp_ivi_application_implementation, + app); + wth_verbose("client %p bound wthp_ivi_application\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * APIs to send pointer events to waltham client + */ + +void +waltham_pointer_enter(struct window *window, uint32_t serial, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_enter [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_enter (pointer->obj, serial, surface->obj, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_leave(struct window *window, uint32_t serial) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wth_verbose("waltham_pointer_leave [%d]\n", window->server_surf->ivi_id); + + wthp_pointer_send_leave (pointer->obj, serial, surface->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_motion(struct window *window, uint32_t time, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_motion (pointer->obj, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_button(struct window *window, uint32_t serial, + uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_button (pointer->obj, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_pointer_axis(struct window *window, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct pointer *pointer = seat->pointer; + + wthp_pointer_send_axis (pointer->obj, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham pointer implementation + */ +static void +pointer_set_cursor(struct wthp_pointer *wthp_pointer, int32_t serial, struct wthp_surface *surface, + int32_t hotspot_x, int32_t hotspot_y) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p (%d, %p, %d, %d)\n", + wthp_pointer, serial, surface, hotspot_x, hotspot_y); + +} + +static void +pointer_release(struct wthp_pointer *wthp_pointer) +{ + struct pointer *pointer = wth_object_get_user_data((struct wth_object *)wthp_pointer); + + wth_verbose("wthp_pointer %p\n",wthp_pointer); +} + +static const struct wthp_pointer_interface pointer_implementation = { + pointer_set_cursor, + pointer_release +}; + +/* + * APIs to send touch events to waltham client + */ + +void +waltham_touch_down(struct window *window, uint32_t serial, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wth_verbose("touch_handle_down surface [%d]\n", surface->ivi_id); + wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_up(struct window *window, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_up(touch->obj, serial, time, id); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_motion(struct window *window, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_frame(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_frame(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +void +waltham_touch_cancel(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat = window->server_seat; + struct touch *touch = seat->touch; + + wthp_touch_send_cancel(touch->obj); + + wth_verbose(" <<< %s \n",__func__); + return; +} + +/* + * waltham touch implementation + */ +static void +touch_release(struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + struct touch *touch = wth_object_get_user_data((struct wth_object *)wthp_touch); + + wth_verbose("%p\n",wthp_touch); +} + +static const struct wthp_touch_interface touch_implementation = { + touch_release, +}; + +/* + * waltham seat implementation + */ +static void +seat_get_pointer(struct wthp_seat *wthp_seat, struct wthp_pointer *wthp_pointer) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("wthp_seat %p get_pointer(%p)\n", + wthp_seat, wthp_pointer); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct pointer *pointer; + + pointer = zalloc(sizeof *pointer); + if (!pointer) { + client_post_out_of_memory(seat->client); + return; + } + + pointer->obj = wthp_pointer; + pointer->seat = seat; + seat->pointer = pointer; + wl_list_insert(&seat->client->pointer_list, &pointer->link); + + wthp_pointer_set_interface(wthp_pointer, &pointer_implementation, pointer); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_get_touch(struct wthp_seat *wthp_seat, struct wthp_touch *wthp_touch) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("wthp_seat %p get_touch(%p)\n", + wthp_seat, wthp_touch); + + struct seat *seat = wth_object_get_user_data((struct wth_object *)wthp_seat); + struct touch *touch; + + touch = zalloc(sizeof *touch); + if (!touch) { + client_post_out_of_memory(seat->client); + return; + } + + touch->obj = wthp_touch; + touch->seat = seat; + seat->touch = touch; + wl_list_insert(&seat->client->touch_list, &touch->link); + + wthp_touch_set_interface(wthp_touch, &touch_implementation, touch); + wth_verbose(" <<< %s \n",__func__); +} + +static void +seat_release(struct wthp_seat *wthp_seat) +{ +} + +static const struct wthp_seat_interface seat_implementation = { + seat_get_pointer, + NULL, + seat_get_touch, + seat_release //, + //NULL +}; + +static void +seat_send_updated_caps(struct seat *seat) +{ + wth_verbose("%s >>> \n",__func__); + enum wthp_seat_capability caps = 0; + + caps |= WTHP_SEAT_CAPABILITY_POINTER; + wth_verbose("WTHP_SEAT_CAPABILITY_POINTER %d\n", caps); + + caps |= WTHP_SEAT_CAPABILITY_TOUCH; + wth_verbose("WTHP_SEAT_CAPABILITY_TOUCH %d\n", caps); + + wthp_seat_send_capabilities(seat->obj, caps); + wth_verbose(" <<< %s \n",__func__); +} + +static void +client_bind_seat(struct client *c, struct wthp_seat *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct seat *seat; + + seat = zalloc(sizeof *seat); + if (!seat) { + client_post_out_of_memory(c); + return; + } + + seat->obj = obj; + seat->client = c; + wl_list_insert(&c->seat_list, &seat->link); + wth_verbose("wthp_seat object=%p and seat=%p\n",obj,seat); + wthp_seat_set_interface(obj, &seat_implementation, + seat); + wth_verbose("client %p bound wthp_seat\n", c); + seat_send_updated_caps(seat); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham region implementation + */ + +static void +region_destroy(struct region *region) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("region %p destroy\n", region->obj); + + wthp_region_free(region->obj); + wl_list_remove(®ion->link); + free(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_destroy(struct wthp_region *wthp_region) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region = wth_object_get_user_data((struct wth_object *)wthp_region); + + assert(wthp_region == region->obj); + + region_destroy(region); + wth_verbose(" <<< %s \n",__func__); +} + +static void +region_handle_add(struct wthp_region *wthp_region, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + wth_verbose("region %p add(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static void +region_handle_subtract(struct wthp_region *wthp_region, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + wth_verbose("region %p subtract(%d, %d, %d, %d)\n", + wthp_region, x, y, width, height); +} + +static const struct wthp_region_interface region_implementation = { + region_handle_destroy, + region_handle_add, + region_handle_subtract +}; + +/* + * waltham compositor implementation + */ +static void +compositor_destroy(struct compositor *comp) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, comp->obj); + + wthp_compositor_free(comp->obj); + wl_list_remove(&comp->link); + free(comp); + wth_verbose(" <<< %s \n",__func__); +} + +extern struct window g_window; // @@@@@ +static void +compositor_handle_create_surface(struct wthp_compositor *compositor, + struct wthp_surface *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct client *client = comp->client; + struct surface *surface; + struct seat *seat, *tmp; + + wth_verbose("client %p create surface %p\n", + comp->client, id); + + surface = zalloc(sizeof *surface); + if (!surface) { + client_post_out_of_memory(comp->client); + return; + } + + surface->obj = id; + wl_list_insert(&comp->client->surface_list, &surface->link); + + wthp_surface_set_interface(id, &surface_implementation, surface); + +// surface->shm_window = calloc(1, sizeof *surface->shm_window); + surface->shm_window = &g_window; + if (!surface->shm_window) + return; + + surface->shm_window->server_surf = surface; + surface->shm_window->ready = false; + surface->ivi_id = 0; + + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + surface->shm_window->server_seat = seat; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static void +compositor_handle_create_region(struct wthp_compositor *compositor, + struct wthp_region *id) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp = wth_object_get_user_data((struct wth_object *)compositor); + struct region *region; + + wth_verbose("client %p create region %p\n", + comp->client, id); + + region = zalloc(sizeof *region); + if (!region) { + client_post_out_of_memory(comp->client); + return; + } + + region->obj = id; + wl_list_insert(&comp->client->region_list, ®ion->link); + + wthp_region_set_interface(id, ®ion_implementation, region); + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_compositor_interface compositor_implementation = { + compositor_handle_create_surface, + compositor_handle_create_region +}; + +static void +client_bind_compositor(struct client *c, struct wthp_compositor *obj) +{ + wth_verbose("%s >>> \n",__func__); + struct compositor *comp; + + comp = zalloc(sizeof *comp); + if (!comp) { + client_post_out_of_memory(c); + return; + } + + comp->obj = obj; + comp->client = c; + wl_list_insert(&c->compositor_list, &comp->link); + + wthp_compositor_set_interface(obj, &compositor_implementation, + comp); + wth_verbose("client %p bound wthp_compositor\n", c); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * waltham registry implementation + */ +static void +registry_destroy(struct registry *reg) +{ + wth_verbose("%s >>> \n",__func__); + wth_verbose("%s: %p\n", __func__, reg->obj); + + wthp_registry_free(reg->obj); + wl_list_remove(®->link); + free(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_destroy(struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + + registry_destroy(reg); + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_bind(struct wthp_registry *registry, + uint32_t name, + struct wth_object *id, + const char *interface, + uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + struct registry *reg = wth_object_get_user_data((struct wth_object *)registry); + wth_verbose("Recieved registry : %s\n", interface); + + if (strcmp(interface, "wthp_compositor") == 0) { + client_bind_compositor(reg->client, (struct wthp_compositor *)id); + } else if (strcmp(interface, "wthp_blob_factory") == 0) { + client_bind_blob_factory(reg->client, (struct wthp_blob_factory *)id); + struct client *client = reg->client; + struct seat *seat, *tmp,*get_seat; + wl_list_for_each_safe(seat, tmp, &client->seat_list, link) { + get_seat = seat; + } + wth_verbose("get_seat : %p\n", get_seat); + seat_send_updated_caps(get_seat); + } else if (strcmp(interface, "wthp_ivi_application") == 0) { + client_bind_wthp_ivi_application(reg->client, (struct wthp_ivi_application *)id); + } else if (strcmp(interface, "wthp_seat") == 0) { + client_bind_seat(reg->client, (struct wthp_seat *)id); + } else { + wth_object_post_error((struct wth_object *)registry, 0, + "%s: unknown name %u", __func__, name); + wth_object_delete(id); + } + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wthp_registry_interface registry_implementation = { + registry_handle_destroy, + registry_handle_bind +}; + +/* + * waltham display implementation + */ + +static void +display_handle_client_version(struct wth_display *wth_display, + uint32_t client_version) +{ + wth_verbose("%s >>> \n",__func__); + wth_object_post_error((struct wth_object *)wth_display, 0, + "unimplemented: %s", __func__); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_sync(struct wth_display * wth_display, struct wthp_callback * callback) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + + wth_verbose("Client %p requested wth_display.sync\n", c); + wthp_callback_send_done(callback, 0); + wthp_callback_free(callback); + wth_verbose(" <<< %s \n",__func__); +} + +static void +display_handle_get_registry(struct wth_display *wth_display, + struct wthp_registry *registry) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = wth_object_get_user_data((struct wth_object *)wth_display); + struct registry *reg; + + reg = zalloc(sizeof *reg); + if (!reg) { + client_post_out_of_memory(c); + return; + } + + reg->obj = registry; + reg->client = c; + wl_list_insert(&c->registry_list, ®->link); + wthp_registry_set_interface(registry, + ®istry_implementation, reg); + + wthp_registry_send_global(registry, 1, "wthp_compositor", 4); + wthp_registry_send_global(registry, 1, "wthp_ivi_application", 1); + wthp_registry_send_global(registry, 1, "wthp_seat", 4); + wthp_registry_send_global(registry, 1, "wthp_blob_factory", 4); + wth_verbose(" <<< %s \n",__func__); +} + +const struct wth_display_interface display_implementation = { + display_handle_client_version, + display_handle_sync, + display_handle_get_registry +}; + +/* + * functions to handle waltham client connections + */ +static void +connection_handle_data(struct watch *w, uint32_t events) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c = container_of(w, struct client, conn_watch); + int ret; + + if (events & EPOLLERR) { + wth_error("Client %p errored out.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLHUP) { + wth_error("Client %p hung up.\n", c); + client_destroy(c); + + return; + } + + if (events & EPOLLOUT) { + ret = wth_connection_flush(c->connection); + if (ret == 0) + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN); + else if (ret < 0 && errno != EAGAIN){ + wth_error("Client %p flush error.\n", c); + client_destroy(c); + + return; + } + } + + if (events & EPOLLIN) { + ret = wth_connection_read(c->connection); + if (ret < 0) { + wth_error("Client %p read error.\n", c); + client_destroy(c); + + return; + } + + ret = wth_connection_dispatch(c->connection); + if (ret < 0 && errno != EPROTO) { + wth_error("Client %p dispatch error.\n", c); + client_destroy(c); + + return; + } + } + wth_verbose(" <<< %s \n",__func__); +} + +/** +* client_create +* +* Create new client connection +* +* @param srv Server structure +* @param wth_connection Waltham connection handle +* @return Pointer to client structure +*/ +static struct client * +client_create(struct server *srv, struct wth_connection *conn) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c; + struct wth_display *disp; + + c = zalloc(sizeof *c); + if (!c) + return NULL; + + c->server = srv; + c->connection = conn; + + c->conn_watch.server = srv; + c->conn_watch.fd = wth_connection_get_fd(conn); + c->conn_watch.cb = connection_handle_data; + if (watch_ctl(&c->conn_watch, EPOLL_CTL_ADD, EPOLLIN) < 0) { + free(c); + return NULL; + } + + wth_verbose("Client %p connected.\n", c); + + wl_list_insert(&srv->client_list, &c->link); + + wl_list_init(&c->registry_list); + wl_list_init(&c->compositor_list); + wl_list_init(&c->seat_list); + wl_list_init(&c->pointer_list); + wl_list_init(&c->touch_list); + wl_list_init(&c->region_list); + wl_list_init(&c->surface_list); + wl_list_init(&c->buffer_list); + + disp = wth_connection_get_display(c->connection); + wth_display_set_interface(disp, &display_implementation, c); + + wth_verbose(" <<< %s \n",__func__); + return c; +} + +/** +* client_destroy +* +* Destroy client connection +* +* @param names struct client *c +* @param value client data +* @return none +*/ +void +client_destroy(struct client *c) +{ + wth_verbose("%s >>> \n",__func__); + struct region *region; + struct compositor *comp; + struct registry *reg; + struct surface *surface; + + wth_verbose("Client %p disconnected.\n", c); + + /* clean up remaining client resources in case the client + * did not. + */ + wl_list_last_until_empty(region, &c->region_list, link) + region_destroy(region); + + wl_list_last_until_empty(comp, &c->compositor_list, link) + compositor_destroy(comp); + + wl_list_last_until_empty(reg, &c->registry_list, link) + registry_destroy(reg); + + wl_list_last_until_empty(surface, &c->surface_list, link) + surface_destroy(surface); + + wl_list_remove(&c->link); + watch_ctl(&c->conn_watch, EPOLL_CTL_DEL, 0); + wth_connection_destroy(c->connection); + free(c); + wth_verbose(" <<< %s \n",__func__); +} + +/** +* server_flush_clients +* +* write all the pending requests from the clients to socket +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_flush_clients(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *c, *tmp; + int ret; + + wl_list_for_each_safe(c, tmp, &srv->client_list, link) { + /* Flush out buffered requests. If the Waltham socket is + * full, poll it for writable too. + */ + ret = wth_connection_flush(c->connection); + if (ret < 0 && errno == EAGAIN) { + watch_ctl(&c->conn_watch, EPOLL_CTL_MOD, EPOLLIN | EPOLLOUT); + } else if (ret < 0) { + perror("Connection flush failed"); + client_destroy(c); + return; + } + } + + wth_verbose(" <<< %s \n",__func__); + +} + +/** +* server_accept_client +* +* Accepts new waltham client connection and instantiates client structure +* +* @param names struct server *srv +* @param value socket connection info and client data +* @return none +*/ +void +server_accept_client(struct server *srv) +{ + wth_verbose("%s >>> \n",__func__); + struct client *client; + struct wth_connection *conn; + struct sockaddr_in addr; + socklen_t len; + + len = sizeof addr; + conn = wth_accept(srv->listen_fd, (struct sockaddr *)&addr, &len); + if (!conn) { + wth_error("Failed to accept a connection.\n"); + return; + } + + client = client_create(srv, conn); + if (!client) { + wth_error("Failed client_create().\n"); + return; + } + wth_verbose(" <<< %s \n",__func__); +} diff --git a/src/wth-server-weston.c b/src/wth-server-weston.c new file mode 100644 index 0000000..6cc309c --- /dev/null +++ b/src/wth-server-weston.c @@ -0,0 +1,811 @@ +/** + * @licence app begin@ + * + * + * TBD + * + * + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: ** +** ** +** TARGET : linux ** +** ** +** PROJECT : waltham-server ** +** ** +** AUTHOR : ** +** ** +** ** +** ** +** PURPOSE : This file is acts as interface to weston compositor at server ** +** side ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +#include +#include +#include + +#include "wth-server-weston.h" +#include "os-compatibility.h" +#include "ivi-application-client-protocol.h" +#include "bitmap.h" + + +static int running = 1; +extern bool get_verbosity(void); +extern int verbose; +/* + * buffer callback + */ +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct shm_buffer *mybuf = data; + + wth_verbose("%s >>> \n",__func__); + + mybuf->busy = 0; + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct display *display, struct shm_buffer *buffer, + int width, int height, uint32_t format) +{ + struct wl_shm_pool *pool; + int fd, size, stride; + void *data; + + wth_verbose("%s >>> \n",__func__); + stride = width * 4; + size = stride * height; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + wth_error("creating a buffer file for %d B failed: %m\n", + size); + return -1; + } + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + wth_error("mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, + stride, format); + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + wl_shm_pool_destroy(pool); + close(fd); + + buffer->shm_data = data; + + wth_verbose(" <<< %s \n",__func__); + return 0; +} + +/* + * ivi surface callback + */ +static void +handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface, + int32_t width, int32_t height) +{ + /* Simple-shm is resizable */ +} + +static const struct ivi_surface_listener ivi_surface_listener = { + handle_ivi_surface_configure, +}; + +static void +create_window(struct window *window, struct display *display, int width, int height) +{ + wth_verbose("%s >>> \n",__func__); + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->surface = wl_compositor_create_surface(display->compositor); + window->window_frames = 0; + window->window_benchmark_time = 0; + + wl_display_roundtrip(display->display); + if (display->ivi_application ) { + uint32_t id_ivisurf = window->id_ivisurf; + window->ivi_surface = + ivi_application_surface_create(display->ivi_application, + id_ivisurf, window->surface); + if (window->ivi_surface == NULL) { + wth_error("Failed to create ivi_client_surface\n"); + abort(); + } + + ivi_surface_add_listener(window->ivi_surface, + &ivi_surface_listener, window); + + } else { + assert(0); + } + + wth_verbose(" <<< %s \n",__func__); + return; +} + +static void +destroy_window(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + wl_surface_destroy(window->surface); + free(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static struct shm_buffer * +window_next_buffer(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + struct shm_buffer *buffer; + int ret = 0; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else { + window->buffers[0].busy = 0; + window->buffers[0].busy = 1; + buffer = &window->buffers[0]; + } + + if (!buffer->buffer) { + ret = create_shm_buffer(window->display, buffer, + window->width, window->height, + WL_SHM_FORMAT_XRGB8888); + + if (ret < 0) + return NULL; + + /* paint the padding */ + memset(buffer->shm_data, 0xff, + window->width * window->height * 4); + } + + wth_verbose(" <<< %s \n",__func__); + return buffer; +} + +static void +paint_pixels(void *image, int padding, int width, int height, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + const int halfh = padding + (height - padding * 2) / 2; + const int halfw = padding + (width - padding * 2) / 2; + int ir, or; + uint32_t *pixel = image; + int y; + + /* squared radii thresholds */ + or = (halfw < halfh ? halfw : halfh) - 8; + ir = or - 32; + or *= or; + ir *= ir; + + pixel += padding * width; + for (y = padding; y < height - padding; y++) { + int x; + int y2 = (y - halfh) * (y - halfh); + + pixel += padding; + for (x = padding; x < width - padding; x++) { + uint32_t v; + + /* squared distance from center */ + int r2 = (x - halfw) * (x - halfw) + y2; + + if (r2 < ir) + v = (r2 / 32 + time / 64) * 0x0080401; + else if (r2 < or) + v = (y + time / 32) * 0x0080401; + else + v = (x + time / 16) * 0x0080401; + v &= 0x00ffffff; + + /* cross if compositor uses X from XRGB as alpha */ + if (abs(x - y) > 6 && abs(x + y - height) > 6) + v |= 0xff000000; + + *pixel++ = v; + } + + pixel += padding; + } + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_attach(struct window *window, uint32_t data_sz, void * data, + int32_t width, int32_t height, int32_t stride, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct timeval tv; + uint32_t time; + struct shm_buffer *buffer; + static int ss_count = 0; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + buffer = window_next_buffer(window); + if (!buffer) { + wth_error("Both buffers busy at redraw().\n"); + return; + } + + char *bitmap; + bitmap = getenv("BITMAP"); + if (bitmap) { + if (!strcmp(bitmap, "1")) { + int len; + const char *path = "/tmp/bitmap"; + len = strlen(path); + char *filename; + filename = (char *)malloc(len + 10); + sprintf(filename, "%s%d.bmp", path, ss_count); + wth_verbose("%s\n", filename); + + save_as_bitmap(filename, data, data_sz, width, height, format); + ss_count++; + free(filename); + } + } + buffer->shm_data = data; + window->width = width; + window->height = height; + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_damage(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + wl_surface_damage(window->surface, + 0, 0, window->width, window->height); + + wth_verbose(" <<< %s \n",__func__); +} + +void +wth_server_weston_shm_commit(struct window *window) +{ + wth_verbose("%s >>> \n",__func__); + + static const uint32_t benchmark_interval = 5; + struct timeval tv; + uint32_t time; + + gettimeofday(&tv, NULL); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + if (window->window_frames == 0) + window->window_benchmark_time = time; + if (time - window->window_benchmark_time > (benchmark_interval * 1000)) { + wth_verbose("-------------------------------%d frames in %d seconds: %f fps\n", + window->window_frames, + benchmark_interval, + (float) window->window_frames / benchmark_interval); + + window->window_benchmark_time = time; + window->window_frames = 0; + } + + wl_surface_commit(window->surface); + + wl_display_flush(window->display->display); + + if (window->wait) + window->wait = 0; + + window->window_frames++; + wth_verbose(" <<< %s \n",__func__); +} + +/* + * frame callback function - this function will display buffer to surface + */ + +static const struct wl_callback_listener frame_listener; +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = data; + struct shm_buffer *buffer; + + buffer = window_next_buffer(window); + if (!buffer) { + if(!callback) + { + wth_error("Failed to create the first buffer.\n"); + } + else + { + wth_error("Both buffers busy at redraw(). Server bug?\n"); + } + abort(); + } + + paint_pixels(buffer->shm_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, + 20, 20, window->width - 40, window->height - 40); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +/* + * shm callbcak function + */ + +static void +shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (format == WL_SHM_FORMAT_XRGB8888) + d->has_xrgb = true; + + wth_verbose(" <<< %s \n",__func__); +} + +struct wl_shm_listener shm_listener = { + shm_format +}; + +/* + * pointer callbcak functions + */ +static void +pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *wl_surface, + wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + struct surface *surface = window->server_surf; + struct seat *seat = window->server_seat; + + waltham_pointer_enter(window, serial, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + wth_verbose("%s >>> \n",__func__); + + wth_verbose("data [%p]\n", data); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_leave(window, serial); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_motion(window, time, sx, sy); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, + uint32_t state) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_button(window, serial, time, button, state); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_pointer_axis(window, time, axis, value); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +/* + * touch callbcak functions + */ + +static void +touch_handle_down(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + int x = (int)wl_fixed_to_double(x_w); + int y = (int)wl_fixed_to_double(y_w); + wth_verbose("%p x %d y %d\n",window, x, y); + + waltham_touch_down(window, serial, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_up(void *data, struct wl_touch *touch, uint32_t serial, + uint32_t time, int32_t id) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_up(window, serial, time, id); +} + +static void +touch_handle_motion(void *data, struct wl_touch *touch, uint32_t time, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_motion(window, time, id, x_w, y_w); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_frame(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_frame(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +touch_handle_cancel(void *data, struct wl_touch *touch) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + struct window *window = display->window; + + waltham_touch_cancel(window); + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel +}; + +/* + * seat callback + */ +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display = data; + + wth_verbose("caps = %d\n", caps); + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->wl_pointer) + { + wth_verbose("WL_SEAT_CAPABILITY_POINTER\n"); + display->wl_pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_set_user_data(display->wl_pointer, display); + wl_pointer_add_listener(display->wl_pointer, &pointer_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->wl_pointer) { + wth_verbose("!WL_SEAT_CAPABILITY_POINTER\n"); + wl_pointer_destroy(display->wl_pointer); + display->wl_pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !display->wl_touch) + { + wth_verbose("WL_SEAT_CAPABILITY_TOUCH\n"); + display->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(display->wl_touch, display); + wl_touch_add_listener(display->wl_touch, &touch_listener, display); + wl_display_roundtrip(display->display); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && display->wl_touch) { + wth_verbose("!WL_SEAT_CAPABILITY_TOUCH\n"); + wl_touch_destroy(display->wl_touch); + display->wl_touch = NULL; + } + + wth_verbose(" <<< %s \n",__func__); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + NULL +}; + +static void +add_seat(struct display *display, uint32_t id, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + display->wl_pointer = NULL; + display->seat = wl_registry_bind(display->registry, id, + &wl_seat_interface, 1); + wl_seat_add_listener(display->seat, &seat_listener, display); + wth_verbose(" <<< %s \n",__func__); +} + +/* + * registry callback + */ +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, + id, &wl_shm_interface, 1); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = + wl_registry_bind(registry, id, + &ivi_application_interface, 1); + } else if (strcmp(interface, "wl_seat") == 0) { + add_seat(d, id, version); + } + wth_verbose(" <<< %s \n",__func__); +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(void) +{ + wth_verbose("%s >>> \n",__func__); + + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + wth_error("out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->has_xrgb = false; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->shm == NULL) { + wth_error("No wl_shm global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (!display->has_xrgb) { + wth_error("WL_SHM_FORMAT_XRGB32 not available\n"); + exit(1); + } + + wth_verbose(" <<< %s \n",__func__); + return display; +} + +static void +destroy_display(struct display *display) +{ + wth_verbose("%s >>> \n",__func__); + + if (display->shm) + wl_shm_destroy(display->shm); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + free(display); + + wth_verbose(" <<< %s \n",__func__); +} + +static void +signal_int(int signum) +{ + running = 0; +} + +/** +* wth_server_weston_main +* +* This is the main function which will handle connection to the compositor at server side +* +* @param names void *data +* @param value struct window data +* @return 0 on success, -1 on error +*/ +int +wth_server_weston_main(void *data) +{ + wth_verbose("%s >>> \n",__func__); + + struct window *window = (struct window *) data; + struct sigaction sigint; + struct display *display; + int ret = 0; + + display = create_display(); + create_window(window, display, 400, 400); + if (!window) + return -1; + wl_display_roundtrip(display->display); + wth_verbose("data %p\n", data); + wth_verbose("window %p\n", window); + + display->window = window; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, + window->width, window->height); + + redraw(window, NULL, 0); + + window->wait = 1; + window->ready = true; + while (window->wait) + { + ret = wl_display_dispatch(display->display); + usleep(1); + } + wth_verbose("debug\n"); + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + wth_verbose("wth_server_weston_main exiting\n"); + + if (window->display->ivi_application) { + ivi_surface_destroy(window->ivi_surface); + ivi_application_destroy(window->display->ivi_application); + } + + destroy_window(window); + destroy_display(display); + + wth_verbose(" <<< %s \n",__func__); + return 0; +} -- cgit 1.2.3-korg