From 3c299579ce714726b268f8f345bd5981426942d5 Mon Sep 17 00:00:00 2001 From: srimaldia Date: Fri, 9 Dec 2016 19:58:35 +0900 Subject: add standalone BT app Signed-off-by: srimaldia --- AUTHORS.txt | 2 + CMakeLists.txt | 68 ++ LICENSE-2.0.txt | 201 ++++++ README.txt | 35 + bluetooth-api.c | 503 +++++++++++++++ bluetooth-api.h | 50 ++ bluetooth-manager.c | 747 ++++++++++++++++++++++ bluetooth-manager.h | 143 +++++ config.xml.in | 9 + doc/AppGrid.qml | 43 ++ doc/AppIcon.qml | 51 ++ doc/BottomBar.qml | 65 ++ doc/GridItem.qml | 45 ++ doc/Key.qml | 85 +++ doc/Keyboard.qml | 137 ++++ doc/Main.qml | 101 +++ doc/README.md | 23 + doc/Rotated.qml | 17 + doc/Scaled.qml | 17 + doc/Scaled_04.qml | 17 + doc/Scaled_720p.qml | 17 + doc/TopBar.qml | 146 +++++ doc/VolumeControl.qml | 97 +++ doc/images/AGL-Logo.png | Bin 0 -> 20091 bytes doc/images/AppHex.png | Bin 0 -> 9827 bytes doc/images/Hex-Background.jpg | Bin 0 -> 119534 bytes doc/images/JLR-Logo.png | Bin 0 -> 35509 bytes doc/images/agl_icon.png | Bin 0 -> 25190 bytes doc/images/application_grid.png | Bin 0 -> 5427 bytes doc/images/backspace_icon.png | Bin 0 -> 640 bytes doc/images/blank_hexagon.png | Bin 0 -> 5405 bytes doc/images/browser_app_icon.png | Bin 0 -> 5474 bytes doc/images/browser_app_icon.svg | 100 +++ doc/images/bt_close.png | Bin 0 -> 1215 bytes doc/images/cameras_app_icon.png | Bin 0 -> 4408 bytes doc/images/cameras_app_icon.svg | 82 +++ doc/images/dashboard_app_icon.png | Bin 0 -> 5530 bytes doc/images/dashboard_app_icon.svg | 130 ++++ doc/images/fingerprint_app_icon.png | Bin 0 -> 5919 bytes doc/images/fmradio_app_icon.png | Bin 0 -> 3732 bytes doc/images/fmradio_app_icon.svg | 110 ++++ doc/images/googlemaps_app_icon.png | Bin 0 -> 3508 bytes doc/images/googlemaps_app_icon.svg | 86 +++ doc/images/homescreen_icon.png | Bin 0 -> 4606 bytes doc/images/hvac_app_icon.png | Bin 0 -> 4236 bytes doc/images/hvac_app_icon.svg | 101 +++ doc/images/icon_apps_blue.png | Bin 0 -> 6342 bytes doc/images/icongear.png | Bin 0 -> 10833 bytes doc/images/media_player_app_icon.png | Bin 0 -> 4347 bytes doc/images/media_player_app_icon.svg | 97 +++ doc/images/news_app_icon.png | Bin 0 -> 2428 bytes doc/images/news_app_icon.svg | 57 ++ doc/images/nfc_app_icon.png | Bin 0 -> 3933 bytes doc/images/nfc_app_icon.svg | 94 +++ doc/images/phone_app_icon.png | Bin 0 -> 4335 bytes doc/images/phone_app_icon.svg | 108 ++++ doc/images/settings_icon.png | Bin 0 -> 6528 bytes doc/images/shift_off_icon.png | Bin 0 -> 825 bytes doc/images/shift_on_icon.png | Bin 0 -> 710 bytes doc/images/space_bar_icon.png | Bin 0 -> 302 bytes doc/images/switchcontrol.png | Bin 0 -> 2269 bytes doc/images/switchplate_off.png | Bin 0 -> 5071 bytes doc/images/switchplate_on.png | Bin 0 -> 4824 bytes doc/images/symbols_icon.png | Bin 0 -> 1373 bytes doc/images/symbols_off_icon.png | Bin 0 -> 1500 bytes doc/images/tizen.png | Bin 0 -> 4391 bytes doc/images/weather_app_icon.png | Bin 0 -> 4615 bytes doc/images/weather_app_icon.svg | 115 ++++ doc/images/white_return.png | Bin 0 -> 728 bytes export.map | 1 + icon_bt.png | Bin 0 -> 4871 bytes imports/components/AwesomeIcon.qml | 26 + imports/components/Box.qml | 49 ++ imports/components/BoxButton.qml | 36 ++ imports/components/BoxHeading.qml | 37 ++ imports/components/Button.qml | 30 + imports/components/DateTime.qml | 35 + imports/components/HexGrid.qml | 32 + imports/components/HexSwitch.qml | 80 +++ imports/components/InShadow.qml | 33 + imports/components/InsetShadow.qml | 40 ++ imports/components/Label.qml | 27 + imports/components/NumberPad.qml | 101 +++ imports/components/OutShadow.qml | 41 ++ imports/components/Switch.qml | 13 + imports/components/qmldir | 16 + imports/radio/Radio.qml | 6 + imports/radio/qmldir | 2 + imports/system/App.qml | 29 + imports/system/System.qml | 15 + imports/system/qmldir | 8 + imports/utils/Marker.qml | 60 ++ imports/utils/Style.qml | 37 ++ imports/utils/qmldir | 8 + imports/vehicle/ClimateModel.qml | 44 ++ imports/vehicle/FuelModel.qml | 46 ++ imports/vehicle/PositionModel.qml | 33 + imports/vehicle/SpeedModel.qml | 38 ++ imports/vehicle/TemperatureModel.qml | 26 + imports/vehicle/qmldir | 11 + oe-sdk_crosscompile.cmake | 20 + qml/bluetooth-settings/bluetooth-settings-app.qml | 404 ++++++++++++ qml/bluetooth-settings/component/images/trash.png | Bin 0 -> 1035 bytes 103 files changed, 5083 insertions(+) create mode 100755 AUTHORS.txt create mode 100755 CMakeLists.txt create mode 100755 LICENSE-2.0.txt create mode 100755 README.txt create mode 100755 bluetooth-api.c create mode 100755 bluetooth-api.h create mode 100755 bluetooth-manager.c create mode 100755 bluetooth-manager.h create mode 100644 config.xml.in create mode 100644 doc/AppGrid.qml create mode 100644 doc/AppIcon.qml create mode 100644 doc/BottomBar.qml create mode 100644 doc/GridItem.qml create mode 100644 doc/Key.qml create mode 100644 doc/Keyboard.qml create mode 100644 doc/Main.qml create mode 100644 doc/README.md create mode 100644 doc/Rotated.qml create mode 100644 doc/Scaled.qml create mode 100644 doc/Scaled_04.qml create mode 100644 doc/Scaled_720p.qml create mode 100644 doc/TopBar.qml create mode 100644 doc/VolumeControl.qml create mode 100755 doc/images/AGL-Logo.png create mode 100755 doc/images/AppHex.png create mode 100755 doc/images/Hex-Background.jpg create mode 100755 doc/images/JLR-Logo.png create mode 100755 doc/images/agl_icon.png create mode 100755 doc/images/application_grid.png create mode 100755 doc/images/backspace_icon.png create mode 100755 doc/images/blank_hexagon.png create mode 100755 doc/images/browser_app_icon.png create mode 100755 doc/images/browser_app_icon.svg create mode 100755 doc/images/bt_close.png create mode 100755 doc/images/cameras_app_icon.png create mode 100755 doc/images/cameras_app_icon.svg create mode 100755 doc/images/dashboard_app_icon.png create mode 100755 doc/images/dashboard_app_icon.svg create mode 100755 doc/images/fingerprint_app_icon.png create mode 100755 doc/images/fmradio_app_icon.png create mode 100755 doc/images/fmradio_app_icon.svg create mode 100755 doc/images/googlemaps_app_icon.png create mode 100755 doc/images/googlemaps_app_icon.svg create mode 100755 doc/images/homescreen_icon.png create mode 100755 doc/images/hvac_app_icon.png create mode 100755 doc/images/hvac_app_icon.svg create mode 100755 doc/images/icon_apps_blue.png create mode 100755 doc/images/icongear.png create mode 100755 doc/images/media_player_app_icon.png create mode 100755 doc/images/media_player_app_icon.svg create mode 100755 doc/images/news_app_icon.png create mode 100755 doc/images/news_app_icon.svg create mode 100755 doc/images/nfc_app_icon.png create mode 100755 doc/images/nfc_app_icon.svg create mode 100755 doc/images/phone_app_icon.png create mode 100755 doc/images/phone_app_icon.svg create mode 100755 doc/images/settings_icon.png create mode 100755 doc/images/shift_off_icon.png create mode 100755 doc/images/shift_on_icon.png create mode 100755 doc/images/space_bar_icon.png create mode 100755 doc/images/switchcontrol.png create mode 100755 doc/images/switchplate_off.png create mode 100755 doc/images/switchplate_on.png create mode 100755 doc/images/symbols_icon.png create mode 100755 doc/images/symbols_off_icon.png create mode 100755 doc/images/tizen.png create mode 100755 doc/images/weather_app_icon.png create mode 100755 doc/images/weather_app_icon.svg create mode 100755 doc/images/white_return.png create mode 100755 export.map create mode 100644 icon_bt.png create mode 100755 imports/components/AwesomeIcon.qml create mode 100755 imports/components/Box.qml create mode 100755 imports/components/BoxButton.qml create mode 100755 imports/components/BoxHeading.qml create mode 100755 imports/components/Button.qml create mode 100755 imports/components/DateTime.qml create mode 100755 imports/components/HexGrid.qml create mode 100755 imports/components/HexSwitch.qml create mode 100755 imports/components/InShadow.qml create mode 100755 imports/components/InsetShadow.qml create mode 100755 imports/components/Label.qml create mode 100755 imports/components/NumberPad.qml create mode 100755 imports/components/OutShadow.qml create mode 100755 imports/components/Switch.qml create mode 100755 imports/components/qmldir create mode 100755 imports/radio/Radio.qml create mode 100755 imports/radio/qmldir create mode 100755 imports/system/App.qml create mode 100755 imports/system/System.qml create mode 100755 imports/system/qmldir create mode 100755 imports/utils/Marker.qml create mode 100755 imports/utils/Style.qml create mode 100755 imports/utils/qmldir create mode 100755 imports/vehicle/ClimateModel.qml create mode 100755 imports/vehicle/FuelModel.qml create mode 100755 imports/vehicle/PositionModel.qml create mode 100755 imports/vehicle/SpeedModel.qml create mode 100755 imports/vehicle/TemperatureModel.qml create mode 100755 imports/vehicle/qmldir create mode 100755 oe-sdk_crosscompile.cmake create mode 100755 qml/bluetooth-settings/bluetooth-settings-app.qml create mode 100755 qml/bluetooth-settings/component/images/trash.png diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100755 index 0000000..61366b4 --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,2 @@ +Jiajun Gu +Yidong Miao diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..b928de7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +project(bluetooth-settings) + +cmake_minimum_required(VERSION 3.3) + +include(GNUInstallDirs) + +set(PROJECT_VERSION "0.1") +set(PROJECT_ICON "icon_bt.png") +set(PROJECT_LIBDIR "lib") +set(PROJECT_QML "qml") +set(PROJECT_IMPORT "imports") +set(PROJECT_DOC "doc") + +set(CMAKE_BUILD_TYPE Debug) + +########################################################################### +add_compile_options(-Wall -Wextra -Wconversion) +add_compile_options(-Wno-unused-parameter) # frankly not using a parameter does it care? +add_compile_options(-Werror=maybe-uninitialized) +add_compile_options(-Werror=implicit-function-declaration) +add_compile_options(-ffunction-sections -fdata-sections) +add_compile_options(-Wl,--as-needed -Wl,--gc-sections) +add_compile_options(-fPIC) + +set(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg -Wp,-U_FORTIFY_SOURCE") +set(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb -Wp,-U_FORTIFY_SOURCE") +set(CMAKE_C_FLAGS_RELEASE "-g -O2") +set(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage") + +########################################################################### + +include(FindPkgConfig) + +pkg_check_modules(EXTRAS REQUIRED json-c afb-daemon glib-2.0 gio-2.0 gobject-2.0 zlib) +add_compile_options(${EXTRAS_CFLAGS}) +include_directories(${EXTRAS_INCLUDE_DIRS}) +link_libraries(${EXTRAS_LIBRARIES}) + +########################################################################### +# the binding for afb + +message(STATUS "Creation of ${PROJECT_NAME} for AFB-DAEMON") + +############################################################### +add_library(${PROJECT_NAME} MODULE bluetooth-api.c bluetooth-manager.c) + +set_target_properties(${PROJECT_NAME} PROPERTIES + PREFIX "" + LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map" +) + +configure_file(config.xml.in config.xml) + +add_custom_command( + OUTPUT ${PROJECT_NAME}.wgt + DEPENDS ${PROJECT_NAME} + COMMAND rm -rf package + COMMAND mkdir -p package/${PROJECT_LIBDIR} package/htdocs + COMMAND cp config.xml package/ + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_ICON} package/icon.png + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_QML} package/${PROJECT_QML} + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_IMPORT} package/${PROJECT_IMPORT} + COMMAND cp -rf ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_DOC} package/${PROJECT_DOC} + COMMAND cp ${PROJECT_NAME}.so package/${PROJECT_LIBDIR} + COMMAND wgtpkg-pack -f -o ${PROJECT_NAME}.wgt package + COMMAND rm -rf package +) +add_custom_target(widget ALL DEPENDS ${PROJECT_NAME}.wgt) diff --git a/LICENSE-2.0.txt b/LICENSE-2.0.txt new file mode 100755 index 0000000..38c2bfb --- /dev/null +++ b/LICENSE-2.0.txt @@ -0,0 +1,201 @@ + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/README.txt b/README.txt new file mode 100755 index 0000000..d0341a7 --- /dev/null +++ b/README.txt @@ -0,0 +1,35 @@ +##Wifi Manager +This folder include BT manager binding and GUI. + +##Function +- Power on/off +- Scan start/stop +- Pair +- Connect (After pairing, support incoming connect as well) +- Disconnect +- Remove + +##Guidance for building Wi-Fi manager Binding +A. Prepare sdk environment + - bitbake below: + $ bitbake agl-demo-platform-crosssdk + - install sdk + $ build/tmp/deploy/sdk/poky-agl-glibc*.sh +B. Build + - Go to folder where WiFi Bindings source code exists + - run below command for setup and make + $ . /opt/poky-agl/xxx/environment-setup-cortexa15hf-vfp-neon-poky-linux-gnueabi + $ mkdir build + $ cmake .. + $ make + +C. Running app + - copy widget to porter board + - do install and start the app + # afm-util install *.wgt + # afm-util start @0.1 + +##TODO +- ADD token security +- ADD event receive + diff --git a/bluetooth-api.c b/bluetooth-api.c new file mode 100755 index 0000000..f7e2d9a --- /dev/null +++ b/bluetooth-api.c @@ -0,0 +1,503 @@ +/* Copyright 2016 ALPS ELECTRIC CO., 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. +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include "bluetooth-api.h" +#include "bluetooth-manager.h" + + +/* + * the interface to afb-daemon + */ +const struct afb_binding_interface *afbitf; + + +/* ------ PUBLIC PLUGIN FUNCTIONS --------- */ + +/**/ +static void bt_power (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + json_object *jresp = NULL; + int ret = 0; + + jresp = json_object_new_object(); + + /* no "?value=" parameter : return current state */ + if (!value) { + gboolean power_value; + ret = adapter_get_powered(&power_value); + + if (0==ret) + { + (TRUE==power_value)?json_object_object_add (jresp, "power", json_object_new_string ("on")) + : json_object_object_add (jresp, "power", json_object_new_string ("off")); + } + else + { + afb_req_fail (request, "failed", "Unable to get power status"); + return; + } + + } + + /* "?value=" parameter is "1" or "true" */ + else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) + { + if (adapter_set_powered (TRUE)) + { + afb_req_fail (request, "failed", "no more radio devices available"); + return; + } + json_object_object_add (jresp, "power", json_object_new_string ("on")); + } + + /* "?value=" parameter is "0" or "false" */ + else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) + { + if (adapter_set_powered (FALSE)) + { + afb_req_fail (request, "failed", "Unable to release radio device"); + return; + } + + json_object_object_add (jresp, "power", json_object_new_string ("off")); + } + else + { + afb_req_fail (request, "failed", "Invalid value"); + return; + } + + afb_req_success (request, jresp, "Radio - Power set"); +} + +/**/ +static void bt_start_discovery (struct afb_req request) +{ + D_PRINTF("\n"); + int ret = 0; + + ret = adapter_start_discovery(); + + if (ret) + { + afb_req_fail (request, "failed", "Unable to start discovery"); + return; + } + + afb_req_success (request, NULL, NULL); +} + +/**/ +static void bt_stop_discovery (struct afb_req request) +{ + D_PRINTF("\n"); + int ret = 0; + + ret = adapter_stop_discovery(); + + if (ret) + { + afb_req_fail (request, "failed", "Unable to stop discovery"); + return; + } + + afb_req_success (request, NULL, NULL); +} + + +/**/ +static void bt_discovery_result (struct afb_req request) +{ + D_PRINTF("\n"); + GSList *list = NULL; + adapter_update_devices(); + list = adapter_get_devices_list(); + if (NULL == list) + { + afb_req_fail (request, "failed", "No find devices"); + return; + } + + json_object *my_array = json_object_new_array(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + //D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + + json_object *jresp = json_object_new_object(); + json_object *jstring1 = NULL; + json_object *jstring2 = NULL; + json_object *jstring3 = NULL; + json_object *jstring4 = NULL; + json_object *jstring5 = NULL; + json_object *jstring6 = NULL; + + + + if (BDdevice->bdaddr) + { + jstring1 = json_object_new_string(BDdevice->bdaddr); + } + else + { + jstring1 = json_object_new_string(""); + } + + + if (BDdevice->name) + { + jstring2 = json_object_new_string(BDdevice->name); + } + else + { + jstring2 = json_object_new_string(""); + } + + jstring3 = (TRUE == BDdevice->paired) ? json_object_new_string("True"):json_object_new_string("False"); + jstring4 = (TRUE == BDdevice->connected) ? json_object_new_string("True"):json_object_new_string("False"); + jstring5 = (TRUE == isAVPConnected(BDdevice)) ? json_object_new_string("True"):json_object_new_string("False"); + jstring6 = (TRUE == isHFPConnected(BDdevice)) ? json_object_new_string("True"):json_object_new_string("False"); + + + json_object_object_add(jresp, "Address", jstring1); + json_object_object_add(jresp, "Name", jstring2); + json_object_object_add(jresp, "Paired", jstring3); + json_object_object_add(jresp, "Connected", jstring4); + json_object_object_add(jresp, "AVPConnected", jstring5); + json_object_object_add(jresp, "HFPConnected", jstring6); + json_object_array_add(my_array, jresp); + } + + afb_req_success(request, my_array, "BT - Scan Result is Displayed"); +} + +/**/ +static void bt_pair (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_pair(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); + +} + +/**/ +static void bt_cancel_pairing (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_cancelPairing(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); + +} + +/**/ +static void bt_connect (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_connect(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + +/**/ +static void bt_disconnect (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_disconnect(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + +/**/ +static void bt_remove_device (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == value) + { + afb_req_fail (request, "failed", "Please Input the Device Address"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,value)) + { + D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = adapter_remove_device(BDdevice); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device pairing failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + + +/**/ +static void bt_set_property (struct afb_req request) +{ + D_PRINTF("\n"); + + const char *address = afb_req_value (request, "Address"); + const char *property = afb_req_value (request, "Property"); + const char *value = afb_req_value (request, "value"); + int ret = 0; + GSList *list = NULL; + + if (NULL == address || NULL==property || NULL==value) + { + afb_req_fail (request, "failed", "Please Check Input Parameter"); + return; + } + + list = adapter_get_devices_list(); + + for(;list;list=list->next) + { + struct btd_device *BDdevice = list->data; + + if ((NULL!=BDdevice->bdaddr)&&g_strrstr(BDdevice->bdaddr,address)) + { + //D_PRINTF("\n%s\t%s\n",BDdevice->bdaddr,BDdevice->name); + ret = device_set_property(BDdevice, property, value); + if (0 == ret) + { + afb_req_success (request, NULL, NULL); + } + else + { + afb_req_fail (request, "failed", "Device set property failed"); + } + return; + } + } + + afb_req_fail (request, "failed", "Not found device"); +} + + + +/* + * array of the verbs exported to afb-daemon + */ +static const struct afb_verb_desc_v1 binding_verbs[]= { +/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */ +{ .name = "power", .session = AFB_SESSION_NONE, .callback = bt_power, .info = "Set Bluetooth Power ON or OFF" }, +{ .name = "start_discovery", .session = AFB_SESSION_NONE, .callback = bt_start_discovery, .info = "Start discovery" }, +{ .name = "stop_discovery", .session = AFB_SESSION_NONE, .callback = bt_stop_discovery, .info = "Stop discovery" }, +{ .name = "discovery_result", .session = AFB_SESSION_NONE, .callback = bt_discovery_result, .info = "Get discovery result" }, +{ .name = "remove_device", .session = AFB_SESSION_NONE, .callback = bt_remove_device, .info = "Remove the special device" }, +{ .name = "pair", .session = AFB_SESSION_NONE, .callback = bt_pair, .info = "Pair to special device" }, +{ .name = "cancel_pair", .session = AFB_SESSION_NONE, .callback = bt_cancel_pairing, .info = "Cancel the pairing process" }, +{ .name = "connect", .session = AFB_SESSION_NONE, .callback = bt_connect, .info = "Connect to special device" }, +{ .name = "disconnect", .session = AFB_SESSION_NONE, .callback = bt_disconnect, .info = "Disconnect special device" }, +{ .name = "set_property", .session = AFB_SESSION_NONE, .callback = bt_set_property, .info = "Set special device property" }, + +{ .name = NULL } /* marker for end of the array */ +}; + +/* + * description of the binding for afb-daemon + */ +static const struct afb_binding binding_description = +{ + .type = AFB_BINDING_VERSION_1, + .v1 = { + .info = "Application Framework Binder - Bluetooth Manager plugin", + .prefix = "Bluetooth-Manager", + .verbs = binding_verbs + } +}; + +/* + * activation function for registering the binding called by afb-daemon + */ +const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf) +{ + afbitf = itf; // records the interface for accessing afb-daemon + //D_PRINTF("\n"); +#if 1 +//temp solution to fix configure Bluetooth USB Dongle + system("rfkill unblock bluetooth"); + system("hciconfig hci0 up"); +#endif + BluetoothManageInit(); + return &binding_description; +} + +#if 0 +int afbBindingV1ServiceInit(struct afb_service service) +{ + return BluetoothManageInit(); +} +#endif + + +/************************************** The End Of File **************************************/ + diff --git a/bluetooth-api.h b/bluetooth-api.h new file mode 100755 index 0000000..8a7e593 --- /dev/null +++ b/bluetooth-api.h @@ -0,0 +1,50 @@ +/* Copyright 2016 ALPS ELECTRIC CO., 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. +*/ + + +#ifndef BLUETOOTH_API_H +#define BLUETOOTH_API_H + + + + +//#define _DEBUG +#ifdef _DEBUG +#define D_PRINTF(fmt, args...) \ + printf("[DEBUG][%s:%d:%s]"fmt, __FILE__, __LINE__, __FUNCTION__, ## args) +#define D_PRINTF_RAW(fmt, args...) \ + printf(""fmt, ## args) +#else /* ifdef _DEBUG */ +#define D_PRINTF(fmt, args...) +#define D_PRINTF_RAW(fmt, args...) +#endif /* ifdef _DEBUG */ +#define E_PRINTF(fmt, args...) \ + printf("[ERROR][%s:%d:%s]"fmt, __FILE__, __LINE__, __FUNCTION__, ## args) + + +/* -------------- PLUGIN DEFINITIONS ----------------- */ + +typedef struct { + void *bt_server; /* handle to implementation */ + unsigned int index; /* currently selected media file */ +} BtCtxHandleT; + +#endif /* BLUETOOTH_API_H */ + + + +/************************************** The End Of File **************************************/ + + diff --git a/bluetooth-manager.c b/bluetooth-manager.c new file mode 100755 index 0000000..4c49196 --- /dev/null +++ b/bluetooth-manager.c @@ -0,0 +1,747 @@ +/* Copyright 2016 ALPS ELECTRIC CO., 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 "bluetooth-api.h" +#include "bluetooth-manager.h" + +Client cli = { 0 }; + +stBluetoothManage BluetoothManage = { 0 }; + +/* ------ LOCAL FUNCTIONS --------- */ + +/* + register the agent, and register signal watch + */ +void bt_manage_dbus_init(void) { + D_PRINTF("\n"); + + //InitDBusCommunication(); + +} +/* ------ PUBLIC PLUGIN FUNCTIONS --------- */ + +/* + * Init the Bluetooth Manager + * Note: bluetooth-api shall do BluetoothManageInit() first before call other APIs. + */ +int BluetoothManageInit() { + D_PRINTF("\n"); + + BluetoothManage.device = NULL; + g_mutex_init(&(BluetoothManage.m)); + + bt_manage_dbus_init(); + + return 0; +} + +/* + * Set the Bluez Adapter Property "Powered" value + * If success return 0, else return -1; + */ +int adapter_set_powered(gboolean powervalue) { + D_PRINTF("value:%d\n",powervalue); + GDBusConnection *connection; + GError *error = NULL; + + GVariant *value; + gboolean result; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + FREEDESKTOP_PROPERTIES, "Set", + g_variant_new("(ssv)", ADAPTER_INTERFACE, "Powered", + g_variant_new("b", powervalue)), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; +} + +/* + * Get the Bluez Adapter Property "Powered" value + * If success return 0, else return -1; + */ +int adapter_get_powered(gboolean *powervalue) { + D_PRINTF("\n"); + GDBusConnection *connection; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + FREEDESKTOP_PROPERTIES, "Get", + g_variant_new("(ss)", ADAPTER_INTERFACE, "Powered"), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_get(value, "(v)", &subValue); + g_variant_get(subValue, "b", powervalue); + g_variant_unref(value); + + D_PRINTF("get ret :%d\n",*powervalue); + return 0; +} + +/* + * Call the Bluez Adapter Method "StartDiscovery" + * If success return 0, else return -1; + */ +int adapter_start_discovery() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "StartDiscovery", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; +} + +/* + * Call the Bluez Adapter Method "StopDiscovery" + * If success return 0, else return -1; + */ +int adapter_stop_discovery() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GVariant *subValue = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "StopDiscovery", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + + return 0; +} + +/* + * Call the Bluez Adapter Method "RemoveDevice" + * If success return 0, else return -1; + */ +int adapter_remove_device(struct btd_device * addr) { + D_PRINTF("\n%s\t%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, ADAPTER_PATH, + ADAPTER_INTERFACE, "RemoveDevice", g_variant_new("(o)", addr->path), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * Get the store device list. + */ +//FIXME: gdevices should be added the lock/unlock +GSList* adapter_get_devices_list() { + return BluetoothManage.device; +} + +void lock_devices_list(void) { + g_mutex_lock(&(BluetoothManage.m)); +} + +void unlock_devices_list(void) { + g_mutex_unlock(&(BluetoothManage.m)); +} + +/* + * Update the device list + * Call GetManagedObjects + * reply type is "Dict of {Object Path, Dict of {String, Dict of {String, Variant}}}" + */ +#if 0 +// Test Function +/* recursively iterate a container */ +void iterate_container_recursive (GVariant *container) +{ + GVariantIter iter; + GVariant *child; + + g_variant_iter_init (&iter, container); + while ((child = g_variant_iter_next_value (&iter))) + { + g_print ("type '%s'\n", g_variant_get_type_string (child)); + + if (g_variant_is_container (child)) + iterate_container_recursive (child); + + g_variant_unref (child); + } +} +#endif + +int adapter_update_devices() { + D_PRINTF("\n"); + GDBusConnection *connection = NULL; + GError *error = NULL; + GVariant *value = NULL; + GSList *newDeviceList = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, "/", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL, + NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + g_error_free(error); + return -1; + } + + GVariant *subValue = NULL; + GVariant *subValue_1 = NULL; + GVariantIter *subValueIter; + + g_variant_get(value, "(*)", &subValue); + + g_variant_get(subValue, "a*", &subValueIter); + while (g_variant_iter_loop(subValueIter, "*", &subValue_1)) { + +#if 0 + iterate_container_recursive(subValue_1); +#else + +//FIXME:Bad solution to get the BT address and name + GVariantIter dbus_object_iter; + GVariant *dbusObjecValue; + GVariant *dbusObjecSubValue; + gchar *dbusObjecPath; + struct btd_device *device; + + g_variant_iter_init(&dbus_object_iter, subValue_1); + + //DBus Object + dbusObjecValue = g_variant_iter_next_value(&dbus_object_iter); + + g_variant_get(dbusObjecValue, "o", &dbusObjecPath); + + //ObjectPath is /org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx + if ((37 != strlen(dbusObjecPath)) + || (NULL + == g_strrstr_len(dbusObjecPath, 19, + "/org/bluez/hci0/dev"))) { + g_variant_unref(dbusObjecValue); + continue; + } + device = g_try_malloc0(sizeof(struct btd_device)); + device->path = g_strdup(dbusObjecPath); + g_variant_unref(dbusObjecValue); + D_PRINTF("Found new device%s\n",device->path ); + + //DBus Interfaces and Method/Properties under Interface + dbusObjecSubValue = g_variant_iter_next_value(&dbus_object_iter); + + GVariantIter *interfaces_iter; + GVariant *interfaces_subValue; + g_variant_get(dbusObjecSubValue, "a*", &interfaces_iter); + + while (g_variant_iter_loop(interfaces_iter, "*", &interfaces_subValue)) { + // D_PRINTF("\t%s\n",g_variant_get_type_string(interfaces_subValue)); + + GVariantIter MethodsSignalProperties_iter; + GVariant *MethodsSignalProperties_name; + GVariant *MethodsSignalProperties_value; + gchar *properties_name; + + g_variant_iter_init(&MethodsSignalProperties_iter, + interfaces_subValue); + + //DBus Interfaces + MethodsSignalProperties_name = g_variant_iter_next_value( + &MethodsSignalProperties_iter); + + g_variant_get(MethodsSignalProperties_name, "s", &properties_name); + //D_PRINTF("\t%s\n",properties_name); + g_variant_unref(MethodsSignalProperties_name); + + if (NULL + == g_strrstr_len(properties_name, 20, + "org.bluez.Device1")) { + continue; + } + + D_PRINTF("\t%s\n",properties_name); + + //DBus XXX + MethodsSignalProperties_value = g_variant_iter_next_value( + &MethodsSignalProperties_iter); + + GVariantIter *subValue_iter; + GVariant *subValueVariant; + g_variant_get(MethodsSignalProperties_value, "a*", &subValue_iter); + + while (g_variant_iter_loop(subValue_iter, "*", &subValueVariant)) { + GVariantIter sub_subValue_iter; + GVariant *sub_subValue_name; + GVariant *sub_subValue_value; + gchar *key_1 = NULL; + gchar *key_2 = NULL; + + g_variant_iter_init(&sub_subValue_iter, subValueVariant); + + //DBus Interfaces + sub_subValue_name = g_variant_iter_next_value( + &sub_subValue_iter); + + g_variant_get(sub_subValue_name, "s", &key_1); + D_PRINTF("\t\t%s\n",key_1); + + //DBus XXX + sub_subValue_value = g_variant_iter_next_value( + &sub_subValue_iter); + + GVariant *dbus_value; + dbus_value = g_variant_get_variant(sub_subValue_value); + + if (g_variant_is_of_type(dbus_value, G_VARIANT_TYPE_STRING)) { + g_variant_get(dbus_value, "s", &key_2); + //D_PRINTF("\t\t\t%s\ts%s\n",key_1,key_2); + + if (g_strrstr_len(key_1, 10, "Address")) { + device->bdaddr = g_strdup(key_2); + } else if (g_strrstr_len(key_1, 10, "Name")) { + device->name = g_strdup(key_2); + } + g_free(key_2); + + } else if (g_variant_is_of_type(dbus_value, + G_VARIANT_TYPE_BOOLEAN)) { + gboolean properties_value; + g_variant_get(dbus_value, "b", &properties_value); + + if (g_strrstr_len(key_1, 10, "Paired")) { + device->paired = properties_value; + } else if (g_strrstr_len(key_1, 10, "Blocked")) { + device->blocked = properties_value; + } else if (g_strrstr_len(key_1, 10, "Connected")) { + device->connected = properties_value; + } else if (g_strrstr_len(key_1, 10, "Trusted")) { + device->trusted = properties_value; + } + + } + g_variant_unref(sub_subValue_name); + g_variant_unref(sub_subValue_value); + + } + g_variant_iter_free(subValue_iter); + + g_variant_unref(MethodsSignalProperties_value); + + } + g_variant_iter_free(interfaces_iter); + + g_variant_unref(dbusObjecSubValue); + +#endif + + newDeviceList = g_slist_append(newDeviceList, device); + + } + + g_variant_iter_free(subValueIter); + + g_variant_unref(value); + + //clean first + GSList * temp = BluetoothManage.device; + while (temp) { + struct btd_device *BDdevice = temp->data; + temp = temp->next; + + BluetoothManage.device = g_slist_remove_all(BluetoothManage.device, + BDdevice); + //D_PRINTF("\n%s\n%s\n",BDdevice->bdaddr,BDdevice->name); + if (BDdevice->bdaddr) { + g_free(BDdevice->bdaddr); + } + if (BDdevice->name) { + g_free(BDdevice->name); + } + if (BDdevice->path) { + g_free(BDdevice->path); + } + g_free(BDdevice); + + } + + BluetoothManage.device = newDeviceList; + +} + +/* + * send pairing command + * If success return 0, else return -1; + */ +int device_pair(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Pair", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * send cancel pairing command + * If success return 0, else return -1; + */ +int device_cancelPairing(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "CancelPairing", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} +/* + * send connect command + * If success return 0, else return -1; + */ +int device_connect(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Connect", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * send disconnect command + * If success return 0, else return -1; + */ +int device_disconnect(struct btd_device * addr) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *value; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + "org.bluez.Device1", "Disconnect", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(value); + return 0; + +} + +/* + * set remote device property + * If success return 0, else return -1; + */ +int device_set_property(struct btd_device * addr, const char *property_name, + const char *property_value) { + D_PRINTF("\n%s\n%s\t%s\n",addr->bdaddr,addr->name,addr->path); + + GDBusConnection *connection; + GError *error = NULL; + GVariant *ret; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + //Only support set "Trusted" + if (strcmp(property_name, "Trusted")) { + D_PRINTF("Not support property name\n"); + return -1; + } + + gboolean value; + if (atoi(property_value) == 1 || !strcasecmp(property_value, "true")) { + value = TRUE; + } else if (atoi(property_value) == 0 + || !strcasecmp(property_value, "false")) { + value = FALSE; + } else { + D_PRINTF("Not support property value\n"); + return -1; + } + + ret = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + FREEDESKTOP_PROPERTIES, "Set", + g_variant_new("(ssv)", DEVICE_INTERFACE, property_name, + g_variant_new("b", value)), NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == ret) { + D_PRINTF ("Error getting object manager client: %s", error->message); + g_error_free(error); + return -1; + } + + g_variant_unref(ret); + return 0; +} + +int isAVPConnected(struct btd_device *addr) { + + GDBusConnection *connection; + + GError *error = NULL; + GVariant *value; + GVariant *variantValue; + gboolean status; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + +// value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, BDdevice->path, FREEDESKTOP_PROPERTIES, +// "Get", g_variant_new("(ss)",MEDIA_CONTROL1_INTERFACE,"Connected"), +// NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + value = g_dbus_connection_call_sync(connection, BLUEZ_SERVICE, addr->path, + FREEDESKTOP_PROPERTIES, "Get", + g_variant_new("(ss)", MEDIA_CONTROL1_INTERFACE, "Connected"), NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + + g_error_free(error); + return -1; + } + + else { + g_variant_get(value, "(v)", &variantValue); + g_variant_get(variantValue, "b", &status); + printf("Address: %s:%i",addr->bdaddr, status); + return status; + } + + return 0; + +} + +int isHFPConnected(struct btd_device *addr) { + + GDBusConnection *connection; + + GError *error = NULL; + GVariant *value; + gchar *ofono_path; + gboolean status; + + GVariantIter *array; + GVariant *var = NULL; + const gchar *key = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (NULL == connection) { + D_PRINTF("GDBusconnection is NULL\n"); + return -1; + } + + +//path=/hfp/org/bluez/hci0/dev_E0_98_61_7D_D3_1E; interface=org.ofono.Modem; member=GetProperties + + ofono_path = g_strconcat("/hfp", addr->path, NULL); + + + value = g_dbus_connection_call_sync(connection, OFONO_SERVICE, ofono_path, + OFONO_MODEM_INTERFACE, "GetProperties", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, + DBUS_REPLY_TIMEOUT, NULL, &error); + + if (NULL == value) { + D_PRINTF ("Error getting object manager client: %s\n", error->message); + + g_error_free(error); + return -1; + } + + else { + + g_variant_get(value, "(a{sv})", &array); + while (g_variant_iter_loop(array, "{sv}", &key, &var)) { + if (g_strcmp0(key, "Powered") == 0) { + + g_variant_get(var, "b", &status); + + return status; + + } + } + g_variant_iter_free(array); + g_variant_unref(value); + g_free(ofono_path); + + return status; + } + + return 0; + +} + +/************************************** The End Of File **************************************/ + diff --git a/bluetooth-manager.h b/bluetooth-manager.h new file mode 100755 index 0000000..cb018b0 --- /dev/null +++ b/bluetooth-manager.h @@ -0,0 +1,143 @@ +/* Copyright 2016 ALPS ELECTRIC CO., 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. +*/ + + +#ifndef BLUETOOTH_MANAGER_H +#define BLUETOOTH_MANAGER_H + +#include +#include +//#include +#include +#include +#include +//service +#define AGENT_SERVICE "org.agent" + +//remote service +#define BLUEZ_SERVICE "org.bluez" +#define OFONO_SERVICE "org.ofono" +#define CLIENT_SERVICE "org.bluez.obex" + +//object path +#define OFONO_MANAGER_PATH "/" +#define ADAPTER_PATH "/org/bluez/hci0" +#define OBEX_CLIENT_PATH "/org/bluez/obex" +#define AGENT_PATH "/org/bluez" + +//interface +#define ADAPTER_INTERFACE "org.bluez.Adapter1" +#define DEVICE_INTERFACE "org.bluez.Device1" +#define AGENT_MANAGER_INTERFACE "org.bluez.AgentManager" +#define SERVICE_INTERFACE "org.bluez.Service" +#define AGENT_INTERFACE "org.bluez.Agent" + +#define CLIENT_INTERFACE "org.bluez.obex.Client" +#define TRANSFER_INTERFACE "org.bluez.obex.Transfer" +#define SESSION_INTERFACE "org.bluez.obex.Session" +#define OBEX_ERROR_INTERFACE "org.bluez.obex.Error" +#define BLUEZ_ERROR_INTERFACE "org.bluez.Error" +#define PBAP_INTERFACE "org.bluez.obex.PhonebookAccess" +#define MAP_INTERFACE "org.bluez.obex.MessageAccess" +#define MAP_MSG_INTERFACE "org.bluez.obex.Message" + +#define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer" +#define MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder" +#define MEDIA_ITEM_INTERFACE "org.bluez.MediaItem" +#define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport" +#define MEDIA_CONTROL1_INTERFACE "org.bluez.MediaControl1" + + +#define OFONO_HANDSFREE_INTERFACE "org.ofono.Handsfree" +#define OFONO_MANAGER_INTERFACE "org.ofono.Manager" +#define OFONO_MODEM_INTERFACE "org.ofono.Modem" +#define OFONO_VOICECALL_INTERFACE "org.ofono.VoiceCall" +#define OFONO_VOICECALL_MANAGER_INTERFACE "org.ofono.VoiceCallManager" +#define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration" +#define OFONO_NETWORK_OPERATOR_INTERFACE "org.ofono.NetworkOperator" +#define OFONO_CALL_VOLUME_INTERFACE "org.ofono.CallVolume" + +#define FREEDESKTOP_INTROSPECT "org.freedesktop.DBus.Introspectable" +#define FREEDESKTOP_PROPERTIES "org.freedesktop.DBus.Properties" + + +#define CONVERTER_CONN (cli.sys_conn) +#define AGENT_CONN (cli.agent_conn) +#define OBEX_CONN (cli.obex_conn) + +#define DBUS_REPLY_TIMEOUT (120 * 1000) +#define DBUS_REPLY_TIMEOUT_SHORT (10 * 1000) + +//typedef void(*callback)(void); +typedef void(*callback)(int password_rejected_flag); +void register_callback(callback ptr); + + +typedef struct _client +{ + GDBusConnection *sys_conn; + GDBusConnection *agent_conn; + GDBusConnection *obex_conn; + GMainLoop *clientloop; +// FILE *fd; +// int conn_fd; +} Client; + +//Bluetooth Device Properties +struct btd_device { + gchar *bdaddr; + gchar *path; + gchar *name; + gboolean paired; + gboolean trusted; + gboolean blocked; + gboolean connected; + gboolean avconnected; + gboolean hfpconnected; + GSList *uuids; +}; + +typedef struct { + gboolean inited; + GMutex m; + GSList * device; +} stBluetoothManage; + +int BluetoothManageInit(void); + +int adapter_set_powered(gboolean value); +int adapter_get_powered(gboolean *value); +int adapter_set_discoverable(gboolean value); +int adapter_start_discovery(); +int adapter_stop_discovery(); +int adapter_update_devices(); +GSList* adapter_get_devices_list(); +int adapter_remove_device(struct btd_device * addr); +int device_pair(struct btd_device * addr); +int device_cancelPairing(struct btd_device * addr); +int device_connect(struct btd_device * addr); +//int device_connectProfile(); +int device_disconnect(struct btd_device * addr); +//int device_disconnectProfile(); +int device_set_property(struct btd_device * addr, const char *property, const char *value); + +int isAVPConnected(struct btd_device *BDdevice); +int isHFPConnected(struct btd_device *BDdevice); + +#endif /* BLUETOOTH_MANAGER_H */ + + +/************************************** The End Of File **************************************/ + diff --git a/config.xml.in b/config.xml.in new file mode 100644 index 0000000..8cf7ff5 --- /dev/null +++ b/config.xml.in @@ -0,0 +1,9 @@ + + + Bluetooth Settings + + + Wifi Settings application + ALPS (Jiajun Gu<jiajun.gu@cn.alps.com>, Yidong Miao<yidong.miao@cn.alps.com>) + APL 2.0 + diff --git a/doc/AppGrid.qml b/doc/AppGrid.qml new file mode 100644 index 0000000..46b7889 --- /dev/null +++ b/doc/AppGrid.qml @@ -0,0 +1,43 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import components 1.0 +import system 1.0 + +App { + id: root + appId: 'appgrid' + + HexGrid { + anchors.centerIn: parent + columns: 5 + spacing: 10 + + Repeater { + model: ListModel { + ListElement { icon: "hvac"; name: "HVAC" } + ListElement { icon: "browser"; name: "DNA Browser" } + ListElement { icon: "dashboard"; name: "Dashboard" } + ListElement { icon: "googlemaps"; name: "Google Maps" } + ListElement { icon: "news"; name: "News" } + ListElement { icon: "nfc"; name: "NFC" } + ListElement { icon: "fmradio"; name: "FM Radio" } + ListElement { icon: "phone"; name: "Phone" } + ListElement { icon: "weather"; name: "Weather" } + ListElement { icon: "media_player"; name: "Media Manager" } + ListElement { icon: "cameras"; name: "Cameras" } + ListElement { icon: "fingerprint"; name: "Fingerprint" } + ListElement { icon: "wayland"; name: "Wayland" } + } + delegate: GridItem { + name: model.name + icon: model.icon + onClicked: System.activeApp = model.icon + } + } + } +} diff --git a/doc/AppIcon.qml b/doc/AppIcon.qml new file mode 100644 index 0000000..b645ed9 --- /dev/null +++ b/doc/AppIcon.qml @@ -0,0 +1,51 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +MouseArea { + id: root + + width: 90 + height: 90 + + property bool active: false + property alias source: icon.source + + function click() { + clicked(undefined) + } + + Image { + id: icon + anchors.centerIn: parent + width: 100 + height: 100 + fillMode: Image.PreserveAspectFit + } + +// states: [ +// State { +// name: "focused" +// when: root.active +// PropertyChanges { +// target: icon +// scale: 2.0 +// anchors.verticalCenterOffset: 20 +// } +// } +// ] + +// transitions: [ +// Transition { +// NumberAnimation { +// properties: 'scale, anchors.verticalCenterOffset' +// easing.type: Easing.OutElastic +// duration: 500 +// } +// } +// ] +} diff --git a/doc/BottomBar.qml b/doc/BottomBar.qml new file mode 100644 index 0000000..0760b71 --- /dev/null +++ b/doc/BottomBar.qml @@ -0,0 +1,65 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import system 1.0 +//import com.pelagicore.qmldevinfo 0.1 + +Item { + height: 120 + + ShaderEffect { + anchors.fill: parent + property color color: "#777" + property real radius: 40 + opacity: 0.24 + + fragmentShader: " +uniform lowp float radius; +uniform lowp float height; +uniform lowp float width; +uniform lowp float qt_Opacity; +uniform lowp vec4 color; +varying highp vec2 qt_TexCoord0; + +void main(void) { + lowp vec2 dist = min(qt_TexCoord0, vec2(1.0) - qt_TexCoord0); + lowp float xval = smoothstep(0.0, radius, dist.x * width); + lowp float yval = smoothstep(0.0, radius, dist.y * height); + gl_FragColor = mix(color, vec4(1.0), sqrt(yval * xval)) * qt_Opacity; +} + " + } + + Image { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + source: "images/settings_icon.png" + + MouseArea { + anchors.fill: parent + onClicked: System.showSettings = !System.showSettings + } + } + +// DevInfo { +// id: devinfo +// } + + Image { + anchors.centerIn: parent + anchors.horizontalCenterOffset: -15 + source: "images/AGL-Logo.png" + height: 80 + fillMode: Image.PreserveAspectFit + } + + VolumeControl { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 40 + } +} diff --git a/doc/GridItem.qml b/doc/GridItem.qml new file mode 100644 index 0000000..93d3031 --- /dev/null +++ b/doc/GridItem.qml @@ -0,0 +1,45 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + id: root + + width: background.width + height: background.height + + property string name + property string icon + + signal clicked() + + Image { + id: background + source: "images/AppHex.png" + } + + Column { + y: 10 + anchors.horizontalCenter: parent.horizontalCenter + spacing: -10 + + AppIcon { + source: "images/%1_app_icon.png".arg(root.icon) + } + + Text { + anchors.horizontalCenter: parent.horizontalCenter + color: "white" + text: root.name + } + } + + MouseArea { + anchors.fill: parent + onClicked: root.clicked() + } +} diff --git a/doc/Key.qml b/doc/Key.qml new file mode 100644 index 0000000..6eb5ae0 --- /dev/null +++ b/doc/Key.qml @@ -0,0 +1,85 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import QtGraphicalEffects 1.0 +import utils 1.0 + +Item { + id: root + + width: 90 + height: 130 + + property color color: Style.orangeViv + property alias text: textItem.text + property alias symbol: symbolItem.text + property real fade: 0.16 + property string icon: "" + + signal clicked() + + Rectangle { + id: keyRect + anchors.fill: parent + radius: 10 + } + + LinearGradient { + anchors.fill: parent + source: keyRect + start: Qt.point(0, 0) + end: Qt.point(0, 130) + gradient: Gradient { + GradientStop { position: 0.0; color: root.color } + GradientStop { position: root.fade; color: Qt.darker(root.color, 2.0) } + GradientStop { position: 0.8; color: "black" } + } + } + + Rectangle { + anchors.fill: parent + color: "transparent" + radius: 10 + border.width: 4 + border.color: Style.orangeLt + + Text { + id: symbolItem + visible: icon === "" + anchors.top: parent.top + anchors.right: parent.right + anchors.topMargin: 15 + anchors.rightMargin: 20 + font.pixelSize: 28 + font.family: "Source Sans Pro" + color: "white" + } + + Text { + id: textItem + visible: icon === "" + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + font.pixelSize: 60 + font.family: "Source Sans Pro" + color: "white" + } + + Image { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 30 + source: icon === "" ? icon : "images/" + icon + ".png" + } + } + + MouseArea { + anchors.fill: parent + onClicked: root.clicked() + } +} diff --git a/doc/Keyboard.qml b/doc/Keyboard.qml new file mode 100644 index 0000000..be79b75 --- /dev/null +++ b/doc/Keyboard.qml @@ -0,0 +1,137 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + id: root + height: 620 + + property var currentString: "" + property bool useSymbols: false + property bool useUppercase: false + + property var rows: [ + ["q","w","e","r","t","y","u","i","o","p"], + ["a","s","d","f","g","h","j","k","l"], + ["z","x","c","v","b","n","m"] + ] + property var symbolRows: [ + ["1","2","3","4","5","6","7","8","9","0"], + ["(",")","-","@","*","^",":",";","~"], + ["/","'","\"",".",",","?","!"] + ] + + function keyPressed(text, symbol) { + if (useSymbols) + currentString += symbol + else + currentString += text + } + + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.7 + } + + Column { + y: 20 + width: parent.width + spacing: 20 + + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: 10 + + Repeater { + model: rows[0] + Key { + text: useUppercase ? modelData.toUpperCase() : modelData + symbol: symbolRows[0][index] + onClicked: keyPressed(text, symbol) + } + } + } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: 10 + + Repeater { + model: rows[1] + Key { + text: useUppercase ? modelData.toUpperCase() : modelData + symbol: symbolRows[1][index] + onClicked: keyPressed(text, symbol) + } + } + } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + spacing: 45 + + Key { + width: 130 + color: Style.orangeLt + fade: 0.3 + icon: "shift_" + (useUppercase ? "on" : "off") + "_icon" + onClicked: useUppercase = !useUppercase + } + + Row { + spacing: 10 + + Repeater { + model: rows[2] + Key { + text: useUppercase ? modelData.toUpperCase() : modelData + symbol: symbolRows[2][index] + onClicked: keyPressed(text, symbol) + } + } + } + + Key { + width: 130 + color: Style.orangeLt + fade: 0.3 + icon: "backspace_icon" + onClicked: currentString = currentString.slice(0, -1) + } + } + + Row { + spacing: 20 + anchors.horizontalCenter: parent.horizontalCenter + + Key { + width: 150 + color: Style.orangeLt + fade: 0.3 + icon: "symbols" + (useSymbols ? "" : "_off") + "_icon" + onClicked: useSymbols = !useSymbols + } + + Key { + width: 700 + color: Style.orangeLt + fade: 0.3 + icon: "space_bar_icon" + onClicked: keyPressed(" ", " ") + } + + Key { + width: 150 + color: Style.orangeLt + fade: 0.3 + icon: "white_return" + } + } + } +} diff --git a/doc/Main.qml b/doc/Main.qml new file mode 100644 index 0000000..8f92511 --- /dev/null +++ b/doc/Main.qml @@ -0,0 +1,101 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.3 +import "apps/Browser" +import "apps/Cameras" +import "apps/Dashboard" +import "apps/Fingerprint" +import "apps/FMRadio" +import "apps/GoogleMaps" +import "apps/Home" +import "apps/HVAC" +import "apps/MediaPlayer" +import "apps/News" +import "apps/NFC" +import "apps/Phone" +import "apps/Settings" +import "apps/Weather" +import "apps/WaylandView" +import system 1.0 + +Item { + width: 1080 + height: 1920 + + Image { + anchors.centerIn: parent + source: "images/Hex-Background.jpg" + } + + Item { + id: appSurface + + anchors.top: topbar.bottom + anchors.bottom: bottombar.top + anchors.left: parent.left + anchors.right: parent.right + + + Home {} + GoogleMaps {} + Browser {} + Dashboard {} + HVAC {} + Weather {} + FMRadio {} + MediaPlayer {} + NFC {} + News {} + Phone {} + WaylandView {} + Cameras {} + Fingerprint {} + AppGrid {} + } + + TopBar { + id: topbar + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + } + + BottomBar { + id: bottombar + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + + Settings { + id: settings + visible: System.showSettings + anchors.fill: parent + anchors.topMargin: 120 + anchors.bottomMargin: 120 + } + + Keyboard { + id: keyboard + y: System.showKeyboard ? parent.height - height : parent.height + width: parent.width + + Behavior on y { YAnimator { duration: 300; easing.type: Easing.OutQuad }} + } + + focus: true + Keys.onLeftPressed: topbar.left() + Keys.onRightPressed: topbar.right() + Keys.onReturnPressed: topbar.click() + Keys.onBackPressed: topbar.home() + Keys.onPressed: { + switch (event.key) { + default: + console.debug('Main.qml', event.key) + } + } +} diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..b01fc55 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,23 @@ +Open source QML UI + +To run on target: +$ cd /usr/AGL/CES2017 +$ /usr/bin/qt5/qmlscene -I imports Main.qml + +For development it can be nice to use Scaled.qml instead so it fits your screen. + + + +© 2015 Jaguar Land Rover. All Rights Reserved. +Licensed under Creative Commons Attribution 4.0 International +https://creativecommons.org/licenses/by/4.0/legalcode + +(Optional) switch shell for weston to ivi-shell and start demo apps if you want to start demo apps with ivi-shell. +$ cd /usr/AGL/CES2017 +$ ./switch_to_ivi-shell +(Option a) $ ./start_ALS2016_ivi-shell.sh +(Option b) $ ./start_ALS2016_with_navi_ivi-shell.sh + +Option a: start QML UI only. +Option b: start QML + CarNavigation:/home/navi. For the time being, CarNavigation expects to be Wayland native application, which will be showed on top of QML by using LayerManagerControl. + diff --git a/doc/Rotated.qml b/doc/Rotated.qml new file mode 100644 index 0000000..4eef7f3 --- /dev/null +++ b/doc/Rotated.qml @@ -0,0 +1,17 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + width: 1920 + height: 1080 + + Main { + anchors.centerIn: parent + rotation: 90 + } +} diff --git a/doc/Scaled.qml b/doc/Scaled.qml new file mode 100644 index 0000000..c566735 --- /dev/null +++ b/doc/Scaled.qml @@ -0,0 +1,17 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + width: 1080*scale + height: 1920*scale + scale: 0.5 + + Main { + anchors.centerIn: parent + } +} diff --git a/doc/Scaled_04.qml b/doc/Scaled_04.qml new file mode 100644 index 0000000..502a663 --- /dev/null +++ b/doc/Scaled_04.qml @@ -0,0 +1,17 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + width: 1080*scale + height: 1920*scale + scale: 0.4 + + Main { + anchors.centerIn: parent + } +} diff --git a/doc/Scaled_720p.qml b/doc/Scaled_720p.qml new file mode 100644 index 0000000..86cb9b1 --- /dev/null +++ b/doc/Scaled_720p.qml @@ -0,0 +1,17 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + width: 1080*scale + height: 1920*scale + scale: 0.666666666 + + Main { + anchors.centerIn: parent + } +} diff --git a/doc/TopBar.qml b/doc/TopBar.qml new file mode 100644 index 0000000..5e0a532 --- /dev/null +++ b/doc/TopBar.qml @@ -0,0 +1,146 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import system 1.0 +import execScript 1.0 + +Item { + id: root + + height: 120 + + ShaderEffect { + anchors.fill: parent + property color color: "#777" + property real radius: 40 + opacity: 0.24 + + fragmentShader: " +uniform lowp float radius; +uniform lowp float height; +uniform lowp float width; +uniform lowp float qt_Opacity; +uniform lowp vec4 color; +varying highp vec2 qt_TexCoord0; + +void main(void) { + lowp vec2 dist = min(qt_TexCoord0, vec2(1.0) - qt_TexCoord0); + lowp float xval = smoothstep(0.0, radius, dist.x * width); + lowp float yval = smoothstep(0.0, radius, dist.y * height); + gl_FragColor = mix(color, vec4(1.0), sqrt(yval * xval)) * qt_Opacity; +} + " + } + + property int currentIndex: 0 + property AppIcon currentItem + + Row { + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 5 + anchors.horizontalCenter: parent.horizontalCenter + spacing: 30 + + AppIcon { + id: homeScreen + active: currentIndex === 0 + onActiveChanged: if (active) root.currentItem = homeScreen + property var mainScreen: root.parent + property bool home: System.activeApp === "home" + source: home ? "images/agl_icon.png" : "images/homescreen_icon.png" + + onClicked: { + if (currentIndex === 1) { + execscript.execute("./switch_off_navi.sh") + } + currentIndex = 0 + System.activeApp = "home" + } + } + + AppIcon { + id: googleMaps + active: currentIndex === 1 + onActiveChanged: if (active) root.currentItem = googleMaps + source: "images/googlemaps_app_icon.png" + + onClicked: { + currentIndex = 1 + System.activeApp = "googlemaps" + execscript.execute("./switch_on_navi.sh") + } + } + + Repeater { + model: ListModel { + id: applicationModel + ListElement { name: "browser" } + ListElement { name: "dashboard" } + ListElement { name: "hvac" } + ListElement { name: "weather" } + ListElement { name: "fmradio" } + ListElement { name: "media_player" } + } + + delegate: AppIcon { + id: app + active: currentIndex === model.index + 2 + onActiveChanged: if (active) root.currentItem = app + source: "images/%1_app_icon.png".arg(model.name) + onClicked: { + if (currentIndex === 1) { + execscript.execute("./switch_off_navi.sh") + } + System.activeApp = model.name + currentIndex = model.index + 2 + } + + Rectangle { + x: -15.5 + y: -15 + height: 123 + width: 1 + color: "black" + } + } + } + + AppIcon { + id: launcher + active: currentIndex === applicationModel.count + 2 + onActiveChanged: if (active) root.currentItem = launcher + source: "images/application_grid.png" + onClicked: { + if (currentIndex === 1) { + execscript.execute("./switch_off_navi.sh") + } + System.activeApp = "appgrid" + currentIndex = applicationModel.count + 2 + } + } + } + + property int __appCount: applicationModel.count + 3 + + function left() { + root.currentIndex = (root.currentIndex + root.__appCount - 1) % root.__appCount + } + + function right() { + root.currentIndex = (root.currentIndex + 1) % root.__appCount + } + + function click() { + currentItem.click() + } + + function home() { + homeScreen.click() + } + + ExecScript { id: execscript } +} diff --git a/doc/VolumeControl.qml b/doc/VolumeControl.qml new file mode 100644 index 0000000..56540a8 --- /dev/null +++ b/doc/VolumeControl.qml @@ -0,0 +1,97 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + height: 100 + width: childrenRect.width + + property alias value: shader.value + + FontLoader { + source: "fontawesome-webfont.ttf" + } + + Row { + spacing: 28 + + Text { + anchors.verticalCenter: parent.verticalCenter + font.family: "FontAwesome" + font.pixelSize: 30 + color: "white" + text: "\uf068" + + MouseArea { + anchors.fill: parent + onClicked: shader.value = Math.max(shader.value - 0.1, 0.0) + } + } + + ShaderEffect { + id: shader + width: 85 + height: 100 + + property color bgColor: "#333" + property color fgColor: "#b2f0ff" + property real value: 0.5 + + fragmentShader: " +uniform lowp float qt_Opacity; +uniform lowp float value; +uniform lowp vec4 bgColor; +uniform lowp vec4 fgColor; +varying highp vec2 qt_TexCoord0; + +void main(void) { + lowp float x = min(qt_TexCoord0.x, 1.0 - qt_TexCoord0.x); + lowp float y = min(qt_TexCoord0.y, 1.0 - qt_TexCoord0.y); + lowp float c = y - 0.5 * (0.5 - x); + lowp float outside = smoothstep(0.0, 0.01, c); + lowp float rim = smoothstep(0.1, 0.11, c - step(x, 0.101)); + lowp float inside = smoothstep(0.125, 0.135, c - step(x, 0.125)); + + lowp vec4 color = mix(bgColor, fgColor, step(qt_TexCoord0.x, value)); + color = mix(color, bgColor, inside * 0.8); + color = mix(color, vec4(1.0), (rim - inside) * 0.6); + + gl_FragColor = mix(vec4(0.0), color, outside) * qt_Opacity; +} + " + + MouseArea { + anchors.fill: parent + onPositionChanged: { + shader.value = Math.min(Math.max(mouse.x / width, 0.0), 1.0) + } + } + + Text { + anchors.centerIn: parent + font.family: "Source Sans Pro" + font.weight: Font.Bold + font.pixelSize: 30 + color: "white" + text: Math.round(shader.value * 100) + } + } + + Text { + anchors.verticalCenter: parent.verticalCenter + font.family: "FontAwesome" + font.pixelSize: 30 + color: "white" + text: "\uf067" + + MouseArea { + anchors.fill: parent + onClicked: shader.value = Math.min(shader.value + 0.1, 1.0) + } + } + } +} diff --git a/doc/images/AGL-Logo.png b/doc/images/AGL-Logo.png new file mode 100755 index 0000000..e869d7f Binary files /dev/null and b/doc/images/AGL-Logo.png differ diff --git a/doc/images/AppHex.png b/doc/images/AppHex.png new file mode 100755 index 0000000..6c9aa68 Binary files /dev/null and b/doc/images/AppHex.png differ diff --git a/doc/images/Hex-Background.jpg b/doc/images/Hex-Background.jpg new file mode 100755 index 0000000..ac9bae0 Binary files /dev/null and b/doc/images/Hex-Background.jpg differ diff --git a/doc/images/JLR-Logo.png b/doc/images/JLR-Logo.png new file mode 100755 index 0000000..50887d1 Binary files /dev/null and b/doc/images/JLR-Logo.png differ diff --git a/doc/images/agl_icon.png b/doc/images/agl_icon.png new file mode 100755 index 0000000..ad36a0d Binary files /dev/null and b/doc/images/agl_icon.png differ diff --git a/doc/images/application_grid.png b/doc/images/application_grid.png new file mode 100755 index 0000000..0cc5b2b Binary files /dev/null and b/doc/images/application_grid.png differ diff --git a/doc/images/backspace_icon.png b/doc/images/backspace_icon.png new file mode 100755 index 0000000..6bc0f20 Binary files /dev/null and b/doc/images/backspace_icon.png differ diff --git a/doc/images/blank_hexagon.png b/doc/images/blank_hexagon.png new file mode 100755 index 0000000..afeb31f Binary files /dev/null and b/doc/images/blank_hexagon.png differ diff --git a/doc/images/browser_app_icon.png b/doc/images/browser_app_icon.png new file mode 100755 index 0000000..9c6ec36 Binary files /dev/null and b/doc/images/browser_app_icon.png differ diff --git a/doc/images/browser_app_icon.svg b/doc/images/browser_app_icon.svg new file mode 100755 index 0000000..14d0ae6 --- /dev/null +++ b/doc/images/browser_app_icon.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + diff --git a/doc/images/bt_close.png b/doc/images/bt_close.png new file mode 100755 index 0000000..51ace79 Binary files /dev/null and b/doc/images/bt_close.png differ diff --git a/doc/images/cameras_app_icon.png b/doc/images/cameras_app_icon.png new file mode 100755 index 0000000..2127f8e Binary files /dev/null and b/doc/images/cameras_app_icon.png differ diff --git a/doc/images/cameras_app_icon.svg b/doc/images/cameras_app_icon.svg new file mode 100755 index 0000000..d8d1610 --- /dev/null +++ b/doc/images/cameras_app_icon.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + diff --git a/doc/images/dashboard_app_icon.png b/doc/images/dashboard_app_icon.png new file mode 100755 index 0000000..f7085d6 Binary files /dev/null and b/doc/images/dashboard_app_icon.png differ diff --git a/doc/images/dashboard_app_icon.svg b/doc/images/dashboard_app_icon.svg new file mode 100755 index 0000000..ca1146a --- /dev/null +++ b/doc/images/dashboard_app_icon.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/fingerprint_app_icon.png b/doc/images/fingerprint_app_icon.png new file mode 100755 index 0000000..abea688 Binary files /dev/null and b/doc/images/fingerprint_app_icon.png differ diff --git a/doc/images/fmradio_app_icon.png b/doc/images/fmradio_app_icon.png new file mode 100755 index 0000000..b781d31 Binary files /dev/null and b/doc/images/fmradio_app_icon.png differ diff --git a/doc/images/fmradio_app_icon.svg b/doc/images/fmradio_app_icon.svg new file mode 100755 index 0000000..5442afe --- /dev/null +++ b/doc/images/fmradio_app_icon.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/googlemaps_app_icon.png b/doc/images/googlemaps_app_icon.png new file mode 100755 index 0000000..3cb3e8d Binary files /dev/null and b/doc/images/googlemaps_app_icon.png differ diff --git a/doc/images/googlemaps_app_icon.svg b/doc/images/googlemaps_app_icon.svg new file mode 100755 index 0000000..425ca66 --- /dev/null +++ b/doc/images/googlemaps_app_icon.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/homescreen_icon.png b/doc/images/homescreen_icon.png new file mode 100755 index 0000000..d736310 Binary files /dev/null and b/doc/images/homescreen_icon.png differ diff --git a/doc/images/hvac_app_icon.png b/doc/images/hvac_app_icon.png new file mode 100755 index 0000000..27df1a0 Binary files /dev/null and b/doc/images/hvac_app_icon.png differ diff --git a/doc/images/hvac_app_icon.svg b/doc/images/hvac_app_icon.svg new file mode 100755 index 0000000..6626041 --- /dev/null +++ b/doc/images/hvac_app_icon.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/icon_apps_blue.png b/doc/images/icon_apps_blue.png new file mode 100755 index 0000000..95b534b Binary files /dev/null and b/doc/images/icon_apps_blue.png differ diff --git a/doc/images/icongear.png b/doc/images/icongear.png new file mode 100755 index 0000000..fa619aa Binary files /dev/null and b/doc/images/icongear.png differ diff --git a/doc/images/media_player_app_icon.png b/doc/images/media_player_app_icon.png new file mode 100755 index 0000000..2495afd Binary files /dev/null and b/doc/images/media_player_app_icon.png differ diff --git a/doc/images/media_player_app_icon.svg b/doc/images/media_player_app_icon.svg new file mode 100755 index 0000000..1bae4ed --- /dev/null +++ b/doc/images/media_player_app_icon.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/news_app_icon.png b/doc/images/news_app_icon.png new file mode 100755 index 0000000..33752f4 Binary files /dev/null and b/doc/images/news_app_icon.png differ diff --git a/doc/images/news_app_icon.svg b/doc/images/news_app_icon.svg new file mode 100755 index 0000000..e30ffe2 --- /dev/null +++ b/doc/images/news_app_icon.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + diff --git a/doc/images/nfc_app_icon.png b/doc/images/nfc_app_icon.png new file mode 100755 index 0000000..43c3a87 Binary files /dev/null and b/doc/images/nfc_app_icon.png differ diff --git a/doc/images/nfc_app_icon.svg b/doc/images/nfc_app_icon.svg new file mode 100755 index 0000000..a104c0f --- /dev/null +++ b/doc/images/nfc_app_icon.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/phone_app_icon.png b/doc/images/phone_app_icon.png new file mode 100755 index 0000000..3e3c9ac Binary files /dev/null and b/doc/images/phone_app_icon.png differ diff --git a/doc/images/phone_app_icon.svg b/doc/images/phone_app_icon.svg new file mode 100755 index 0000000..606dde9 --- /dev/null +++ b/doc/images/phone_app_icon.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/settings_icon.png b/doc/images/settings_icon.png new file mode 100755 index 0000000..44fb3d8 Binary files /dev/null and b/doc/images/settings_icon.png differ diff --git a/doc/images/shift_off_icon.png b/doc/images/shift_off_icon.png new file mode 100755 index 0000000..720a69a Binary files /dev/null and b/doc/images/shift_off_icon.png differ diff --git a/doc/images/shift_on_icon.png b/doc/images/shift_on_icon.png new file mode 100755 index 0000000..503ff24 Binary files /dev/null and b/doc/images/shift_on_icon.png differ diff --git a/doc/images/space_bar_icon.png b/doc/images/space_bar_icon.png new file mode 100755 index 0000000..2b5c2fa Binary files /dev/null and b/doc/images/space_bar_icon.png differ diff --git a/doc/images/switchcontrol.png b/doc/images/switchcontrol.png new file mode 100755 index 0000000..1c350b5 Binary files /dev/null and b/doc/images/switchcontrol.png differ diff --git a/doc/images/switchplate_off.png b/doc/images/switchplate_off.png new file mode 100755 index 0000000..16250c5 Binary files /dev/null and b/doc/images/switchplate_off.png differ diff --git a/doc/images/switchplate_on.png b/doc/images/switchplate_on.png new file mode 100755 index 0000000..43bb554 Binary files /dev/null and b/doc/images/switchplate_on.png differ diff --git a/doc/images/symbols_icon.png b/doc/images/symbols_icon.png new file mode 100755 index 0000000..07e1deb Binary files /dev/null and b/doc/images/symbols_icon.png differ diff --git a/doc/images/symbols_off_icon.png b/doc/images/symbols_off_icon.png new file mode 100755 index 0000000..59cd170 Binary files /dev/null and b/doc/images/symbols_off_icon.png differ diff --git a/doc/images/tizen.png b/doc/images/tizen.png new file mode 100755 index 0000000..c6674d6 Binary files /dev/null and b/doc/images/tizen.png differ diff --git a/doc/images/weather_app_icon.png b/doc/images/weather_app_icon.png new file mode 100755 index 0000000..dcb46ee Binary files /dev/null and b/doc/images/weather_app_icon.png differ diff --git a/doc/images/weather_app_icon.svg b/doc/images/weather_app_icon.svg new file mode 100755 index 0000000..d1fb79c --- /dev/null +++ b/doc/images/weather_app_icon.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/white_return.png b/doc/images/white_return.png new file mode 100755 index 0000000..0385846 Binary files /dev/null and b/doc/images/white_return.png differ diff --git a/export.map b/export.map new file mode 100755 index 0000000..0ef1ac7 --- /dev/null +++ b/export.map @@ -0,0 +1 @@ +{ global: afbBindingV1Register; local: *; }; diff --git a/icon_bt.png b/icon_bt.png new file mode 100644 index 0000000..ac3233b Binary files /dev/null and b/icon_bt.png differ diff --git a/imports/components/AwesomeIcon.qml b/imports/components/AwesomeIcon.qml new file mode 100755 index 0000000..542fb0f --- /dev/null +++ b/imports/components/AwesomeIcon.qml @@ -0,0 +1,26 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import system 1.0 +import components 1.0 +import utils 1.0 + +Item { + height: icon.height + width: icon.height + + property alias iconSize: icon.font.pixelSize + property alias ucKey: icon.text + property alias iconColor: icon.color + + Text { + id: icon + font.family: "FontAwesome" + color: "white" + } +} + diff --git a/imports/components/Box.qml b/imports/components/Box.qml new file mode 100755 index 0000000..a2f2ae0 --- /dev/null +++ b/imports/components/Box.qml @@ -0,0 +1,49 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + id: root + + opacity: 0.8 + property color color: Style.grey + property color border: color + property string shadow: "" + + OutShadow { + color: root.color + visible: root.shadow === "out" + } + + Rectangle { + id: rect + anchors.fill: parent + color: Style.black + border.width: 1 + border.color: root.border + } + + InsetShadow { + color: root.color + visible: root.shadow === "fill" + } + + InShadow { + color: root.color + visible: root.shadow === "in" + } + + Rectangle { + visible: root.shadow === "fill" + anchors.fill: parent + color: "transparent" + border.width: 1 + border.color: root.border + } + +} diff --git a/imports/components/BoxButton.qml b/imports/components/BoxButton.qml new file mode 100755 index 0000000..0969f46 --- /dev/null +++ b/imports/components/BoxButton.qml @@ -0,0 +1,36 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import components 1.0 + +Item { + id: root + + property alias shadow: box.shadow + property alias color: box.color + property alias text: textItem.text + + signal clicked() + + Box { + id: box + anchors.fill: parent + + Text { + id: textItem + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 28 + color: "white" + } + + MouseArea { + anchors.fill: parent + onClicked: root.clicked() + } + } +} diff --git a/imports/components/BoxHeading.qml b/imports/components/BoxHeading.qml new file mode 100755 index 0000000..bb2c62a --- /dev/null +++ b/imports/components/BoxHeading.qml @@ -0,0 +1,37 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Row { + id: root + + property color color: Style.blueViv + property alias fontSize: headingText.font.pixelSize + property alias text: headingText.text + property alias boxWidth: box.width + property alias boxHeight: box.height + + spacing: 10 + + Rectangle { + id: box + anchors.bottom: headingText.baseline + anchors.bottomMargin: 0 + width: 100 + height: 16 + color: root.color + } + + Text { + id: headingText + font.family: "Source Sans Pro" + font.pixelSize: 22 + font.weight: Font.Bold + color: root.color + } +} diff --git a/imports/components/Button.qml b/imports/components/Button.qml new file mode 100755 index 0000000..9d5c495 --- /dev/null +++ b/imports/components/Button.qml @@ -0,0 +1,30 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Rectangle { + id: root + border.color: "#cccccc" + color:"#222" + border.width: 2 + height: pairText.height + 20 + width: pairText.width + 20 + + property string buttonText + + + Text { + id: pairText + anchors.centerIn: parent + font.family: "Source Sans Pro" + font.pixelSize: 48 + font.weight: Font.Bold + color: "white" + font.capitalization: Font.AllUppercase + text: buttonText + } +} diff --git a/imports/components/DateTime.qml b/imports/components/DateTime.qml new file mode 100755 index 0000000..6203712 --- /dev/null +++ b/imports/components/DateTime.qml @@ -0,0 +1,35 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + id: dateTime + anchors.left: parent.left + anchors.right: parent.right + height: 120 + property var timeStamp: new Date() + + Timer { + interval: 1000 + running: true + repeat: true + onTriggered: timeStamp = new Date() + } + + Label { + fontColor: Style.grey + text: Qt.formatDate(timeStamp, "ddd MMM d") + } + + Label { + anchors.right: parent.right + fontColor: Style.grey + text: Qt.formatTime(timeStamp, "h:mm AP") + } +} + diff --git a/imports/components/HexGrid.qml b/imports/components/HexGrid.qml new file mode 100755 index 0000000..b81a09a --- /dev/null +++ b/imports/components/HexGrid.qml @@ -0,0 +1,32 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Item { + property real spacing: 0 + property int columns: 3 + + width: childrenRect.width + height: childrenRect.height + + Component.onCompleted: { + var sizeX = childrenRect.height + var sizeY = childrenRect.width + var column = 0 + var row = 0 + + for (var n = 0; n < children.length; n++) { + children[n].x = column * (sizeX + spacing) + children[n].y = row * (0.5 * sizeY + spacing) + column += 2 + if (column >= columns) { + row++ + column = row % 2 + } + } + } +} diff --git a/imports/components/HexSwitch.qml b/imports/components/HexSwitch.qml new file mode 100755 index 0000000..cce82b3 --- /dev/null +++ b/imports/components/HexSwitch.qml @@ -0,0 +1,80 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Item { + width: 170 * height / 80 + height: 80 + + property bool value + property bool showLabels: false + + Image { + anchors.fill: parent + source: "../../doc/images/switchplate_" + (value ? "on" : "off") + ".png" + } + + Item { + id: shadowTarget + x: value ? parent.width * 0.375 : -11 + width: parent.width * 0.7 + height: parent.height + + Image { + id: control + anchors.centerIn: parent + width: parent.height * 0.9 + fillMode: Image.PreserveAspectFit + source: "../../doc/images/switchcontrol.png" + } + } + + DropShadow { + anchors.fill: shadowTarget + cached: true + horizontalOffset: parent.height * 0.05 + verticalOffset: parent.height * 0.05 + radius: 16 + samples: 32 + color: Qt.rgba(0, 0, 0, 0.35) + smooth: true + source: shadowTarget + } + + Text { + text: qsTr("OFF") + font.family: "Source Sans Pro" + anchors.right: parent.left + anchors.rightMargin: 30 + anchors.verticalCenter: parent.verticalCenter + font.pointSize: 25 + font.letterSpacing: -0.5 + font.weight: value ? Font.Normal : Font.Bold + color: value ? "#C4C4C4" : "#FE9C00" + visible: showLabels + } + + Text { + id: onText + text: qsTr("ON") + font.family: "Source Sans Pro" + anchors.left: parent.right + anchors.leftMargin: 30 + font.pointSize: 25 + anchors.verticalCenter: parent.verticalCenter + font.letterSpacing: -0.5 + font.weight: value ? Font.Bold : Font.Normal + color: value ? "#59FF00" : "#C4C4C4" + visible: showLabels + } + + MouseArea { + anchors.fill: parent + onClicked: value = !value + } +} diff --git a/imports/components/InShadow.qml b/imports/components/InShadow.qml new file mode 100755 index 0000000..2d64c2a --- /dev/null +++ b/imports/components/InShadow.qml @@ -0,0 +1,33 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +ShaderEffect { + anchors.fill: parent + property color color + property real radius: 16 + + fragmentShader: " +uniform lowp float radius; +uniform lowp float height; +uniform lowp float width; +uniform lowp float qt_Opacity; +uniform lowp vec4 color; +varying highp vec2 qt_TexCoord0; + +void main(void) { + lowp vec2 dist = min(qt_TexCoord0, vec2(1.0) - qt_TexCoord0); + // Border shadow + lowp float xval = smoothstep(0.0, radius, dist.x * width); + lowp float yval = smoothstep(0.0, radius, dist.y * height); + lowp float borderVal = sqrt(yval * xval) * 0.5 + 0.5; + + lowp vec4 borderColor = mix(color, vec4(0.0, 0.0, 0.0, 1.0), borderVal); + gl_FragColor = borderColor * qt_Opacity; +} + " +} diff --git a/imports/components/InsetShadow.qml b/imports/components/InsetShadow.qml new file mode 100755 index 0000000..6ad17cd --- /dev/null +++ b/imports/components/InsetShadow.qml @@ -0,0 +1,40 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +ShaderEffect { + anchors.fill: parent + property color color + property real radius: 100 + property real border: 20 + + fragmentShader: " +uniform lowp float radius; +uniform lowp float border; +uniform lowp float height; +uniform lowp float width; +uniform lowp float qt_Opacity; +uniform lowp vec4 color; +varying highp vec2 qt_TexCoord0; + +void main(void) { + lowp vec2 dist = min(qt_TexCoord0, vec2(1.0) - qt_TexCoord0); + // Border shadow + lowp float xval = smoothstep(0.0, border, dist.x * width); + lowp float yval = smoothstep(0.0, border, dist.y * height); + lowp float borderVal = sqrt(yval * xval) * 0.5 + 0.5; + // Inner shadow + xval = smoothstep(0.0, radius, dist.x * width); + yval = smoothstep(0.0, radius, dist.y * width); + lowp float innerVal = sqrt(yval * xval) * 0.5 + 0.5; + + lowp vec4 innerColor = mix(vec4(0.0, 0.0, 0.0, 0.5), color, innerVal); + lowp vec4 borderColor = mix(vec4(0.0, 0.0, 0.0, 1.0), innerColor, borderVal); + gl_FragColor = borderColor * qt_Opacity; +} + " +} diff --git a/imports/components/Label.qml b/imports/components/Label.qml new file mode 100755 index 0000000..e1e0b30 --- /dev/null +++ b/imports/components/Label.qml @@ -0,0 +1,27 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + // Tracer {} + width: childrenRect.width + height: childrenRect.height + property alias text: text.text + property alias label: text + property alias fontSize: text.font.pixelSize + property alias fontColor: text.color + + Text { + id: text + color: "#ddd" + font.family: "Source Sans Pro" + font.pixelSize: 40 + font.capitalization: Font.AllUppercase + font.weight: Font.Bold + } +} diff --git a/imports/components/NumberPad.qml b/imports/components/NumberPad.qml new file mode 100755 index 0000000..b7763ca --- /dev/null +++ b/imports/components/NumberPad.qml @@ -0,0 +1,101 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + id: root + height: childrenRect.height + property var letters: ["","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"] + property var bottomRow: ["*","0","#"] + + signal number(string number) + + Grid { + id: numberGrid + columns: 3 + spacing: 20 + + Repeater { + model: 9 + delegate: Item { + id: numberKey + width: (root.width - ( numberGrid.spacing*(numberGrid.columns-1)))/numberGrid.columns + height: numberKey.width * 0.8 + anchors.margins: 10 + + Rectangle { + id: shadowTarget + anchors.fill: parent + border.width: 1 + border.color: "white" + color: "#6653b5ce" + } + + Item { + height: childrenRect.height + width: parent.width + anchors.centerIn: parent + + Label { + anchors.horizontalCenter: parent.horizontalCenter + id: keypadNumber + text: index + 1 + } + + Label { + anchors.horizontalCenter: parent.horizontalCenter + id: keypadLetters + anchors.top: keypadNumber.bottom + fontSize: 30 + fontColor: "#53b5ce" + text: letters[index] + } + } + + MouseArea { + anchors.fill: parent + onClicked: root.number(keypadNumber.text) + } + } + } + + Repeater { + model: 3 + delegate: Item { + width: (root.width - ( numberGrid.spacing*(numberGrid.columns-1)))/numberGrid.columns + height: width * 0.8 + anchors.margins: 10 + + Rectangle { + id: shadowTarget + anchors.fill: parent + border.width: 1 + border.color: "white" + color: "#6653b5ce" + } + + Item { + height: childrenRect.height + width: parent.width + anchors.centerIn: parent + + Label { + anchors.horizontalCenter: parent.horizontalCenter + id: keypadNumber + text: bottomRow[index] + } + } + + MouseArea { + anchors.fill: parent + onClicked: root.number(keypadNumber.text) + } + } + } + } +} diff --git a/imports/components/OutShadow.qml b/imports/components/OutShadow.qml new file mode 100755 index 0000000..f4d8407 --- /dev/null +++ b/imports/components/OutShadow.qml @@ -0,0 +1,41 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Item { + id: root + + anchors.fill: parent + property alias color: shadow.color + property alias radius: shadow.radius + + Item { + id: shadowTarget + x: -radius + y: -radius + width: parent.width + 2 * radius + height: parent.height + 2 * radius + + Rectangle { + anchors.centerIn: parent + width: root.width + height: root.height + color: "black" + } + } + + DropShadow { + id: shadow + anchors.fill: shadowTarget + horizontalOffset: 0 + verticalOffset: 0 + radius: 16 + samples: 32 + source: shadowTarget + } +} diff --git a/imports/components/Switch.qml b/imports/components/Switch.qml new file mode 100755 index 0000000..6cd50c7 --- /dev/null +++ b/imports/components/Switch.qml @@ -0,0 +1,13 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 + +Switch { + width: 100 + height: 62 +} + diff --git a/imports/components/qmldir b/imports/components/qmldir new file mode 100755 index 0000000..57e4d2d --- /dev/null +++ b/imports/components/qmldir @@ -0,0 +1,16 @@ +#/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. +# * +# * This Source Code Form is subject to the terms of the Mozilla Public +# * License, v. 2.0. If a copy of the MPL was not distributed with this +# * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +AwesomeIcon 1.0 AwesomeIcon.qml +Box 1.0 Box.qml +BoxButton 1.0 BoxButton.qml +BoxHeading 1.0 BoxHeading.qml +DateTime 1.0 DateTime.qml +HexGrid 1.0 HexGrid.qml +HexSwitch 1.0 HexSwitch.qml +Label 1.0 Label.qml +NumberPad 1.0 NumberPad.qml +Button 1.0 Button.qml diff --git a/imports/radio/Radio.qml b/imports/radio/Radio.qml new file mode 100755 index 0000000..cea2e1a --- /dev/null +++ b/imports/radio/Radio.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Item { + signal stopped + signal playing +} diff --git a/imports/radio/qmldir b/imports/radio/qmldir new file mode 100755 index 0000000..e334188 --- /dev/null +++ b/imports/radio/qmldir @@ -0,0 +1,2 @@ +Radio 1.0 Radio.qml +RadioPropertyItem 1.0 Radio.qml diff --git a/imports/system/App.qml b/imports/system/App.qml new file mode 100755 index 0000000..d7da73c --- /dev/null +++ b/imports/system/App.qml @@ -0,0 +1,29 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import system 1.0 + +FocusScope { + id: root + property string appId + anchors.fill: parent + visible: System.activeApp === appId + property bool hasKeyFocus: false + focus: visible + onFocusChanged: if (focus) hasKeyFocus = true + + Keys.onPressed: { + switch (event.key) { + case Qt.Key_Left: + case Qt.Key_Right: + root.hasKeyFocus = false + break + default: + break + } + } +} diff --git a/imports/system/System.qml b/imports/system/System.qml new file mode 100755 index 0000000..8e155fd --- /dev/null +++ b/imports/system/System.qml @@ -0,0 +1,15 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton +import QtQuick 2.0 + +Item { + property string activeApp: "home" + property string activeSetting: "settings" + property bool showKeyboard: false + property bool showSettings: false +} diff --git a/imports/system/qmldir b/imports/system/qmldir new file mode 100755 index 0000000..afa0f56 --- /dev/null +++ b/imports/system/qmldir @@ -0,0 +1,8 @@ +#/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. +# * +# * This Source Code Form is subject to the terms of the Mozilla Public +# * License, v. 2.0. If a copy of the MPL was not distributed with this +# * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +singleton System 1.0 System.qml +App 1.0 App.qml diff --git a/imports/utils/Marker.qml b/imports/utils/Marker.qml new file mode 100755 index 0000000..c7a377e --- /dev/null +++ b/imports/utils/Marker.qml @@ -0,0 +1,60 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import utils 1.0 + +Item { + id: root + width: 120 + height: 120 + property string text + signal clicked() + property alias pressed: area.pressed + property alias color: background.color + property alias fontSize: label.font.pixelSize + property bool fill: false + + Rectangle { + id: background + anchors.fill: parent + color: Style.backgroundColor + opacity: root.fill ? 1.0: 0.2 + } + + Rectangle { + id: frame + anchors.fill: parent + color: 'transparent' + border.color: Qt.darker(background.color, 1.4) + border.width: 2 + opacity: 1.0 + } + + + Rectangle { + anchors.fill: label + anchors.margins: -2 + color: Style.backgroundColor + opacity: root.text ? 1.0 : 0.0 + } + + Text { + id: label + anchors.centerIn: parent + font.pixelSize: 14 + color: Style.greyDarkColor + opacity: 0.75 + text: root.text + } + MouseArea { + id: area + anchors.fill: parent + onClicked: root.clicked() + onPressed: background.color = Qt.darker(background.color, 1.5) + onReleased: background.color = Qt.lighter(background.color, 1.5) + } +} diff --git a/imports/utils/Style.qml b/imports/utils/Style.qml new file mode 100755 index 0000000..ef544a6 --- /dev/null +++ b/imports/utils/Style.qml @@ -0,0 +1,37 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton +import QtQuick 2.2 + +QtObject { + property bool debugMode: false + property bool debugFill: false + + // Primary colors + property color orangeLt: "#ffd38c" + property color orangeViv: "#fe9c00" + property color blueLt: "#b2f0ff" + property color blueViv: "#53b5ce" + // Secondary colors + property color yellowLt: "#ffffb2" + property color yellowViv: "#ffff00" + property color greenLt: "#cdffb2" + property color greenViv: "#59ff00" + // Neutral colors + property color white: "#ffffff" + property color grey: "#c4c4c4" + property color black: "#000000" + property color overlay: Qt.rgba(0, 0, 0, 0.8) + + function getGfxPath() { + return Qt.resolvedUrl("../assets/") + } + + function gfx(name) { + return Qt.resolvedUrl("../../doc/images/" + name ) + } +} diff --git a/imports/utils/qmldir b/imports/utils/qmldir new file mode 100755 index 0000000..c2df9de --- /dev/null +++ b/imports/utils/qmldir @@ -0,0 +1,8 @@ +#/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. +# * +# * This Source Code Form is subject to the terms of the Mozilla Public +# * License, v. 2.0. If a copy of the MPL was not distributed with this +# * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +singleton Style 1.0 Style.qml +Marker 1.0 Marker.qml diff --git a/imports/vehicle/ClimateModel.qml b/imports/vehicle/ClimateModel.qml new file mode 100755 index 0000000..9633f16 --- /dev/null +++ b/imports/vehicle/ClimateModel.qml @@ -0,0 +1,44 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton + +import QtQuick 2.0 +import Automotive.ClimateControl 1.0 + +Item { + property real fanStepSize:1/255 //Represents the stepSize for a given Climate control. + property alias fanSpeed: fanControl.fanSpeedLevel + + property real temperatureStepSize:1/15 //0== 15c, 15 == 30c + + property alias leftTemp: leftFront.targetTemperature + property alias rightTemp: rightFront.targetTemperature + + ClimateControlItem { + id:fanControl + } + + ClimateControlItem { + id: leftFront + zone: 9 + } + + ClimateControlItem { + id: rightFront + zone: 5 + } + + function getRangeValue(inputVal,stepSize){ + if(inputVal > 0){ + return Math.ceil(inputVal/stepSize); + }else{ + return 0; + } + } + +} + diff --git a/imports/vehicle/FuelModel.qml b/imports/vehicle/FuelModel.qml new file mode 100755 index 0000000..fa064e2 --- /dev/null +++ b/imports/vehicle/FuelModel.qml @@ -0,0 +1,46 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton + +import QtQuick 2.0 + +Item { + property bool metric: false + + function galToL(value) { + return (metric ? 3.78541 : 1) * value + } + + function mpgToLp100(value) { + return metric ? 235.214583571 / value : value + } + + property real baseTank: 25 + property real tankSize: galToL(baseTank) + property real level: tankSize * percentage * 0.01 + property real percentage: 100 + property real range: metric ? 100 * level / average : level * average + property real baseAverage: 20.7 + property real average: mpgToLp100(baseAverage + mpgDiff) + property real mpgDiff: 0 + + NumberAnimation on percentage { + from: 100 + to: 0 + duration: 5000 + loops: Animation.Infinite + easing.type: Easing.CosineCurve + } + + NumberAnimation on mpgDiff { + from: -2 + to: 2 + duration: 11200 + loops: Animation.Infinite + easing.type: Easing.CosineCurve + } +} diff --git a/imports/vehicle/PositionModel.qml b/imports/vehicle/PositionModel.qml new file mode 100755 index 0000000..00956aa --- /dev/null +++ b/imports/vehicle/PositionModel.qml @@ -0,0 +1,33 @@ +/* Copyright (C) 2015, Jaguar Land Rover, IoT.bzh. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton + +import QtQuick 2.0 +import amb 0.1 + +Item { + property string nmeaString: nmea.value + property real satellites: satsUsed.value + + AutomotivePropertyItem { + id: nmea + + objectName: "GpsNmea" + propertyName: "Nmea" + + Component.onCompleted: nmea.connect(); + } + + AutomotivePropertyItem { + id: satsUsed + + objectName: "GpsSatsUsed" + propertyName: "SatsUsed" + + Component.onCompleted: satsUsed.connect(); + } +} diff --git a/imports/vehicle/SpeedModel.qml b/imports/vehicle/SpeedModel.qml new file mode 100755 index 0000000..03422b0 --- /dev/null +++ b/imports/vehicle/SpeedModel.qml @@ -0,0 +1,38 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton + +import QtQuick 2.0 +import amb 0.1 + +Item { + property bool metric: false + + function mphToKph(value) { + return (metric ? 1.60934 : 1 ) * value + } + + property real max:Math.ceil(mphToKph(baseMaxSpeed)/30)*30 + property real baseMaxSpeed: 255 + property real textSpeed: prop.value + property real percentage: textSpeed / max * 100 + + AutomotivePropertyItem { + id: prop + + objectName: "VehicleSpeed" + propertyName: "Speed" + + Component.onCompleted: prop.connect(); + } + + Behavior on percentage { + SmoothedAnimation { + velocity: 100 + } + } +} diff --git a/imports/vehicle/TemperatureModel.qml b/imports/vehicle/TemperatureModel.qml new file mode 100755 index 0000000..2bfbbf4 --- /dev/null +++ b/imports/vehicle/TemperatureModel.qml @@ -0,0 +1,26 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pragma Singleton + +import QtQuick 2.0 + +Item { + property bool metric: true + + function unit(value) { + return celsiusToFahrenheit(value).toFixed(1) + "\u00b0" + (metric ? "C" : "F") + } + + function celsiusToFahrenheit(value) { + return (metric ? value : 1.8 * value + 32) + } + + property real indoor: 20.4 + property string indoorString: unit(indoor) + property real outdoor: 28.9 + property string outdoorString: unit(outdoor) +} diff --git a/imports/vehicle/qmldir b/imports/vehicle/qmldir new file mode 100755 index 0000000..6538e95 --- /dev/null +++ b/imports/vehicle/qmldir @@ -0,0 +1,11 @@ +#/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. +# * +# * This Source Code Form is subject to the terms of the Mozilla Public +# * License, v. 2.0. If a copy of the MPL was not distributed with this +# * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +singleton FuelModel 1.0 FuelModel.qml +singleton SpeedModel 1.0 SpeedModel.qml +singleton TemperatureModel 1.0 TemperatureModel.qml +singleton PositionModel 1.0 PositionModel.qml +singleton ClimateModel 1.0 ClimateModel.qml diff --git a/oe-sdk_crosscompile.cmake b/oe-sdk_crosscompile.cmake new file mode 100755 index 0000000..9669344 --- /dev/null +++ b/oe-sdk_crosscompile.cmake @@ -0,0 +1,20 @@ +# this toolchain file comes from gnuradio project +# https://raw.githubusercontent.com/intel-iot-devkit/upm/master/cmake/Toolchains/oe-sdk_cross.cmake + +set( CMAKE_SYSTEM_NAME Linux ) +#set( CMAKE_C_COMPILER $ENV{CC} ) +#set( CMAKE_CXX_COMPILER $ENV{CXX} ) +string(REGEX MATCH "sysroots/([a-zA-Z0-9]+)" CMAKE_SYSTEM_PROCESSOR $ENV{SDKTARGETSYSROOT}) +string(REGEX REPLACE "sysroots/" "" CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}) +set( CMAKE_CXX_FLAGS $ENV{CXXFLAGS} CACHE STRING "" FORCE ) +set( CMAKE_C_FLAGS $ENV{CFLAGS} CACHE STRING "" FORCE ) #same flags for C sources +set( CMAKE_LDFLAGS_FLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE ) #same flags for C sources +set( CMAKE_LIBRARY_PATH ${OECORE_TARGET_SYSROOT}/usr/lib ) +set( CMAKE_FIND_ROOT_PATH $ENV{OECORE_TARGET_SYSROOT} $ENV{OECORE_NATIVE_SYSROOT} ) +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +set( CMAKE_INSTALL_PREFIX $ENV{OECORE_TARGET_SYSROOT}/usr CACHE STRING "" FORCE) +set( ORC_INCLUDE_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/include/orc-0.4 ) +set( ORC_LIBRARY_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/lib ) + diff --git a/qml/bluetooth-settings/bluetooth-settings-app.qml b/qml/bluetooth-settings/bluetooth-settings-app.qml new file mode 100755 index 0000000..31ba001 --- /dev/null +++ b/qml/bluetooth-settings/bluetooth-settings-app.qml @@ -0,0 +1,404 @@ +/* Copyright (C) 2015, Jaguar Land Rover. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import QtQuick 2.0 +import system 1.0 +import components 1.0 +import utils 1.0 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles 1.0 + +import "../../doc/" +import "../../imports/system/" + +ApplicationWindow { + visible: true + width: 1080 + height: 1920 + property string protocol: 'http://' + property string ipAddress: '127.0.0.1' + property string portNumber: Qt.application.arguments[1] + property string tokenString: Qt.application.arguments[2] + property string btAPI: '/api/Bluetooth-manager/' + + property string btAPIpath: protocol + ipAddress + ':' + portNumber + btAPI + property var jsonObjectBT + property string currentState: 'idle' + + function showRequestInfo(text) { + log.text = log.text + "\n" + text + console.log(text) + } + + Text { + id: log + anchors.fill: parent + anchors.margins: 10 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + //text: "log" + } + + GridLayout { + ExclusiveGroup { + id: btPowerGroup + } + visible: true + + id: seekDeviceType + //x: 400 + //y: 105 + anchors.top: parent.top + anchors.topMargin: 30 + + //anchors.bottomMargin: -30 //-20 + anchors.horizontalCenter: parent.horizontalCenter + //visible: !tuningMethodManualSwitchButton.checked + + //anchors.top: functionalityCheckBoxGrid.bottom + columns: 13 + rows: 1 + + columnSpacing: 60 + + Text { + text: qsTr("Bluetooth power") + } + + RadioButton { + id: btPowerOFF + exclusiveGroup: btPowerGroup + checked: true + onClicked: { + console.log("OFF") + //console.log(networkPath) + btDeviceList.clear() + periodicRefresh.stop() + request(btAPIpath + 'stop_discovery', function (o) { + // log the json response + //showRequestInfo(o.responseText) + console.log(o.responseText) + }) + request(btAPIpath + 'power?value=0', function (o) { + // log the json response + //showRequestInfo(o.responseText) + console.log(o.responseText) + }) + currentState = 'idle' + } + Text { + text: qsTr("OFF") + anchors.left: parent.left + anchors.leftMargin: 30 + } + + } + + RadioButton { + id: btPowerON + exclusiveGroup: btPowerGroup + onClicked: { + + console.log("ON") + request(btAPIpath + 'power?value=1', function (o) { + console.log(o.responseText) + }) + request(btAPIpath + 'start_discovery', function (o) { + console.log(o.responseText) + }) + currentState = 'discovering' + //search_device() + periodicRefresh.start() + /*buttonScanText.text = "CANCEL"*/ + + } + Text { + text: qsTr("ON") + anchors.left: parent.left + anchors.leftMargin: 30 + //color: checkBoxTextStyleBands.fontColor + //font.pixelSize: checkBoxTextStyleBands.fontSize + } + } + } + ListModel { + id: btDeviceList + } + + Rectangle { + //id: buttonScan + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.margins: 80 + width: buttonScan.width + 10 + height: buttonScan.height + 10 + //border.width: mouseArea.pressed ? 2 : 1 + //radius: 5 + //antialiasing: true + //color: "black" + color: "#222" + border.color: "white" + + Button { + id: buttonScan + anchors.centerIn: parent + width: 100 + text: "SEARCH" + + MouseArea { + //id: mouseArea + anchors.fill: parent + + onClicked: { + if (buttonScan.text == "SEARCH"){ + request(btAPIpath + 'start_discovery', function (o) { + + // log the json response + //showRequestInfo(o.responseText) + console.log(o.responseText) + }) + buttonScan.text = "CANCEL" + currentState = 'discovering' + periodicRefresh.start() + }else{ + request(btAPIpath + 'stop_discovery', function (o) { + + // log the json response + //showRequestInfo(o.responseText) + console.log(o.responseText) + }) + buttonScan.text = "SEARCH" + currentState = 'idle' + //periodicRefresh.stop() //in order to update the content from bluez + } + } + } + } + } + + function request(url, callback) { + var xhr = new XMLHttpRequest() + xhr.onreadystatechange = (function (myxhr) { + + return function () { + if (xhr.readyState == 4 && xhr.status == 200){ + callback(myxhr) + } + } + })(xhr) + xhr.open('GET', url, false) + xhr.send('') + } + + Component { + id:blueToothDevice + + Rectangle { + height: 150 + width: parent.width + color: "#222" + + Column { + Text { + id: btName + text: deviceName + font.pointSize: 36 + color: "#ffffff" + } + + Text { + id: btAddr + text: deviceAddress + visible: false + } + Text { + text: { + if ((devicePairable === "True") + && (deviceConnect === "False")) + text = "paired" + else if ((devicePairable === "True") + && (deviceConnect === "True") + && (connectAVP) === "True") + text = "AV Connection" + else if ((devicePairable === "True") + && (deviceConnect === "True") + && (connectHFP) === "True") + text = "Handsfree Connection" + else + text = "" + } + font.pointSize: 18 + color: "#ffffff" + font.italic: true + } + Text { + id: btPairable + text: devicePairable + visible: false + } + Text { + id: btConnectstatus + text: deviceConnect + visible: false + } + + } + + Button { + id: connectButton + anchors.top:parent.top + anchors.topMargin: 15 + anchors.right: removeDevice.left + anchors.rightMargin: 10 + + text:(btConnectstatus.text == "True")? "Disconnect":((btPairable.text == "True")? "Connect":"Pair") + MouseArea { + anchors.fill: parent + onClicked: { + if (currentState == 'discovering'){ + request(btAPIpath + 'stop_discovery', function (o) { + currentState = "idle" + console.log(o.responseText) + }) + } + if (connectButton.text == "Pair"){ + connectButton.text = "Connect" + request(btAPIpath + 'pair?value=' + btAddr.text, function (o) { + btPairable.text = "True" + console.log(o.responseText) + }) + request(btAPIpath + 'set_property?Address=' + btAddr.text + '\&Property=Trusted\&value=true', function (o) { + console.log(o.responseText) + }) + } + else if (connectButton.text == "Connect"){ + connectButton.text = "Disconnect" + request(btAPIpath + 'connect?value=' + btAddr.text, function (o) { + console.log(o.responseText) + }) + } + else if (connectButton.text == "Disconnect"){ + request(btAPIpath + 'disconnect?value=' + btAddr.text, function (o) { + console.log(o.responseText) + }) + connectButton.text = "Connect" + btDeviceList.remove(findDevice(btAddr.text)) + } + } + } + } + Image{ + id: removeDevice + anchors.top:parent.top + anchors.topMargin: 15 + anchors.right: parent.right + anchors.rightMargin: 5 + width: 25 + height: 25 + source: "component/images/trash.png" + + + MouseArea { + anchors.fill: parent + onClicked: { + request(btAPIpath + 'remove_device?value=' + btAddr.text, function (o) { + console.log(o.responseText) + }) + btDeviceList.remove(findDevice(btAddr.text)) + } + } + } + } + } + + + ListView { + width: parent.width + anchors.top: parent.top + anchors.topMargin: 200 + anchors.bottom: parent.bottom + anchors.bottomMargin: 150 + model: btDeviceList + delegate: blueToothDevice + clip: true + } + + function findDevice(address){ + for (var i = 0; i < jsonObjectBT.length; i++) { + if (address === jsonObjectBT[i].Address){ + return i + } + } + } + function search_device(){ + btDeviceList.clear() + request(btAPIpath + 'discovery_result', function (o) { + + // log the json response + console.log(o.responseText) + + // translate response into object + var jsonObject = eval('(' + o.responseText + ')') + + jsonObjectBT = eval('(' + JSON.stringify( + jsonObject.response) + ')') + + console.log("BT list refreshed") + + //console.log(jsonObject.response) + for (var i = 0; i < jsonObjectBT.length; i++) { + btDeviceList.append({ + deviceAddress: jsonObjectBT[i].Address, + deviceName: jsonObjectBT[i].Name, + devicePairable:jsonObjectBT[i].Paired, + deviceConnect: jsonObjectBT[i].Connected, + connectAVP: jsonObjectBT[i].AVPConnected, + connectHFP: jsonObjectBT[i].HFPConnected + }) + } + }) + } + + + //Timer for periodic refresh; this is BAD solution, need to figure out how to subscribe for events + Timer { + id: periodicRefresh + interval: (currentState == "idle")? 10000:5000 // 5seconds + onTriggered: { + + btDeviceList.clear() + + request(btAPIpath + 'discovery_result', function (o) { + + // log the json response + console.log(o.responseText) + + // translate response into object + var jsonObject = eval('(' + o.responseText + ')') + + jsonObjectBT = eval('(' + JSON.stringify( + jsonObject.response) + ')') + + console.log("BT list refreshed") + + //console.log(jsonObject.response) + for (var i = 0; i < jsonObjectBT.length; i++) { + btDeviceList.append({ + deviceAddress: jsonObjectBT[i].Address, + deviceName: jsonObjectBT[i].Name, + devicePairable:jsonObjectBT[i].Paired, + deviceConnect: jsonObjectBT[i].Connected, + connectAVP: jsonObjectBT[i].AVPConnected, + connectHFP: jsonObjectBT[i].HFPConnected + }) + } + }) + + start() + } + } +} diff --git a/qml/bluetooth-settings/component/images/trash.png b/qml/bluetooth-settings/component/images/trash.png new file mode 100755 index 0000000..6774448 Binary files /dev/null and b/qml/bluetooth-settings/component/images/trash.png differ -- cgit 1.2.3-korg