```
$ mkdir WORK
$ cd WORK
-$ repo init -b dab -m dab_4.0.0_xml -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo
+$ repo init -b master -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo
$ repo sync
-$ git clone git clone https://gerrit.automotivelinux.org/gerrit/staging/meta-hmi-framework
```
**Bitbake**
```
-$ source meta-agl/scripts/aglsetup.sh -m m3ulcb agl-demo agl-devel agl-appfw-smack agl-hmi-framework
+$ source meta-agl/scripts/aglsetup.sh -m m3ulcb agl-demo agl-devel
$ bitbake homescreen
```
-Instructions for building HomeScreen app
+Instructions for building Home Screen app
----------------------------------------
-The HomeScreen app is part of the
-packagegroup-agl-demo-platform
+The Home Screen app is part of the packagegroup-agl-demo-platform
packagegroup.
-This also includes the following apps:
-- WindowManager
-- HomeScreen Binder
-
-And the library
-- libhomescreen
-- libwindowmanager
-
-
To build all the above, follow the instrucions on the AGL
documentation website:
http://docs.automotivelinux.org/docs/getting_started/en/dev/reference/source-code.html#features-supported-by-aglsetup
http://docs.automotivelinux.org/docs/getting_started/en/dev/reference/source-code.html#features-supported-by-aglsetup
-Launch HomeScreen App:
+Launch Home Screen App:
Usage:
```
-afm-util start homescreen
+systemctl start homescreen
```
+++ /dev/null
-#!/usr/bin/make -f
-# Copyright (C) 2015 - 2018 "IoT.bzh"
-# Copyright (C) 2020 Konsulko Group
-# Author "Romain Forlot" <romain.forlot@iot.bzh>
-#
-# 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.
-
-THISFILE := $(lastword $(MAKEFILE_LIST))
-ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
-
-# Build directories
-# Note that the debug directory is defined in relation to the release
-# directory (BUILD_DIR), this needs to be kept in mind if over-riding
-# it and building that widget types, the specific widget type variable
-# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
-# desired output hierarchy.
-BUILD_DIR = $(ROOT_DIR)/build
-BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
-
-# Output directory variable for use in pattern rules.
-# This is intended for internal use only, hence the explicit override
-# definition.
-override OUTPUT_DIR = $(BUILD_DIR)
-
-# Final install directory for widgets
-DEST = $(OUTPUT_DIR)
-
-# Default build type for release builds
-BUILD_TYPE = release
-
-.PHONY: all help update install distclean
-.PHONY: clean clean-release clean-debug clean-all
-.PHONY: configure configure-release configure-debug
-.PHONY: build build-release build-debug build-all
-.PHONY: package package-release package-debug package-all
-
-help:
- @echo "List of targets available:"
- @echo ""
- @echo "- all"
- @echo "- help"
- @echo "- clean"
- @echo "- distclean"
- @echo "- configure"
- @echo "- build: compilation, link and prepare files for package into a widget"
- @echo "- package: output a widget file '*.wgt'"
- @echo "- install: install in $(DEST) directory"
- @echo ""
- @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
- @echo "Don't use your build dir as DEST as wgt file is generated at this location"
-
-all: package-all
-
-# Target specific variable over-rides so static pattern rules can be
-# used for the various type-specific targets.
-
-configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
-configure-debug build-debug package-debug: BUILD_TYPE = debug
-
-clean-release clean-debug:
- @if [ -d $(OUTPUT_DIR) ]; then \
- $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
- else \
- echo Nothing to clean; \
- fi
-
-clean: clean-release
-
-clean-all: clean-release clean-debug
-
-distclean: clean-all
-
-configure-release configure-debug:
- @mkdir -p $(OUTPUT_DIR)
- @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
- (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
- fi
-
-configure: configure-release
-
-build-release build-debug: build-%: configure-%
- @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
-
-build: build-release
-
-build-all: build-release build-debug
-
-package-release package-debug: package-%: build-%
- @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
- @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
- mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
- fi
-
-
-package: package-release
-
-package-all: package-release package-debug
-
-install: build
- @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
+++ /dev/null
-#!/usr/bin/make -f
-# Copyright (C) 2015 - 2018 "IoT.bzh"
-# Copyright (C) 2020 Konsulko Group
-# Author "Romain Forlot" <romain.forlot@iot.bzh>
-#
-# 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.
-
-THISFILE := $(lastword $(MAKEFILE_LIST))
-ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
-
-# Build directories
-# Note that the debug directory is defined in relation to the release
-# directory (BUILD_DIR), this needs to be kept in mind if over-riding
-# it and building that widget types, the specific widget type variable
-# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
-# desired output hierarchy.
-BUILD_DIR = $(ROOT_DIR)/build
-BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
-
-# Output directory variable for use in pattern rules.
-# This is intended for internal use only, hence the explicit override
-# definition.
-override OUTPUT_DIR = $(BUILD_DIR)
-
-# Final install directory for widgets
-DEST = $(OUTPUT_DIR)
-
-# Default build type for release builds
-BUILD_TYPE = release
-
-.PHONY: all help update install distclean
-.PHONY: clean clean-release clean-debug clean-all
-.PHONY: configure configure-release configure-debug
-.PHONY: build build-release build-debug build-all
-.PHONY: package package-release package-debug package-all
-
-help:
- @echo "List of targets available:"
- @echo ""
- @echo "- all"
- @echo "- help"
- @echo "- clean"
- @echo "- distclean"
- @echo "- configure"
- @echo "- build: compilation, link and prepare files for package into a widget"
- @echo "- package: output a widget file '*.wgt'"
- @echo "- install: install in $(DEST) directory"
- @echo ""
- @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
- @echo "Don't use your build dir as DEST as wgt file is generated at this location"
-
-all: package-all
-
-# Target specific variable over-rides so static pattern rules can be
-# used for the various type-specific targets.
-
-configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
-configure-debug build-debug package-debug: BUILD_TYPE = debug
-
-clean-release clean-debug:
- @if [ -d $(OUTPUT_DIR) ]; then \
- $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
- else \
- echo Nothing to clean; \
- fi
-
-clean: clean-release
-
-clean-all: clean-release clean-debug
-
-distclean: clean-all
-
-configure-release configure-debug:
- @mkdir -p $(OUTPUT_DIR)
- @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
- (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
- fi
-
-configure: configure-release
-
-build-release build-debug: build-%: configure-%
- @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
-
-build: build-release
-
-build-all: build-release build-debug
-
-package-release package-debug: package-%: build-%
- @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
- @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
- mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
- fi
-
-
-package: package-release
-
-package-all: package-release package-debug
-
-install: build
- @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
load(configure)
SUBDIRS = \
- homescreen \
- package
-
-package.depends += homescreen
+ homescreen
+++ /dev/null
-type: books
-books:
--
- id: homescreen
- title: HomeScreen (old)
- description: Homescreen documentation
- keywords:
- author: "TOYOTA MOTOR CORPORATION"
- version: master
- chapters:
- - url: homescreen_api.md
- name: HomeScreen API
\ No newline at end of file
+++ /dev/null
-type: books
-books:
--
- id: homescreen
- title: HomeScreen
- description: HomeScreen documentation
- keywords:
- author:
- version: master
- chapters:
- - url: index.md
- name: Overview
+++ /dev/null
-# HomeScreen API\r
-The HomeScreen app provides an own interface for some special use cases concerning the surfaces and user inputs.\r
-\r
-The interface is implemented as D-Bus interface.\r
-This is the introspection, describing the interface:\r
-\r
-```\r
-<node>\r
- <interface name="org.agl.homescreen">\r
- <method name="hardKeyPressed">\r
- <arg name="key" type="i" direction="in"/>\r
- </method>\r
- <method name="getSurfaceStatus">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="status" type="i" direction="out"/>\r
- </method>\r
- <method name="requestSurfaceIdToFullScreen">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- </method>\r
- <method name="getAllSurfacesOfProcess">\r
- <arg name="pid" type="i" direction="in"/>\r
- <arg name="surfaceIds" type="ai" direction="out"/>\r
- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<int>"/>\r
- </method>\r
- <method name="getLayoutRenderAreaForSurfaceId">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="renderArea" type="(iiii)" direction="out"/>\r
- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QRect"/>\r
- </method>\r
- <method name="renderSurfaceToAreaAllowed">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="layoutArea" type="i" direction="in"/>\r
- <arg name="allowed" type="b" direction="out"/>\r
- </method>\r
- <method name="renderSurfaceToArea">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="layoutArea" type="i" direction="in"/>\r
- </method>\r
- </interface>\r
-</node>\r
-```\r
-\r
-These interface will change during further development, so check back frequently.\r
-\r
-## User Input Events API calls\r
-\r
-### hardKeyPressed\r
-\r
-Use hardKeyPressed to inject hard key press events into the HomeScreen app.\r
-This Interface call can be used by applications like the InputEventManager to inject hard keys into the HomeScreen application.\r
-\r
-#### Example\r
-\r
-if someone presses the Hard Key “NAV” on the target, this key may be injected using this interface to make the HomeScreen launch the navigation application.\r
-Right now, only a few keys are defined (in inputevent.hpp):\r
-\r
-```\r
-namespace InputEvent {\r
- typedef enum HardKey\r
- {\r
- HARDKEY_UNDEFINED,\r
- HARDKEY_NAV,\r
- HARDKEY_MEDIA\r
- } eHardKey;\r
-}\r
-```\r
-\r
-This will change in the future.\r
- \r
-\r
- \r
-A “normal” application would not need to call this API.\r
-\r
-## Surface control API calls\r
-\r
-The normal use case when starting an application is:\r
-The user presses a hard key or uses the app launcher to start an app. The app is then started and is shown full screen.\r
-The org.agl.homescreen API provides some methods to get information about some status and some methods to show surfaces on the screen.\r
-\r
-### getSurfaceStatus\r
-\r
-A surface can be visible or invisible (please do not confuse “visible” and “visibility”). This function allows to request the current status.\r
-\r
-```\r
-<method name="getSurfaceStatus">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="status" type="i" direction="out"/>\r
-</method>\r
-```\r
-\r
-Right now an application has to pull this information.\r
-This is not optimal and will change in the future. There are two options:\r
-\r
- - The homescreen API will provide a signal that is emitted every time the visible status of surfaces changes. This would be way more efficient, because it would save time and avoid a re-occurring API call. __UPDATE:__ There is a D-Bus signal implemented in this API\r
- - For Qt, there is already a patch available that provides this information as a base class property. See https://codereview.qt-project.org/#/c/176211/ This would be optimal for Qt widget applications. But not useful for other languages, e.g. Java. __UPDATE:__ This patch got reverted in AGL!\r
-\r
-#### Current implementation\r
- \r
-\r
- \r
-#### Option 1\r
-\r
-\r
-\r
-#### Option 2\r
-\r
-\r
-\r
-### requestSurfaceIdToFullScreen\r
-\r
-This function will set the given surface to full screen.\r
-\r
-```\r
-<method name="requestSurfaceIdToFullScreen">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
-</method>\r
-```\r
-\r
-It will hide all other surfaces.\r
-\r
-\r
- \r
-### getAllSurfacesOfProcess\r
-\r
-This returns all surfaces that are created by the given process ID.\r
-\r
-```\r
-<method name="getAllSurfacesOfProcess">\r
- <arg name="pid" type="i" direction="in"/>\r
- <arg name="surfaceIds" type="ai" direction="out"/>\r
- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList<int>"/>\r
-</method>\r
-```\r
-\r
-A process can create more than one surface. By default, the surface with the lowest surface ID is shown on the screen. If an application wants to know all surfaces that were created by an application, this method will provide them.\r
-\r
-\r
-\r
-### renderSurfaceToAreaAllowed\r
-\r
-Before calling renderSurfaceToArea, an application can request, if it is allowed to render the surface to this area. This makes sense for an application that would begin to allocate resources to render. But if it is not allowed to render the surface, the application could avoid allocating the resources.\r
-\r
-```\r
-<method name="renderSurfaceToAreaAllowed">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="layoutArea" type="i" direction="in"/>\r
- <arg name="allowed" type="b" direction="out"/>\r
-</method>\r
-```\r
-\r
-The call will not affect the current setup, it will only request if it is allowed or not.\r
-\r
-\r
-\r
-### renderSurfaceToArea\r
-\r
-By default, the HomeScreen application decides, where to render an applications surface. The concept of Layouts defines this. This API call can override the default behavior. An app can request to render a surface in a specific Layout Area.\r
-\r
-```\r
-<method name="renderSurfaceToArea">\r
- <arg name="surfaceId" type="i" direction="in"/>\r
- <arg name="layoutArea" type="i" direction="in"/>\r
-</method>\r
-```\r
-\r
-The surface that was previously rendered in this Layout are will be hidden.\r
-\r
-\r
-\r
-The homescreen interface functionality is not fully implemented, but the API is available. For example using the libhomescreen.so.\r
-\r
-### surfaceVisibilityChanged\r
-\r
-Whenever the visibility property of a surface changes, this signal is emitted.\r
-\r
-```\r
-<signal name="surfaceVisibilityChanged">\r
- <arg name="surfaceId" type="i"/>\r
- <arg name="visible" type="b"/>\r
-</signal>\r
-```\r
-\r
-Visibility here means visible. The name of the signal is from the Weston surface property “visibility”.\r
-See here for reference: https://github.com/ntanibata/wayland-ivi-extension/blob/master/ivi-layermanagement-api/ilmCommon/include/ilm_types.h\r
- \r
-\r
+++ /dev/null
-# Welcome to your AGL system!
-When booting up an AGL system, the first thing that your eyes will spot is this:
-
-
-
-**The AGL HomeScreen!**
-
-Intended to be used with touch presses, the reference HMI provides access to all pre-installed AGL demo applications as well as in the future access to user installed apps. The list of demo apps contains some automotive applications like HVAC-control, Navigation or Dashboard, as well as some infotainment apps. Radio, Multimedia, Phone...
-This applications are already available and were presented at CES 2017.
-
-## Here are some screenshots of the pre-installed demo applications:
-
-## HVAC
-
-
-
-## Phone
-
-
-
-## Dashboard
-
-
-
-## Settings
-
-
-
-#### Note:
-* All current demos (including HomeScreen) are optimized for landscape full HD resolution (1080x1920).
-
# limitations under the License.
TEMPLATE = app
-TARGET = HomeScreen
-QT = qml quick websockets gui-private
+TARGET = homescreen
+QT = qml quick gui-private
CONFIG += c++11 link_pkgconfig wayland-scanner
-DESTDIR = $${OUT_PWD}/../package/root/bin
-PKGCONFIG += qtappfw-weather qtappfw-network qtappfw-bt afb-helpers-qt wayland-client json-c
-
-LIBS += -lhomescreen
-
-CONFIG(release, debug|release) {
- QMAKE_POST_LINK = $(STRIP) --strip-unneeded $(TARGET)
-}
+PKGCONFIG += wayland-client
SOURCES += \
src/main.cpp \
+ src/shell.cpp \
src/statusbarmodel.cpp \
src/statusbarserver.cpp \
src/applicationlauncher.cpp \
src/mastervolume.cpp \
- src/homescreenhandler.cpp \
- src/shell.cpp \
- src/aglsocketwrapper.cpp \
- src/chromecontroller.cpp
+ src/homescreenhandler.cpp
HEADERS += \
+ src/shell.h \
+ src/constants.h \
src/statusbarmodel.h \
src/statusbarserver.h \
src/applicationlauncher.h \
src/mastervolume.h \
- src/homescreenhandler.h \
- src/shell.h \
- src/aglsocketwrapper.h \
- src/chromecontroller.h \
- src/constants.h
+ src/homescreenhandler.h
+
OTHER_FILES += \
README.md
qml/images/Shortcut/shortcut.qrc \
qml/images/Status/status.qrc \
qml/images/images.qrc \
- qml/qml.qrc \
- qml/images/SpeechChrome/speechchrome.qrc
-
+ qml/qml.qrc
AGL_SHELL_PATH = $$system(pkg-config --variable=pkgdatadir agl-compositor-0.0.19-protocols)
WAYLANDCLIENTSOURCES += $$AGL_SHELL_PATH/agl-shell.xml
+
+target.path = $${PREFIX}/usr/bin
+target.files += $${OUT_PWD}/$${TARGET}
+target.CONFIG = no_check_exist executable
+
+INSTALLS += target
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0
import AGL.Demo.Controls 1.0
+/*
import MasterVolume 1.0
+*/
Image {
anchors.fill: parent
PropertyChanges { target: master_volume; opacity: 1.0 }
PropertyChanges { target: slider; enabled: true }
PropertyChanges { target: logo_image; opacity: 0.0 }
- PropertyChanges { target: speech_chrome; visible: false }
},
State { when: !displayVolume;
PropertyChanges { target: master_volume; opacity: 0.0 }
PropertyChanges { target: slider; enabled: false }
PropertyChanges { target: logo_image; opacity: 1.0 }
- PropertyChanges { target: speech_chrome; visible: speech_chrome.agentPresent }
}
]
transitions: Transition {
NumberAnimation { property: "opacity"; duration: 500}
}
-
+/*
MasterVolume {
id: mv
objectName: "mv"
mv.open(bindingAddress);
}
}
-
+*/
Item {
id: master_volume
anchors.fill: parent
to: 100
stepSize: 1
snapMode: Slider.SnapOnRelease
+/*
onValueChanged: mv.volume = value
Component.onCompleted: value = mv.volume
+*/
onPressedChanged: {
if (pressed) {volume_timer.stop()}
else {volume_timer.restart()}
}
}
}
-
- SpeechChrome {
- id: speech_chrome
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- height: parent.height
- }
}
interval: 100; running: true; repeat: true;
onTriggered: root.now = new Date
}
-
+/*
Connections {
target: weather
temperature_item.text = temperature.split(".")[0] + '°F'
}
}
-
+*/
RowLayout {
anchors.fill: parent
spacing: 0
fillMode: Image.PreserveAspectFit
property string deviceName: "none"
property bool connStatus: false
+/*
Connections {
target: bluetooth
bt_icon.connStatus = state
}
}
+*/
}
+/*
Repeater {
model: StatusBarModel { objectName: "statusBar" }
delegate: Image {
fillMode: Image.PreserveAspectFit
}
}
+*/
}
}
}
Layout.preferredWidth: 291
}
}
-
+/*
Timer {
id: launching
interval: 500
indeterminate: visible
visible: launcher.launching && !launching.running
}
+*/
}
<file>MediaAreaRadio.qml</file>
<file>ShortcutArea.qml</file>
<file>ShortcutIcon.qml</file>
- <file>SpeechChrome.qml</file>
<file>StatusArea.qml</file>
<file>TopArea.qml</file>
<file>IconItem.qml</file>
+++ /dev/null
-#include "aglsocketwrapper.h"
-#include "constants.h"
-
-#include <QWebSocket>
-#include <QUuid>
-#include <QJsonArray>
-#include <QJsonObject>
-#include <QJsonDocument>
-
-#include <QDebug>
-
-namespace {
-enum MessageTypes {
- Call = 2,
- Success = 3,
- Error = 4,
- Event = 5
-};
-}
-
-AglSocketWrapper::AglSocketWrapper(QObject *parent) :
- QObject(parent)
- , m_socket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
-{
- connect(m_socket, &QWebSocket::connected, this, &AglSocketWrapper::connected);
- connect(m_socket, &QWebSocket::disconnected, this, &AglSocketWrapper::disconnected);
- connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
- [](QAbstractSocket::SocketError error) -> void {
- qWarning() << "AglSocketWrapper internal socket error" << error;
- });
- connect(m_socket, &QWebSocket::textMessageReceived,
- this, [this](const QString &msg) -> void {
- const QJsonDocument doc = QJsonDocument::fromJson(msg.toUtf8());
- if (doc.isArray()) {
- const QJsonArray msgArray = doc.array();
- if (msgArray.count() >= 3) {
- const int msgType = msgArray.at(0).toInt();
- switch (msgType) {
- case Success:
- case Error: {
- auto callbackIt = m_callbacks.find( msgArray.at(1).toString());
- if (callbackIt != m_callbacks.constEnd()) {
- (*callbackIt)(msgType == Success, msgArray.at(2));
- m_callbacks.erase(callbackIt);
- }
- }
- break;
- case Event: {
- const QJsonObject eventObj = msgArray.at(2).toObject();
- emit eventReceived(msgArray.at(1).toString(), eventObj.value(vshl::DATA_TAG));
- }
- break;
- default:
- break;
- }
- return;
- }
- }
- qWarning() << "Unsupported message format:" << msg;
- });
-}
-
-void AglSocketWrapper::open(const QUrl &url)
-{
- m_socket->open(url);
-}
-
-void AglSocketWrapper::close()
-{
- m_socket->close();
-}
-
-void AglSocketWrapper::apiCall(const QString &api, const QString &verb, const QJsonValue &args,
- AglSocketWrapper::ApiCallback callback)
-{
- const QString id = QUuid::createUuid().toString();
- if (callback)
- m_callbacks.insert(id, callback);
-
- QJsonArray callData;
- callData.append(Call);
- callData.append(id);
- callData.append(api + QLatin1String("/") + verb);
- callData.append(args);
-
- const QString msg = QLatin1String(QJsonDocument(callData).toJson(QJsonDocument::Compact));
- m_socket->sendTextMessage(msg);
-
- qDebug() << Q_FUNC_INFO << "Data sent:" << msg;
-}
+++ /dev/null
-#ifndef AGLSOCKETWRAPPER_H
-#define AGLSOCKETWRAPPER_H
-
-#include <QUrl>
-#include <QMap>
-#include <QObject>
-#include <QJsonValue>
-
-#include <functional>
-
-class QWebSocket;
-class AglSocketWrapper : public QObject
-{
- Q_OBJECT
-public:
- explicit AglSocketWrapper(QObject *parent = nullptr);
-
- void open(const QUrl &url);
- void close();
-
- using ApiCallback = std::function<void(bool, const QJsonValue&)>;
- void apiCall(const QString &api, const QString &verb, const QJsonValue &args = QJsonValue(),
- ApiCallback callback = nullptr);
-
-signals:
- void connected();
- void disconnected();
- void eventReceived(const QString &eventName, const QJsonValue &data);
-
-private:
- QWebSocket *m_socket;
- QMap<QString, ApiCallback> m_callbacks;
-};
-
-#endif // AGLSOCKETWRAPPER_H
+++ /dev/null
-#include "chromecontroller.h"
-#include "aglsocketwrapper.h"
-#include "constants.h"
-
-#include <QTimer>
-#include <QDebug>
-#include <QJsonDocument>
-
-ChromeController::ChromeController(const QUrl &bindingUrl, QObject *parent) :
- QObject(parent)
- , m_aglSocket(new AglSocketWrapper(this))
-{
- //Alexa voice agent subscription----------------------------------------------------------------
- {
- connect(m_aglSocket, &AglSocketWrapper::connected,
- this, [this]() -> void {
- m_aglSocket->apiCall(vshl::API, vshl::VOICE_AGENT_ENUMERATION_VERB, QJsonValue(),
- [this](bool result, const QJsonValue &data) -> void {
- qDebug() << (vshl::API + QLatin1String(":") + vshl::VOICE_AGENT_ENUMERATION_VERB)
- << "result: " << result << " val: " << data;
- if (!result) {
- qWarning() << "Failed to enumerate voice agents";
- return;
- }
-
- QJsonObject dataObj = data.toObject();
- auto objIt = dataObj.find(vshl::RESPONSE_TAG);
- if (objIt == dataObj.constEnd()) {
- qWarning() << "Voice agent enumeration response tag missing."
- << dataObj;
- return;
- }
-
- // Get default voice agent
- dataObj = objIt.value().toObject();
- QJsonObject responseObj = dataObj;
- objIt = dataObj.find(vshl::DEFAULT_TAG);
- if (objIt == dataObj.constEnd()) {
- qWarning() << "Voice agent enumeration default agent tag missing."
- << dataObj;
- return;
- }
- QString agentId = objIt.value().toString();
- if (agentId.isEmpty()) {
- qWarning() << "Default voice agent not found";
- return;
- }
- qDebug() << (vshl::API + QLatin1String(":") + vshl::VOICE_AGENT_ENUMERATION_VERB) << "default: " << agentId;
-
- objIt = dataObj.find(vshl::AGENTS_TAG);
- if (objIt == dataObj.constEnd()) {
- qWarning() << "Voice agent enumeration agents tag missing."
- << dataObj;
- return;
- }
-
- // Sanity check that the default agent is actually listed
- bool agentFound = false;
- const QJsonArray agents = objIt.value().toArray();
- for (const QJsonValue &agent : agents) {
- const QJsonObject agentObj = agent.toObject();
- auto agentIt = agentObj.find(vshl::ID_TAG);
- if (agentIt == agentObj.constEnd())
- continue;
- if (agentId.compare(agentIt.value().toString()) == 0) {
- agentFound = true;
- auto nameIt = agentObj.find(vshl::NAME_TAG);
- if (nameIt != agentObj.constEnd()) {
- m_voiceAgentName = nameIt.value().toString();
- emit agentNameChanged();
- }
- break;
- }
- }
- if (!agentFound) {
- qWarning() << "Default voice agent configuration not found";
- return;
- }
- m_agentPresent = true;
- emit agentPresentChanged();
-
- //Voice agent subscription------------------------------------------------------
- {
- m_voiceAgentId = agentId;
- const QJsonObject args {
- { vshl::VOICE_AGENT_ID_ARG, agentId },
- { vshl::VOICE_AGENT_EVENTS_ARG, vshl::VOICE_AGENT_EVENTS_ARRAY }
- };
- m_aglSocket->apiCall(vshl::API, vshl::SUBSCRIBE_VERB, args,
- [](bool result, const QJsonValue &data) -> void {
- qDebug() << (vshl::API + QLatin1String(":") + vshl::SUBSCRIBE_VERB)
- << "result: " << result << " val: " << data;
- });
- }
- //------------------------------------------------------------------------------
- });
- });
- }
- //----------------------------------------------------------------------------------------------<
-
- //Socket connection management------------------------------------------------------------------
- {
- auto connectToBinding = [bindingUrl, this]() -> void {
- m_aglSocket->open(bindingUrl);
- qDebug() << "Connecting to:" << bindingUrl;
- };
- connect(m_aglSocket, &AglSocketWrapper::disconnected, this, [connectToBinding]() -> void {
- QTimer::singleShot(2500, connectToBinding);
- });
- connectToBinding();
- }
- //----------------------------------------------------------------------------------------------
-
- //Speech chrome state change event handling-----------------------------------------------------
- {
- connect(m_aglSocket, &AglSocketWrapper::eventReceived,
- this, [this](const QString &eventName, const QJsonValue &data) -> void {
- if (eventName.compare(vshl::VOICE_DIALOG_STATE_EVENT + m_voiceAgentId) == 0) {
- const QJsonObject dataObj = data.toObject();
- auto objIt = dataObj.find(vshl::STATE_TAG);
- if (objIt == dataObj.constEnd()) {
- qWarning() << "Voice dialog state event state missing.";
- return;
- }
- const QString stateStr = objIt.value().toString();
- if (stateStr.compare(vshl::VOICE_DIALOG_IDLE) == 0) {
- setChromeState(Idle);
- } else if (stateStr.compare(vshl::VOICE_DIALOG_LISTENING) == 0) {
- setChromeState(Listening);
- } else if (stateStr.compare(vshl::VOICE_DIALOG_THINKING) == 0) {
- setChromeState(Thinking);
- } else if (stateStr.compare(vshl::VOICE_DIALOG_SPEAKING) == 0) {
- setChromeState(Speaking);
- } else if (stateStr.compare(vshl::VOICE_DIALOG_MICROPHONEOFF) == 0) {
- setChromeState(MicrophoneOff);
- }
- }
- });
- }
- //----------------------------------------------------------------------------------------------
-}
-
-void ChromeController::pushToTalk()
-{
- m_aglSocket->apiCall(vshl::API, vshl::TAP_TO_TALK_VERB, QJsonValue(),
- [](bool result, const QJsonValue &data) -> void {
- qDebug() << (vshl::API + QLatin1String(":") + vshl::TAP_TO_TALK_VERB)
- << "result: " << result << " val: " << data;
- });
-}
-
-void ChromeController::setChromeState(ChromeController::ChromeState state)
-{
- const char* ChromeStateNames[MicrophoneOff + 1] = { "Idle", "Listening", "Thinking", "Speaking", "MicrophoneOff" };
-
- if (m_chromeState != state) {
- m_chromeState = state;
- emit chromeStateChanged();
- if(state <= MicrophoneOff)
- qDebug() << "new state = " << ChromeStateNames[state];
- else
- qDebug() << "new state = " << state;
- }
-}
+++ /dev/null
-#pragma once
-
-#include <QObject>
-#include <QUrl>
-
-class AglSocketWrapper;
-class ChromeController : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool agentPresent READ agentPresent NOTIFY agentPresentChanged)
- Q_PROPERTY(QString agentName READ agentName NOTIFY agentNameChanged)
- Q_PROPERTY(int chromeState READ chromeState NOTIFY chromeStateChanged)
-
-public:
- enum ChromeState {
- Idle = 0,
- Listening,
- Thinking,
- Speaking,
- MicrophoneOff
- };
- Q_ENUM(ChromeState)
-
- explicit ChromeController(const QUrl &bindingUrl, QObject *parent = nullptr);
- bool agentPresent() const { return m_agentPresent; }
- int chromeState() const { return m_chromeState; }
- QString agentName() const { return m_voiceAgentName; }
-
-public slots:
- void pushToTalk();
-
-signals:
- void agentPresentChanged();
- void agentNameChanged();
- void chromeStateChanged();
-
-private:
- void setChromeState(ChromeState state);
-
- AglSocketWrapper *m_aglSocket;
- QString m_voiceAgentId = "";
- QString m_voiceAgentName = "";
- bool m_agentPresent = false;
- ChromeState m_chromeState = Idle;
-};
HomescreenHandler::~HomescreenHandler()
{
+#if 0
if (mp_hs != NULL) {
delete mp_hs;
}
+#endif
}
-void HomescreenHandler::init(int port, const char *token)
+void HomescreenHandler::init(void)
{
+#if 0
mp_hs = new LibHomeScreen();
mp_hs->init(port, token);
-
+#endif
myThis = this;
-
+#if 0
mp_hs->registerCallback(nullptr, HomescreenHandler::onRep_static);
mp_hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, [this](json_object *object){
emit showInformation(QString(QLatin1String(info)));
});
+#endif
}
static struct wl_output *
void HomescreenHandler::tapShortcut(QString application_id)
{
HMI_DEBUG("HomeScreen","tapShortcut %s", application_id.toStdString().c_str());
-
+#if 0
struct json_object* j_json = json_object_new_object();
struct json_object* value;
if (mp_launcher) {
mp_launcher->setCurrent(application_id);
}
+#endif
}
+#if 0
void HomescreenHandler::onRep_static(struct json_object* reply_contents)
{
static_cast<HomescreenHandler*>(HomescreenHandler::myThis)->onRep(reply_contents);
HMI_DEBUG("HomeScreen","display_message = %s", display_message);
}
}
+#endif
#include <QObject>
-#include <libhomescreen.hpp>
#include "applicationlauncher.h"
#include "shell.h"
explicit HomescreenHandler(Shell *aglShell, ApplicationLauncher *launcher = 0, QObject *parent = 0);
~HomescreenHandler();
- void init(int port, const char* token);
+ void init(void);
Q_INVOKABLE void tapShortcut(QString application_id);
+#if 0
void onRep(struct json_object* reply_contents);
void onEv(const string& event, struct json_object* event_contents);
-
+#endif
static void* myThis;
+#if 0
static void onRep_static(struct json_object* reply_contents);
static void onEv_static(const string& event, struct json_object* event_contents);
+#endif
signals:
void showNotification(QString application_id, QString icon_path, QString text);
void showInformation(QString info);
private:
- LibHomeScreen *mp_hs;
ApplicationLauncher *mp_launcher;
Shell *aglShell;
};
#include <QQuickWindow>
#include <QTimer>
+#if 0
#include <weather.h>
#include <bluetooth.h>
+#endif
#include "applicationlauncher.h"
#include "statusbarmodel.h"
#include "mastervolume.h"
#include "homescreenhandler.h"
#include "hmi-debug.h"
-#include "chromecontroller.h"
#include <qpa/qplatformnativeinterface.h>
#include <wayland-client.h>
static void
load_agl_shell_app(QPlatformNativeInterface *native,
QQmlApplicationEngine *engine,
- struct agl_shell *agl_shell, QUrl &bindingAddress,
- const char *screen_name, bool is_demo)
+ struct agl_shell *agl_shell,
+ const char *screen_name,
+ bool is_demo)
{
struct wl_surface *bg, *top, *bottom;
struct wl_output *output;
"first screen " << qApp->screens().first()->name();
output = getWlOutput(native, screen);
-
/* engine.rootObjects() works only if we had a load() */
StatusBarModel *statusBar = qobj_top->findChild<StatusBarModel *>("statusBar");
if (statusBar) {
qDebug() << "got statusBar objectname, doing init()";
- statusBar->init(bindingAddress, engine->rootContext());
+ statusBar->init(engine->rootContext());
}
agl_shell_set_panel(agl_shell, top, output, AGL_SHELL_EDGE_TOP);
/* we need to have an app_id */
a.setDesktopFileName("homescreen");
- QCommandLineParser parser;
- parser.addPositionalArgument("port", a.translate("main", "port for binding"));
- parser.addPositionalArgument("secret", a.translate("main", "secret for binding"));
- parser.addHelpOption();
- parser.addVersionOption();
- parser.process(a);
- QStringList positionalArguments = parser.positionalArguments();
-
- int port = 1700;
- QString token = "wm";
- QString graphic_role = "homescreen"; // defined in layers.json in Window Manager
-
- if (positionalArguments.length() == 2) {
- port = positionalArguments.takeFirst().toInt();
- token = positionalArguments.takeFirst();
- }
-
- HMI_DEBUG("HomeScreen","port = %d, token = %s", port, token.toStdString().c_str());
-
agl_shell = register_agl_shell(native);
if (!agl_shell) {
fprintf(stderr, "agl_shell extension is not advertised. "
// import C++ class to QML
qmlRegisterType<StatusBarModel>("HomeScreen", 1, 0, "StatusBarModel");
qmlRegisterType<MasterVolume>("MasterVolume", 1, 0, "MasterVolume");
- qmlRegisterUncreatableType<ChromeController>("SpeechChrome", 1, 0, "SpeechChromeController",
- QLatin1String("SpeechChromeController is uncreatable."));
ApplicationLauncher *launcher = new ApplicationLauncher();
launcher->setCurrent(QStringLiteral("launcher"));
HomescreenHandler* homescreenHandler = new HomescreenHandler(aglShell, launcher);
- homescreenHandler->init(port, token.toStdString().c_str());
-
- QUrl bindingAddress;
- bindingAddress.setScheme(QStringLiteral("ws"));
- bindingAddress.setHost(QStringLiteral("localhost"));
- bindingAddress.setPort(port);
- bindingAddress.setPath(QStringLiteral("/api"));
-
- QUrlQuery query;
- query.addQueryItem(QStringLiteral("token"), token);
- bindingAddress.setQuery(query);
+ homescreenHandler->init();
QQmlApplicationEngine engine;
QQmlContext *context = engine.rootContext();
- context->setContextProperty("bindingAddress", bindingAddress);
context->setContextProperty("homescreenHandler", homescreenHandler);
context->setContextProperty("launcher", launcher);
+#if 0
context->setContextProperty("weather", new Weather(bindingAddress));
context->setContextProperty("bluetooth", new Bluetooth(bindingAddress, context));
- context->setContextProperty("speechChromeController", new ChromeController(bindingAddress, &engine));
+#endif
// we add it here even if we don't use it
context->setContextProperty("shell", aglShell);
/* instead of loading main.qml we load one-by-one each of the QMLs,
* divided now between several surfaces: panels, background.
*/
- load_agl_shell_app(native, &engine, agl_shell, bindingAddress, screen_name, is_demo_val);
+ load_agl_shell_app(native, &engine, agl_shell, screen_name, is_demo_val);
return a.exec();
}
*/
#include "mastervolume.h"
-#include <QJsonObject>
#include <QTimer>
#include <QtDebug>
: QObject(parent)
, m_volume{50}
{
+#if 0
connect(&m_client, SIGNAL(connected()), this, SLOT(onClientConnected()));
connect(&m_client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
connect(&m_client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onClientError(QAbstractSocket::SocketError)));
connect(&m_client, SIGNAL(eventReceived(QString, const QJsonValue&)), this, SLOT(onClientEventReceived(QString, const QJsonValue&)));
+#endif
}
+#if 0
void MasterVolume::open(const QUrl& url)
{
- m_url = url;
- TryOpen();
}
+#endif
qint32 MasterVolume::getVolume() const
{
if (m_volume != volume)
{
m_volume = volume;
+#if 0
QJsonObject arg;
arg.insert("control", MASTER_CONTROL);
double v = (double) volume / 100.0;
arg.insert("value", v);
m_client.call("audiomixer", "volume", arg);
+#endif
}
}
+#if 0
+
void MasterVolume::onClientConnected()
{
+
QJsonObject arg;
arg.insert("control", MASTER_CONTROL);
m_client.call("audiomixer", "volume", arg, [this](bool r, const QJsonValue& v) {
}
}
-void MasterVolume::TryOpen()
-{
- m_client.open(m_url);
-}
+#endif
#include <QtCore/QObject>
#include <QQmlEngine>
-#include "../qafbwebsocketclient.h"
class MasterVolume
: public QObject
Q_PROPERTY (uint32_t volume READ getVolume WRITE setVolume NOTIFY VolumeChanged)
private:
- QAfbWebsocketClient m_client;
- QUrl m_url;
qint32 m_volume;
public:
MasterVolume(QObject* parent = nullptr);
~MasterVolume() = default;
- Q_INVOKABLE void open(const QUrl& url);
+ //Q_INVOKABLE void open(const QUrl& url);
Q_INVOKABLE qint32 getVolume() const;
Q_INVOKABLE void setVolume(qint32 val);
private slots:
+#if 0
void onClientConnected();
void onClientDisconnected();
void onClientError(QAbstractSocket::SocketError se);
void onClientEventReceived(QString name, const QJsonValue& data);
void TryOpen();
+#endif
signals:
void VolumeChanged();
#include "statusbarmodel.h"
#include "statusbarserver.h"
+#if 0
#include "network.h"
+#endif
class StatusBarModel::Private
{
public:
StatusBarServer server;
QString iconList[StatusBarServer::SupportedCount];
+#if 0
Network *network;
WifiAdapter *wifi_a;
+#endif
};
StatusBarModel::Private::Private(StatusBarModel *parent)
delete d;
}
-void StatusBarModel::init(QUrl &url, QQmlContext *context)
+void StatusBarModel::init(QQmlContext *context)
{
+#if 0
d->network = new Network(url, context);
context->setContextProperty("network", d->network);
d->wifi_a = static_cast<WifiAdapter*>(d->network->findAdapter("wifi"));
this, &StatusBarModel::onWifiStrengthChanged);
setWifiStatus(d->wifi_a->wifiConnected(), d->wifi_a->wifiEnabled(), d->wifi_a->wifiStrength());
+#endif
}
void StatusBarModel::setWifiStatus(bool connected, bool enabled, int strength)
{
+#if 0
if (enabled && connected)
if (strength < 30)
d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_1Bar-01.png"));
d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_Full-01.png"));
else
d->server.setStatusIcon(0, QStringLiteral("qrc:/images/Status/HMI_Status_Wifi_NoBars-01.png"));
+#endif
}
void StatusBarModel::onWifiConnectedChanged(bool connected)
{
+#if 0
setWifiStatus(connected, d->wifi_a->wifiEnabled(), d->wifi_a->wifiStrength());
+#endif
}
void StatusBarModel::onWifiEnabledChanged(bool enabled)
{
+#if 0
setWifiStatus(d->wifi_a->wifiConnected(), enabled, d->wifi_a->wifiStrength());
+#endif
}
void StatusBarModel::onWifiStrengthChanged(int strength)
{
+#if 0
qInfo() << "Strength changed: " << strength;
setWifiStatus(d->wifi_a->wifiConnected(), d->wifi_a->wifiEnabled(), strength);
+#endif
}
int StatusBarModel::rowCount(const QModelIndex &parent) const
explicit StatusBarModel(QObject *parent = NULL);
~StatusBarModel();
- void init(QUrl &url, QQmlContext *context);
+ void init(QQmlContext *context);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<widget xmlns="http://www.w3.org/ns/widgets" id="homescreen" version="0.1">
- <name>homescreen</name>
- <icon src="icon.svg"/>
- <content src="bin/HomeScreen" type="application/vnd.agl.native"/>
- <description>This is a demo application for homescreen</description>
- <author>TOYOTA</author>
- <license>APL 2.0</license>
- <feature name="urn:AGL:widget:required-api">
- <param name="homescreen" value="ws" />
- <param name="network-manager" value="ws" />
- <param name="weather" value="ws" />
- <param name="Bluetooth-Manager" value="ws" />
- <param name="audiomixer" value="ws" />
- <param name="vshl-core" value="ws" />
- </feature>
- <feature name="urn:AGL:widget:required-permission">
- <param name="urn:AGL:permission::public:no-htdocs" value="required" />
- <param name="urn:AGL:permission::system:run-by-default" value="required" />
- <param name="urn:AGL:permission::public:display" value="required" />
- </feature>
-</widget>